/spare/repo/netdev-2.6 branch 'sis190'
authorJeff Garzik <jgarzik@pobox.com>
Mon, 29 Aug 2005 19:52:56 +0000 (15:52 -0400)
committerJeff Garzik <jgarzik@pobox.com>
Mon, 29 Aug 2005 19:52:56 +0000 (15:52 -0400)
804 files changed:
CREDITS
Documentation/SubmittingPatches
Documentation/acpi-hotkey.txt
Documentation/arm/Samsung-S3C24XX/USB-Host.txt [new file with mode: 0644]
Documentation/dontdiff
Documentation/fb/vesafb.txt
Documentation/kernel-parameters.txt
Documentation/kprobes.txt [new file with mode: 0644]
Documentation/networking/bonding.txt
Documentation/networking/phy.txt [new file with mode: 0644]
Documentation/pci.txt
Documentation/usb/usbmon.txt
Documentation/video4linux/CARDLIST.cx88
Documentation/video4linux/CARDLIST.tuner
Documentation/video4linux/bttv/Insmod-options
Documentation/x86_64/boot-options.txt
MAINTAINERS
Makefile
REPORTING-BUGS
arch/alpha/Kconfig
arch/alpha/kernel/pci.c
arch/alpha/kernel/signal.c
arch/alpha/kernel/smp.c
arch/alpha/oprofile/common.c
arch/arm/Kconfig
arch/arm/common/Kconfig
arch/arm/common/Makefile
arch/arm/common/gic.c [new file with mode: 0644]
arch/arm/kernel/bios32.c
arch/arm/kernel/calls.S
arch/arm/kernel/entry-armv.S
arch/arm/kernel/signal.c
arch/arm/kernel/traps.c
arch/arm/lib/bitops.h
arch/arm/mach-ixp4xx/coyote-setup.c
arch/arm/mach-ixp4xx/gtwx5715-setup.c
arch/arm/mach-ixp4xx/ixdp425-setup.c
arch/arm/mach-s3c2410/mach-bast.c
arch/arm/mach-s3c2410/s3c2410.c
arch/arm/mach-s3c2410/usb-simtec.c
arch/arm/mach-sa1100/assabet.c
arch/arm/mach-sa1100/cerf.c
arch/arm/mach-sa1100/generic.c
arch/arm/mach-sa1100/generic.h
arch/arm/mach-sa1100/jornada720.c
arch/arm/mach-sa1100/lart.c
arch/arm/mach-sa1100/shannon.c
arch/arm/mach-sa1100/simpad.c
arch/arm/mm/Kconfig
arch/arm/mm/fault.c
arch/arm/mm/mm-armv.c
arch/arm/mm/proc-v6.S
arch/arm/mm/proc-xscale.S
arch/arm/nwfpe/double_cpdo.c
arch/arm/nwfpe/extended_cpdo.c
arch/arm/nwfpe/fpa11.c
arch/arm/nwfpe/fpa11.h
arch/arm/nwfpe/fpa11_cpdo.c
arch/arm/nwfpe/fpa11_cpdt.c
arch/arm/nwfpe/fpa11_cprt.c
arch/arm/nwfpe/fpmodule.c
arch/arm/nwfpe/fpopcode.h
arch/arm/nwfpe/single_cpdo.c
arch/arm/nwfpe/softfloat.c
arch/arm/nwfpe/softfloat.h
arch/arm/oprofile/backtrace.c
arch/arm/vfp/vfpdouble.c
arch/arm26/kernel/signal.c
arch/arm26/mm/fault.c
arch/cris/arch-v10/kernel/signal.c
arch/cris/arch-v32/kernel/signal.c
arch/cris/mm/fault.c
arch/frv/kernel/signal.c
arch/frv/mm/fault.c
arch/h8300/kernel/signal.c
arch/i386/Kconfig
arch/i386/kernel/apic.c
arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
arch/i386/kernel/cpu/transmeta.c
arch/i386/kernel/nmi.c
arch/i386/kernel/signal.c
arch/i386/kernel/syscall_table.S
arch/i386/kernel/traps.c
arch/i386/mach-visws/reboot.c
arch/i386/mach-visws/setup.c
arch/i386/mach-voyager/voyager_basic.c
arch/i386/mm/discontig.c
arch/i386/pci/acpi.c
arch/i386/pci/common.c
arch/i386/pci/irq.c
arch/i386/pci/pci.h
arch/i386/pci/visws.c
arch/ia64/Kconfig
arch/ia64/configs/sn2_defconfig
arch/ia64/configs/tiger_defconfig
arch/ia64/configs/zx1_defconfig
arch/ia64/hp/sim/boot/boot_head.S
arch/ia64/kernel/domain.c
arch/ia64/kernel/entry.S
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/process.c
arch/ia64/kernel/salinfo.c
arch/ia64/kernel/signal.c
arch/ia64/pci/pci.c
arch/ia64/sn/kernel/io_init.c
arch/m32r/Kconfig
arch/m32r/Kconfig.debug
arch/m32r/kernel/setup_m32700ut.c
arch/m32r/kernel/setup_opsput.c
arch/m32r/kernel/signal.c
arch/m32r/kernel/smpboot.c
arch/m32r/kernel/time.c
arch/m32r/lib/csum_partial_copy.c
arch/m32r/mm/discontig.c
arch/m68k/mm/fault.c
arch/m68knommu/kernel/signal.c
arch/mips/kernel/irixsig.c
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c
arch/parisc/kernel/signal.c
arch/parisc/mm/fault.c
arch/ppc/8xx_io/Kconfig
arch/ppc/8xx_io/commproc.c
arch/ppc/8xx_io/fec.c
arch/ppc/Kconfig
arch/ppc/boot/simple/Makefile
arch/ppc/boot/simple/pibs.c
arch/ppc/configs/bamboo_defconfig [new file with mode: 0644]
arch/ppc/kernel/cputable.c
arch/ppc/kernel/entry.S
arch/ppc/kernel/head_44x.S
arch/ppc/kernel/misc.S
arch/ppc/kernel/pci.c
arch/ppc/kernel/ppc_ksyms.c
arch/ppc/kernel/signal.c
arch/ppc/platforms/4xx/Kconfig
arch/ppc/platforms/4xx/Makefile
arch/ppc/platforms/4xx/bamboo.c [new file with mode: 0644]
arch/ppc/platforms/4xx/bamboo.h [new file with mode: 0644]
arch/ppc/platforms/4xx/ebony.c
arch/ppc/platforms/4xx/ebony.h
arch/ppc/platforms/4xx/ibm440ep.c [new file with mode: 0644]
arch/ppc/platforms/4xx/ibm440ep.h [new file with mode: 0644]
arch/ppc/platforms/4xx/ocotea.c
arch/ppc/platforms/4xx/ocotea.h
arch/ppc/syslib/Makefile
arch/ppc/syslib/ibm440gx_common.c
arch/ppc/syslib/ibm44x_common.h
arch/ppc/syslib/m8xx_setup.c
arch/ppc/syslib/mpc83xx_devices.c
arch/ppc/syslib/ppc4xx_dma.c
arch/ppc64/boot/zlib.c
arch/ppc64/configs/bpa_defconfig [new file with mode: 0644]
arch/ppc64/configs/g5_defconfig
arch/ppc64/configs/iSeries_defconfig
arch/ppc64/configs/maple_defconfig
arch/ppc64/configs/pSeries_defconfig
arch/ppc64/defconfig
arch/ppc64/kernel/LparData.c
arch/ppc64/kernel/Makefile
arch/ppc64/kernel/head.S
arch/ppc64/kernel/iommu.c
arch/ppc64/kernel/lparmap.c [new file with mode: 0644]
arch/ppc64/kernel/machine_kexec.c
arch/ppc64/kernel/misc.S
arch/ppc64/kernel/mpic.c
arch/ppc64/kernel/mpic.h
arch/ppc64/kernel/pci.c
arch/ppc64/kernel/prom.c
arch/ppc64/kernel/prom_init.c
arch/ppc64/kernel/setup.c
arch/ppc64/kernel/signal.c
arch/ppc64/kernel/signal32.c
arch/ppc64/kernel/xics.c
arch/ppc64/mm/numa.c
arch/ppc64/xmon/xmon.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/cpcmd.c
arch/s390/kernel/machine_kexec.c
arch/s390/kernel/relocate_kernel.S
arch/s390/kernel/relocate_kernel64.S
arch/s390/kernel/signal.c
arch/s390/kernel/smp.c
arch/s390/kernel/syscalls.S
arch/s390/kernel/traps.c
arch/sh/kernel/entry.S
arch/sh/kernel/signal.c
arch/sh64/kernel/signal.c
arch/sh64/kernel/syscalls.S
arch/sh64/mm/fault.c
arch/sparc/kernel/signal.c
arch/sparc/kernel/sparc_ksyms.c
arch/sparc64/kernel/Makefile
arch/sparc64/kernel/pci.c
arch/sparc64/kernel/signal.c
arch/sparc64/kernel/signal32.c
arch/sparc64/kernel/traps.c
arch/sparc64/kernel/una_asm.S [new file with mode: 0644]
arch/sparc64/kernel/unaligned.c
arch/sparc64/kernel/us2e_cpufreq.c
arch/sparc64/kernel/us3_cpufreq.c
arch/sparc64/solaris/socket.c
arch/um/drivers/mmapper_kern.c
arch/um/kernel/signal_kern.c
arch/um/kernel/skas/process.c
arch/um/os-Linux/elf_aux.c
arch/v850/kernel/signal.c
arch/x86_64/crypto/aes.c
arch/x86_64/defconfig
arch/x86_64/ia32/ptrace32.c
arch/x86_64/kernel/e820.c
arch/x86_64/kernel/mce.c
arch/x86_64/kernel/mpparse.c
arch/x86_64/kernel/setup.c
arch/x86_64/kernel/signal.c
arch/x86_64/kernel/smpboot.c
arch/x86_64/lib/csum-copy.S
arch/x86_64/mm/fault.c
arch/x86_64/mm/init.c
arch/x86_64/mm/numa.c
arch/x86_64/pci/k8-bus.c
arch/xtensa/kernel/signal.c
drivers/Kconfig
drivers/Makefile
drivers/acorn/block/fd1772.c
drivers/acpi/Kconfig
drivers/acpi/button.c
drivers/acpi/dispatcher/dswload.c
drivers/acpi/ec.c
drivers/acpi/hotkey.c
drivers/acpi/osl.c
drivers/acpi/pci_irq.c
drivers/acpi/pci_link.c
drivers/acpi/processor_idle.c
drivers/acpi/sleep/poweroff.c
drivers/base/bus.c
drivers/base/class.c
drivers/block/cfq-iosched.c
drivers/block/ll_rw_blk.c
drivers/bluetooth/bpa10x.c
drivers/bluetooth/hci_bcsp.c
drivers/bluetooth/hci_h4.c
drivers/bluetooth/hci_ldisc.c
drivers/bluetooth/hci_usb.c
drivers/char/Kconfig
drivers/char/mem.c
drivers/char/rtc.c
drivers/char/tpm/Kconfig
drivers/char/tpm/tpm_infineon.c
drivers/char/vt.c
drivers/char/watchdog/i8xx_tco.c
drivers/char/watchdog/sa1100_wdt.c
drivers/fc4/fc.c
drivers/hwmon/adm1026.c
drivers/hwmon/adm1031.c
drivers/hwmon/adm9240.c
drivers/hwmon/fscpos.c
drivers/hwmon/smsc47b397.c
drivers/hwmon/smsc47m1.c
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-sibyte.c
drivers/ide/Kconfig
drivers/ide/ide-disk.c
drivers/ide/ide-floppy.c
drivers/ide/ide-probe.c
drivers/ide/legacy/ide-cs.c
drivers/ide/pci/generic.c
drivers/ide/pci/serverworks.c
drivers/ide/ppc/pmac.c
drivers/ide/setup-pci.c
drivers/ieee1394/ohci1394.c
drivers/infiniband/Kconfig
drivers/infiniband/core/Makefile
drivers/infiniband/core/agent.c
drivers/infiniband/core/agent_priv.h
drivers/infiniband/core/cache.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/cm_msgs.h
drivers/infiniband/core/core_priv.h
drivers/infiniband/core/device.c
drivers/infiniband/core/fmr_pool.c
drivers/infiniband/core/mad.c
drivers/infiniband/core/mad_priv.h
drivers/infiniband/core/mad_rmpp.c
drivers/infiniband/core/packer.c
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/smi.c
drivers/infiniband/core/sysfs.c
drivers/infiniband/core/ucm.c
drivers/infiniband/core/ucm.h
drivers/infiniband/core/ud_header.c
drivers/infiniband/core/user_mad.c
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/core/uverbs_mem.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/mthca/Makefile
drivers/infiniband/hw/mthca/mthca_allocator.c
drivers/infiniband/hw/mthca/mthca_av.c
drivers/infiniband/hw/mthca/mthca_cmd.c
drivers/infiniband/hw/mthca/mthca_cmd.h
drivers/infiniband/hw/mthca/mthca_config_reg.h
drivers/infiniband/hw/mthca/mthca_cq.c
drivers/infiniband/hw/mthca/mthca_dev.h
drivers/infiniband/hw/mthca/mthca_doorbell.h
drivers/infiniband/hw/mthca/mthca_eq.c
drivers/infiniband/hw/mthca/mthca_mad.c
drivers/infiniband/hw/mthca/mthca_main.c
drivers/infiniband/hw/mthca/mthca_mcg.c
drivers/infiniband/hw/mthca/mthca_memfree.c
drivers/infiniband/hw/mthca/mthca_memfree.h
drivers/infiniband/hw/mthca/mthca_mr.c
drivers/infiniband/hw/mthca/mthca_pd.c
drivers/infiniband/hw/mthca/mthca_profile.c
drivers/infiniband/hw/mthca/mthca_profile.h
drivers/infiniband/hw/mthca/mthca_provider.c
drivers/infiniband/hw/mthca/mthca_provider.h
drivers/infiniband/hw/mthca/mthca_qp.c
drivers/infiniband/hw/mthca/mthca_srq.c [new file with mode: 0644]
drivers/infiniband/hw/mthca/mthca_user.h
drivers/infiniband/hw/mthca/mthca_wqe.h [new file with mode: 0644]
drivers/infiniband/ulp/ipoib/Makefile
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_fs.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/infiniband/ulp/ipoib/ipoib_verbs.c
drivers/infiniband/ulp/ipoib/ipoib_vlan.c
drivers/input/gameport/ns558.c
drivers/isdn/capi/capifs.c
drivers/isdn/hisax/Kconfig
drivers/isdn/icn/icn.c
drivers/macintosh/Kconfig
drivers/md/bitmap.c
drivers/md/dm-raid1.c
drivers/md/md.c
drivers/md/raid1.c
drivers/md/raid5.c
drivers/md/raid6main.c
drivers/media/dvb/dvb-usb/dibusb-common.c
drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/dvb-pll.c
drivers/media/dvb/frontends/dvb-pll.h
drivers/media/dvb/frontends/lgdt330x.c
drivers/media/dvb/frontends/lgdt330x.h
drivers/media/dvb/frontends/lgdt330x_priv.h
drivers/media/dvb/frontends/tda80xx.c
drivers/media/video/Kconfig
drivers/media/video/bttv-cards.c
drivers/media/video/bttv-driver.c
drivers/media/video/bttv.h
drivers/media/video/bttvp.h
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/cx88/cx88.h
drivers/media/video/msp3400.c
drivers/media/video/saa7134/saa7134-i2c.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/tea5767.c
drivers/media/video/tuner-core.c
drivers/media/video/tuner-simple.c
drivers/media/video/tveeprom.c
drivers/message/i2o/Kconfig
drivers/message/i2o/config-osm.c
drivers/message/i2o/pci.c
drivers/mfd/Kconfig [new file with mode: 0644]
drivers/mfd/Makefile [new file with mode: 0644]
drivers/mfd/mcp-core.c [new file with mode: 0644]
drivers/mfd/mcp-sa11x0.c [new file with mode: 0644]
drivers/mfd/mcp.h [new file with mode: 0644]
drivers/mmc/mmc.c
drivers/mmc/mmc.h
drivers/mmc/mmc_sysfs.c
drivers/mmc/mmci.c
drivers/mmc/wbsd.c
drivers/net/8139cp.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/Space.c
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bonding.h
drivers/net/cs89x0.c
drivers/net/cs89x0.h
drivers/net/dm9000.c
drivers/net/e1000/e1000_main.c
drivers/net/eepro100.c
drivers/net/forcedeth.c
drivers/net/hamradio/6pack.c
drivers/net/hamradio/Kconfig
drivers/net/hamradio/baycom_epp.c
drivers/net/hamradio/baycom_par.c
drivers/net/hamradio/baycom_ser_fdx.c
drivers/net/hamradio/baycom_ser_hdx.c
drivers/net/hamradio/mkiss.c
drivers/net/ibm_emac/ibm_emac_core.c
drivers/net/ioc3-eth.c
drivers/net/ixgb/ixgb.h
drivers/net/ixgb/ixgb_ee.c
drivers/net/ixgb/ixgb_ethtool.c
drivers/net/ixgb/ixgb_hw.h
drivers/net/ixgb/ixgb_main.c
drivers/net/jazzsonic.c
drivers/net/loopback.c
drivers/net/macsonic.c
drivers/net/mv643xx_eth.c
drivers/net/mv643xx_eth.h
drivers/net/pci-skeleton.c
drivers/net/pcmcia/fmvj18x_cs.c
drivers/net/phy/Kconfig [new file with mode: 0644]
drivers/net/phy/Makefile [new file with mode: 0644]
drivers/net/phy/cicada.c [new file with mode: 0644]
drivers/net/phy/davicom.c [new file with mode: 0644]
drivers/net/phy/lxt.c [new file with mode: 0644]
drivers/net/phy/marvell.c [new file with mode: 0644]
drivers/net/phy/mdio_bus.c [new file with mode: 0644]
drivers/net/phy/phy.c [new file with mode: 0644]
drivers/net/phy/phy_device.c [new file with mode: 0644]
drivers/net/phy/qsemi.c [new file with mode: 0644]
drivers/net/r8169.c
drivers/net/s2io-regs.h
drivers/net/s2io.c
drivers/net/s2io.h
drivers/net/sk98lin/skge.c
drivers/net/sk98lin/skgeinit.c
drivers/net/sk98lin/skxmac2.c
drivers/net/skge.c
drivers/net/skge.h
drivers/net/smc-ultra.c
drivers/net/smc91x.h
drivers/net/sonic.c
drivers/net/sonic.h
drivers/net/tg3.c
drivers/net/tokenring/Kconfig
drivers/net/tokenring/abyss.c
drivers/net/tokenring/madgemc.c
drivers/net/tokenring/proteon.c
drivers/net/tokenring/skisa.c
drivers/net/tokenring/tms380tr.c
drivers/net/tokenring/tms380tr.h
drivers/net/tokenring/tmspci.c
drivers/net/tulip/Kconfig
drivers/net/tulip/Makefile
drivers/net/tulip/media.c
drivers/net/tulip/timer.c
drivers/net/tulip/tulip.h
drivers/net/tulip/tulip_core.c
drivers/net/tulip/uli526x.c [new file with mode: 0644]
drivers/net/wan/cycx_drv.c
drivers/net/wireless/Kconfig
drivers/net/wireless/orinoco.c
drivers/parport/Kconfig
drivers/parport/parport_serial.c
drivers/pci/bus.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/pciehp_pci.c
drivers/pci/hotplug/pciehprm.h
drivers/pci/hotplug/pciehprm_acpi.c
drivers/pci/hotplug/pciehprm_nonacpi.c
drivers/pci/hotplug/pciehprm_nonacpi.h
drivers/pci/hotplug/shpchp.h
drivers/pci/hotplug/shpchp_core.c
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/hotplug/shpchp_hpc.c
drivers/pci/hotplug/shpchp_pci.c
drivers/pci/hotplug/shpchprm.h
drivers/pci/hotplug/shpchprm_acpi.c
drivers/pci/hotplug/shpchprm_legacy.c
drivers/pci/hotplug/shpchprm_legacy.h
drivers/pci/hotplug/shpchprm_nonacpi.c
drivers/pci/hotplug/shpchprm_nonacpi.h
drivers/pci/msi.c
drivers/pci/pci.h
drivers/pci/quirks.c
drivers/pci/setup-bus.c
drivers/pci/setup-res.c
drivers/pcmcia/ds.c
drivers/pcmcia/pcmcia_resource.c
drivers/pcmcia/yenta_socket.c
drivers/pnp/card.c
drivers/s390/cio/qdio.c
drivers/s390/crypto/z90crypt.h
drivers/s390/net/qeth_main.c
drivers/s390/net/qeth_proc.c
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_ccw.c
drivers/s390/scsi/zfcp_def.h
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_ext.h
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_scsi.c
drivers/s390/scsi/zfcp_sysfs_port.c
drivers/sbus/char/bbc_envctrl.c
drivers/sbus/char/envctrl.c
drivers/sbus/char/vfc.h
drivers/sbus/char/vfc_dev.c
drivers/sbus/char/vfc_i2c.c
drivers/scsi/Kconfig
drivers/scsi/aacraid/aacraid.h
drivers/scsi/aacraid/linit.c
drivers/scsi/ahci.c
drivers/scsi/aic7xxx/aic7xxx_osm.c
drivers/scsi/aic7xxx/aicasm/aicasm.c
drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h
drivers/scsi/arm/Kconfig
drivers/scsi/ata_piix.c
drivers/scsi/dc395x.c
drivers/scsi/dpt_i2o.c
drivers/scsi/ibmvscsi/srp.h
drivers/scsi/ips.c
drivers/scsi/ips.h
drivers/scsi/libata-core.c
drivers/scsi/libata-scsi.c
drivers/scsi/libata.h
drivers/scsi/sata_nv.c
drivers/scsi/sata_promise.c
drivers/scsi/sata_qstor.c
drivers/scsi/sata_sil.c
drivers/scsi/sata_sis.c
drivers/scsi/sata_svw.c
drivers/scsi/sata_sx4.c
drivers/scsi/sata_uli.c
drivers/scsi/sata_via.c
drivers/scsi/sata_vsc.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_transport_fc.c
drivers/scsi/sg.c
drivers/scsi/st.c
drivers/serial/8250_pci.c
drivers/serial/Kconfig
drivers/serial/cpm_uart/cpm_uart.h
drivers/serial/cpm_uart/cpm_uart_core.c
drivers/serial/cpm_uart/cpm_uart_cpm1.c
drivers/serial/m32r_sio.c
drivers/serial/sn_console.c
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-q.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci.h
drivers/usb/host/isp116x-hcd.c
drivers/usb/input/wacom.c
drivers/usb/mon/Kconfig
drivers/usb/mon/Makefile
drivers/usb/mon/mon_main.c
drivers/usb/mon/usb_mon.h
drivers/usb/net/usbnet.c
drivers/usb/net/zd1201.c
drivers/video/console/Kconfig
drivers/video/fbmem.c
drivers/video/fbsysfs.c
drivers/video/intelfb/intelfbdrv.c
drivers/video/modedb.c
drivers/video/nvidia/nvidia.c
drivers/video/pxafb.c
drivers/video/radeonfb.c
drivers/video/sa1100fb.c
drivers/video/tridentfb.c
drivers/w1/w1.c
fs/Kconfig
fs/adfs/adfs.h
fs/afs/mntpt.c
fs/autofs/symlink.c
fs/autofs4/symlink.c
fs/befs/linuxvfs.c
fs/bio.c
fs/cifs/CHANGES
fs/cifs/cifsfs.h
fs/cifs/cifssmb.c
fs/cifs/file.c
fs/cifs/link.c
fs/cifs/misc.c
fs/dcache.c
fs/devfs/base.c
fs/ext2/symlink.c
fs/ext3/symlink.c
fs/freevxfs/vxfs_immed.c
fs/hfs/bnode.c
fs/hfs/extent.c
fs/hfsplus/bnode.c
fs/hfsplus/extents.c
fs/hppfs/hppfs_kern.c
fs/inotify.c
fs/ioprio.c
fs/isofs/compress.c
fs/jffs2/symlink.c
fs/jfs/inode.c
fs/jfs/jfs_logmgr.c
fs/jfs/jfs_logmgr.h
fs/jfs/jfs_txnmgr.c
fs/jfs/super.c
fs/jfs/symlink.c
fs/namei.c
fs/namespace.c
fs/nfs/dir.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/nfs3acl.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4proc.c
fs/nfs/proc.c
fs/nfs/read.c
fs/nfs/symlink.c
fs/nfs_common/nfsacl.c
fs/nfsd/nfssvc.c
fs/ntfs/ChangeLog
fs/ntfs/aops.c
fs/ntfs/mft.c
fs/proc/base.c
fs/proc/generic.c
fs/reiserfs/inode.c
fs/reiserfs/namei.c
fs/smbfs/symlink.c
fs/sysfs/inode.c
fs/sysfs/symlink.c
fs/sysv/symlink.c
fs/ufs/symlink.c
fs/xfs/linux-2.6/xfs_iops.c
include/acpi/acpi_drivers.h
include/asm-alpha/pci.h
include/asm-alpha/system.h
include/asm-arm/arch-ixp4xx/timex.h
include/asm-arm/arch-s3c2410/usb-control.h
include/asm-arm/arch-sa1100/mcp.h [new file with mode: 0644]
include/asm-arm/bug.h
include/asm-arm/cpu-multi32.h
include/asm-arm/cpu-single.h
include/asm-arm/hardware/gic.h [new file with mode: 0644]
include/asm-arm/pci.h
include/asm-arm/pgtable.h
include/asm-arm/unistd.h
include/asm-generic/pci.h
include/asm-i386/mach-visws/do_timer.h
include/asm-i386/processor.h
include/asm-ia64/io.h
include/asm-ia64/iosapic.h
include/asm-m32r/smp.h
include/asm-m68k/page.h
include/asm-parisc/pci.h
include/asm-ppc/ibm44x.h
include/asm-ppc/ibm4xx.h
include/asm-ppc/ibm_ocp.h
include/asm-ppc/pci.h
include/asm-ppc/pgtable.h
include/asm-ppc/ppc4xx_dma.h
include/asm-ppc/ppc_asm.h
include/asm-ppc/time.h
include/asm-ppc/unistd.h
include/asm-ppc64/bug.h
include/asm-ppc64/iSeries/LparMap.h
include/asm-ppc64/machdep.h
include/asm-ppc64/pci.h
include/asm-ppc64/topology.h
include/asm-ppc64/unistd.h
include/asm-ppc64/xics.h
include/asm-s390/uaccess.h
include/asm-s390/unistd.h
include/asm-sh/unistd.h
include/asm-sh64/unistd.h
include/asm-sparc64/thread_info.h
include/asm-um/page.h
include/asm-x86_64/e820.h
include/asm-x86_64/processor.h
include/linux/8250_pci.h
include/linux/acpi.h
include/linux/ata.h
include/linux/blkdev.h
include/linux/dcookies.h
include/linux/ethtool.h
include/linux/fs.h
include/linux/fsnotify.h
include/linux/ide.h
include/linux/inotify.h
include/linux/libata.h
include/linux/mii.h
include/linux/mm.h
include/linux/mmc/host.h
include/linux/mod_devicetable.h
include/linux/netlink.h
include/linux/netpoll.h
include/linux/nfs_fs.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/phy.h [new file with mode: 0644]
include/linux/raid/bitmap.h
include/linux/serialP.h
include/linux/skbuff.h
include/linux/sunrpc/xdr.h
include/linux/swap.h
include/linux/zlib.h
include/media/tuner.h
include/net/ax25.h
include/net/bluetooth/bluetooth.h
include/net/sock.h
include/net/tcp.h
include/rdma/ib_cache.h [moved from drivers/infiniband/include/ib_cache.h with 96% similarity]
include/rdma/ib_cm.h [moved from drivers/infiniband/include/ib_cm.h with 89% similarity]
include/rdma/ib_fmr_pool.h [moved from drivers/infiniband/include/ib_fmr_pool.h with 99% similarity]
include/rdma/ib_mad.h [moved from drivers/infiniband/include/ib_mad.h with 98% similarity]
include/rdma/ib_pack.h [moved from drivers/infiniband/include/ib_pack.h with 99% similarity]
include/rdma/ib_sa.h [moved from drivers/infiniband/include/ib_sa.h with 98% similarity]
include/rdma/ib_smi.h [moved from drivers/infiniband/include/ib_smi.h with 95% similarity]
include/rdma/ib_user_cm.h [moved from drivers/infiniband/include/ib_user_cm.h with 95% similarity]
include/rdma/ib_user_mad.h [moved from drivers/infiniband/include/ib_user_mad.h with 97% similarity]
include/rdma/ib_user_verbs.h [moved from drivers/infiniband/include/ib_user_verbs.h with 92% similarity]
include/rdma/ib_verbs.h [moved from drivers/infiniband/include/ib_verbs.h with 91% similarity]
include/scsi/scsi_transport.h
include/sound/core.h
ipc/sem.c
ipc/shm.c
kernel/cpuset.c
kernel/exit.c
kernel/module.c
kernel/posix-timers.c
kernel/sched.c
kernel/signal.c
kernel/softirq.c
kernel/sys.c
kernel/sys_ni.c
kernel/timer.c
kernel/workqueue.c
lib/crc32.c
lib/idr.c
lib/inflate.c
lib/vsprintf.c
mm/hugetlb.c
mm/memory.c
mm/mempolicy.c
mm/mmap.c
mm/mremap.c
mm/nommu.c
mm/page_alloc.c
mm/shmem.c
net/802/tr.c
net/ax25/af_ax25.c
net/ax25/ax25_route.c
net/ax25/ax25_uid.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/lib.c
net/bluetooth/rfcomm/core.c
net/compat.c
net/core/dev.c
net/core/dst.c
net/core/netpoll.c
net/decnet/af_decnet.c
net/decnet/dn_neigh.c
net/ipv4/fib_semantics.c
net/ipv4/fib_trie.c
net/ipv4/icmp.c
net/ipv4/inetpeer.c
net/ipv4/ip_fragment.c
net/ipv4/ip_gre.c
net/ipv4/ip_sockglue.c
net/ipv4/ipcomp.c
net/ipv4/ipip.c
net/ipv4/ipmr.c
net/ipv4/netfilter/ip_conntrack_core.c
net/ipv4/netfilter/ip_nat_standalone.c
net/ipv4/netfilter/ip_queue.c
net/ipv4/netfilter/ipt_ECN.c
net/ipv4/netfilter/ipt_TCPMSS.c
net/ipv4/tcp.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv6/ip6_input.c
net/ipv6/ipcomp6.c
net/ipv6/ipv6_sockglue.c
net/ipv6/netfilter/ip6_queue.c
net/ipv6/raw.c
net/ipv6/sit.c
net/ipv6/tcp_ipv6.c
net/netrom/af_netrom.c
net/rose/af_rose.c
net/rose/rose_route.c
net/sched/sch_generic.c
net/sctp/proc.c
net/sunrpc/auth_gss/gss_krb5_crypto.c
net/sunrpc/svcsock.c
net/sunrpc/xdr.c
scripts/mod/modpost.c
security/keys/keyctl.c
security/keys/keyring.c
security/keys/process_keys.c
security/keys/request_key.c
sound/Kconfig
sound/core/Makefile
sound/core/sound.c
sound/isa/Kconfig
sound/oss/Kconfig
sound/oss/Makefile
sound/oss/i810_audio.c
sound/oss/vidc.h
sound/pci/Kconfig
sound/pci/intel8x0.c
sound/ppc/pmac.c

diff --git a/CREDITS b/CREDITS
index d97e625..f553f8c 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -2380,8 +2380,8 @@ E: tmolina@cablespeed.com
 D: bug fixes, documentation, minor hackery
 
 N: James Morris
-E: jmorris@redhat.com
-W: http://www.intercode.com.au/jmorris/
+E: jmorris@namei.org
+W: http://namei.org/
 D: Netfilter, Linux Security Modules (LSM), SELinux, IPSec,
 D: Crypto API, general networking, miscellaneous.
 S: PO Box 707
@@ -2423,8 +2423,7 @@ S: Toronto, Ontario
 S: Canada
 
 N: Zwane Mwaikambo
-E: zwane@linuxpower.ca
-W: http://function.linuxpower.ca
+E: zwane@arm.linux.org.uk
 D: Various driver hacking
 D: Lowlevel x86 kernel hacking
 D: General debugging
index 6761a7b..7f43b04 100644 (file)
@@ -149,6 +149,11 @@ USB, framebuffer devices, the VFS, the SCSI subsystem, etc.  See the
 MAINTAINERS file for a mailing list that relates specifically to
 your change.
 
+If changes affect userland-kernel interfaces, please send
+the MAN-PAGES maintainer (as listed in the MAINTAINERS file)
+a man-pages patch, or at least a notification of the change,
+so that some information makes its way into the manual pages.
+
 Even if the maintainer did not respond in step #4, make sure to ALWAYS
 copy the maintainer when you change their code.
 
index 4c115a7..0acdc80 100644 (file)
@@ -33,3 +33,6 @@ The result of the execution of this aml method is
 attached to /proc/acpi/hotkey/poll_method, which is dnyamically
 created.  Please use command "cat /proc/acpi/hotkey/polling_method" 
 to retrieve it.
+
+Note: Use cmdline "acpi_generic_hotkey" to over-ride
+loading any platform specific drivers.
diff --git a/Documentation/arm/Samsung-S3C24XX/USB-Host.txt b/Documentation/arm/Samsung-S3C24XX/USB-Host.txt
new file mode 100644 (file)
index 0000000..b93b68e
--- /dev/null
@@ -0,0 +1,93 @@
+                       S3C24XX USB Host support
+                       ========================
+
+
+
+Introduction
+------------
+
+  This document details the S3C2410/S3C2440 in-built OHCI USB host support.
+
+Configuration
+-------------
+
+  Enable at least the following kernel options:
+
+  menuconfig:
+
+   Device Drivers  --->
+     USB support  --->
+       <*> Support for Host-side USB
+       <*>   OHCI HCD support
+
+
+  .config:
+    CONFIG_USB
+    CONFIG_USB_OHCI_HCD
+
+
+  Once these options are configured, the standard set of USB device
+  drivers can be configured and used.
+
+
+Board Support
+-------------
+
+  The driver attaches to a platform device, which will need to be
+  added by the board specific support file in linux/arch/arm/mach-s3c2410,
+  such as mach-bast.c or mach-smdk2410.c
+
+  The platform device's platform_data field is only needed if the
+  board implements extra power control or over-current monitoring.
+
+  The OHCI driver does not ensure the state of the S3C2410's MISCCTRL
+  register, so if both ports are to be used for the host, then it is
+  the board support file's responsibility to ensure that the second
+  port is configured to be connected to the OHCI core.
+
+
+Platform Data
+-------------
+
+  See linux/include/asm-arm/arch-s3c2410/usb-control.h for the
+  descriptions of the platform device data. An implementation
+  can be found in linux/arch/arm/mach-s3c2410/usb-simtec.c .
+
+  The `struct s3c2410_hcd_info` contains a pair of functions
+  that get called to enable over-current detection, and to
+  control the port power status.
+
+  The ports are numbered 0 and 1.
+
+  power_control:
+
+    Called to enable or disable the power on the port.
+
+  enable_oc:
+
+    Called to enable or disable the over-current monitoring.
+    This should claim or release the resources being used to
+    check the power condition on the port, such as an IRQ.
+
+  report_oc:
+
+    The OHCI driver fills this field in for the over-current code
+    to call when there is a change to the over-current state on
+    an port. The ports argument is a bitmask of 1 bit per port,
+    with bit X being 1 for an over-current on port X.
+
+    The function s3c2410_usb_report_oc() has been provided to
+    ensure this is called correctly.
+
+  port[x]:
+
+    This is struct describes each port, 0 or 1. The platform driver
+    should set the flags field of each port to S3C_HCDFLG_USED if
+    the port is enabled.
+
+
+
+Document Author
+---------------
+
+Ben Dooks, (c) 2005 Simtec Electronics
index b974cf5..96bea27 100644 (file)
@@ -104,6 +104,7 @@ logo_*.c
 logo_*_clut224.c
 logo_*_mono.c
 lxdialog
+mach-types
 mach-types.h
 make_times_h
 map
index 814e2f5..62db675 100644 (file)
@@ -144,7 +144,21 @@ vgapal     Use the standard vga registers for palette changes.
        This is the default.
 pmipal Use the protected mode interface for palette changes.
 
-mtrr   setup memory type range registers for the vesafb framebuffer.
+mtrr:n setup memory type range registers for the vesafb framebuffer
+       where n:
+             0 - disabled (equivalent to nomtrr)
+             1 - uncachable
+             2 - write-back
+             3 - write-combining (default)
+             4 - write-through
+
+       If you see the following in dmesg, choose the type that matches the
+       old one. In this example, use "mtrr:2".
+...
+mtrr: type mismatch for e0000000,8000000 old: write-back new: write-combining
+...
+
+nomtrr  disable mtrr
 
 vremap:n
         remap 'n' MiB of video RAM. If 0 or not specified, remap memory
index a998a8c..3d5cd7a 100644 (file)
@@ -159,6 +159,11 @@ running once the system is up.
 
        acpi_fake_ecdt  [HW,ACPI] Workaround failure due to BIOS lacking ECDT
 
+       acpi_generic_hotkey [HW,ACPI]
+                       Allow consolidated generic hotkey driver to
+                       over-ride platform specific driver.
+                       See also Documentation/acpi-hotkey.txt.
+
        ad1816=         [HW,OSS]
                        Format: <io>,<irq>,<dma>,<dma2>
                        See also Documentation/sound/oss/AD1816.
diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt
new file mode 100644 (file)
index 0000000..0541fe1
--- /dev/null
@@ -0,0 +1,588 @@
+Title  : Kernel Probes (Kprobes)
+Authors        : Jim Keniston <jkenisto@us.ibm.com>
+       : Prasanna S Panchamukhi <prasanna@in.ibm.com>
+
+CONTENTS
+
+1. Concepts: Kprobes, Jprobes, Return Probes
+2. Architectures Supported
+3. Configuring Kprobes
+4. API Reference
+5. Kprobes Features and Limitations
+6. Probe Overhead
+7. TODO
+8. Kprobes Example
+9. Jprobes Example
+10. Kretprobes Example
+
+1. Concepts: Kprobes, Jprobes, Return Probes
+
+Kprobes enables you to dynamically break into any kernel routine and
+collect debugging and performance information non-disruptively. You
+can trap at almost any kernel code address, specifying a handler
+routine to be invoked when the breakpoint is hit.
+
+There are currently three types of probes: kprobes, jprobes, and
+kretprobes (also called return probes).  A kprobe can be inserted
+on virtually any instruction in the kernel.  A jprobe is inserted at
+the entry to a kernel function, and provides convenient access to the
+function's arguments.  A return probe fires when a specified function
+returns.
+
+In the typical case, Kprobes-based instrumentation is packaged as
+a kernel module.  The module's init function installs ("registers")
+one or more probes, and the exit function unregisters them.  A
+registration function such as register_kprobe() specifies where
+the probe is to be inserted and what handler is to be called when
+the probe is hit.
+
+The next three subsections explain how the different types of
+probes work.  They explain certain things that you'll need to
+know in order to make the best use of Kprobes -- e.g., the
+difference between a pre_handler and a post_handler, and how
+to use the maxactive and nmissed fields of a kretprobe.  But
+if you're in a hurry to start using Kprobes, you can skip ahead
+to section 2.
+
+1.1 How Does a Kprobe Work?
+
+When a kprobe is registered, Kprobes makes a copy of the probed
+instruction and replaces the first byte(s) of the probed instruction
+with a breakpoint instruction (e.g., int3 on i386 and x86_64).
+
+When a CPU hits the breakpoint instruction, a trap occurs, the CPU's
+registers are saved, and control passes to Kprobes via the
+notifier_call_chain mechanism.  Kprobes executes the "pre_handler"
+associated with the kprobe, passing the handler the addresses of the
+kprobe struct and the saved registers.
+
+Next, Kprobes single-steps its copy of the probed instruction.
+(It would be simpler to single-step the actual instruction in place,
+but then Kprobes would have to temporarily remove the breakpoint
+instruction.  This would open a small time window when another CPU
+could sail right past the probepoint.)
+
+After the instruction is single-stepped, Kprobes executes the
+"post_handler," if any, that is associated with the kprobe.
+Execution then continues with the instruction following the probepoint.
+
+1.2 How Does a Jprobe Work?
+
+A jprobe is implemented using a kprobe that is placed on a function's
+entry point.  It employs a simple mirroring principle to allow
+seamless access to the probed function's arguments.  The jprobe
+handler routine should have the same signature (arg list and return
+type) as the function being probed, and must always end by calling
+the Kprobes function jprobe_return().
+
+Here's how it works.  When the probe is hit, Kprobes makes a copy of
+the saved registers and a generous portion of the stack (see below).
+Kprobes then points the saved instruction pointer at the jprobe's
+handler routine, and returns from the trap.  As a result, control
+passes to the handler, which is presented with the same register and
+stack contents as the probed function.  When it is done, the handler
+calls jprobe_return(), which traps again to restore the original stack
+contents and processor state and switch to the probed function.
+
+By convention, the callee owns its arguments, so gcc may produce code
+that unexpectedly modifies that portion of the stack.  This is why
+Kprobes saves a copy of the stack and restores it after the jprobe
+handler has run.  Up to MAX_STACK_SIZE bytes are copied -- e.g.,
+64 bytes on i386.
+
+Note that the probed function's args may be passed on the stack
+or in registers (e.g., for x86_64 or for an i386 fastcall function).
+The jprobe will work in either case, so long as the handler's
+prototype matches that of the probed function.
+
+1.3 How Does a Return Probe Work?
+
+When you call register_kretprobe(), Kprobes establishes a kprobe at
+the entry to the function.  When the probed function is called and this
+probe is hit, Kprobes saves a copy of the return address, and replaces
+the return address with the address of a "trampoline."  The trampoline
+is an arbitrary piece of code -- typically just a nop instruction.
+At boot time, Kprobes registers a kprobe at the trampoline.
+
+When the probed function executes its return instruction, control
+passes to the trampoline and that probe is hit.  Kprobes' trampoline
+handler calls the user-specified handler associated with the kretprobe,
+then sets the saved instruction pointer to the saved return address,
+and that's where execution resumes upon return from the trap.
+
+While the probed function is executing, its return address is
+stored in an object of type kretprobe_instance.  Before calling
+register_kretprobe(), the user sets the maxactive field of the
+kretprobe struct to specify how many instances of the specified
+function can be probed simultaneously.  register_kretprobe()
+pre-allocates the indicated number of kretprobe_instance objects.
+
+For example, if the function is non-recursive and is called with a
+spinlock held, maxactive = 1 should be enough.  If the function is
+non-recursive and can never relinquish the CPU (e.g., via a semaphore
+or preemption), NR_CPUS should be enough.  If maxactive <= 0, it is
+set to a default value.  If CONFIG_PREEMPT is enabled, the default
+is max(10, 2*NR_CPUS).  Otherwise, the default is NR_CPUS.
+
+It's not a disaster if you set maxactive too low; you'll just miss
+some probes.  In the kretprobe struct, the nmissed field is set to
+zero when the return probe is registered, and is incremented every
+time the probed function is entered but there is no kretprobe_instance
+object available for establishing the return probe.
+
+2. Architectures Supported
+
+Kprobes, jprobes, and return probes are implemented on the following
+architectures:
+
+- i386
+- x86_64 (AMD-64, E64MT)
+- ppc64
+- ia64 (Support for probes on certain instruction types is still in progress.)
+- sparc64 (Return probes not yet implemented.)
+
+3. Configuring Kprobes
+
+When configuring the kernel using make menuconfig/xconfig/oldconfig,
+ensure that CONFIG_KPROBES is set to "y".  Under "Kernel hacking",
+look for "Kprobes".  You may have to enable "Kernel debugging"
+(CONFIG_DEBUG_KERNEL) before you can enable Kprobes.
+
+You may also want to ensure that CONFIG_KALLSYMS and perhaps even
+CONFIG_KALLSYMS_ALL are set to "y", since kallsyms_lookup_name()
+is a handy, version-independent way to find a function's address.
+
+If you need to insert a probe in the middle of a function, you may find
+it useful to "Compile the kernel with debug info" (CONFIG_DEBUG_INFO),
+so you can use "objdump -d -l vmlinux" to see the source-to-object
+code mapping.
+
+4. API Reference
+
+The Kprobes API includes a "register" function and an "unregister"
+function for each type of probe.  Here are terse, mini-man-page
+specifications for these functions and the associated probe handlers
+that you'll write.  See the latter half of this document for examples.
+
+4.1 register_kprobe
+
+#include <linux/kprobes.h>
+int register_kprobe(struct kprobe *kp);
+
+Sets a breakpoint at the address kp->addr.  When the breakpoint is
+hit, Kprobes calls kp->pre_handler.  After the probed instruction
+is single-stepped, Kprobe calls kp->post_handler.  If a fault
+occurs during execution of kp->pre_handler or kp->post_handler,
+or during single-stepping of the probed instruction, Kprobes calls
+kp->fault_handler.  Any or all handlers can be NULL.
+
+register_kprobe() returns 0 on success, or a negative errno otherwise.
+
+User's pre-handler (kp->pre_handler):
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
+int pre_handler(struct kprobe *p, struct pt_regs *regs);
+
+Called with p pointing to the kprobe associated with the breakpoint,
+and regs pointing to the struct containing the registers saved when
+the breakpoint was hit.  Return 0 here unless you're a Kprobes geek.
+
+User's post-handler (kp->post_handler):
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
+void post_handler(struct kprobe *p, struct pt_regs *regs,
+       unsigned long flags);
+
+p and regs are as described for the pre_handler.  flags always seems
+to be zero.
+
+User's fault-handler (kp->fault_handler):
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
+int fault_handler(struct kprobe *p, struct pt_regs *regs, int trapnr);
+
+p and regs are as described for the pre_handler.  trapnr is the
+architecture-specific trap number associated with the fault (e.g.,
+on i386, 13 for a general protection fault or 14 for a page fault).
+Returns 1 if it successfully handled the exception.
+
+4.2 register_jprobe
+
+#include <linux/kprobes.h>
+int register_jprobe(struct jprobe *jp)
+
+Sets a breakpoint at the address jp->kp.addr, which must be the address
+of the first instruction of a function.  When the breakpoint is hit,
+Kprobes runs the handler whose address is jp->entry.
+
+The handler should have the same arg list and return type as the probed
+function; and just before it returns, it must call jprobe_return().
+(The handler never actually returns, since jprobe_return() returns
+control to Kprobes.)  If the probed function is declared asmlinkage,
+fastcall, or anything else that affects how args are passed, the
+handler's declaration must match.
+
+register_jprobe() returns 0 on success, or a negative errno otherwise.
+
+4.3 register_kretprobe
+
+#include <linux/kprobes.h>
+int register_kretprobe(struct kretprobe *rp);
+
+Establishes a return probe for the function whose address is
+rp->kp.addr.  When that function returns, Kprobes calls rp->handler.
+You must set rp->maxactive appropriately before you call
+register_kretprobe(); see "How Does a Return Probe Work?" for details.
+
+register_kretprobe() returns 0 on success, or a negative errno
+otherwise.
+
+User's return-probe handler (rp->handler):
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
+int kretprobe_handler(struct kretprobe_instance *ri, struct pt_regs *regs);
+
+regs is as described for kprobe.pre_handler.  ri points to the
+kretprobe_instance object, of which the following fields may be
+of interest:
+- ret_addr: the return address
+- rp: points to the corresponding kretprobe object
+- task: points to the corresponding task struct
+The handler's return value is currently ignored.
+
+4.4 unregister_*probe
+
+#include <linux/kprobes.h>
+void unregister_kprobe(struct kprobe *kp);
+void unregister_jprobe(struct jprobe *jp);
+void unregister_kretprobe(struct kretprobe *rp);
+
+Removes the specified probe.  The unregister function can be called
+at any time after the probe has been registered.
+
+5. Kprobes Features and Limitations
+
+As of Linux v2.6.12, Kprobes allows multiple probes at the same
+address.  Currently, however, there cannot be multiple jprobes on
+the same function at the same time.
+
+In general, you can install a probe anywhere in the kernel.
+In particular, you can probe interrupt handlers.  Known exceptions
+are discussed in this section.
+
+For obvious reasons, it's a bad idea to install a probe in
+the code that implements Kprobes (mostly kernel/kprobes.c and
+arch/*/kernel/kprobes.c).  A patch in the v2.6.13 timeframe instructs
+Kprobes to reject such requests.
+
+If you install a probe in an inline-able function, Kprobes makes
+no attempt to chase down all inline instances of the function and
+install probes there.  gcc may inline a function without being asked,
+so keep this in mind if you're not seeing the probe hits you expect.
+
+A probe handler can modify the environment of the probed function
+-- e.g., by modifying kernel data structures, or by modifying the
+contents of the pt_regs struct (which are restored to the registers
+upon return from the breakpoint).  So Kprobes can be used, for example,
+to install a bug fix or to inject faults for testing.  Kprobes, of
+course, has no way to distinguish the deliberately injected faults
+from the accidental ones.  Don't drink and probe.
+
+Kprobes makes no attempt to prevent probe handlers from stepping on
+each other -- e.g., probing printk() and then calling printk() from a
+probe handler.  As of Linux v2.6.12, if a probe handler hits a probe,
+that second probe's handlers won't be run in that instance.
+
+In Linux v2.6.12 and previous versions, Kprobes' data structures are
+protected by a single lock that is held during probe registration and
+unregistration and while handlers are run.  Thus, no two handlers
+can run simultaneously.  To improve scalability on SMP systems,
+this restriction will probably be removed soon, in which case
+multiple handlers (or multiple instances of the same handler) may
+run concurrently on different CPUs.  Code your handlers accordingly.
+
+Kprobes does not use semaphores or allocate memory except during
+registration and unregistration.
+
+Probe handlers are run with preemption disabled.  Depending on the
+architecture, handlers may also run with interrupts disabled.  In any
+case, your handler should not yield the CPU (e.g., by attempting to
+acquire a semaphore).
+
+Since a return probe is implemented by replacing the return
+address with the trampoline's address, stack backtraces and calls
+to __builtin_return_address() will typically yield the trampoline's
+address instead of the real return address for kretprobed functions.
+(As far as we can tell, __builtin_return_address() is used only
+for instrumentation and error reporting.)
+
+If the number of times a function is called does not match the
+number of times it returns, registering a return probe on that
+function may produce undesirable results.  We have the do_exit()
+and do_execve() cases covered.  do_fork() is not an issue.  We're
+unaware of other specific cases where this could be a problem.
+
+6. Probe Overhead
+
+On a typical CPU in use in 2005, a kprobe hit takes 0.5 to 1.0
+microseconds to process.  Specifically, a benchmark that hits the same
+probepoint repeatedly, firing a simple handler each time, reports 1-2
+million hits per second, depending on the architecture.  A jprobe or
+return-probe hit typically takes 50-75% longer than a kprobe hit.
+When you have a return probe set on a function, adding a kprobe at
+the entry to that function adds essentially no overhead.
+
+Here are sample overhead figures (in usec) for different architectures.
+k = kprobe; j = jprobe; r = return probe; kr = kprobe + return probe
+on same function; jr = jprobe + return probe on same function
+
+i386: Intel Pentium M, 1495 MHz, 2957.31 bogomips
+k = 0.57 usec; j = 1.00; r = 0.92; kr = 0.99; jr = 1.40
+
+x86_64: AMD Opteron 246, 1994 MHz, 3971.48 bogomips
+k = 0.49 usec; j = 0.76; r = 0.80; kr = 0.82; jr = 1.07
+
+ppc64: POWER5 (gr), 1656 MHz (SMT disabled, 1 virtual CPU per physical CPU)
+k = 0.77 usec; j = 1.31; r = 1.26; kr = 1.45; jr = 1.99
+
+7. TODO
+
+a. SystemTap (http://sourceware.org/systemtap): Work in progress
+to provide a simplified programming interface for probe-based
+instrumentation.
+b. Improved SMP scalability: Currently, work is in progress to handle
+multiple kprobes in parallel.
+c. Kernel return probes for sparc64.
+d. Support for other architectures.
+e. User-space probes.
+
+8. Kprobes Example
+
+Here's a sample kernel module showing the use of kprobes to dump a
+stack trace and selected i386 registers when do_fork() is called.
+----- cut here -----
+/*kprobe_example.c*/
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+#include <linux/sched.h>
+
+/*For each probe you need to allocate a kprobe structure*/
+static struct kprobe kp;
+
+/*kprobe pre_handler: called just before the probed instruction is executed*/
+int handler_pre(struct kprobe *p, struct pt_regs *regs)
+{
+       printk("pre_handler: p->addr=0x%p, eip=%lx, eflags=0x%lx\n",
+               p->addr, regs->eip, regs->eflags);
+       dump_stack();
+       return 0;
+}
+
+/*kprobe post_handler: called after the probed instruction is executed*/
+void handler_post(struct kprobe *p, struct pt_regs *regs, unsigned long flags)
+{
+       printk("post_handler: p->addr=0x%p, eflags=0x%lx\n",
+               p->addr, regs->eflags);
+}
+
+/* fault_handler: this is called if an exception is generated for any
+ * instruction within the pre- or post-handler, or when Kprobes
+ * single-steps the probed instruction.
+ */
+int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr)
+{
+       printk("fault_handler: p->addr=0x%p, trap #%dn",
+               p->addr, trapnr);
+       /* Return 0 because we don't handle the fault. */
+       return 0;
+}
+
+int init_module(void)
+{
+       int ret;
+       kp.pre_handler = handler_pre;
+       kp.post_handler = handler_post;
+       kp.fault_handler = handler_fault;
+       kp.addr = (kprobe_opcode_t*) kallsyms_lookup_name("do_fork");
+       /* register the kprobe now */
+       if (!kp.addr) {
+               printk("Couldn't find %s to plant kprobe\n", "do_fork");
+               return -1;
+       }
+       if ((ret = register_kprobe(&kp) < 0)) {
+               printk("register_kprobe failed, returned %d\n", ret);
+               return -1;
+       }
+       printk("kprobe registered\n");
+       return 0;
+}
+
+void cleanup_module(void)
+{
+       unregister_kprobe(&kp);
+       printk("kprobe unregistered\n");
+}
+
+MODULE_LICENSE("GPL");
+----- cut here -----
+
+You can build the kernel module, kprobe-example.ko, using the following
+Makefile:
+----- cut here -----
+obj-m := kprobe-example.o
+KDIR := /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+default:
+       $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
+clean:
+       rm -f *.mod.c *.ko *.o
+----- cut here -----
+
+$ make
+$ su -
+...
+# insmod kprobe-example.ko
+
+You will see the trace data in /var/log/messages and on the console
+whenever do_fork() is invoked to create a new process.
+
+9. Jprobes Example
+
+Here's a sample kernel module showing the use of jprobes to dump
+the arguments of do_fork().
+----- cut here -----
+/*jprobe-example.c */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/uio.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+/*
+ * Jumper probe for do_fork.
+ * Mirror principle enables access to arguments of the probed routine
+ * from the probe handler.
+ */
+
+/* Proxy routine having the same arguments as actual do_fork() routine */
+long jdo_fork(unsigned long clone_flags, unsigned long stack_start,
+             struct pt_regs *regs, unsigned long stack_size,
+             int __user * parent_tidptr, int __user * child_tidptr)
+{
+       printk("jprobe: clone_flags=0x%lx, stack_size=0x%lx, regs=0x%p\n",
+              clone_flags, stack_size, regs);
+       /* Always end with a call to jprobe_return(). */
+       jprobe_return();
+       /*NOTREACHED*/
+       return 0;
+}
+
+static struct jprobe my_jprobe = {
+       .entry = (kprobe_opcode_t *) jdo_fork
+};
+
+int init_module(void)
+{
+       int ret;
+       my_jprobe.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("do_fork");
+       if (!my_jprobe.kp.addr) {
+               printk("Couldn't find %s to plant jprobe\n", "do_fork");
+               return -1;
+       }
+
+       if ((ret = register_jprobe(&my_jprobe)) <0) {
+               printk("register_jprobe failed, returned %d\n", ret);
+               return -1;
+       }
+       printk("Planted jprobe at %p, handler addr %p\n",
+              my_jprobe.kp.addr, my_jprobe.entry);
+       return 0;
+}
+
+void cleanup_module(void)
+{
+       unregister_jprobe(&my_jprobe);
+       printk("jprobe unregistered\n");
+}
+
+MODULE_LICENSE("GPL");
+----- cut here -----
+
+Build and insert the kernel module as shown in the above kprobe
+example.  You will see the trace data in /var/log/messages and on
+the console whenever do_fork() is invoked to create a new process.
+(Some messages may be suppressed if syslogd is configured to
+eliminate duplicate messages.)
+
+10. Kretprobes Example
+
+Here's a sample kernel module showing the use of return probes to
+report failed calls to sys_open().
+----- cut here -----
+/*kretprobe-example.c*/
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+static const char *probed_func = "sys_open";
+
+/* Return-probe handler: If the probed function fails, log the return value. */
+static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+       // Substitute the appropriate register name for your architecture --
+       // e.g., regs->rax for x86_64, regs->gpr[3] for ppc64.
+       int retval = (int) regs->eax;
+       if (retval < 0) {
+               printk("%s returns %d\n", probed_func, retval);
+       }
+       return 0;
+}
+
+static struct kretprobe my_kretprobe = {
+       .handler = ret_handler,
+       /* Probe up to 20 instances concurrently. */
+       .maxactive = 20
+};
+
+int init_module(void)
+{
+       int ret;
+       my_kretprobe.kp.addr =
+               (kprobe_opcode_t *) kallsyms_lookup_name(probed_func);
+       if (!my_kretprobe.kp.addr) {
+               printk("Couldn't find %s to plant return probe\n", probed_func);
+               return -1;
+       }
+       if ((ret = register_kretprobe(&my_kretprobe)) < 0) {
+               printk("register_kretprobe failed, returned %d\n", ret);
+               return -1;
+       }
+       printk("Planted return probe at %p\n", my_kretprobe.kp.addr);
+       return 0;
+}
+
+void cleanup_module(void)
+{
+       unregister_kretprobe(&my_kretprobe);
+       printk("kretprobe unregistered\n");
+       /* nmissed > 0 suggests that maxactive was set too low. */
+       printk("Missed probing %d instances of %s\n",
+               my_kretprobe.nmissed, probed_func);
+}
+
+MODULE_LICENSE("GPL");
+----- cut here -----
+
+Build and insert the kernel module as shown in the above kprobe
+example.  You will see the trace data in /var/log/messages and on the
+console whenever sys_open() returns a negative value.  (Some messages
+may be suppressed if syslogd is configured to eliminate duplicate
+messages.)
+
+For additional information on Kprobes, refer to the following URLs:
+http://www-106.ibm.com/developerworks/library/l-kprobes.html?ca=dgr-lnxw42Kprobe
+http://www.redhat.com/magazine/005mar05/features/kprobes/
index 0bc2ed1..24d0294 100644 (file)
@@ -1,5 +1,7 @@
 
-                   Linux Ethernet Bonding Driver HOWTO
+               Linux Ethernet Bonding Driver HOWTO
+
+               Latest update: 21 June 2005
 
 Initial release : Thomas Davis <tadavis at lbl.gov>
 Corrections, HA extensions : 2000/10/03-15 :
@@ -11,15 +13,22 @@ Corrections, HA extensions : 2000/10/03-15 :
 
 Reorganized and updated Feb 2005 by Jay Vosburgh
 
-Note :
-------
+Introduction
+============
+
+       The Linux bonding driver provides a method for aggregating
+multiple network interfaces into a single logical "bonded" interface.
+The behavior of the bonded interfaces depends upon the mode; generally
+speaking, modes provide either hot standby or load balancing services.
+Additionally, link integrity monitoring may be performed.
        
-The bonding driver originally came from Donald Becker's beowulf patches for
-kernel 2.0. It has changed quite a bit since, and the original tools from
-extreme-linux and beowulf sites will not work with this version of the driver.
+       The bonding driver originally came from Donald Becker's
+beowulf patches for kernel 2.0. It has changed quite a bit since, and
+the original tools from extreme-linux and beowulf sites will not work
+with this version of the driver.
 
-For new versions of the driver, patches for older kernels and the updated
-userspace tools, please follow the links at the end of this file.
+       For new versions of the driver, updated userspace tools, and
+who to ask for help, please follow the links at the end of this file.
 
 Table of Contents
 =================
@@ -30,9 +39,13 @@ Table of Contents
 
 3. Configuring Bonding Devices
 3.1    Configuration with sysconfig support
+3.1.1          Using DHCP with sysconfig
+3.1.2          Configuring Multiple Bonds with sysconfig
 3.2    Configuration with initscripts support
+3.2.1          Using DHCP with initscripts
+3.2.2          Configuring Multiple Bonds with initscripts
 3.3    Configuring Bonding Manually
-3.4    Configuring Multiple Bonds
+3.3.1          Configuring Multiple Bonds Manually
 
 5. Querying Bonding Configuration
 5.1    Bonding Configuration
@@ -56,21 +69,30 @@ Table of Contents
 
 11. Promiscuous mode
 
-12. High Availability Information
+12. Configuring Bonding for High Availability
 12.1   High Availability in a Single Switch Topology
-12.1.1         Bonding Mode Selection for Single Switch Topology
-12.1.2         Link Monitoring for Single Switch Topology
 12.2   High Availability in a Multiple Switch Topology
-12.2.1         Bonding Mode Selection for Multiple Switch Topology
-12.2.2         Link Monitoring for Multiple Switch Topology
-12.3   Switch Behavior Issues for High Availability
+12.2.1         HA Bonding Mode Selection for Multiple Switch Topology
+12.2.2         HA Link Monitoring for Multiple Switch Topology
+
+13. Configuring Bonding for Maximum Throughput
+13.1   Maximum Throughput in a Single Switch Topology
+13.1.1         MT Bonding Mode Selection for Single Switch Topology
+13.1.2         MT Link Monitoring for Single Switch Topology
+13.2   Maximum Throughput in a Multiple Switch Topology
+13.2.1         MT Bonding Mode Selection for Multiple Switch Topology
+13.2.2         MT Link Monitoring for Multiple Switch Topology
 
-13. Hardware Specific Considerations
-13.1   IBM BladeCenter
+14. Switch Behavior Issues
+14.1   Link Establishment and Failover Delays
+14.2   Duplicated Incoming Packets
 
-14. Frequently Asked Questions
+15. Hardware Specific Considerations
+15.1   IBM BladeCenter
 
-15. Resources and Links
+16. Frequently Asked Questions
+
+17. Resources and Links
 
 
 1. Bonding Driver Installation
@@ -86,16 +108,10 @@ the following steps:
 1.1 Configure and build the kernel with bonding
 -----------------------------------------------
 
-       The latest version of the bonding driver is available in the
+       The current version of the bonding driver is available in the
 drivers/net/bonding subdirectory of the most recent kernel source
-(which is available on http://kernel.org).
-
-       Prior to the 2.4.11 kernel, the bonding driver was maintained
-largely outside the kernel tree; patches for some earlier kernels are
-available on the bonding sourceforge site, although those patches are
-still several years out of date.  Most users will want to use either
-the most recent kernel from kernel.org or whatever kernel came with
-their distro.
+(which is available on http://kernel.org).  Most users "rolling their
+own" will want to use the most recent kernel from kernel.org.
 
        Configure kernel with "make menuconfig" (or "make xconfig" or
 "make config"), then select "Bonding driver support" in the "Network
@@ -103,8 +119,8 @@ device support" section.  It is recommended that you configure the
 driver as module since it is currently the only way to pass parameters
 to the driver or configure more than one bonding device.
 
-       Build and install the new kernel and modules, then proceed to
-step 2.
+       Build and install the new kernel and modules, then continue
+below to install ifenslave.
 
 1.2 Install ifenslave Control Utility
 -------------------------------------
@@ -147,9 +163,9 @@ default kernel source include directory.
        Options for the bonding driver are supplied as parameters to
 the bonding module at load time.  They may be given as command line
 arguments to the insmod or modprobe command, but are usually specified
-in either the /etc/modprobe.conf configuration file, or in a
-distro-specific configuration file (some of which are detailed in the
-next section).
+in either the /etc/modules.conf or /etc/modprobe.conf configuration
+file, or in a distro-specific configuration file (some of which are
+detailed in the next section).
 
        The available bonding driver parameters are listed below. If a
 parameter is not specified the default value is used.  When initially
@@ -162,34 +178,34 @@ degradation will occur during link failures.  Very few devices do not
 support at least miimon, so there is really no reason not to use it.
 
        Options with textual values will accept either the text name
-       or, for backwards compatibility, the option value.  E.g.,
-       "mode=802.3ad" and "mode=4" set the same mode.
+or, for backwards compatibility, the option value.  E.g.,
+"mode=802.3ad" and "mode=4" set the same mode.
 
        The parameters are as follows:
 
 arp_interval
 
-       Specifies the ARP monitoring frequency in milli-seconds. If
-       ARP monitoring is used in a load-balancing mode (mode 0 or 2),
-       the switch should be configured in a mode that evenly
-       distributes packets across all links - such as round-robin. If
-       the switch is configured to distribute the packets in an XOR
+       Specifies the ARP link monitoring frequency in milliseconds.
+       If ARP monitoring is used in an etherchannel compatible mode
+       (modes 0 and 2), the switch should be configured in a mode
+       that evenly distributes packets across all links. If the
+       switch is configured to distribute the packets in an XOR
        fashion, all replies from the ARP targets will be received on
        the same link which could cause the other team members to
-       fail. ARP monitoring should not be used in conjunction with
-       miimon. A value of 0 disables ARP monitoring. The default
+       fail.  ARP monitoring should not be used in conjunction with
+       miimon.  A value of 0 disables ARP monitoring.  The default
        value is 0.
 
 arp_ip_target
 
-       Specifies the ip addresses to use when arp_interval is > 0.
-       These are the targets of the ARP request sent to determine the
-       health of the link to the targets.  Specify these values in
-       ddd.ddd.ddd.ddd format.  Multiple ip adresses must be
-       seperated by a comma.  At least one IP address must be given
-       for ARP monitoring to function.  The maximum number of targets
-       that can be specified is 16.  The default value is no IP
-       addresses.
+       Specifies the IP addresses to use as ARP monitoring peers when
+       arp_interval is > 0.  These are the targets of the ARP request
+       sent to determine the health of the link to the targets.
+       Specify these values in ddd.ddd.ddd.ddd format.  Multiple IP
+       addresses must be separated by a comma.  At least one IP
+       address must be given for ARP monitoring to function.  The
+       maximum number of targets that can be specified is 16.  The
+       default value is no IP addresses.
 
 downdelay
 
@@ -207,11 +223,13 @@ lacp_rate
        are:
 
        slow or 0
-               Request partner to transmit LACPDUs every 30 seconds (default)
+               Request partner to transmit LACPDUs every 30 seconds
 
        fast or 1
                Request partner to transmit LACPDUs every 1 second
 
+       The default is slow.
+
 max_bonds
 
        Specifies the number of bonding devices to create for this
@@ -221,10 +239,11 @@ max_bonds
 
 miimon
 
-       Specifies the frequency in milli-seconds that MII link
-       monitoring will occur.  A value of zero disables MII link
-       monitoring.  A value of 100 is a good starting point.  The
-       use_carrier option, below, affects how the link state is
+       Specifies the MII link monitoring frequency in milliseconds.
+       This determines how often the link state of each slave is
+       inspected for link failures.  A value of zero disables MII
+       link monitoring.  A value of 100 is a good starting point.
+       The use_carrier option, below, affects how the link state is
        determined.  See the High Availability section for additional
        information.  The default value is 0.
 
@@ -246,17 +265,31 @@ mode
                active.  A different slave becomes active if, and only
                if, the active slave fails.  The bond's MAC address is
                externally visible on only one port (network adapter)
-               to avoid confusing the switch.  This mode provides
-               fault tolerance.  The primary option affects the
-               behavior of this mode.
+               to avoid confusing the switch.
+
+               In bonding version 2.6.2 or later, when a failover
+               occurs in active-backup mode, bonding will issue one
+               or more gratuitous ARPs on the newly active slave.
+               One gratutious ARP is issued for the bonding master
+               interface and each VLAN interfaces configured above
+               it, provided that the interface has at least one IP
+               address configured.  Gratuitous ARPs issued for VLAN
+               interfaces are tagged with the appropriate VLAN id.
+
+               This mode provides fault tolerance.  The primary
+               option, documented below, affects the behavior of this
+               mode.
 
        balance-xor or 2
 
-               XOR policy: Transmit based on [(source MAC address
-               XOR'd with destination MAC address) modulo slave
-               count].  This selects the same slave for each
-               destination MAC address.  This mode provides load
-               balancing and fault tolerance.
+               XOR policy: Transmit based on the selected transmit
+               hash policy.  The default policy is a simple [(source
+               MAC address XOR'd with destination MAC address) modulo
+               slave count].  Alternate transmit policies may be
+               selected via the xmit_hash_policy option, described
+               below.
+
+               This mode provides load balancing and fault tolerance.
 
        broadcast or 3
 
@@ -270,7 +303,17 @@ mode
                duplex settings.  Utilizes all slaves in the active
                aggregator according to the 802.3ad specification.
 
-               Pre-requisites:
+               Slave selection for outgoing traffic is done according
+               to the transmit hash policy, which may be changed from
+               the default simple XOR policy via the xmit_hash_policy
+               option, documented below.  Note that not all transmit
+               policies may be 802.3ad compliant, particularly in
+               regards to the packet mis-ordering requirements of
+               section 43.2.4 of the 802.3ad standard.  Differing
+               peer implementations will have varying tolerances for
+               noncompliance.
+
+               Prerequisites:
 
                1. Ethtool support in the base drivers for retrieving
                the speed and duplex of each slave.
@@ -333,7 +376,7 @@ mode
 
                When a link is reconnected or a new slave joins the
                bond the receive traffic is redistributed among all
-               active slaves in the bond by intiating ARP Replies
+               active slaves in the bond by initiating ARP Replies
                with the selected mac address to each of the
                clients. The updelay parameter (detailed below) must
                be set to a value equal or greater than the switch's
@@ -396,6 +439,60 @@ use_carrier
        0 will use the deprecated MII / ETHTOOL ioctls.  The default
        value is 1.
 
+xmit_hash_policy
+
+       Selects the transmit hash policy to use for slave selection in
+       balance-xor and 802.3ad modes.  Possible values are:
+
+       layer2
+
+               Uses XOR of hardware MAC addresses to generate the
+               hash.  The formula is
+
+               (source MAC XOR destination MAC) modulo slave count
+
+               This algorithm will place all traffic to a particular
+               network peer on the same slave.
+
+               This algorithm is 802.3ad compliant.
+
+       layer3+4
+
+               This policy uses upper layer protocol information,
+               when available, to generate the hash.  This allows for
+               traffic to a particular network peer to span multiple
+               slaves, although a single connection will not span
+               multiple slaves.
+
+               The formula for unfragmented TCP and UDP packets is
+
+               ((source port XOR dest port) XOR
+                        ((source IP XOR dest IP) AND 0xffff)
+                               modulo slave count
+
+               For fragmented TCP or UDP packets and all other IP
+               protocol traffic, the source and destination port
+               information is omitted.  For non-IP traffic, the
+               formula is the same as for the layer2 transmit hash
+               policy.
+
+               This policy is intended to mimic the behavior of
+               certain switches, notably Cisco switches with PFC2 as
+               well as some Foundry and IBM products.
+
+               This algorithm is not fully 802.3ad compliant.  A
+               single TCP or UDP conversation containing both
+               fragmented and unfragmented packets will see packets
+               striped across two interfaces.  This may result in out
+               of order delivery.  Most traffic types will not meet
+               this criteria, as TCP rarely fragments traffic, and
+               most UDP traffic is not involved in extended
+               conversations.  Other implementations of 802.3ad may
+               or may not tolerate this noncompliance.
+
+       The default value is layer2.  This option was added in bonding
+version 2.6.3.  In earlier versions of bonding, this parameter does
+not exist, and the layer2 policy is the only policy.
 
 
 3. Configuring Bonding Devices
@@ -448,8 +545,9 @@ Bonding devices can be managed by hand, however, as follows.
 slave devices.  On SLES 9, this is most easily done by running the
 yast2 sysconfig configuration utility.  The goal is for to create an
 ifcfg-id file for each slave device.  The simplest way to accomplish
-this is to configure the devices for DHCP.  The name of the
-configuration file for each device will be of the form:
+this is to configure the devices for DHCP (this is only to get the
+file ifcfg-id file created; see below for some issues with DHCP).  The
+name of the configuration file for each device will be of the form:
 
 ifcfg-id-xx:xx:xx:xx:xx:xx
 
@@ -459,7 +557,7 @@ the device's permanent MAC address.
        Once the set of ifcfg-id-xx:xx:xx:xx:xx:xx files has been
 created, it is necessary to edit the configuration files for the slave
 devices (the MAC addresses correspond to those of the slave devices).
-Before editing, the file will contain muliple lines, and will look
+Before editing, the file will contain multiple lines, and will look
 something like this:
 
 BOOTPROTO='dhcp'
@@ -496,16 +594,11 @@ STARTMODE="onboot"
 BONDING_MASTER="yes"
 BONDING_MODULE_OPTS="mode=active-backup miimon=100"
 BONDING_SLAVE0="eth0"
-BONDING_SLAVE1="eth1"
+BONDING_SLAVE1="bus-pci-0000:06:08.1"
 
        Replace the sample BROADCAST, IPADDR, NETMASK and NETWORK
 values with the appropriate values for your network.
 
-       Note that configuring the bonding device with BOOTPROTO='dhcp'
-does not work; the scripts attempt to obtain the device address from
-DHCP prior to adding any of the slave devices.  Without active slaves,
-the DHCP requests are not sent to the network.
-
        The STARTMODE specifies when the device is brought online.
 The possible values are:
 
@@ -531,9 +624,17 @@ for the bonding mode, link monitoring, and so on here.  Do not include
 the max_bonds bonding parameter; this will confuse the configuration
 system if you have multiple bonding devices.
 
-       Finally, supply one BONDING_SLAVEn="ethX" for each slave,
-where "n" is an increasing value, one for each slave, and "ethX" is
-the name of the slave device (eth0, eth1, etc).
+       Finally, supply one BONDING_SLAVEn="slave device" for each
+slave.  where "n" is an increasing value, one for each slave.  The
+"slave device" is either an interface name, e.g., "eth0", or a device
+specifier for the network device.  The interface name is easier to
+find, but the ethN names are subject to change at boot time if, e.g.,
+a device early in the sequence has failed.  The device specifiers
+(bus-pci-0000:06:08.1 in the example above) specify the physical
+network device, and will not change unless the device's bus location
+changes (for example, it is moved from one PCI slot to another).  The
+example above uses one of each type for demonstration purposes; most
+configurations will choose one or the other for all slave devices.
 
        When all configuration files have been modified or created,
 networking must be restarted for the configuration changes to take
@@ -544,7 +645,7 @@ effect.  This can be accomplished via the following:
        Note that the network control script (/sbin/ifdown) will
 remove the bonding module as part of the network shutdown processing,
 so it is not necessary to remove the module by hand if, e.g., the
-module paramters have changed.
+module parameters have changed.
 
        Also, at this writing, YaST/YaST2 will not manage bonding
 devices (they do not show bonding interfaces on its list of network
@@ -559,12 +660,37 @@ format can be found in an example ifcfg template file:
        Note that the template does not document the various BONDING_
 settings described above, but does describe many of the other options.
 
+3.1.1 Using DHCP with sysconfig
+-------------------------------
+
+       Under sysconfig, configuring a device with BOOTPROTO='dhcp'
+will cause it to query DHCP for its IP address information.  At this
+writing, this does not function for bonding devices; the scripts
+attempt to obtain the device address from DHCP prior to adding any of
+the slave devices.  Without active slaves, the DHCP requests are not
+sent to the network.
+
+3.1.2 Configuring Multiple Bonds with sysconfig
+-----------------------------------------------
+
+       The sysconfig network initialization system is capable of
+handling multiple bonding devices.  All that is necessary is for each
+bonding instance to have an appropriately configured ifcfg-bondX file
+(as described above).  Do not specify the "max_bonds" parameter to any
+instance of bonding, as this will confuse sysconfig.  If you require
+multiple bonding devices with identical parameters, create multiple
+ifcfg-bondX files.
+
+       Because the sysconfig scripts supply the bonding module
+options in the ifcfg-bondX file, it is not necessary to add them to
+the system /etc/modules.conf or /etc/modprobe.conf configuration file.
+
 3.2 Configuration with initscripts support
 ------------------------------------------
 
        This section applies to distros using a version of initscripts
 with bonding support, for example, Red Hat Linux 9 or Red Hat
-Enterprise Linux version 3.  On these systems, the network
+Enterprise Linux version 3 or 4.  On these systems, the network
 initialization scripts have some knowledge of bonding, and can be
 configured to control bonding devices.
 
@@ -614,10 +740,11 @@ USERCTL=no
        Be sure to change the networking specific lines (IPADDR,
 NETMASK, NETWORK and BROADCAST) to match your network configuration.
 
-       Finally, it is necessary to edit /etc/modules.conf to load the
-bonding module when the bond0 interface is brought up.  The following
-sample lines in /etc/modules.conf will load the bonding module, and
-select its options:
+       Finally, it is necessary to edit /etc/modules.conf (or
+/etc/modprobe.conf, depending upon your distro) to load the bonding
+module with your desired options when the bond0 interface is brought
+up.  The following lines in /etc/modules.conf (or modprobe.conf) will
+load the bonding module, and select its options:
 
 alias bond0 bonding
 options bond0 mode=balance-alb miimon=100
@@ -629,6 +756,33 @@ options for your configuration.
 will restart the networking subsystem and your bond link should be now
 up and running.
 
+3.2.1 Using DHCP with initscripts
+---------------------------------
+
+       Recent versions of initscripts (the version supplied with
+Fedora Core 3 and Red Hat Enterprise Linux 4 is reported to work) do
+have support for assigning IP information to bonding devices via DHCP.
+
+       To configure bonding for DHCP, configure it as described
+above, except replace the line "BOOTPROTO=none" with "BOOTPROTO=dhcp"
+and add a line consisting of "TYPE=Bonding".  Note that the TYPE value
+is case sensitive.
+
+3.2.2 Configuring Multiple Bonds with initscripts
+-------------------------------------------------
+
+       At this writing, the initscripts package does not directly
+support loading the bonding driver multiple times, so the process for
+doing so is the same as described in the "Configuring Multiple Bonds
+Manually" section, below.
+
+       NOTE: It has been observed that some Red Hat supplied kernels
+are apparently unable to rename modules at load time (the "-obonding1"
+part).  Attempts to pass that option to modprobe will produce an
+"Operation not permitted" error.  This has been reported on some
+Fedora Core kernels, and has been seen on RHEL 4 as well.  On kernels
+exhibiting this problem, it will be impossible to configure multiple
+bonds with differing parameters.
 
 3.3 Configuring Bonding Manually
 --------------------------------
@@ -638,10 +792,11 @@ scripts (the sysconfig or initscripts package) do not have specific
 knowledge of bonding.  One such distro is SuSE Linux Enterprise Server
 version 8.
 
-       The general methodology for these systems is to place the
-bonding module parameters into /etc/modprobe.conf, then add modprobe
-and/or ifenslave commands to the system's global init script.  The
-name of the global init script differs; for sysconfig, it is
+       The general method for these systems is to place the bonding
+module parameters into /etc/modules.conf or /etc/modprobe.conf (as
+appropriate for the installed distro), then add modprobe and/or
+ifenslave commands to the system's global init script.  The name of
+the global init script differs; for sysconfig, it is
 /etc/init.d/boot.local and for initscripts it is /etc/rc.d/rc.local.
 
        For example, if you wanted to make a simple bond of two e100
@@ -649,7 +804,7 @@ devices (presumed to be eth0 and eth1), and have it persist across
 reboots, edit the appropriate file (/etc/init.d/boot.local or
 /etc/rc.d/rc.local), and add the following:
 
-modprobe bonding -obond0 mode=balance-alb miimon=100
+modprobe bonding mode=balance-alb miimon=100
 modprobe e100
 ifconfig bond0 192.168.1.1 netmask 255.255.255.0 up
 ifenslave bond0 eth0
@@ -657,11 +812,7 @@ ifenslave bond0 eth1
 
        Replace the example bonding module parameters and bond0
 network configuration (IP address, netmask, etc) with the appropriate
-values for your configuration.  The above example loads the bonding
-module with the name "bond0," this simplifies the naming if multiple
-bonding modules are loaded (each successive instance of the module is
-given a different name, and the module instance names match the
-bonding interface names).
+values for your configuration.
 
        Unfortunately, this method will not provide support for the
 ifup and ifdown scripts on the bond devices.  To reload the bonding
@@ -684,20 +835,23 @@ appropriate device driver modules.  For our example above, you can do
 the following:
 
 # ifconfig bond0 down
-# rmmod bond0
+# rmmod bonding
 # rmmod e100
 
        Again, for convenience, it may be desirable to create a script
 with these commands.
 
 
-3.4 Configuring Multiple Bonds
-------------------------------
+3.3.1 Configuring Multiple Bonds Manually
+-----------------------------------------
 
        This section contains information on configuring multiple
-bonding devices with differing options.  If you require multiple
-bonding devices, but all with the same options, see the "max_bonds"
-module paramter, documented above.
+bonding devices with differing options for those systems whose network
+initialization scripts lack support for configuring multiple bonds.
+
+       If you require multiple bonding devices, but all with the same
+options, you may wish to use the "max_bonds" module parameter,
+documented above.
 
        To create multiple bonding devices with differing options, it
 is necessary to load the bonding driver multiple times.  Note that
@@ -724,11 +878,16 @@ named "bond0" and creates the bond0 device in balance-rr mode with an
 miimon of 100.  The second instance is named "bond1" and creates the
 bond1 device in balance-alb mode with an miimon of 50.
 
+       In some circumstances (typically with older distributions),
+the above does not work, and the second bonding instance never sees
+its options.  In that case, the second options line can be substituted
+as follows:
+
+install bonding1 /sbin/modprobe bonding -obond1 mode=balance-alb miimon=50
+
        This may be repeated any number of times, specifying a new and
-unique name in place of bond0 or bond1 for each instance.
+unique name in place of bond1 for each subsequent instance.
 
-       When the appropriate module paramters are in place, then
-configure bonding according to the instructions for your distro.
 
 5. Querying Bonding Configuration 
 =================================
@@ -846,8 +1005,8 @@ tagged internally by bonding itself.  As a result, bonding must
 self generated packets.
 
        For reasons of simplicity, and to support the use of adapters
-that can do VLAN hardware acceleration offloding, the bonding
-interface declares itself as fully hardware offloaing capable, it gets
+that can do VLAN hardware acceleration offloading, the bonding
+interface declares itself as fully hardware offloading capable, it gets
 the add_vid/kill_vid notifications to gather the necessary
 information, and it propagates those actions to the slaves.  In case
 of mixed adapter types, hardware accelerated tagged packets that
@@ -880,7 +1039,7 @@ bond interface:
 matches the hardware address of the VLAN interfaces.
 
        Note that changing a VLAN interface's HW address would set the
-underlying device -- i.e. the bonding interface -- to promiscouos
+underlying device -- i.e. the bonding interface -- to promiscuous
 mode, which might not be what you want.
 
 
@@ -923,7 +1082,7 @@ down or have a problem making it unresponsive to ARP requests.  Having
 an additional target (or several) increases the reliability of the ARP
 monitoring.
 
-       Multiple ARP targets must be seperated by commas as follows:
+       Multiple ARP targets must be separated by commas as follows:
 
 # example options for ARP monitoring with three targets
 alias bond0 bonding
@@ -1045,7 +1204,7 @@ install bonding /sbin/modprobe tg3; /sbin/modprobe e1000;
        This will, when loading the bonding module, rather than
 performing the normal action, instead execute the provided command.
 This command loads the device drivers in the order needed, then calls
-modprobe with --ingore-install to cause the normal action to then take
+modprobe with --ignore-install to cause the normal action to then take
 place.  Full documentation on this can be found in the modprobe.conf
 and modprobe manual pages.
 
@@ -1130,14 +1289,14 @@ association.
 common to enable promiscuous mode on the device, so that all traffic
 is seen (instead of seeing only traffic destined for the local host).
 The bonding driver handles promiscuous mode changes to the bonding
-master device (e.g., bond0), and propogates the setting to the slave
+master device (e.g., bond0), and propagates the setting to the slave
 devices.
 
        For the balance-rr, balance-xor, broadcast, and 802.3ad modes,
-the promiscuous mode setting is propogated to all slaves.
+the promiscuous mode setting is propagated to all slaves.
 
        For the active-backup, balance-tlb and balance-alb modes, the
-promiscuous mode setting is propogated only to the active slave.
+promiscuous mode setting is propagated only to the active slave.
 
        For balance-tlb mode, the active slave is the slave currently
 receiving inbound traffic.
@@ -1148,46 +1307,182 @@ sending to peers that are unassigned or if the load is unbalanced.
 
        For the active-backup, balance-tlb and balance-alb modes, when
 the active slave changes (e.g., due to a link failure), the
-promiscuous setting will be propogated to the new active slave.
+promiscuous setting will be propagated to the new active slave.
 
-12. High Availability Information
-=================================
+12. Configuring Bonding for High Availability
+=============================================
 
        High Availability refers to configurations that provide
 maximum network availability by having redundant or backup devices,
-links and switches between the host and the rest of the world.
-
-       There are currently two basic methods for configuring to
-maximize availability. They are dependent on the network topology and
-the primary goal of the configuration, but in general, a configuration
-can be optimized for maximum available bandwidth, or for maximum
-network availability.
+links or switches between the host and the rest of the world.  The
+goal is to provide the maximum availability of network connectivity
+(i.e., the network always works), even though other configurations
+could provide higher throughput.
 
 12.1 High Availability in a Single Switch Topology
 --------------------------------------------------
 
-       If two hosts (or a host and a switch) are directly connected
-via multiple physical links, then there is no network availability
-penalty for optimizing for maximum bandwidth: there is only one switch
-(or peer), so if it fails, you have no alternative access to fail over
-to.
+       If two hosts (or a host and a single switch) are directly
+connected via multiple physical links, then there is no availability
+penalty to optimizing for maximum bandwidth.  In this case, there is
+only one switch (or peer), so if it fails, there is no alternative
+access to fail over to.  Additionally, the bonding load balance modes
+support link monitoring of their members, so if individual links fail,
+the load will be rebalanced across the remaining devices.
+
+       See Section 13, "Configuring Bonding for Maximum Throughput"
+for information on configuring bonding with one peer device.
+
+12.2 High Availability in a Multiple Switch Topology
+----------------------------------------------------
+
+       With multiple switches, the configuration of bonding and the
+network changes dramatically.  In multiple switch topologies, there is
+a trade off between network availability and usable bandwidth.
+
+       Below is a sample network, configured to maximize the
+availability of the network:
 
-Example 1 : host to switch (or other host)
+                |                                     |
+                |port3                           port3|
+          +-----+----+                          +-----+----+
+          |          |port2       ISL      port2|          |
+          | switch A +--------------------------+ switch B |
+          |          |                          |          |
+          +-----+----+                          +-----++---+
+                |port1                           port1|
+                |             +-------+               |
+                +-------------+ host1 +---------------+
+                         eth0 +-------+ eth1
 
-          +----------+                          +----------+
-          |          |eth0                  eth0|  switch  |
-          | Host A   +--------------------------+    or    |
-          |          +--------------------------+  other   |
-          |          |eth1                  eth1|  host    |
-          +----------+                          +----------+
+       In this configuration, there is a link between the two
+switches (ISL, or inter switch link), and multiple ports connecting to
+the outside world ("port3" on each switch).  There is no technical
+reason that this could not be extended to a third switch.
 
+12.2.1 HA Bonding Mode Selection for Multiple Switch Topology
+-------------------------------------------------------------
 
-12.1.1 Bonding Mode Selection for single switch topology
---------------------------------------------------------
+       In a topology such as the example above, the active-backup and
+broadcast modes are the only useful bonding modes when optimizing for
+availability; the other modes require all links to terminate on the
+same peer for them to behave rationally.
+
+active-backup: This is generally the preferred mode, particularly if
+       the switches have an ISL and play together well.  If the
+       network configuration is such that one switch is specifically
+       a backup switch (e.g., has lower capacity, higher cost, etc),
+       then the primary option can be used to insure that the
+       preferred link is always used when it is available.
+
+broadcast: This mode is really a special purpose mode, and is suitable
+       only for very specific needs.  For example, if the two
+       switches are not connected (no ISL), and the networks beyond
+       them are totally independent.  In this case, if it is
+       necessary for some specific one-way traffic to reach both
+       independent networks, then the broadcast mode may be suitable.
+
+12.2.2 HA Link Monitoring Selection for Multiple Switch Topology
+----------------------------------------------------------------
+
+       The choice of link monitoring ultimately depends upon your
+switch.  If the switch can reliably fail ports in response to other
+failures, then either the MII or ARP monitors should work.  For
+example, in the above example, if the "port3" link fails at the remote
+end, the MII monitor has no direct means to detect this.  The ARP
+monitor could be configured with a target at the remote end of port3,
+thus detecting that failure without switch support.
+
+       In general, however, in a multiple switch topology, the ARP
+monitor can provide a higher level of reliability in detecting end to
+end connectivity failures (which may be caused by the failure of any
+individual component to pass traffic for any reason).  Additionally,
+the ARP monitor should be configured with multiple targets (at least
+one for each switch in the network).  This will insure that,
+regardless of which switch is active, the ARP monitor has a suitable
+target to query.
+
+
+13. Configuring Bonding for Maximum Throughput
+==============================================
+
+13.1 Maximizing Throughput in a Single Switch Topology
+------------------------------------------------------
+
+       In a single switch configuration, the best method to maximize
+throughput depends upon the application and network environment.  The
+various load balancing modes each have strengths and weaknesses in
+different environments, as detailed below.
+
+       For this discussion, we will break down the topologies into
+two categories.  Depending upon the destination of most traffic, we
+categorize them into either "gatewayed" or "local" configurations.
+
+       In a gatewayed configuration, the "switch" is acting primarily
+as a router, and the majority of traffic passes through this router to
+other networks.  An example would be the following:
+
+
+     +----------+                     +----------+
+     |          |eth0            port1|          | to other networks
+     | Host A   +---------------------+ router   +------------------->
+     |          +---------------------+          | Hosts B and C are out
+     |          |eth1            port2|          | here somewhere
+     +----------+                     +----------+
+
+       The router may be a dedicated router device, or another host
+acting as a gateway.  For our discussion, the important point is that
+the majority of traffic from Host A will pass through the router to
+some other network before reaching its final destination.
+
+       In a gatewayed network configuration, although Host A may
+communicate with many other systems, all of its traffic will be sent
+and received via one other peer on the local network, the router.
+
+       Note that the case of two systems connected directly via
+multiple physical links is, for purposes of configuring bonding, the
+same as a gatewayed configuration.  In that case, it happens that all
+traffic is destined for the "gateway" itself, not some other network
+beyond the gateway.
+
+       In a local configuration, the "switch" is acting primarily as
+a switch, and the majority of traffic passes through this switch to
+reach other stations on the same network.  An example would be the
+following:
+
+    +----------+            +----------+       +--------+
+    |          |eth0   port1|          +-------+ Host B |
+    |  Host A  +------------+  switch  |port3  +--------+
+    |          +------------+          |                  +--------+
+    |          |eth1   port2|          +------------------+ Host C |
+    +----------+            +----------+port4             +--------+
+
+
+       Again, the switch may be a dedicated switch device, or another
+host acting as a gateway.  For our discussion, the important point is
+that the majority of traffic from Host A is destined for other hosts
+on the same local network (Hosts B and C in the above example).
+
+       In summary, in a gatewayed configuration, traffic to and from
+the bonded device will be to the same MAC level peer on the network
+(the gateway itself, i.e., the router), regardless of its final
+destination.  In a local configuration, traffic flows directly to and
+from the final destinations, thus, each destination (Host B, Host C)
+will be addressed directly by their individual MAC addresses.
+
+       This distinction between a gatewayed and a local network
+configuration is important because many of the load balancing modes
+available use the MAC addresses of the local network source and
+destination to make load balancing decisions.  The behavior of each
+mode is described below.
+
+
+13.1.1 MT Bonding Mode Selection for Single Switch Topology
+-----------------------------------------------------------
 
        This configuration is the easiest to set up and to understand,
 although you will have to decide which bonding mode best suits your
-needs.  The tradeoffs for each mode are detailed below:
+needs.  The trade offs for each mode are detailed below:
 
 balance-rr: This mode is the only mode that will permit a single
        TCP/IP connection to stripe traffic across multiple
@@ -1206,6 +1501,23 @@ balance-rr: This mode is the only mode that will permit a single
        interface's worth of throughput, even after adjusting
        tcp_reordering.
 
+       Note that this out of order delivery occurs when both the
+       sending and receiving systems are utilizing a multiple
+       interface bond.  Consider a configuration in which a
+       balance-rr bond feeds into a single higher capacity network
+       channel (e.g., multiple 100Mb/sec ethernets feeding a single
+       gigabit ethernet via an etherchannel capable switch).  In this
+       configuration, traffic sent from the multiple 100Mb devices to
+       a destination connected to the gigabit device will not see
+       packets out of order.  However, traffic sent from the gigabit
+       device to the multiple 100Mb devices may or may not see
+       traffic out of order, depending upon the balance policy of the
+       switch.  Many switches do not support any modes that stripe
+       traffic (instead choosing a port based upon IP or MAC level
+       addresses); for those devices, traffic flowing from the
+       gigabit device to the many 100Mb devices will only utilize one
+       interface.
+
        If you are utilizing protocols other than TCP/IP, UDP for
        example, and your application can tolerate out of order
        delivery, then this mode can allow for single stream datagram
@@ -1220,16 +1532,21 @@ active-backup: There is not much advantage in this network topology to
        connected to the same peer as the primary.  In this case, a
        load balancing mode (with link monitoring) will provide the
        same level of network availability, but with increased
-       available bandwidth.  On the plus side, it does not require
-       any configuration of the switch.
+       available bandwidth.  On the plus side, active-backup mode
+       does not require any configuration of the switch, so it may
+       have value if the hardware available does not support any of
+       the load balance modes.
 
 balance-xor: This mode will limit traffic such that packets destined
        for specific peers will always be sent over the same
        interface.  Since the destination is determined by the MAC
-       addresses involved, this may be desirable if you have a large
-       network with many hosts.  It is likely to be suboptimal if all
-       your traffic is passed through a single router, however.  As
-       with balance-rr, the switch ports need to be configured for
+       addresses involved, this mode works best in a "local" network
+       configuration (as described above), with destinations all on
+       the same local network.  This mode is likely to be suboptimal
+       if all your traffic is passed through a single router (i.e., a
+       "gatewayed" network configuration, as described above).
+
+       As with balance-rr, the switch ports need to be configured for
        "etherchannel" or "trunking."
 
 broadcast: Like active-backup, there is not much advantage to this
@@ -1241,122 +1558,131 @@ broadcast: Like active-backup, there is not much advantage to this
        protocol includes automatic configuration of the aggregates,
        so minimal manual configuration of the switch is needed
        (typically only to designate that some set of devices is
-       usable for 802.3ad).  The 802.3ad standard also mandates that
-       frames be delivered in order (within certain limits), so in
-       general single connections will not see misordering of
+       available for 802.3ad).  The 802.3ad standard also mandates
+       that frames be delivered in order (within certain limits), so
+       in general single connections will not see misordering of
        packets.  The 802.3ad mode does have some drawbacks: the
        standard mandates that all devices in the aggregate operate at
        the same speed and duplex.  Also, as with all bonding load
        balance modes other than balance-rr, no single connection will
        be able to utilize more than a single interface's worth of
-       bandwidth.  Additionally, the linux bonding 802.3ad
-       implementation distributes traffic by peer (using an XOR of
-       MAC addresses), so in general all traffic to a particular
-       destination will use the same interface.  Finally, the 802.3ad
-       mode mandates the use of the MII monitor, therefore, the ARP
-       monitor is not available in this mode.
-
-balance-tlb: This mode is also a good choice for this type of
-       topology.  It has no special switch configuration
-       requirements, and balances outgoing traffic by peer, in a
-       vaguely intelligent manner (not a simple XOR as in balance-xor
-       or 802.3ad mode), so that unlucky MAC addresses will not all
-       "bunch up" on a single interface.  Interfaces may be of
-       differing speeds.  On the down side, in this mode all incoming
-       traffic arrives over a single interface, this mode requires
-       certain ethtool support in the network device driver of the
-       slave interfaces, and the ARP monitor is not available.
-
-balance-alb: This mode is everything that balance-tlb is, and more. It
-       has all of the features (and restrictions) of balance-tlb, and
-       will also balance incoming traffic from peers (as described in
-       the Bonding Module Options section, above).  The only extra
-       down side to this mode is that the network device driver must
-       support changing the hardware address while the device is
-       open.
-
-12.1.2 Link Monitoring for Single Switch Topology
--------------------------------------------------
+       bandwidth.  
+
+       Additionally, the linux bonding 802.3ad implementation
+       distributes traffic by peer (using an XOR of MAC addresses),
+       so in a "gatewayed" configuration, all outgoing traffic will
+       generally use the same device.  Incoming traffic may also end
+       up on a single device, but that is dependent upon the
+       balancing policy of the peer's 8023.ad implementation.  In a
+       "local" configuration, traffic will be distributed across the
+       devices in the bond.
+
+       Finally, the 802.3ad mode mandates the use of the MII monitor,
+       therefore, the ARP monitor is not available in this mode.
+
+balance-tlb: The balance-tlb mode balances outgoing traffic by peer.
+       Since the balancing is done according to MAC address, in a
+       "gatewayed" configuration (as described above), this mode will
+       send all traffic across a single device.  However, in a
+       "local" network configuration, this mode balances multiple
+       local network peers across devices in a vaguely intelligent
+       manner (not a simple XOR as in balance-xor or 802.3ad mode),
+       so that mathematically unlucky MAC addresses (i.e., ones that
+       XOR to the same value) will not all "bunch up" on a single
+       interface.
+
+       Unlike 802.3ad, interfaces may be of differing speeds, and no
+       special switch configuration is required.  On the down side,
+       in this mode all incoming traffic arrives over a single
+       interface, this mode requires certain ethtool support in the
+       network device driver of the slave interfaces, and the ARP
+       monitor is not available.
+
+balance-alb: This mode is everything that balance-tlb is, and more.
+       It has all of the features (and restrictions) of balance-tlb,
+       and will also balance incoming traffic from local network
+       peers (as described in the Bonding Module Options section,
+       above).
+
+       The only additional down side to this mode is that the network
+       device driver must support changing the hardware address while
+       the device is open.
+
+13.1.2 MT Link Monitoring for Single Switch Topology
+----------------------------------------------------
 
        The choice of link monitoring may largely depend upon which
 mode you choose to use.  The more advanced load balancing modes do not
 support the use of the ARP monitor, and are thus restricted to using
-the MII monitor (which does not provide as high a level of assurance
-as the ARP monitor).
-
-
-12.2 High Availability in a Multiple Switch Topology
-----------------------------------------------------
-
-       With multiple switches, the configuration of bonding and the
-network changes dramatically.  In multiple switch topologies, there is
-a tradeoff between network availability and usable bandwidth.
-
-       Below is a sample network, configured to maximize the
-availability of the network:
-
-                |                                     |
-                |port3                           port3|
-          +-----+----+                          +-----+----+
-          |          |port2       ISL      port2|          |
-          | switch A +--------------------------+ switch B |
-          |          |                          |          |
-          +-----+----+                          +-----++---+
-                |port1                           port1|
-                |             +-------+               |
-                +-------------+ host1 +---------------+
-                         eth0 +-------+ eth1
-
-       In this configuration, there is a link between the two
-switches (ISL, or inter switch link), and multiple ports connecting to
-the outside world ("port3" on each switch).  There is no technical
-reason that this could not be extended to a third switch.
-
-12.2.1 Bonding Mode Selection for Multiple Switch Topology
-----------------------------------------------------------
-
-       In a topology such as this, the active-backup and broadcast
-modes are the only useful bonding modes; the other modes require all
-links to terminate on the same peer for them to behave rationally.
-
-active-backup: This is generally the preferred mode, particularly if
-       the switches have an ISL and play together well.  If the
-       network configuration is such that one switch is specifically
-       a backup switch (e.g., has lower capacity, higher cost, etc),
-       then the primary option can be used to insure that the
-       preferred link is always used when it is available.
-
-broadcast: This mode is really a special purpose mode, and is suitable
-       only for very specific needs.  For example, if the two
-       switches are not connected (no ISL), and the networks beyond
-       them are totally independant.  In this case, if it is
-       necessary for some specific one-way traffic to reach both
-       independent networks, then the broadcast mode may be suitable.
-
-12.2.2 Link Monitoring Selection for Multiple Switch Topology
+the MII monitor (which does not provide as high a level of end to end
+assurance as the ARP monitor).
+
+13.2 Maximum Throughput in a Multiple Switch Topology
+-----------------------------------------------------
+
+       Multiple switches may be utilized to optimize for throughput
+when they are configured in parallel as part of an isolated network
+between two or more systems, for example:
+
+                       +-----------+
+                       |  Host A   | 
+                       +-+---+---+-+
+                         |   |   |
+                +--------+   |   +---------+
+                |            |             |
+         +------+---+  +-----+----+  +-----+----+
+         | Switch A |  | Switch B |  | Switch C |
+         +------+---+  +-----+----+  +-----+----+
+                |            |             |
+                +--------+   |   +---------+
+                         |   |   |
+                       +-+---+---+-+
+                       |  Host B   | 
+                       +-----------+
+
+       In this configuration, the switches are isolated from one
+another.  One reason to employ a topology such as this is for an
+isolated network with many hosts (a cluster configured for high
+performance, for example), using multiple smaller switches can be more
+cost effective than a single larger switch, e.g., on a network with 24
+hosts, three 24 port switches can be significantly less expensive than
+a single 72 port switch.
+
+       If access beyond the network is required, an individual host
+can be equipped with an additional network device connected to an
+external network; this host then additionally acts as a gateway.
+
+13.2.1 MT Bonding Mode Selection for Multiple Switch Topology
 -------------------------------------------------------------
 
-       The choice of link monitoring ultimately depends upon your
-switch.  If the switch can reliably fail ports in response to other
-failures, then either the MII or ARP monitors should work.  For
-example, in the above example, if the "port3" link fails at the remote
-end, the MII monitor has no direct means to detect this.  The ARP
-monitor could be configured with a target at the remote end of port3,
-thus detecting that failure without switch support.
+       In actual practice, the bonding mode typically employed in
+configurations of this type is balance-rr.  Historically, in this
+network configuration, the usual caveats about out of order packet
+delivery are mitigated by the use of network adapters that do not do
+any kind of packet coalescing (via the use of NAPI, or because the
+device itself does not generate interrupts until some number of
+packets has arrived).  When employed in this fashion, the balance-rr
+mode allows individual connections between two hosts to effectively
+utilize greater than one interface's bandwidth.
 
-       In general, however, in a multiple switch topology, the ARP
-monitor can provide a higher level of reliability in detecting link
-failures.  Additionally, it should be configured with multiple targets
-(at least one for each switch in the network).  This will insure that,
-regardless of which switch is active, the ARP monitor has a suitable
-target to query.
+13.2.2 MT Link Monitoring for Multiple Switch Topology
+------------------------------------------------------
 
+       Again, in actual practice, the MII monitor is most often used
+in this configuration, as performance is given preference over
+availability.  The ARP monitor will function in this topology, but its
+advantages over the MII monitor are mitigated by the volume of probes
+needed as the number of systems involved grows (remember that each
+host in the network is configured with bonding).
 
-12.3 Switch Behavior Issues for High Availability
--------------------------------------------------
+14. Switch Behavior Issues
+==========================
 
-       You may encounter issues with the timing of link up and down
-reporting by the switch.
+14.1 Link Establishment and Failover Delays
+-------------------------------------------
+
+       Some switches exhibit undesirable behavior with regard to the
+timing of link up and down reporting by the switch.
 
        First, when a link comes up, some switches may indicate that
 the link is up (carrier available), but not pass traffic over the
@@ -1370,30 +1696,70 @@ relevant interface(s).
        Second, some switches may "bounce" the link state one or more
 times while a link is changing state.  This occurs most commonly while
 the switch is initializing.  Again, an appropriate updelay value may
-help, but note that if all links are down, then updelay is ignored
-when any link becomes active (the slave closest to completing its
-updelay is chosen).
+help.
 
        Note that when a bonding interface has no active links, the
-driver will immediately reuse the first link that goes up, even if
-updelay parameter was specified.  If there are slave interfaces
-waiting for the updelay timeout to expire, the interface that first
-went into that state will be immediately reused.  This reduces down
-time of the network if the value of updelay has been overestimated.
+driver will immediately reuse the first link that goes up, even if the
+updelay parameter has been specified (the updelay is ignored in this
+case).  If there are slave interfaces waiting for the updelay timeout
+to expire, the interface that first went into that state will be
+immediately reused.  This reduces down time of the network if the
+value of updelay has been overestimated, and since this occurs only in
+cases with no connectivity, there is no additional penalty for
+ignoring the updelay.
 
        In addition to the concerns about switch timings, if your
 switches take a long time to go into backup mode, it may be desirable
 to not activate a backup interface immediately after a link goes down.
 Failover may be delayed via the downdelay bonding module option.
 
-13. Hardware Specific Considerations
+14.2 Duplicated Incoming Packets
+--------------------------------
+
+       It is not uncommon to observe a short burst of duplicated
+traffic when the bonding device is first used, or after it has been
+idle for some period of time.  This is most easily observed by issuing
+a "ping" to some other host on the network, and noticing that the
+output from ping flags duplicates (typically one per slave).
+
+       For example, on a bond in active-backup mode with five slaves
+all connected to one switch, the output may appear as follows:
+
+# ping -n 10.0.4.2
+PING 10.0.4.2 (10.0.4.2) from 10.0.3.10 : 56(84) bytes of data.
+64 bytes from 10.0.4.2: icmp_seq=1 ttl=64 time=13.7 ms
+64 bytes from 10.0.4.2: icmp_seq=1 ttl=64 time=13.8 ms (DUP!)
+64 bytes from 10.0.4.2: icmp_seq=1 ttl=64 time=13.8 ms (DUP!)
+64 bytes from 10.0.4.2: icmp_seq=1 ttl=64 time=13.8 ms (DUP!)
+64 bytes from 10.0.4.2: icmp_seq=1 ttl=64 time=13.8 ms (DUP!)
+64 bytes from 10.0.4.2: icmp_seq=2 ttl=64 time=0.216 ms
+64 bytes from 10.0.4.2: icmp_seq=3 ttl=64 time=0.267 ms
+64 bytes from 10.0.4.2: icmp_seq=4 ttl=64 time=0.222 ms
+
+       This is not due to an error in the bonding driver, rather, it
+is a side effect of how many switches update their MAC forwarding
+tables.  Initially, the switch does not associate the MAC address in
+the packet with a particular switch port, and so it may send the
+traffic to all ports until its MAC forwarding table is updated.  Since
+the interfaces attached to the bond may occupy multiple ports on a
+single switch, when the switch (temporarily) floods the traffic to all
+ports, the bond device receives multiple copies of the same packet
+(one per slave device).
+
+       The duplicated packet behavior is switch dependent, some
+switches exhibit this, and some do not.  On switches that display this
+behavior, it can be induced by clearing the MAC forwarding table (on
+most Cisco switches, the privileged command "clear mac address-table
+dynamic" will accomplish this).
+
+15. Hardware Specific Considerations
 ====================================
 
        This section contains additional information for configuring
 bonding on specific hardware platforms, or for interfacing bonding
 with particular switches or other devices.
 
-13.1 IBM BladeCenter
+15.1 IBM BladeCenter
 --------------------
 
        This applies to the JS20 and similar systems.
@@ -1407,12 +1773,12 @@ JS20 network adapter information
 --------------------------------
 
        All JS20s come with two Broadcom Gigabit Ethernet ports
-integrated on the planar.  In the BladeCenter chassis, the eth0 port
-of all JS20 blades is hard wired to I/O Module #1; similarly, all eth1
-ports are wired to I/O Module #2.  An add-on Broadcom daughter card
-can be installed on a JS20 to provide two more Gigabit Ethernet ports.
-These ports, eth2 and eth3, are wired to I/O Modules 3 and 4,
-respectively.
+integrated on the planar (that's "motherboard" in IBM-speak).  In the
+BladeCenter chassis, the eth0 port of all JS20 blades is hard wired to
+I/O Module #1; similarly, all eth1 ports are wired to I/O Module #2.
+An add-on Broadcom daughter card can be installed on a JS20 to provide
+two more Gigabit Ethernet ports.  These ports, eth2 and eth3, are
+wired to I/O Modules 3 and 4, respectively.
 
        Each I/O Module may contain either a switch or a passthrough
 module (which allows ports to be directly connected to an external
@@ -1432,29 +1798,30 @@ BladeCenter networking configuration
 of ways, this discussion will be confined to describing basic
 configurations.
 
-       Normally, Ethernet Switch Modules (ESM) are used in I/O
+       Normally, Ethernet Switch Modules (ESMs) are used in I/O
 modules 1 and 2.  In this configuration, the eth0 and eth1 ports of a
 JS20 will be connected to different internal switches (in the
 respective I/O modules).
 
-       An optical passthru module (OPM) connects the I/O module
-directly to an external switch.  By using OPMs in I/O module #1 and
-#2, the eth0 and eth1 interfaces of a JS20 can be redirected to the
-outside world and connected to a common external switch.
-
-       Depending upon the mix of ESM and OPM modules, the network
-will appear to bonding as either a single switch topology (all OPM
-modules) or as a multiple switch topology (one or more ESM modules,
-zero or more OPM modules).  It is also possible to connect ESM modules
-together, resulting in a configuration much like the example in "High
-Availability in a multiple switch topology."
-
-Requirements for specifc modes
-------------------------------
-
-       The balance-rr mode requires the use of OPM modules for
-devices in the bond, all connected to an common external switch.  That
-switch must be configured for "etherchannel" or "trunking" on the
+       A passthrough module (OPM or CPM, optical or copper,
+passthrough module) connects the I/O module directly to an external
+switch.  By using PMs in I/O module #1 and #2, the eth0 and eth1
+interfaces of a JS20 can be redirected to the outside world and
+connected to a common external switch.
+
+       Depending upon the mix of ESMs and PMs, the network will
+appear to bonding as either a single switch topology (all PMs) or as a
+multiple switch topology (one or more ESMs, zero or more PMs).  It is
+also possible to connect ESMs together, resulting in a configuration
+much like the example in "High Availability in a Multiple Switch
+Topology," above.
+
+Requirements for specific modes
+-------------------------------
+
+       The balance-rr mode requires the use of passthrough modules
+for devices in the bond, all connected to an common external switch.
+That switch must be configured for "etherchannel" or "trunking" on the
 appropriate ports, as is usual for balance-rr.
 
        The balance-alb and balance-tlb modes will function with
@@ -1484,17 +1851,18 @@ connected to the JS20 system.
 Other concerns
 --------------
 
-       The Serial Over LAN link is established over the primary
+       The Serial Over LAN (SoL) link is established over the primary
 ethernet (eth0) only, therefore, any loss of link to eth0 will result
 in losing your SoL connection.  It will not fail over with other
-network traffic.
+network traffic, as the SoL system is beyond the control of the
+bonding driver.
 
        It may be desirable to disable spanning tree on the switch
 (either the internal Ethernet Switch Module, or an external switch) to
-avoid fail-over delays issues when using bonding.
+avoid fail-over delay issues when using bonding.
 
        
-14. Frequently Asked Questions
+16. Frequently Asked Questions
 ==============================
 
 1.  Is it SMP safe?
@@ -1505,8 +1873,8 @@ The new driver was designed to be SMP safe from the start.
 2.  What type of cards will work with it?
 
        Any Ethernet type cards (you can even mix cards - a Intel
-EtherExpress PRO/100 and a 3com 3c905b, for example).  They need not
-be of the same speed.
+EtherExpress PRO/100 and a 3com 3c905b, for example).  For most modes,
+devices need not be of the same speed.
 
 3.  How many bonding devices can I have?
 
@@ -1524,11 +1892,12 @@ system.
 disabled.  The active-backup mode will fail over to a backup link, and
 other modes will ignore the failed link.  The link will continue to be
 monitored, and should it recover, it will rejoin the bond (in whatever
-manner is appropriate for the mode). See the section on High
-Availability for additional information.
+manner is appropriate for the mode). See the sections on High
+Availability and the documentation for each mode for additional
+information.
        
        Link monitoring can be enabled via either the miimon or
-arp_interval paramters (described in the module paramters section,
+arp_interval parameters (described in the module parameters section,
 above).  In general, miimon monitors the carrier state as sensed by
 the underlying network device, and the arp monitor (arp_interval)
 monitors connectivity to another host on the local network.
@@ -1536,7 +1905,7 @@ monitors connectivity to another host on the local network.
        If no link monitoring is configured, the bonding driver will
 be unable to detect link failures, and will assume that all links are
 always available.  This will likely result in lost packets, and a
-resulting degredation of performance.  The precise performance loss
+resulting degradation of performance.  The precise performance loss
 depends upon the bonding mode and network configuration.
 
 6.  Can bonding be used for High Availability?
@@ -1550,12 +1919,12 @@ depends upon the bonding mode and network configuration.
        In the basic balance modes (balance-rr and balance-xor), it
 works with any system that supports etherchannel (also called
 trunking).  Most managed switches currently available have such
-support, and many unmananged switches as well.
+support, and many unmanaged switches as well.
 
        The advanced balance modes (balance-tlb and balance-alb) do
 not have special switch requirements, but do need device drivers that
 support specific features (described in the appropriate section under
-module paramters, above).
+module parameters, above).
 
        In 802.3ad mode, it works with with systems that support IEEE
 802.3ad Dynamic Link Aggregation.  Most managed and many unmanaged
@@ -1565,17 +1934,19 @@ switches currently available support 802.3ad.
 
 8.  Where does a bonding device get its MAC address from?
 
-       If not explicitly configured with ifconfig, the MAC address of
-the bonding device is taken from its first slave device. This MAC
-address is then passed to all following slaves and remains persistent
-(even if the the first slave is removed) until the bonding device is
-brought down or reconfigured.
+       If not explicitly configured (with ifconfig or ip link), the
+MAC address of the bonding device is taken from its first slave
+device.  This MAC address is then passed to all following slaves and
+remains persistent (even if the the first slave is removed) until the
+bonding device is brought down or reconfigured.
 
        If you wish to change the MAC address, you can set it with
-ifconfig:
+ifconfig or ip link:
 
 # ifconfig bond0 hw ether 00:11:22:33:44:55
 
+# ip link set bond0 address 66:77:88:99:aa:bb
+
        The MAC address can be also changed by bringing down/up the
 device and then changing its slaves (or their order):
 
@@ -1591,23 +1962,28 @@ from the bond (`ifenslave -d bond0 eth0'). The bonding driver will
 then restore the MAC addresses that the slaves had before they were
 enslaved.
 
-15. Resources and Links
+16. Resources and Links
 =======================
 
 The latest version of the bonding driver can be found in the latest
 version of the linux kernel, found on http://kernel.org
 
+The latest version of this document can be found in either the latest
+kernel source (named Documentation/networking/bonding.txt), or on the
+bonding sourceforge site:
+
+http://www.sourceforge.net/projects/bonding
+
 Discussions regarding the bonding driver take place primarily on the
 bonding-devel mailing list, hosted at sourceforge.net.  If you have
-questions or problems, post them to the list.
+questions or problems, post them to the list.  The list address is:
 
 bonding-devel@lists.sourceforge.net
 
-https://lists.sourceforge.net/lists/listinfo/bonding-devel
-
-There is also a project site on sourceforge.
+       The administrative interface (to subscribe or unsubscribe) can
+be found at:
 
-http://www.sourceforge.net/projects/bonding
+https://lists.sourceforge.net/lists/listinfo/bonding-devel
 
 Donald Becker's Ethernet Drivers and diag programs may be found at :
  - http://www.scyld.com/network/
diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt
new file mode 100644 (file)
index 0000000..29ccae4
--- /dev/null
@@ -0,0 +1,288 @@
+
+-------
+PHY Abstraction Layer
+(Updated 2005-07-21)
+
+Purpose
+
+ Most network devices consist of set of registers which provide an interface
+ to a MAC layer, which communicates with the physical connection through a
+ PHY.  The PHY concerns itself with negotiating link parameters with the link
+ partner on the other side of the network connection (typically, an ethernet
+ cable), and provides a register interface to allow drivers to determine what
+ settings were chosen, and to configure what settings are allowed.
+
+ While these devices are distinct from the network devices, and conform to a
+ standard layout for the registers, it has been common practice to integrate
+ the PHY management code with the network driver.  This has resulted in large
+ amounts of redundant code.  Also, on embedded systems with multiple (and
+ sometimes quite different) ethernet controllers connected to the same 
+ management bus, it is difficult to ensure safe use of the bus.
+
+ Since the PHYs are devices, and the management busses through which they are
+ accessed are, in fact, busses, the PHY Abstraction Layer treats them as such.
+ In doing so, it has these goals:
+
+   1) Increase code-reuse
+   2) Increase overall code-maintainability
+   3) Speed development time for new network drivers, and for new systems
+ Basically, this layer is meant to provide an interface to PHY devices which
+ allows network driver writers to write as little code as possible, while
+ still providing a full feature set.
+
+The MDIO bus
+
+ Most network devices are connected to a PHY by means of a management bus.
+ Different devices use different busses (though some share common interfaces).
+ In order to take advantage of the PAL, each bus interface needs to be
+ registered as a distinct device.
+
+ 1) read and write functions must be implemented.  Their prototypes are:
+
+     int write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
+     int read(struct mii_bus *bus, int mii_id, int regnum);
+
+   mii_id is the address on the bus for the PHY, and regnum is the register
+   number.  These functions are guaranteed not to be called from interrupt
+   time, so it is safe for them to block, waiting for an interrupt to signal
+   the operation is complete
+ 2) A reset function is necessary.  This is used to return the bus to an
+   initialized state.
+
+ 3) A probe function is needed.  This function should set up anything the bus
+   driver needs, setup the mii_bus structure, and register with the PAL using
+   mdiobus_register.  Similarly, there's a remove function to undo all of
+   that (use mdiobus_unregister).
+ 4) Like any driver, the device_driver structure must be configured, and init
+   exit functions are used to register the driver.
+
+ 5) The bus must also be declared somewhere as a device, and registered.
+
+ As an example for how one driver implemented an mdio bus driver, see
+ drivers/net/gianfar_mii.c and arch/ppc/syslib/mpc85xx_devices.c
+
+Connecting to a PHY
+
+ Sometime during startup, the network driver needs to establish a connection
+ between the PHY device, and the network device.  At this time, the PHY's bus
+ and drivers need to all have been loaded, so it is ready for the connection.
+ At this point, there are several ways to connect to the PHY:
+
+ 1) The PAL handles everything, and only calls the network driver when
+   the link state changes, so it can react.
+
+ 2) The PAL handles everything except interrupts (usually because the
+   controller has the interrupt registers).
+
+ 3) The PAL handles everything, but checks in with the driver every second,
+   allowing the network driver to react first to any changes before the PAL
+   does.
+ 4) The PAL serves only as a library of functions, with the network device
+   manually calling functions to update status, and configure the PHY
+
+
+Letting the PHY Abstraction Layer do Everything
+
+ If you choose option 1 (The hope is that every driver can, but to still be
+ useful to drivers that can't), connecting to the PHY is simple:
+
+ First, you need a function to react to changes in the link state.  This
+ function follows this protocol:
+
+   static void adjust_link(struct net_device *dev);
+ Next, you need to know the device name of the PHY connected to this device. 
+ The name will look something like, "phy0:0", where the first number is the
+ bus id, and the second is the PHY's address on that bus.
+ Now, to connect, just call this function:
+   phydev = phy_connect(dev, phy_name, &adjust_link, flags);
+
+ phydev is a pointer to the phy_device structure which represents the PHY.  If
+ phy_connect is successful, it will return the pointer.  dev, here, is the
+ pointer to your net_device.  Once done, this function will have started the
+ PHY's software state machine, and registered for the PHY's interrupt, if it
+ has one.  The phydev structure will be populated with information about the
+ current state, though the PHY will not yet be truly operational at this
+ point.
+
+ flags is a u32 which can optionally contain phy-specific flags.
+ This is useful if the system has put hardware restrictions on
+ the PHY/controller, of which the PHY needs to be aware.
+
+ Now just make sure that phydev->supported and phydev->advertising have any
+ values pruned from them which don't make sense for your controller (a 10/100
+ controller may be connected to a gigabit capable PHY, so you would need to
+ mask off SUPPORTED_1000baseT*).  See include/linux/ethtool.h for definitions
+ for these bitfields. Note that you should not SET any bits, or the PHY may
+ get put into an unsupported state.
+
+ Lastly, once the controller is ready to handle network traffic, you call
+ phy_start(phydev).  This tells the PAL that you are ready, and configures the
+ PHY to connect to the network.  If you want to handle your own interrupts,
+ just set phydev->irq to PHY_IGNORE_INTERRUPT before you call phy_start.
+ Similarly, if you don't want to use interrupts, set phydev->irq to PHY_POLL.
+
+ When you want to disconnect from the network (even if just briefly), you call
+ phy_stop(phydev).
+
+Keeping Close Tabs on the PAL
+
+ It is possible that the PAL's built-in state machine needs a little help to
+ keep your network device and the PHY properly in sync.  If so, you can
+ register a helper function when connecting to the PHY, which will be called
+ every second before the state machine reacts to any changes.  To do this, you
+ need to manually call phy_attach() and phy_prepare_link(), and then call
+ phy_start_machine() with the second argument set to point to your special
+ handler.
+
+ Currently there are no examples of how to use this functionality, and testing
+ on it has been limited because the author does not have any drivers which use
+ it (they all use option 1).  So Caveat Emptor.
+
+Doing it all yourself
+
+ There's a remote chance that the PAL's built-in state machine cannot track
+ the complex interactions between the PHY and your network device.  If this is
+ so, you can simply call phy_attach(), and not call phy_start_machine or
+ phy_prepare_link().  This will mean that phydev->state is entirely yours to
+ handle (phy_start and phy_stop toggle between some of the states, so you
+ might need to avoid them).
+
+ An effort has been made to make sure that useful functionality can be
+ accessed without the state-machine running, and most of these functions are
+ descended from functions which did not interact with a complex state-machine.
+ However, again, no effort has been made so far to test running without the
+ state machine, so tryer beware.
+
+ Here is a brief rundown of the functions:
+
+ int phy_read(struct phy_device *phydev, u16 regnum);
+ int phy_write(struct phy_device *phydev, u16 regnum, u16 val);
+
+   Simple read/write primitives.  They invoke the bus's read/write function
+   pointers.
+
+ void phy_print_status(struct phy_device *phydev);
+   A convenience function to print out the PHY status neatly.
+
+ int phy_clear_interrupt(struct phy_device *phydev);
+ int phy_config_interrupt(struct phy_device *phydev, u32 interrupts);
+   
+   Clear the PHY's interrupt, and configure which ones are allowed,
+   respectively.  Currently only supports all on, or all off.
+ int phy_enable_interrupts(struct phy_device *phydev);
+ int phy_disable_interrupts(struct phy_device *phydev);
+
+   Functions which enable/disable PHY interrupts, clearing them
+   before and after, respectively.
+
+ int phy_start_interrupts(struct phy_device *phydev);
+ int phy_stop_interrupts(struct phy_device *phydev);
+
+   Requests the IRQ for the PHY interrupts, then enables them for
+   start, or disables then frees them for stop.
+
+ struct phy_device * phy_attach(struct net_device *dev, const char *phy_id,
+                u32 flags);
+
+   Attaches a network device to a particular PHY, binding the PHY to a generic
+   driver if none was found during bus initialization.  Passes in
+   any phy-specific flags as needed.
+
+ int phy_start_aneg(struct phy_device *phydev);
+   
+   Using variables inside the phydev structure, either configures advertising
+   and resets autonegotiation, or disables autonegotiation, and configures
+   forced settings.
+
+ static inline int phy_read_status(struct phy_device *phydev);
+
+   Fills the phydev structure with up-to-date information about the current
+   settings in the PHY.
+
+ void phy_sanitize_settings(struct phy_device *phydev)
+   
+   Resolves differences between currently desired settings, and
+   supported settings for the given PHY device.  Does not make
+   the changes in the hardware, though.
+
+ int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
+ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
+
+   Ethtool convenience functions.
+
+ int phy_mii_ioctl(struct phy_device *phydev,
+                 struct mii_ioctl_data *mii_data, int cmd);
+
+   The MII ioctl.  Note that this function will completely screw up the state
+   machine if you write registers like BMCR, BMSR, ADVERTISE, etc.  Best to
+   use this only to write registers which are not standard, and don't set off
+   a renegotiation.
+
+
+PHY Device Drivers
+
+ With the PHY Abstraction Layer, adding support for new PHYs is
+ quite easy.  In some cases, no work is required at all!  However,
+ many PHYs require a little hand-holding to get up-and-running.
+
+Generic PHY driver
+
+ If the desired PHY doesn't have any errata, quirks, or special
+ features you want to support, then it may be best to not add
+ support, and let the PHY Abstraction Layer's Generic PHY Driver
+ do all of the work.  
+
+Writing a PHY driver
+
+ If you do need to write a PHY driver, the first thing to do is
+ make sure it can be matched with an appropriate PHY device.
+ This is done during bus initialization by reading the device's
+ UID (stored in registers 2 and 3), then comparing it to each
+ driver's phy_id field by ANDing it with each driver's
+ phy_id_mask field.  Also, it needs a name.  Here's an example:
+
+   static struct phy_driver dm9161_driver = {
+         .phy_id         = 0x0181b880,
+        .name           = "Davicom DM9161E",
+        .phy_id_mask    = 0x0ffffff0,
+        ...
+   }
+
+ Next, you need to specify what features (speed, duplex, autoneg,
+ etc) your PHY device and driver support.  Most PHYs support
+ PHY_BASIC_FEATURES, but you can look in include/mii.h for other
+ features.
+
+ Each driver consists of a number of function pointers:
+
+   config_init: configures PHY into a sane state after a reset.
+     For instance, a Davicom PHY requires descrambling disabled.
+   probe: Does any setup needed by the driver
+   suspend/resume: power management
+   config_aneg: Changes the speed/duplex/negotiation settings
+   read_status: Reads the current speed/duplex/negotiation settings
+   ack_interrupt: Clear a pending interrupt
+   config_intr: Enable or disable interrupts
+   remove: Does any driver take-down
+
+ Of these, only config_aneg and read_status are required to be
+ assigned by the driver code.  The rest are optional.  Also, it is
+ preferred to use the generic phy driver's versions of these two
+ functions if at all possible: genphy_read_status and
+ genphy_config_aneg.  If this is not possible, it is likely that
+ you only need to perform some actions before and after invoking
+ these functions, and so your functions will wrap the generic
+ ones.
+
+ Feel free to look at the Marvell, Cicada, and Davicom drivers in
+ drivers/net/phy/ for examples (the lxt and qsemi drivers have
+ not been tested as of this writing)
index 62b1dc5..76d28d0 100644 (file)
@@ -266,20 +266,6 @@ port an old driver to the new PCI interface.  They are no longer present
 in the kernel as they aren't compatible with hotplug or PCI domains or
 having sane locking.
 
-pcibios_present() and          Since ages, you don't need to test presence
-pci_present()                  of PCI subsystem when trying to talk to it.
-                               If it's not there, the list of PCI devices
-                               is empty and all functions for searching for
-                               devices just return NULL.
-pcibios_(read|write)_*         Superseded by their pci_(read|write)_*
-                               counterparts.
-pcibios_find_*                 Superseded by their pci_get_* counterparts.
-pci_for_each_dev()             Superseded by pci_get_device()
-pci_for_each_dev_reverse()     Superseded by pci_find_device_reverse()
-pci_for_each_bus()             Superseded by pci_find_next_bus()
 pci_find_device()              Superseded by pci_get_device()
 pci_find_subsys()              Superseded by pci_get_subsys()
 pci_find_slot()                        Superseded by pci_get_slot()
-pcibios_find_class()           Superseded by pci_get_class()
-pci_find_class()               Superseded by pci_get_class()
-pci_(read|write)_*_nodev()     Superseded by pci_bus_(read|write)_*()
index f1896ee..63cb7ed 100644 (file)
@@ -102,7 +102,7 @@ Here is the list of words, from left to right:
 - URB Status. This field makes no sense for submissions, but is present
   to help scripts with parsing. In error case, it contains the error code.
   In case of a setup packet, it contains a Setup Tag. If scripts read a number
-  in this field, the proceed to read Data Length. Otherwise, they read
+  in this field, they proceed to read Data Length. Otherwise, they read
   the setup packet before reading the Data Length.
 - Setup packet, if present, consists of 5 words: one of each for bmRequestType,
   bRequest, wValue, wIndex, wLength, as specified by the USB Specification 2.0.
index 6d44958..03deb07 100644 (file)
@@ -29,3 +29,4 @@ card=27 - PixelView PlayTV Ultra Pro (Stereo)
 card=28 - DViCO FusionHDTV 3 Gold-T
 card=29 - ADS Tech Instant TV DVB-T PCI
 card=30 - TerraTec Cinergy 1400 DVB-T
+card=31 - DViCO FusionHDTV 5 Gold
index d1b9d21..f3302e1 100644 (file)
@@ -62,3 +62,5 @@ tuner=60 - Thomson DDT 7611 (ATSC/NTSC)
 tuner=61 - Tena TNF9533-D/IF/TNF9533-B/DF
 tuner=62 - Philips TEA5767HN FM Radio
 tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner
+tuner=64 - LG TDVS-H062F/TUA6034
+tuner=65 - Ymec TVF66T5-B/DFF
index 7bb5a50..fc94ff2 100644 (file)
@@ -44,6 +44,9 @@ bttv.o
                                push used by bttv.  bttv will disable overlay
                                by default on this hardware to avoid crashes.
                                With this insmod option you can override this.
+               no_overlay=1    Disable overlay. It should be used by broken
+                               hardware that doesn't support PCI2PCI direct
+                               transfers.
                automute=0/1    Automatically mutes the sound if there is
                                no TV signal, on by default.  You might try
                                to disable this if you have bad input signal
index 476c0c2..678e8f1 100644 (file)
@@ -6,6 +6,11 @@ only the AMD64 specific ones are listed here.
 Machine check
 
    mce=off disable machine check
+   mce=bootlog Enable logging of machine checks left over from booting.
+               Disabled by default because some BIOS leave bogus ones.
+               If your BIOS doesn't do that it's a good idea to enable though
+               to make sure you log even machine check events that result
+               in a reboot.
 
    nomce (for compatibility with i386): same as mce=off
 
index b39faa3..e8214fe 100644 (file)
@@ -784,7 +784,7 @@ DVB SUBSYSTEM AND DRIVERS
 P:     LinuxTV.org Project
 M:     linux-dvb-maintainer@linuxtv.org
 L:     linux-dvb@linuxtv.org (subscription required)
-W:     http://linuxtv.org/developer/dvb.xml
+W:     http://linuxtv.org/
 S:     Supported
 
 EATA-DMA SCSI DRIVER
@@ -1521,6 +1521,12 @@ P:       Zach Brown
 M:     zab@zabbo.net
 S:     Odd Fixes
 
+MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
+P: Michael Kerrisk
+M: mtk-manpages@gmx.net
+W: ftp://ftp.kernel.org/pub/linux/docs/manpages
+S: Maintained
+
 MARVELL MV64340 ETHERNET DRIVER
 P:     Manish Lachwani
 M:     Manish_Lachwani@pmc-sierra.com
@@ -1652,7 +1658,7 @@ M:        kuznet@ms2.inr.ac.ru
 P:     Pekka Savola (ipv6)
 M:     pekkas@netcore.fi
 P:     James Morris
-M:     jmorris@redhat.com
+M:     jmorris@namei.org
 P:     Hideaki YOSHIFUJI
 M:     yoshfuji@linux-ipv6.org
 P:     Patrick McHardy
@@ -1733,7 +1739,7 @@ S:        Maintained
 
 OPL3-SA2, SA3, and SAx DRIVER
 P:     Zwane Mwaikambo
-M:     zwane@commfireservices.com
+M:     zwane@arm.linux.org.uk
 L:     linux-sound@vger.kernel.org
 S:     Maintained
 
@@ -1819,6 +1825,12 @@ P:       Greg Kroah-Hartman
 M:     greg@kroah.com
 S:     Maintained
 
+PCIE HOTPLUG DRIVER
+P:     Kristen Carlson Accardi
+M:     kristen.c.accardi@intel.com
+L:     pcihpd-discuss@lists.sourceforge.net
+S:     Maintained
+
 PCMCIA SUBSYSTEM
 P:     Linux PCMCIA Team
 L:     http://lists.infradead.org/mailman/listinfo/linux-pcmcia
@@ -1983,7 +1995,7 @@ S:        Maintained
 
 SC1200 WDT DRIVER
 P:     Zwane Mwaikambo
-M:     zwane@commfireservices.com
+M:     zwane@arm.linux.org.uk
 S:     Maintained
 
 SCHEDULER
@@ -2041,7 +2053,7 @@ SELINUX SECURITY MODULE
 P:     Stephen Smalley
 M:     sds@epoch.ncsc.mil
 P:     James Morris
-M:     jmorris@redhat.com
+M:     jmorris@namei.org
 L:     linux-kernel@vger.kernel.org (kernel issues)
 L:     selinux@tycho.nsa.gov (general discussion)
 W:     http://www.nsa.gov/selinux
@@ -2201,6 +2213,12 @@ W:       http://projects.buici.com/arm
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
+SHPC HOTPLUG DRIVER
+P:     Kristen Carlson Accardi
+M:     kristen.c.accardi@intel.com
+L:     pcihpd-discuss@lists.sourceforge.net
+S:     Maintained
+
 SPARC (sparc32):
 P:     William L. Irwin
 M:     wli@holomorphy.com
index 717b9b9..3d84df5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 13
-EXTRAVERSION =-rc4
-NAME=Woozy Numbat
+EXTRAVERSION =
+NAME=Affluent Albatross
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
index 2045eae..224c347 100644 (file)
@@ -41,18 +41,19 @@ summary from [1.]>" for easy identification by the developers
 [2.] Full description of the problem/report:
 [3.] Keywords (i.e., modules, networking, kernel):
 [4.] Kernel version (from /proc/version):
-[5.] Output of Oops.. message (if applicable) with symbolic information 
+[5.] Most recent kernel version which did not have the bug:
+[6.] Output of Oops.. message (if applicable) with symbolic information
      resolved (see Documentation/oops-tracing.txt)
-[6.] A small shell script or example program which triggers the
+[7.] A small shell script or example program which triggers the
      problem (if possible)
-[7.] Environment
-[7.1.] Software (add the output of the ver_linux script here)
-[7.2.] Processor information (from /proc/cpuinfo):
-[7.3.] Module information (from /proc/modules):
-[7.4.] Loaded driver and hardware information (/proc/ioports, /proc/iomem)
-[7.5.] PCI information ('lspci -vvv' as root)
-[7.6.] SCSI information (from /proc/scsi/scsi)
-[7.7.] Other information that might be relevant to the problem
+[8.] Environment
+[8.1.] Software (add the output of the ver_linux script here)
+[8.2.] Processor information (from /proc/cpuinfo):
+[8.3.] Module information (from /proc/modules):
+[8.4.] Loaded driver and hardware information (/proc/ioports, /proc/iomem)
+[8.5.] PCI information ('lspci -vvv' as root)
+[8.6.] SCSI information (from /proc/scsi/scsi)
+[8.7.] Other information that might be relevant to the problem
        (please look in /proc and include all information that you
        think to be relevant):
 [X.] Other notes, patches, fixes, workarounds:
index 083c5df..189d5ea 100644 (file)
@@ -522,7 +522,7 @@ source "mm/Kconfig"
 
 config NUMA
        bool "NUMA Support (EXPERIMENTAL)"
-       depends on DISCONTIGMEM
+       depends on DISCONTIGMEM && BROKEN
        help
          Say Y to compile the kernel to support NUMA (Non-Uniform Memory
          Access).  This option is for configuring high-end multiprocessor
index 1f36bbd..2a8b364 100644 (file)
@@ -350,8 +350,24 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
        region->end = res->end - offset;
 }
 
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+                            struct pci_bus_region *region)
+{
+       struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
+       unsigned long offset = 0;
+
+       if (res->flags & IORESOURCE_IO)
+               offset = hose->io_space->start;
+       else if (res->flags & IORESOURCE_MEM)
+               offset = hose->mem_space->start;
+
+       res->start = region->start + offset;
+       res->end = region->end + offset;
+}
+
 #ifdef CONFIG_HOTPLUG
 EXPORT_SYMBOL(pcibios_resource_to_bus);
+EXPORT_SYMBOL(pcibios_bus_to_resource);
 #endif
 
 int
index 08fe807..2e45e86 100644 (file)
@@ -566,13 +566,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
        if (ka->sa.sa_flags & SA_RESETHAND)
                ka->sa.sa_handler = SIG_DFL;
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER)) 
                sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 }
 
 static inline void
index 8f1e785..e211aa7 100644 (file)
@@ -1036,7 +1036,7 @@ debug_spin_lock(spinlock_t * lock, const char *base_file, int line_no)
        "       br      1b\n"
        ".previous"
        : "=r" (tmp), "=m" (lock->lock), "=r" (stuck)
-       : "1" (lock->lock), "2" (stuck) : "memory");
+       : "m" (lock->lock), "2" (stuck) : "memory");
 
        if (stuck < 0) {
                printk(KERN_WARNING
@@ -1115,7 +1115,7 @@ void _raw_write_lock(rwlock_t * lock)
        ".previous"
        : "=m" (*(volatile int *)lock), "=&r" (regx), "=&r" (regy),
          "=&r" (stuck_lock), "=&r" (stuck_reader)
-       : "0" (*(volatile int *)lock), "3" (stuck_lock), "4" (stuck_reader) : "memory");
+       : "m" (*(volatile int *)lock), "3" (stuck_lock), "4" (stuck_reader) : "memory");
 
        if (stuck_lock < 0) {
                printk(KERN_WARNING "write_lock stuck at %p\n", inline_pc);
@@ -1153,7 +1153,7 @@ void _raw_read_lock(rwlock_t * lock)
        "       br      1b\n"
        ".previous"
        : "=m" (*(volatile int *)lock), "=&r" (regx), "=&r" (stuck_lock)
-       : "0" (*(volatile int *)lock), "2" (stuck_lock) : "memory");
+       : "m" (*(volatile int *)lock), "2" (stuck_lock) : "memory");
 
        if (stuck_lock < 0) {
                printk(KERN_WARNING "read_lock stuck at %p\n", inline_pc);
index 908eb4a..ba788cf 100644 (file)
@@ -65,7 +65,7 @@ op_axp_setup(void)
        model->reg_setup(&reg, ctr, &sys);
 
        /* Configure the registers on all cpus.  */
-       smp_call_function(model->cpu_setup, &reg, 0, 1);
+       (void)smp_call_function(model->cpu_setup, &reg, 0, 1);
        model->cpu_setup(&reg);
        return 0;
 }
@@ -86,7 +86,7 @@ op_axp_cpu_start(void *dummy)
 static int
 op_axp_start(void)
 {
-       smp_call_function(op_axp_cpu_start, NULL, 0, 1);
+       (void)smp_call_function(op_axp_cpu_start, NULL, 0, 1);
        op_axp_cpu_start(NULL);
        return 0;
 }
@@ -101,7 +101,7 @@ op_axp_cpu_stop(void *dummy)
 static void
 op_axp_stop(void)
 {
-       smp_call_function(op_axp_cpu_stop, NULL, 0, 1);
+       (void)smp_call_function(op_axp_cpu_stop, NULL, 0, 1);
        op_axp_cpu_stop(NULL);
 }
 
index 7bc4a58..4bf0e87 100644 (file)
@@ -310,7 +310,7 @@ menu "Kernel Features"
 
 config SMP
        bool "Symmetric Multi-Processing (EXPERIMENTAL)"
-       depends on EXPERIMENTAL #&& n
+       depends on EXPERIMENTAL && BROKEN #&& n
        help
          This enables support for systems with more than one CPU. If you have
          a system with only one CPU, like most personal computers, say N. If
@@ -635,10 +635,6 @@ config PM
          and the Battery Powered Linux mini-HOWTO, available from
          <http://www.tldp.org/docs.html#howto>.
 
-         Note that, even if you say N here, Linux on the x86 architecture
-         will issue the hlt instruction if nothing is to be done, thereby
-         sending the processor to sleep and saving power.
-
 config APM
        tristate "Advanced Power Management Emulation"
        depends on PM
@@ -650,12 +646,6 @@ config APM
          battery status information, and user-space programs will receive
          notification of APM "events" (e.g. battery status change).
 
-         If you select "Y" here, you can disable actual use of the APM
-         BIOS by passing the "apm=off" option to the kernel at boot time.
-
-         Note that the APM support is almost completely disabled for
-         machines with more than one CPU.
-
          In order to use APM, you will need supporting software. For location
          and more information, read <file:Documentation/pm.txt> and the
          Battery Powered Linux mini-HOWTO, available from
@@ -665,39 +655,12 @@ config APM
          manpage ("man 8 hdparm") for that), and it doesn't turn off
          VESA-compliant "green" monitors.
 
-         This driver does not support the TI 4000M TravelMate and the ACER
-         486/DX4/75 because they don't have compliant BIOSes. Many "green"
-         desktop machines also don't have compliant BIOSes, and this driver
-         may cause those machines to panic during the boot phase.
-
          Generally, if you don't have a battery in your machine, there isn't
          much point in using this driver and you should say N. If you get
          random kernel OOPSes or reboots that don't seem to be related to
          anything, try disabling/enabling this option (or disabling/enabling
          APM in your BIOS).
 
-         Some other things you should try when experiencing seemingly random,
-         "weird" problems:
-
-         1) make sure that you have enough swap space and that it is
-         enabled.
-         2) pass the "no-hlt" option to the kernel
-         3) switch on floating point emulation in the kernel and pass
-         the "no387" option to the kernel
-         4) pass the "floppy=nodma" option to the kernel
-         5) pass the "mem=4M" option to the kernel (thereby disabling
-         all but the first 4 MB of RAM)
-         6) make sure that the CPU is not over clocked.
-         7) read the sig11 FAQ at <http://www.bitwizard.nl/sig11/>
-         8) disable the cache from your BIOS settings
-         9) install a fan for the video card or exchange video RAM
-         10) install a better fan for the CPU
-         11) exchange RAM chips
-         12) exchange the motherboard.
-
-         To compile this driver as a module, choose M here: the
-         module will be called apm.
-
 endmenu
 
 source "net/Kconfig"
@@ -752,6 +715,8 @@ source "drivers/hwmon/Kconfig"
 
 source "drivers/misc/Kconfig"
 
+source "drivers/mfd/Kconfig"
+
 source "drivers/media/Kconfig"
 
 source "drivers/video/Kconfig"
index 692af6b..666ba39 100644 (file)
@@ -1,6 +1,9 @@
 config ICST525
        bool
 
+config ARM_GIC
+       bool
+
 config ICST307
        bool
 
index 11f20a4..a878865 100644 (file)
@@ -4,6 +4,7 @@
 
 obj-y                          += rtctime.o
 obj-$(CONFIG_ARM_AMBA)         += amba.o
+obj-$(CONFIG_ARM_GIC)          += gic.o
 obj-$(CONFIG_ICST525)          += icst525.o
 obj-$(CONFIG_ICST307)          += icst307.o
 obj-$(CONFIG_SA1111)           += sa1111.o
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
new file mode 100644 (file)
index 0000000..51dbf54
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ *  linux/arch/arm/common/gic.c
+ *
+ *  Copyright (C) 2002 ARM Limited, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Interrupt architecture for the GIC:
+ *
+ * o There is one Interrupt Distributor, which receives interrupts
+ *   from system devices and sends them to the Interrupt Controllers.
+ *
+ * o There is one CPU Interface per CPU, which sends interrupts sent
+ *   by the Distributor, and interrupts generated locally, to the
+ *   associated CPU.
+ *
+ * Note that IRQs 0-31 are special - they are local to each CPU.
+ * As such, the enable set/clear, pending set/clear and active bit
+ * registers are banked per-cpu for these sources.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/smp.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mach/irq.h>
+#include <asm/hardware/gic.h>
+
+static void __iomem *gic_dist_base;
+static void __iomem *gic_cpu_base;
+
+/*
+ * Routines to acknowledge, disable and enable interrupts
+ *
+ * Linux assumes that when we're done with an interrupt we need to
+ * unmask it, in the same way we need to unmask an interrupt when
+ * we first enable it.
+ *
+ * The GIC has a seperate notion of "end of interrupt" to re-enable
+ * an interrupt after handling, in order to support hardware
+ * prioritisation.
+ *
+ * We can make the GIC behave in the way that Linux expects by making
+ * our "acknowledge" routine disable the interrupt, then mark it as
+ * complete.
+ */
+static void gic_ack_irq(unsigned int irq)
+{
+       u32 mask = 1 << (irq % 32);
+       writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4);
+       writel(irq, gic_cpu_base + GIC_CPU_EOI);
+}
+
+static void gic_mask_irq(unsigned int irq)
+{
+       u32 mask = 1 << (irq % 32);
+       writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4);
+}
+
+static void gic_unmask_irq(unsigned int irq)
+{
+       u32 mask = 1 << (irq % 32);
+       writel(mask, gic_dist_base + GIC_DIST_ENABLE_SET + (irq / 32) * 4);
+}
+
+static void gic_set_cpu(struct irqdesc *desc, unsigned int irq, unsigned int cpu)
+{
+       void __iomem *reg = gic_dist_base + GIC_DIST_TARGET + (irq & ~3);
+       unsigned int shift = (irq % 4) * 8;
+       u32 val;
+
+       val = readl(reg) & ~(0xff << shift);
+       val |= 1 << (cpu + shift);
+       writel(val, reg);
+}
+
+static struct irqchip gic_chip = {
+       .ack            = gic_ack_irq,
+       .mask           = gic_mask_irq,
+       .unmask         = gic_unmask_irq,
+#ifdef CONFIG_SMP
+       .set_cpu        = gic_set_cpu,
+#endif
+};
+
+void __init gic_dist_init(void __iomem *base)
+{
+       unsigned int max_irq, i;
+       u32 cpumask = 1 << smp_processor_id();
+
+       cpumask |= cpumask << 8;
+       cpumask |= cpumask << 16;
+
+       gic_dist_base = base;
+
+       writel(0, base + GIC_DIST_CTRL);
+
+       /*
+        * Find out how many interrupts are supported.
+        */
+       max_irq = readl(base + GIC_DIST_CTR) & 0x1f;
+       max_irq = (max_irq + 1) * 32;
+
+       /*
+        * The GIC only supports up to 1020 interrupt sources.
+        * Limit this to either the architected maximum, or the
+        * platform maximum.
+        */
+       if (max_irq > max(1020, NR_IRQS))
+               max_irq = max(1020, NR_IRQS);
+
+       /*
+        * Set all global interrupts to be level triggered, active low.
+        */
+       for (i = 32; i < max_irq; i += 16)
+               writel(0, base + GIC_DIST_CONFIG + i * 4 / 16);
+
+       /*
+        * Set all global interrupts to this CPU only.
+        */
+       for (i = 32; i < max_irq; i += 4)
+               writel(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
+
+       /*
+        * Set priority on all interrupts.
+        */
+       for (i = 0; i < max_irq; i += 4)
+               writel(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
+
+       /*
+        * Disable all interrupts.
+        */
+       for (i = 0; i < max_irq; i += 32)
+               writel(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
+
+       /*
+        * Setup the Linux IRQ subsystem.
+        */
+       for (i = 29; i < max_irq; i++) {
+               set_irq_chip(i, &gic_chip);
+               set_irq_handler(i, do_level_IRQ);
+               set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+       }
+
+       writel(1, base + GIC_DIST_CTRL);
+}
+
+void __cpuinit gic_cpu_init(void __iomem *base)
+{
+       gic_cpu_base = base;
+       writel(0xf0, base + GIC_CPU_PRIMASK);
+       writel(1, base + GIC_CPU_CTRL);
+}
+
+#ifdef CONFIG_SMP
+void gic_raise_softirq(cpumask_t cpumask, unsigned int irq)
+{
+       unsigned long map = *cpus_addr(cpumask);
+
+       writel(map << 16 | irq, gic_dist_base + GIC_DIST_SOFTINT);
+}
+#endif
index ad26e98..c4923fa 100644 (file)
@@ -447,9 +447,26 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
        region->end   = res->end - offset;
 }
 
+void __devinit
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+                       struct pci_bus_region *region)
+{
+       struct pci_sys_data *root = dev->sysdata;
+       unsigned long offset = 0;
+
+       if (res->flags & IORESOURCE_IO)
+               offset = root->io_offset;
+       if (res->flags & IORESOURCE_MEM)
+               offset = root->mem_offset;
+
+       res->start = region->start + offset;
+       res->end   = region->end + offset;
+}
+
 #ifdef CONFIG_HOTPLUG
 EXPORT_SYMBOL(pcibios_fixup_bus);
 EXPORT_SYMBOL(pcibios_resource_to_bus);
+EXPORT_SYMBOL(pcibios_bus_to_resource);
 #endif
 
 /*
index e5d370c..2b6b4c7 100644 (file)
@@ -327,6 +327,12 @@ __syscall_start:
 /* 310 */      .long   sys_request_key
                .long   sys_keyctl
                .long   sys_semtimedop
+/* vserver */  .long   sys_ni_syscall
+               .long   sys_ioprio_set
+/* 315 */      .long   sys_ioprio_get
+               .long   sys_inotify_init
+               .long   sys_inotify_add_watch
+               .long   sys_inotify_rm_watch
 __syscall_end:
 
                .rept   NR_syscalls - (__syscall_end - __syscall_start) / 4
index 39a6c1b..7152bfb 100644 (file)
@@ -533,6 +533,13 @@ ENTRY(__switch_to)
        ldr     r3, [r2, #TI_TP_VALUE]
        stmia   ip!, {r4 - sl, fp, sp, lr}      @ Store most regs on stack
        ldr     r6, [r2, #TI_CPU_DOMAIN]!
+#if __LINUX_ARM_ARCH__ >= 6
+#ifdef CONFIG_CPU_MPCORE
+       clrex
+#else
+       strex   r3, r4, [ip]                    @ Clear exclusive monitor
+#endif
+#endif
 #if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT)
        mra     r4, r5, acc0
        stmia   ip, {r4, r5}
index 5e435e4..a94d75f 100644 (file)
@@ -658,11 +658,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
        /*
         * Block the signal if we were unsuccessful.
         */
-       if (ret != 0 || !(ka->sa.sa_flags & SA_NODEFER)) {
+       if (ret != 0) {
                spin_lock_irq(&tsk->sighand->siglock);
                sigorsets(&tsk->blocked, &tsk->blocked,
                          &ka->sa.sa_mask);
-               sigaddset(&tsk->blocked, sig);
+               if (!(ka->sa.sa_flags & SA_NODEFER))
+                       sigaddset(&tsk->blocked, sig);
                recalc_sigpending();
                spin_unlock_irq(&tsk->sighand->siglock);
        }
index d571c37..4554c96 100644 (file)
@@ -617,7 +617,7 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
        notify_die("unknown data abort code", regs, &info, instr, 0);
 }
 
-volatile void __bug(const char *file, int line, void *data)
+void __attribute__((noreturn)) __bug(const char *file, int line, void *data)
 {
        printk(KERN_CRIT"kernel BUG at %s:%d!", file, line);
        if (data)
index 2036ff1..64a988c 100644 (file)
@@ -1,4 +1,6 @@
-#if __LINUX_ARM_ARCH__ >= 6
+#include <linux/config.h>
+
+#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_CPU_MPCORE)
        .macro  bitop, instr
        mov     r2, #1
        and     r3, r0, #7              @ Get bit offset
index 4ff4393..411ea99 100644 (file)
@@ -36,7 +36,7 @@ static struct flash_platform_data coyote_flash_data = {
 
 static struct resource coyote_flash_resource = {
        .start          = COYOTE_FLASH_BASE,
-       .end            = COYOTE_FLASH_BASE + COYOTE_FLASH_SIZE,
+       .end            = COYOTE_FLASH_BASE + COYOTE_FLASH_SIZE - 1,
        .flags          = IORESOURCE_MEM,
 };
 
@@ -61,7 +61,7 @@ static struct plat_serial8250_port coyote_uart_data[] = {
                .mapbase        = IXP4XX_UART2_BASE_PHYS,
                .membase        = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
                .irq            = IRQ_IXP4XX_UART2,
-               .flags          = UPF_BOOT_AUTOCONF,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
                .iotype         = UPIO_MEM,
                .regshift       = 2,
                .uartclk        = IXP4XX_UART_XTAL,
index 8ba1cd9..333459d 100644 (file)
@@ -83,7 +83,7 @@ static struct plat_serial8250_port gtwx5715_uart_platform_data[] = {
        .mapbase        = IXP4XX_UART2_BASE_PHYS,
        .membase        = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
        .irq            = IRQ_IXP4XX_UART2,
-       .flags          = UPF_BOOT_AUTOCONF,
+       .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
        .iotype         = UPIO_MEM,
        .regshift       = 2,
        .uartclk        = IXP4XX_UART_XTAL,
@@ -114,7 +114,7 @@ static struct flash_platform_data gtwx5715_flash_data = {
 
 static struct resource gtwx5715_flash_resource = {
        .start          = GTWX5715_FLASH_BASE,
-       .end            = GTWX5715_FLASH_BASE + GTWX5715_FLASH_SIZE,
+       .end            = GTWX5715_FLASH_BASE + GTWX5715_FLASH_SIZE - 1,
        .flags          = IORESOURCE_MEM,
 };
 
index c2ba759..fa0646c 100644 (file)
@@ -36,7 +36,7 @@ static struct flash_platform_data ixdp425_flash_data = {
 
 static struct resource ixdp425_flash_resource = {
        .start          = IXDP425_FLASH_BASE,
-       .end            = IXDP425_FLASH_BASE + IXDP425_FLASH_SIZE,
+       .end            = IXDP425_FLASH_BASE + IXDP425_FLASH_SIZE - 1,
        .flags          = IORESOURCE_MEM,
 };
 
@@ -82,7 +82,7 @@ static struct plat_serial8250_port ixdp425_uart_data[] = {
                .mapbase        = IXP4XX_UART1_BASE_PHYS,
                .membase        = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
                .irq            = IRQ_IXP4XX_UART1,
-               .flags          = UPF_BOOT_AUTOCONF,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
                .iotype         = UPIO_MEM,
                .regshift       = 2,
                .uartclk        = IXP4XX_UART_XTAL,
@@ -91,7 +91,7 @@ static struct plat_serial8250_port ixdp425_uart_data[] = {
                .mapbase        = IXP4XX_UART2_BASE_PHYS,
                .membase        = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
                .irq            = IRQ_IXP4XX_UART1,
-               .flags          = UPF_BOOT_AUTOCONF,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
                .iotype         = UPIO_MEM,
                .regshift       = 2,
                .uartclk        = IXP4XX_UART_XTAL,
index 1e7f343..e918224 100644 (file)
@@ -30,6 +30,7 @@
  *     28-Jun-2005 BJD  Moved pm functionality out to common code
  *     17-Jul-2005 BJD  Changed to platform device for SuperIO 16550s
  *     25-Jul-2005 BJD  Removed ASIX static mappings
+ *     27-Jul-2005 BJD  Ensure maximum frequency of i2c bus
 */
 
 #include <linux/kernel.h>
@@ -60,6 +61,7 @@
 #include <asm/arch/regs-mem.h>
 #include <asm/arch/regs-lcd.h>
 #include <asm/arch/nand.h>
+#include <asm/arch/iic.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -304,7 +306,7 @@ static void bast_nand_select(struct s3c2410_nand_set *set, int slot)
 }
 
 static struct s3c2410_platform_nand bast_nand_info = {
-       .tacls          = 80,
+       .tacls          = 40,
        .twrph0         = 80,
        .twrph1         = 80,
        .nr_sets        = ARRAY_SIZE(bast_nand_sets),
@@ -385,6 +387,17 @@ static struct platform_device bast_sio = {
        },
 };
 
+/* we have devices on the bus which cannot work much over the
+ * standard 100KHz i2c bus frequency
+*/
+
+static struct s3c2410_platform_i2c bast_i2c_info = {
+       .flags          = 0,
+       .slave_addr     = 0x10,
+       .bus_freq       = 100*1000,
+       .max_freq       = 130*1000,
+};
+
 /* Standard BAST devices */
 
 static struct platform_device *bast_devices[] __initdata = {
@@ -431,6 +444,7 @@ void __init bast_map_io(void)
        s3c24xx_uclk.parent  = &s3c24xx_clkout1;
 
        s3c_device_nand.dev.platform_data = &bast_nand_info;
+       s3c_device_i2c.dev.platform_data = &bast_i2c_info;
 
        s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
        s3c24xx_init_clocks(0);
index ff2f254..0b88993 100644 (file)
@@ -18,6 +18,7 @@
  *     28-Sep-2004 BJD  Updates for new serial port bits
  *     04-Nov-2004 BJD  Updated UART configuration process
  *     10-Jan-2005 BJD  Removed s3c2410_clock_tick_rate
+ *     13-Aug-2005 DA   Removed UART from initial I/O mappings
 */
 
 #include <linux/kernel.h>
@@ -49,10 +50,9 @@ static struct map_desc s3c2410_iodesc[] __initdata = {
        IODESC_ENT(USBHOST),
        IODESC_ENT(CLKPWR),
        IODESC_ENT(LCD),
-       IODESC_ENT(UART),
        IODESC_ENT(TIMER),
        IODESC_ENT(ADC),
-       IODESC_ENT(WATCHDOG)
+       IODESC_ENT(WATCHDOG),
 };
 
 static struct resource s3c_uart0_resource[] = {
index 7f2b613..f021fd8 100644 (file)
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s3c2410/usb-simtec.c
  *
- * Copyright (c) 2004 Simtec Electronics
+ * Copyright (c) 2004,2005 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
  *
  * http://www.simtec.co.uk/products/EB2410ITX/
@@ -14,6 +14,8 @@
  * Modifications:
  *     14-Sep-2004 BJD  Created
  *     18-Oct-2004 BJD  Cleanups, and added code to report OC cleared
+ *     09-Aug-2005 BJD  Renamed s3c2410_report_oc to s3c2410_usb_report_oc
+ *     09-Aug-2005 BJD  Ports powered only if both are enabled
 */
 
 #define DEBUG
  * designed boards.
 */
 
+static unsigned int power_state[2];
+
 static void
 usb_simtec_powercontrol(int port, int to)
 {
        pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to);
 
-       if (port == 1)
-               s3c2410_gpio_setpin(S3C2410_GPB4, to ? 0:1);
+       power_state[port] = to;
+
+       if (power_state[0] && power_state[1])
+               s3c2410_gpio_setpin(S3C2410_GPB4, 0);
+       else
+               s3c2410_gpio_setpin(S3C2410_GPB4, 1);
 }
 
 static irqreturn_t
@@ -63,10 +71,10 @@ usb_simtec_ocirq(int irq, void *pw, struct pt_regs *regs)
 
        if (s3c2410_gpio_getpin(S3C2410_GPG10) == 0) {
                pr_debug("usb_simtec: over-current irq (oc detected)\n");
-               s3c2410_report_oc(info, 3);
+               s3c2410_usb_report_oc(info, 3);
        } else {
                pr_debug("usb_simtec: over-current irq (oc cleared)\n");
-               s3c2410_report_oc(info, 0);
+               s3c2410_usb_report_oc(info, 0);
        }
 
        return IRQ_HANDLED;
index 4d4d303..24687f5 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/serial_sa1100.h>
 #include <asm/arch/assabet.h>
+#include <asm/arch/mcp.h>
 
 #include "generic.h"
 
@@ -198,6 +199,11 @@ static struct irda_platform_data assabet_irda_data = {
        .set_speed      = assabet_irda_set_speed,
 };
 
+static struct mcp_plat_data assabet_mcp_data = {
+       .mccr0          = MCCR0_ADM,
+       .sclk_rate      = 11981000,
+};
+
 static void __init assabet_init(void)
 {
        /*
@@ -246,6 +252,7 @@ static void __init assabet_init(void)
        sa11x0_set_flash_data(&assabet_flash_data, assabet_flash_resources,
                              ARRAY_SIZE(assabet_flash_resources));
        sa11x0_set_irda_data(&assabet_irda_data);
+       sa11x0_set_mcp_data(&assabet_mcp_data);
 }
 
 /*
index 0aa918e..9484be7 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/mach/serial_sa1100.h>
 
 #include <asm/arch/cerf.h>
+#include <asm/arch/mcp.h>
 #include "generic.h"
 
 static struct resource cerfuart2_resources[] = {
@@ -116,10 +117,16 @@ static void __init cerf_map_io(void)
        GPDR |= CERF_GPIO_CF_RESET;
 }
 
+static struct mcp_plat_data cerf_mcp_data = {
+       .mccr0          = MCCR0_ADM,
+       .sclk_rate      = 11981000,
+};
+
 static void __init cerf_init(void)
 {
        platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices));
        sa11x0_set_flash_data(&cerf_flash_data, &cerf_flash_resource, 1);
+       sa11x0_set_mcp_data(&cerf_mcp_data);
 }
 
 MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube")
index 95ae217..3f1e358 100644 (file)
@@ -221,6 +221,11 @@ static struct platform_device sa11x0mcp_device = {
        .resource       = sa11x0mcp_resources,
 };
 
+void sa11x0_set_mcp_data(struct mcp_plat_data *data)
+{
+       sa11x0mcp_device.dev.platform_data = data;
+}
+
 static struct resource sa11x0ssp_resources[] = {
        [0] = {
                .start  = 0x80070000,
index bfe41da..279e3af 100644 (file)
@@ -34,5 +34,8 @@ struct resource;
 extern void sa11x0_set_flash_data(struct flash_platform_data *flash,
                                  struct resource *res, int nr);
 
+struct sa11x0_ssp_plat_ops;
+extern void sa11x0_set_ssp_data(struct sa11x0_ssp_plat_ops *ops);
+
 struct irda_platform_data;
 void sa11x0_set_irda_data(struct irda_platform_data *irda);
index eee3cbc..2f49711 100644 (file)
@@ -97,6 +97,7 @@ static void __init jornada720_map_io(void)
 }
 
 MACHINE_START(JORNADA720, "HP Jornada 720")
+       /* Maintainer: Michael Gernoth <michael@gernoth.net> */
        .phys_ram       = 0xc0000000,
        .phys_io        = 0x80000000,
        .io_pg_offst    = ((0xf8000000) >> 18) & 0xfffc,
index 870b488..ed6744d 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/serial_sa1100.h>
+#include <asm/arch/mcp.h>
 
 #include "generic.h"
 
 
 #warning "include/asm/arch-sa1100/ide.h needs fixing for lart"
 
+static struct mcp_plat_data lart_mcp_data = {
+       .mccr0          = MCCR0_ADM,
+       .sclk_rate      = 11981000,
+};
+
+static void __init lart_init(void)
+{
+       sa11x0_set_mcp_data(&lart_mcp_data);
+}
+
 static struct map_desc lart_io_desc[] __initdata = {
  /* virtual     physical    length      type */
   { 0xe8000000, 0x00000000, 0x00400000, MT_DEVICE }, /* main flash memory */
@@ -47,5 +58,6 @@ MACHINE_START(LART, "LART")
        .boot_params    = 0xc0000100,
        .map_io         = lart_map_io,
        .init_irq       = sa1100_init_irq,
+       .init_machine   = lart_init,
        .timer          = &sa1100_timer,
 MACHINE_END
index 43a0035..7482288 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
 #include <asm/mach/serial_sa1100.h>
+#include <asm/arch/mcp.h>
 #include <asm/arch/shannon.h>
 
 #include "generic.h"
@@ -52,9 +53,15 @@ static struct resource shannon_flash_resource = {
        .flags          = IORESOURCE_MEM,
 };
 
+static struct mcp_plat_data shannon_mcp_data = {
+       .mccr0          = MCCR0_ADM,
+       .sclk_rate      = 11981000,
+};
+
 static void __init shannon_init(void)
 {
        sa11x0_set_flash_data(&shannon_flash_data, &shannon_flash_resource, 1);
+       sa11x0_set_mcp_data(&shannon_mcp_data);
 }
 
 static void __init shannon_map_io(void)
index 7797858..07f6d5f 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
 #include <asm/mach/serial_sa1100.h>
+#include <asm/arch/mcp.h>
 #include <asm/arch/simpad.h>
 
 #include <linux/serial_core.h>
@@ -123,6 +124,11 @@ static struct resource simpad_flash_resources [] = {
        }
 };
 
+static struct mcp_plat_data simpad_mcp_data = {
+       .mccr0          = MCCR0_ADM,
+       .sclk_rate      = 11981000,
+};
+
 
 
 static void __init simpad_map_io(void)
@@ -157,6 +163,7 @@ static void __init simpad_map_io(void)
 
        sa11x0_set_flash_data(&simpad_flash_data, simpad_flash_resources,
                              ARRAY_SIZE(simpad_flash_resources));
+       sa11x0_set_mcp_data(&simpad_mcp_data);
 }
 
 static void simpad_power_off(void)
index afbbeb6..db5e47d 100644 (file)
@@ -384,7 +384,7 @@ config CPU_DCACHE_DISABLE
 
 config CPU_DCACHE_WRITETHROUGH
        bool "Force write through D-cache"
-       depends on (CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020) && !CPU_DISABLE_DCACHE
+       depends on (CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020) && !CPU_DCACHE_DISABLE
        default y if CPU_ARM925T
        help
          Say Y here to use the data cache in writethrough mode. Unless you
index 65bfe84..0b6c4db 100644 (file)
@@ -238,9 +238,9 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        up_read(&mm->mmap_sem);
 
        /*
-        * Handle the "normal" case first
+        * Handle the "normal" case first - VM_FAULT_MAJOR / VM_FAULT_MINOR
         */
-       if (fault > 0)
+       if (fault >= VM_FAULT_MINOR)
                return 0;
 
        /*
@@ -261,7 +261,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
                do_exit(SIGKILL);
                return 0;
 
-       case 0:
+       case VM_FAULT_SIGBUS:
                /*
                 * We had some memory, but were unable to
                 * successfully fix up this page fault.
index e33fe42..3c655c5 100644 (file)
@@ -383,6 +383,7 @@ static void __init build_mem_type_table(void)
 {
        struct cachepolicy *cp;
        unsigned int cr = get_cr();
+       unsigned int user_pgprot;
        int cpu_arch = cpu_architecture();
        int i;
 
@@ -408,6 +409,9 @@ static void __init build_mem_type_table(void)
                }
        }
 
+       cp = &cache_policies[cachepolicy];
+       user_pgprot = cp->pte;
+
        /*
         * ARMv6 and above have extended page tables.
         */
@@ -426,11 +430,18 @@ static void __init build_mem_type_table(void)
                mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
                mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
 
+               /*
+                * Mark the device area as "shared device"
+                */
                mem_types[MT_DEVICE].prot_pte |= L_PTE_BUFFERABLE;
                mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
-       }
 
-       cp = &cache_policies[cachepolicy];
+               /*
+                * User pages need to be mapped with the ASID
+                * (iow, non-global)
+                */
+               user_pgprot |= L_PTE_ASID;
+       }
 
        if (cpu_arch >= CPU_ARCH_ARMv5) {
                mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE;
@@ -448,7 +459,7 @@ static void __init build_mem_type_table(void)
 
        for (i = 0; i < 16; i++) {
                unsigned long v = pgprot_val(protection_map[i]);
-               v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | cp->pte;
+               v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot;
                protection_map[i] = __pgprot(v);
        }
 
index 352db98..139a386 100644 (file)
@@ -105,18 +105,12 @@ ENTRY(cpu_v6_dcache_clean_area)
 ENTRY(cpu_v6_switch_mm)
        mov     r2, #0
        ldr     r1, [r1, #MM_CONTEXT_ID]        @ get mm->context.id
-       mcr     p15, 0, r2, c7, c5, 6           @ flush BTAC/BTB
+       mcr     p15, 0, r2, c7, c5, 6           @ flush BTAC/BTB
        mcr     p15, 0, r2, c7, c10, 4          @ drain write buffer
        mcr     p15, 0, r0, c2, c0, 0           @ set TTB 0
        mcr     p15, 0, r1, c13, c0, 1          @ set context ID
        mov     pc, lr
 
-#define nG     (1 << 11)
-#define APX    (1 << 9)
-#define AP1    (1 << 5)
-#define AP0    (1 << 4)
-#define XN     (1 << 0)
-
 /*
  *     cpu_v6_set_pte(ptep, pte)
  *
@@ -139,24 +133,24 @@ ENTRY(cpu_v6_switch_mm)
 ENTRY(cpu_v6_set_pte)
        str     r1, [r0], #-2048                @ linux version
 
-       bic     r2, r1, #0x00000ff0
+       bic     r2, r1, #0x000007f0
        bic     r2, r2, #0x00000003
-       orr     r2, r2, #AP0 | 2
+       orr     r2, r2, #PTE_EXT_AP0 | 2
 
        tst     r1, #L_PTE_WRITE
        tstne   r1, #L_PTE_DIRTY
-       orreq   r2, r2, #APX
+       orreq   r2, r2, #PTE_EXT_APX
 
        tst     r1, #L_PTE_USER
-       orrne   r2, r2, #AP1 | nG
-       tstne   r2, #APX
-       bicne   r2, r2, #APX | AP0
+       orrne   r2, r2, #PTE_EXT_AP1
+       tstne   r2, #PTE_EXT_APX
+       bicne   r2, r2, #PTE_EXT_APX | PTE_EXT_AP0
 
        tst     r1, #L_PTE_YOUNG
-       biceq   r2, r2, #APX | AP1 | AP0
+       biceq   r2, r2, #PTE_EXT_APX | PTE_EXT_AP_MASK
 
 @      tst     r1, #L_PTE_EXEC
-@      orreq   r2, r2, #XN
+@      orreq   r2, r2, #PTE_EXT_XN
 
        tst     r1, #L_PTE_PRESENT
        moveq   r2, #0
index 2d977b4..b88de27 100644 (file)
@@ -370,142 +370,6 @@ ENTRY(cpu_xscale_dcache_clean_area)
        bhi     1b
        mov     pc, lr
 
-/* ================================ CACHE LOCKING============================
- *
- * The XScale MicroArchitecture implements support for locking entries into
- * the data and instruction cache.  The following functions implement the core
- * low level instructions needed to accomplish the locking.  The developer's
- * manual states that the code that performs the locking must be in non-cached
- * memory.  To accomplish this, the code in xscale-cache-lock.c copies the
- * following functions from the cache into a non-cached memory region that
- * is allocated through consistent_alloc().
- *
- */
-       .align  5
-/*
- * xscale_icache_lock
- *
- * r0: starting address to lock
- * r1: end address to lock
- */
-ENTRY(xscale_icache_lock)
-
-iLockLoop:
-       bic     r0, r0, #CACHELINESIZE - 1
-       mcr     p15, 0, r0, c9, c1, 0   @ lock into cache
-       cmp     r0, r1                  @ are we done?
-       add     r0, r0, #CACHELINESIZE  @ advance to next cache line
-       bls     iLockLoop
-       mov     pc, lr
-
-/*
- * xscale_icache_unlock
- */
-ENTRY(xscale_icache_unlock)
-       mcr     p15, 0, r0, c9, c1, 1   @ Unlock icache
-       mov     pc, lr
-
-/*
- * xscale_dcache_lock
- *
- * r0: starting address to lock
- * r1: end address to lock
- */
-ENTRY(xscale_dcache_lock)
-       mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
-       mov     r2, #1
-       mcr     p15, 0, r2, c9, c2, 0   @ Put dcache in lock mode
-       cpwait  ip                      @ Wait for completion
-
-       mrs     r2, cpsr
-       orr     r3, r2, #PSR_F_BIT | PSR_I_BIT
-dLockLoop:
-       msr     cpsr_c, r3
-       mcr     p15, 0, r0, c7, c10, 1  @ Write back line if it is dirty
-       mcr     p15, 0, r0, c7, c6, 1   @ Flush/invalidate line
-       msr     cpsr_c, r2
-       ldr     ip, [r0], #CACHELINESIZE @ Preload 32 bytes into cache from
-                                       @ location [r0]. Post-increment
-                                       @ r3 to next cache line
-       cmp     r0, r1                  @ Are we done?
-       bls     dLockLoop
-
-       mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
-       mov     r2, #0
-       mcr     p15, 0, r2, c9, c2, 0   @ Get out of lock mode
-       cpwait_ret lr, ip
-
-/*
- * xscale_dcache_unlock
- */
-ENTRY(xscale_dcache_unlock)
-       mcr     p15, 0, ip, c7, c10, 4          @ Drain Write (& Fill) Buffer
-       mcr     p15, 0, ip, c9, c2, 1   @ Unlock cache
-       mov     pc, lr
-
-/*
- * Needed to determine the length of the code that needs to be copied.
- */
-       .align  5
-ENTRY(xscale_cache_dummy)
-       mov     pc, lr
-
-/* ================================ TLB LOCKING==============================
- *
- * The XScale MicroArchitecture implements support for locking entries into
- * the Instruction and Data TLBs.  The following functions provide the
- * low level support for supporting these under Linux.  xscale-lock.c
- * implements some higher level management code.  Most of the following
- * is taken straight out of the Developer's Manual.
- */
-
-/*
- * Lock I-TLB entry
- *
- * r0: Virtual address to translate and lock
- */
-       .align  5
-ENTRY(xscale_itlb_lock)
-       mrs     r2, cpsr
-       orr     r3, r2, #PSR_F_BIT | PSR_I_BIT
-       msr     cpsr_c, r3                      @ Disable interrupts
-       mcr     p15, 0, r0, c8, c5, 1           @ Invalidate I-TLB entry
-       mcr     p15, 0, r0, c10, c4, 0          @ Translate and lock
-       msr     cpsr_c, r2                      @ Restore interrupts
-       cpwait_ret lr, ip
-
-/*
- * Lock D-TLB entry
- *
- * r0: Virtual address to translate and lock
- */
-       .align  5
-ENTRY(xscale_dtlb_lock)
-       mrs     r2, cpsr
-       orr     r3, r2, #PSR_F_BIT | PSR_I_BIT
-       msr     cpsr_c, r3                      @ Disable interrupts
-       mcr     p15, 0, r0, c8, c6, 1           @ Invalidate D-TLB entry
-       mcr     p15, 0, r0, c10, c8, 0          @ Translate and lock
-       msr     cpsr_c, r2                      @ Restore interrupts
-       cpwait_ret lr, ip
-
-/*
- * Unlock all I-TLB entries
- */
-       .align  5
-ENTRY(xscale_itlb_unlock)
-       mcr     p15, 0, ip, c10, c4, 1          @ Unlock I-TLB
-       mcr     p15, 0, ip, c8, c5, 0           @ Invalidate I-TLB
-       cpwait_ret lr, ip
-
-/*
- * Unlock all D-TLB entries
- */
-ENTRY(xscale_dtlb_unlock)
-       mcr     p15, 0, ip, c10, c8, 1          @ Unlock D-TBL
-       mcr     p15, 0, ip, c8, c6, 0           @ Invalidate D-TLB
-       cpwait_ret lr, ip
-
 /* =============================== PageTable ============================== */
 
 #define PTE_CACHE_WRITE_ALLOCATE 0
index 7ffd8cb..c51d138 100644 (file)
@@ -40,17 +40,17 @@ float64 float64_arccos(float64 rFm);
 float64 float64_pow(float64 rFn, float64 rFm);
 float64 float64_pol(float64 rFn, float64 rFm);
 
-static float64 float64_rsf(float64 rFn, float64 rFm)
+static float64 float64_rsf(struct roundingData *roundData, float64 rFn, float64 rFm)
 {
-       return float64_sub(rFm, rFn);
+       return float64_sub(roundData, rFm, rFn);
 }
 
-static float64 float64_rdv(float64 rFn, float64 rFm)
+static float64 float64_rdv(struct roundingData *roundData, float64 rFn, float64 rFm)
 {
-       return float64_div(rFm, rFn);
+       return float64_div(roundData, rFm, rFn);
 }
 
-static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = {
+static float64 (*const dyadic_double[16])(struct roundingData*, float64 rFn, float64 rFm) = {
        [ADF_CODE >> 20] = float64_add,
        [MUF_CODE >> 20] = float64_mul,
        [SUF_CODE >> 20] = float64_sub,
@@ -65,12 +65,12 @@ static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = {
        [FRD_CODE >> 20] = float64_rdv,
 };
 
-static float64 float64_mvf(float64 rFm)
+static float64 float64_mvf(struct roundingData *roundData,float64 rFm)
 {
        return rFm;
 }
 
-static float64 float64_mnf(float64 rFm)
+static float64 float64_mnf(struct roundingData *roundData,float64 rFm)
 {
        union float64_components u;
 
@@ -84,7 +84,7 @@ static float64 float64_mnf(float64 rFm)
        return u.f64;
 }
 
-static float64 float64_abs(float64 rFm)
+static float64 float64_abs(struct roundingData *roundData,float64 rFm)
 {
        union float64_components u;
 
@@ -98,7 +98,7 @@ static float64 float64_abs(float64 rFm)
        return u.f64;
 }
 
-static float64 (*const monadic_double[16])(float64 rFm) = {
+static float64 (*const monadic_double[16])(struct roundingData *, float64 rFm) = {
        [MVF_CODE >> 20] = float64_mvf,
        [MNF_CODE >> 20] = float64_mnf,
        [ABS_CODE >> 20] = float64_abs,
@@ -108,7 +108,7 @@ static float64 (*const monadic_double[16])(float64 rFm) = {
        [NRM_CODE >> 20] = float64_mvf,
 };
 
-unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd)
+unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
 {
        FPA11 *fpa11 = GET_FPA11();
        float64 rFm;
@@ -151,13 +151,13 @@ unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd)
                }
 
                if (dyadic_double[opc_mask_shift]) {
-                       rFd->fDouble = dyadic_double[opc_mask_shift](rFn, rFm);
+                       rFd->fDouble = dyadic_double[opc_mask_shift](roundData, rFn, rFm);
                } else {
                        return 0;
                }
        } else {
                if (monadic_double[opc_mask_shift]) {
-                       rFd->fDouble = monadic_double[opc_mask_shift](rFm);
+                       rFd->fDouble = monadic_double[opc_mask_shift](roundData, rFm);
                } else {
                        return 0;
                }
index c39f68a..65a279b 100644 (file)
@@ -35,17 +35,17 @@ floatx80 floatx80_arccos(floatx80 rFm);
 floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm);
 floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm);
 
-static floatx80 floatx80_rsf(floatx80 rFn, floatx80 rFm)
+static floatx80 floatx80_rsf(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
 {
-       return floatx80_sub(rFm, rFn);
+       return floatx80_sub(roundData, rFm, rFn);
 }
 
-static floatx80 floatx80_rdv(floatx80 rFn, floatx80 rFm)
+static floatx80 floatx80_rdv(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
 {
-       return floatx80_div(rFm, rFn);
+       return floatx80_div(roundData, rFm, rFn);
 }
 
-static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = {
+static floatx80 (*const dyadic_extended[16])(struct roundingData*, floatx80 rFn, floatx80 rFm) = {
        [ADF_CODE >> 20] = floatx80_add,
        [MUF_CODE >> 20] = floatx80_mul,
        [SUF_CODE >> 20] = floatx80_sub,
@@ -60,24 +60,24 @@ static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = {
        [FRD_CODE >> 20] = floatx80_rdv,
 };
 
-static floatx80 floatx80_mvf(floatx80 rFm)
+static floatx80 floatx80_mvf(struct roundingData *roundData, floatx80 rFm)
 {
        return rFm;
 }
 
-static floatx80 floatx80_mnf(floatx80 rFm)
+static floatx80 floatx80_mnf(struct roundingData *roundData, floatx80 rFm)
 {
        rFm.high ^= 0x8000;
        return rFm;
 }
 
-static floatx80 floatx80_abs(floatx80 rFm)
+static floatx80 floatx80_abs(struct roundingData *roundData, floatx80 rFm)
 {
        rFm.high &= 0x7fff;
        return rFm;
 }
 
-static floatx80 (*const monadic_extended[16])(floatx80 rFm) = {
+static floatx80 (*const monadic_extended[16])(struct roundingData*, floatx80 rFm) = {
        [MVF_CODE >> 20] = floatx80_mvf,
        [MNF_CODE >> 20] = floatx80_mnf,
        [ABS_CODE >> 20] = floatx80_abs,
@@ -87,7 +87,7 @@ static floatx80 (*const monadic_extended[16])(floatx80 rFm) = {
        [NRM_CODE >> 20] = floatx80_mvf,
 };
 
-unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd)
+unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
 {
        FPA11 *fpa11 = GET_FPA11();
        floatx80 rFm;
@@ -138,13 +138,13 @@ unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd)
                }
 
                if (dyadic_extended[opc_mask_shift]) {
-                       rFd->fExtended = dyadic_extended[opc_mask_shift](rFn, rFm);
+                       rFd->fExtended = dyadic_extended[opc_mask_shift](roundData, rFn, rFm);
                } else {
                        return 0;
                }
        } else {
                if (monadic_extended[opc_mask_shift]) {
-                       rFd->fExtended = monadic_extended[opc_mask_shift](rFm);
+                       rFd->fExtended = monadic_extended[opc_mask_shift](roundData, rFm);
                } else {
                        return 0;
                }
index bf61696..7690f73 100644 (file)
@@ -51,48 +51,42 @@ static void resetFPA11(void)
        fpa11->fpsr = FP_EMULATOR | BIT_AC;
 }
 
-void SetRoundingMode(const unsigned int opcode)
+int8 SetRoundingMode(const unsigned int opcode)
 {
        switch (opcode & MASK_ROUNDING_MODE) {
        default:
        case ROUND_TO_NEAREST:
-               float_rounding_mode = float_round_nearest_even;
-               break;
+               return float_round_nearest_even;
 
        case ROUND_TO_PLUS_INFINITY:
-               float_rounding_mode = float_round_up;
-               break;
+               return float_round_up;
 
        case ROUND_TO_MINUS_INFINITY:
-               float_rounding_mode = float_round_down;
-               break;
+               return float_round_down;
 
        case ROUND_TO_ZERO:
-               float_rounding_mode = float_round_to_zero;
-               break;
+               return float_round_to_zero;
        }
 }
 
-void SetRoundingPrecision(const unsigned int opcode)
+int8 SetRoundingPrecision(const unsigned int opcode)
 {
 #ifdef CONFIG_FPE_NWFPE_XP
        switch (opcode & MASK_ROUNDING_PRECISION) {
        case ROUND_SINGLE:
-               floatx80_rounding_precision = 32;
-               break;
+               return 32;
 
        case ROUND_DOUBLE:
-               floatx80_rounding_precision = 64;
-               break;
+               return 64;
 
        case ROUND_EXTENDED:
-               floatx80_rounding_precision = 80;
-               break;
+               return 80;
 
        default:
-               floatx80_rounding_precision = 80;
+               return 80;
        }
 #endif
+       return 80;
 }
 
 void nwfpe_init_fpa(union fp_state *fp)
@@ -103,8 +97,6 @@ void nwfpe_init_fpa(union fp_state *fp)
 #endif
        memset(fpa11, 0, sizeof(FPA11));
        resetFPA11();
-       SetRoundingMode(ROUND_TO_NEAREST);
-       SetRoundingPrecision(ROUND_EXTENDED);
        fpa11->initflag = 1;
 }
 
index e4a61ae..93523ae 100644 (file)
 /* includes */
 #include "fpsr.h"              /* FP control and status register definitions */
 #include "milieu.h"
+
+struct roundingData {
+    int8 mode;
+    int8 precision;
+    signed char exception;
+};
+
 #include "softfloat.h"
 
 #define                typeNone                0x00
@@ -84,8 +91,8 @@ typedef struct tagFPA11 {
                                   initialised. */
 } FPA11;
 
-extern void SetRoundingMode(const unsigned int);
-extern void SetRoundingPrecision(const unsigned int);
+extern int8 SetRoundingMode(const unsigned int);
+extern int8 SetRoundingPrecision(const unsigned int);
 extern void nwfpe_init_fpa(union fp_state *fp);
 
 #endif
index 1bea674..4a31dfd 100644 (file)
 #include "fpa11.h"
 #include "fpopcode.h"
 
-unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd);
-unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd);
-unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd);
+unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
+unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
+unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
 
 unsigned int EmulateCPDO(const unsigned int opcode)
 {
        FPA11 *fpa11 = GET_FPA11();
        FPREG *rFd;
        unsigned int nType, nDest, nRc;
+       struct roundingData roundData;
 
        /* Get the destination size.  If not valid let Linux perform
           an invalid instruction trap. */
@@ -40,7 +41,9 @@ unsigned int EmulateCPDO(const unsigned int opcode)
        if (typeNone == nDest)
                return 0;
 
-       SetRoundingMode(opcode);
+       roundData.mode = SetRoundingMode(opcode);
+       roundData.precision = SetRoundingPrecision(opcode);
+       roundData.exception = 0;
 
        /* Compare the size of the operands in Fn and Fm.
           Choose the largest size and perform operations in that size,
@@ -63,14 +66,14 @@ unsigned int EmulateCPDO(const unsigned int opcode)
 
        switch (nType) {
        case typeSingle:
-               nRc = SingleCPDO(opcode, rFd);
+               nRc = SingleCPDO(&roundData, opcode, rFd);
                break;
        case typeDouble:
-               nRc = DoubleCPDO(opcode, rFd);
+               nRc = DoubleCPDO(&roundData, opcode, rFd);
                break;
 #ifdef CONFIG_FPE_NWFPE_XP
        case typeExtended:
-               nRc = ExtendedCPDO(opcode, rFd);
+               nRc = ExtendedCPDO(&roundData, opcode, rFd);
                break;
 #endif
        default:
@@ -93,9 +96,9 @@ unsigned int EmulateCPDO(const unsigned int opcode)
                        case typeSingle:
                                {
                                        if (typeDouble == nType)
-                                               rFd->fSingle = float64_to_float32(rFd->fDouble);
+                                               rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
                                        else
-                                               rFd->fSingle = floatx80_to_float32(rFd->fExtended);
+                                               rFd->fSingle = floatx80_to_float32(&roundData, rFd->fExtended);
                                }
                                break;
 
@@ -104,7 +107,7 @@ unsigned int EmulateCPDO(const unsigned int opcode)
                                        if (typeSingle == nType)
                                                rFd->fDouble = float32_to_float64(rFd->fSingle);
                                        else
-                                               rFd->fDouble = floatx80_to_float64(rFd->fExtended);
+                                               rFd->fDouble = floatx80_to_float64(&roundData, rFd->fExtended);
                                }
                                break;
 
@@ -121,12 +124,15 @@ unsigned int EmulateCPDO(const unsigned int opcode)
 #else
                if (nDest != nType) {
                        if (nDest == typeSingle)
-                               rFd->fSingle = float64_to_float32(rFd->fDouble);
+                               rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
                        else
                                rFd->fDouble = float32_to_float64(rFd->fSingle);
                }
 #endif
        }
 
+       if (roundData.exception)
+               float_raise(roundData.exception);
+
        return nRc;
 }
index 95fb63f..b0db5cb 100644 (file)
@@ -96,7 +96,7 @@ static inline void loadMultiple(const unsigned int Fn, const unsigned int __user
        }
 }
 
-static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem)
+static inline void storeSingle(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
 {
        FPA11 *fpa11 = GET_FPA11();
        union {
@@ -106,12 +106,12 @@ static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem)
 
        switch (fpa11->fType[Fn]) {
        case typeDouble:
-               val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble);
+               val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble);
                break;
 
 #ifdef CONFIG_FPE_NWFPE_XP
        case typeExtended:
-               val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);
+               val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended);
                break;
 #endif
 
@@ -122,7 +122,7 @@ static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem)
        put_user(val.i[0], pMem);
 }
 
-static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem)
+static inline void storeDouble(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
 {
        FPA11 *fpa11 = GET_FPA11();
        union {
@@ -137,7 +137,7 @@ static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem)
 
 #ifdef CONFIG_FPE_NWFPE_XP
        case typeExtended:
-               val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);
+               val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended);
                break;
 #endif
 
@@ -259,8 +259,11 @@ unsigned int PerformSTF(const unsigned int opcode)
 {
        unsigned int __user *pBase, *pAddress, *pFinal;
        unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
+       struct roundingData roundData;
 
-       SetRoundingMode(ROUND_TO_NEAREST);
+       roundData.mode = SetRoundingMode(opcode);
+       roundData.precision = SetRoundingPrecision(opcode);
+       roundData.exception = 0;
 
        pBase = (unsigned int __user *) readRegister(getRn(opcode));
        if (REG_PC == getRn(opcode)) {
@@ -281,10 +284,10 @@ unsigned int PerformSTF(const unsigned int opcode)
 
        switch (opcode & MASK_TRANSFER_LENGTH) {
        case TRANSFER_SINGLE:
-               storeSingle(getFd(opcode), pAddress);
+               storeSingle(&roundData, getFd(opcode), pAddress);
                break;
        case TRANSFER_DOUBLE:
-               storeDouble(getFd(opcode), pAddress);
+               storeDouble(&roundData, getFd(opcode), pAddress);
                break;
 #ifdef CONFIG_FPE_NWFPE_XP
        case TRANSFER_EXTENDED:
@@ -295,6 +298,9 @@ unsigned int PerformSTF(const unsigned int opcode)
                nRc = 0;
        }
 
+       if (roundData.exception)
+               float_raise(roundData.exception);
+
        if (write_back)
                writeRegister(getRn(opcode), (unsigned long) pFinal);
        return nRc;
index db01fbc..adf8d30 100644 (file)
@@ -33,8 +33,6 @@ extern flag floatx80_is_nan(floatx80);
 extern flag float64_is_nan(float64);
 extern flag float32_is_nan(float32);
 
-void SetRoundingMode(const unsigned int opcode);
-
 unsigned int PerformFLT(const unsigned int opcode);
 unsigned int PerformFIX(const unsigned int opcode);
 
@@ -77,14 +75,17 @@ unsigned int EmulateCPRT(const unsigned int opcode)
 unsigned int PerformFLT(const unsigned int opcode)
 {
        FPA11 *fpa11 = GET_FPA11();
-       SetRoundingMode(opcode);
-       SetRoundingPrecision(opcode);
+       struct roundingData roundData;
+
+       roundData.mode = SetRoundingMode(opcode);
+       roundData.precision = SetRoundingPrecision(opcode);
+       roundData.exception = 0;
 
        switch (opcode & MASK_ROUNDING_PRECISION) {
        case ROUND_SINGLE:
                {
                        fpa11->fType[getFn(opcode)] = typeSingle;
-                       fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(readRegister(getRd(opcode)));
+                       fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(&roundData, readRegister(getRd(opcode)));
                }
                break;
 
@@ -108,6 +109,9 @@ unsigned int PerformFLT(const unsigned int opcode)
                return 0;
        }
 
+       if (roundData.exception)
+               float_raise(roundData.exception);
+
        return 1;
 }
 
@@ -115,26 +119,29 @@ unsigned int PerformFIX(const unsigned int opcode)
 {
        FPA11 *fpa11 = GET_FPA11();
        unsigned int Fn = getFm(opcode);
+       struct roundingData roundData;
 
-       SetRoundingMode(opcode);
+       roundData.mode = SetRoundingMode(opcode);
+       roundData.precision = SetRoundingPrecision(opcode);
+       roundData.exception = 0;
 
        switch (fpa11->fType[Fn]) {
        case typeSingle:
                {
-                       writeRegister(getRd(opcode), float32_to_int32(fpa11->fpreg[Fn].fSingle));
+                       writeRegister(getRd(opcode), float32_to_int32(&roundData, fpa11->fpreg[Fn].fSingle));
                }
                break;
 
        case typeDouble:
                {
-                       writeRegister(getRd(opcode), float64_to_int32(fpa11->fpreg[Fn].fDouble));
+                       writeRegister(getRd(opcode), float64_to_int32(&roundData, fpa11->fpreg[Fn].fDouble));
                }
                break;
 
 #ifdef CONFIG_FPE_NWFPE_XP
        case typeExtended:
                {
-                       writeRegister(getRd(opcode), floatx80_to_int32(fpa11->fpreg[Fn].fExtended));
+                       writeRegister(getRd(opcode), floatx80_to_int32(&roundData, fpa11->fpreg[Fn].fExtended));
                }
                break;
 #endif
@@ -143,6 +150,9 @@ unsigned int PerformFIX(const unsigned int opcode)
                return 0;
        }
 
+       if (roundData.exception)
+               float_raise(roundData.exception);
+
        return 1;
 }
 
index 12885f3..2dfe1ac 100644 (file)
@@ -116,8 +116,6 @@ fpmodule.c to integrate with the NetBSD kernel (I hope!).
 code to access data in user space in some other source files at the 
 moment (grep for get_user / put_user calls).  --philb]
 
-float_exception_flags is a global variable in SoftFloat.
-
 This function is called by the SoftFloat routines to raise a floating
 point exception.  We check the trap enable byte in the FPSR, and raise
 a SIGFPE exception if necessary.  If not the relevant bits in the 
@@ -129,15 +127,14 @@ void float_raise(signed char flags)
        register unsigned int fpsr, cumulativeTraps;
 
 #ifdef CONFIG_DEBUG_USER
-       printk(KERN_DEBUG
-              "NWFPE: %s[%d] takes exception %08x at %p from %08lx\n",
-              current->comm, current->pid, flags,
-              __builtin_return_address(0), GET_USERREG()->ARM_pc);
+       /* Ignore inexact errors as there are far too many of them to log */
+       if (flags & ~BIT_IXC)
+               printk(KERN_DEBUG
+                      "NWFPE: %s[%d] takes exception %08x at %p from %08lx\n",
+                      current->comm, current->pid, flags,
+                      __builtin_return_address(0), GET_USERREG()->ARM_pc);
 #endif
 
-       /* Keep SoftFloat exception flags up to date.  */
-       float_exception_flags |= flags;
-
        /* Read fpsr and initialize the cumulativeTraps.  */
        fpsr = readFPSR();
        cumulativeTraps = 0;
index 8035f4f..1777e92 100644 (file)
@@ -370,20 +370,20 @@ TABLE 5
 #define getRoundingMode(opcode)                ((opcode & MASK_ROUNDING_MODE) >> 5)
 
 #ifdef CONFIG_FPE_NWFPE_XP
-static inline const floatx80 getExtendedConstant(const unsigned int nIndex)
+static inline __attribute_pure__ floatx80 getExtendedConstant(const unsigned int nIndex)
 {
        extern const floatx80 floatx80Constant[];
        return floatx80Constant[nIndex];
 }
 #endif
 
-static inline const float64 getDoubleConstant(const unsigned int nIndex)
+static inline __attribute_pure__ float64 getDoubleConstant(const unsigned int nIndex)
 {
        extern const float64 float64Constant[];
        return float64Constant[nIndex];
 }
 
-static inline const float32 getSingleConstant(const unsigned int nIndex)
+static inline __attribute_pure__ float32 getSingleConstant(const unsigned int nIndex)
 {
        extern const float32 float32Constant[];
        return float32Constant[nIndex];
index 705808e..c66981d 100644 (file)
@@ -36,17 +36,17 @@ float32 float32_arccos(float32 rFm);
 float32 float32_pow(float32 rFn, float32 rFm);
 float32 float32_pol(float32 rFn, float32 rFm);
 
-static float32 float32_rsf(float32 rFn, float32 rFm)
+static float32 float32_rsf(struct roundingData *roundData, float32 rFn, float32 rFm)
 {
-       return float32_sub(rFm, rFn);
+       return float32_sub(roundData, rFm, rFn);
 }
 
-static float32 float32_rdv(float32 rFn, float32 rFm)
+static float32 float32_rdv(struct roundingData *roundData, float32 rFn, float32 rFm)
 {
-       return float32_div(rFm, rFn);
+       return float32_div(roundData, rFm, rFn);
 }
 
-static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = {
+static float32 (*const dyadic_single[16])(struct roundingData *, float32 rFn, float32 rFm) = {
        [ADF_CODE >> 20] = float32_add,
        [MUF_CODE >> 20] = float32_mul,
        [SUF_CODE >> 20] = float32_sub,
@@ -60,22 +60,22 @@ static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = {
        [FRD_CODE >> 20] = float32_rdv,
 };
 
-static float32 float32_mvf(float32 rFm)
+static float32 float32_mvf(struct roundingData *roundData, float32 rFm)
 {
        return rFm;
 }
 
-static float32 float32_mnf(float32 rFm)
+static float32 float32_mnf(struct roundingData *roundData, float32 rFm)
 {
        return rFm ^ 0x80000000;
 }
 
-static float32 float32_abs(float32 rFm)
+static float32 float32_abs(struct roundingData *roundData, float32 rFm)
 {
        return rFm & 0x7fffffff;
 }
 
-static float32 (*const monadic_single[16])(float32 rFm) = {
+static float32 (*const monadic_single[16])(struct roundingData*, float32 rFm) = {
        [MVF_CODE >> 20] = float32_mvf,
        [MNF_CODE >> 20] = float32_mnf,
        [ABS_CODE >> 20] = float32_abs,
@@ -85,7 +85,7 @@ static float32 (*const monadic_single[16])(float32 rFm) = {
        [NRM_CODE >> 20] = float32_mvf,
 };
 
-unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd)
+unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
 {
        FPA11 *fpa11 = GET_FPA11();
        float32 rFm;
@@ -108,13 +108,13 @@ unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd)
                if (fpa11->fType[Fn] == typeSingle &&
                    dyadic_single[opc_mask_shift]) {
                        rFn = fpa11->fpreg[Fn].fSingle;
-                       rFd->fSingle = dyadic_single[opc_mask_shift](rFn, rFm);
+                       rFd->fSingle = dyadic_single[opc_mask_shift](roundData, rFn, rFm);
                } else {
                        return 0;
                }
        } else {
                if (monadic_single[opc_mask_shift]) {
-                       rFd->fSingle = monadic_single[opc_mask_shift](rFm);
+                       rFd->fSingle = monadic_single[opc_mask_shift](roundData, rFm);
                } else {
                        return 0;
                }
index e038dd3..f9f0491 100644 (file)
@@ -34,16 +34,6 @@ this code that are retained.
 //#include "milieu.h"
 //#include "softfloat.h"
 
-/*
--------------------------------------------------------------------------------
-Floating-point rounding mode, extended double-precision rounding precision,
-and exception flags.
--------------------------------------------------------------------------------
-*/
-int8 float_rounding_mode = float_round_nearest_even;
-int8 floatx80_rounding_precision = 80;
-int8 float_exception_flags;
-
 /*
 -------------------------------------------------------------------------------
 Primitive arithmetic functions, including multi-word arithmetic, and
@@ -77,14 +67,14 @@ input is too large, however, the invalid exception is raised and the largest
 positive or negative integer is returned.
 -------------------------------------------------------------------------------
 */
-static int32 roundAndPackInt32( flag zSign, bits64 absZ )
+static int32 roundAndPackInt32( struct roundingData *roundData, flag zSign, bits64 absZ )
 {
     int8 roundingMode;
     flag roundNearestEven;
     int8 roundIncrement, roundBits;
     int32 z;
 
-    roundingMode = float_rounding_mode;
+    roundingMode = roundData->mode;
     roundNearestEven = ( roundingMode == float_round_nearest_even );
     roundIncrement = 0x40;
     if ( ! roundNearestEven ) {
@@ -107,10 +97,10 @@ static int32 roundAndPackInt32( flag zSign, bits64 absZ )
     z = absZ;
     if ( zSign ) z = - z;
     if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) {
-        float_exception_flags |= float_flag_invalid;
+        roundData->exception |= float_flag_invalid;
         return zSign ? 0x80000000 : 0x7FFFFFFF;
     }
-    if ( roundBits ) float_exception_flags |= float_flag_inexact;
+    if ( roundBits ) roundData->exception |= float_flag_inexact;
     return z;
 
 }
@@ -224,14 +214,14 @@ The handling of underflow and overflow follows the IEC/IEEE Standard for
 Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
+static float32 roundAndPackFloat32( struct roundingData *roundData, flag zSign, int16 zExp, bits32 zSig )
 {
     int8 roundingMode;
     flag roundNearestEven;
     int8 roundIncrement, roundBits;
     flag isTiny;
 
-    roundingMode = float_rounding_mode;
+    roundingMode = roundData->mode;
     roundNearestEven = ( roundingMode == float_round_nearest_even );
     roundIncrement = 0x40;
     if ( ! roundNearestEven ) {
@@ -254,7 +244,7 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
              || (    ( zExp == 0xFD )
                   && ( (sbits32) ( zSig + roundIncrement ) < 0 ) )
            ) {
-            float_raise( float_flag_overflow | float_flag_inexact );
+            roundData->exception |= float_flag_overflow | float_flag_inexact;
             return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 );
         }
         if ( zExp < 0 ) {
@@ -265,10 +255,10 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
             shift32RightJamming( zSig, - zExp, &zSig );
             zExp = 0;
             roundBits = zSig & 0x7F;
-            if ( isTiny && roundBits ) float_raise( float_flag_underflow );
+            if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow;
         }
     }
-    if ( roundBits ) float_exception_flags |= float_flag_inexact;
+    if ( roundBits ) roundData->exception |= float_flag_inexact;
     zSig = ( zSig + roundIncrement )>>7;
     zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
     if ( zSig == 0 ) zExp = 0;
@@ -287,12 +277,12 @@ point exponent.
 -------------------------------------------------------------------------------
 */
 static float32
- normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
+ normalizeRoundAndPackFloat32( struct roundingData *roundData, flag zSign, int16 zExp, bits32 zSig )
 {
     int8 shiftCount;
 
     shiftCount = countLeadingZeros32( zSig ) - 1;
-    return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<<shiftCount );
+    return roundAndPackFloat32( roundData, zSign, zExp - shiftCount, zSig<<shiftCount );
 
 }
 
@@ -395,14 +385,14 @@ The handling of underflow and overflow follows the IEC/IEEE Standard for
 Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
+static float64 roundAndPackFloat64( struct roundingData *roundData, flag zSign, int16 zExp, bits64 zSig )
 {
     int8 roundingMode;
     flag roundNearestEven;
     int16 roundIncrement, roundBits;
     flag isTiny;
 
-    roundingMode = float_rounding_mode;
+    roundingMode = roundData->mode;
     roundNearestEven = ( roundingMode == float_round_nearest_even );
     roundIncrement = 0x200;
     if ( ! roundNearestEven ) {
@@ -427,7 +417,7 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
            ) {
             //register int lr = __builtin_return_address(0);
             //printk("roundAndPackFloat64 called from 0x%08x\n",lr);
-            float_raise( float_flag_overflow | float_flag_inexact );
+            roundData->exception |= float_flag_overflow | float_flag_inexact;
             return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 );
         }
         if ( zExp < 0 ) {
@@ -438,10 +428,10 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
             shift64RightJamming( zSig, - zExp, &zSig );
             zExp = 0;
             roundBits = zSig & 0x3FF;
-            if ( isTiny && roundBits ) float_raise( float_flag_underflow );
+            if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow;
         }
     }
-    if ( roundBits ) float_exception_flags |= float_flag_inexact;
+    if ( roundBits ) roundData->exception |= float_flag_inexact;
     zSig = ( zSig + roundIncrement )>>10;
     zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven );
     if ( zSig == 0 ) zExp = 0;
@@ -460,12 +450,12 @@ point exponent.
 -------------------------------------------------------------------------------
 */
 static float64
- normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
+ normalizeRoundAndPackFloat64( struct roundingData *roundData, flag zSign, int16 zExp, bits64 zSig )
 {
     int8 shiftCount;
 
     shiftCount = countLeadingZeros64( zSig ) - 1;
-    return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<<shiftCount );
+    return roundAndPackFloat64( roundData, zSign, zExp - shiftCount, zSig<<shiftCount );
 
 }
 
@@ -572,14 +562,15 @@ Floating-point Arithmetic.
 */
 static floatx80
  roundAndPackFloatx80(
-     int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
+     struct roundingData *roundData, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
  )
 {
-    int8 roundingMode;
+    int8 roundingMode, roundingPrecision;
     flag roundNearestEven, increment, isTiny;
     int64 roundIncrement, roundMask, roundBits;
 
-    roundingMode = float_rounding_mode;
+    roundingMode = roundData->mode;
+    roundingPrecision = roundData->precision;
     roundNearestEven = ( roundingMode == float_round_nearest_even );
     if ( roundingPrecision == 80 ) goto precision80;
     if ( roundingPrecision == 64 ) {
@@ -623,8 +614,8 @@ static floatx80
             shift64RightJamming( zSig0, 1 - zExp, &zSig0 );
             zExp = 0;
             roundBits = zSig0 & roundMask;
-            if ( isTiny && roundBits ) float_raise( float_flag_underflow );
-            if ( roundBits ) float_exception_flags |= float_flag_inexact;
+            if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow;
+            if ( roundBits ) roundData->exception |= float_flag_inexact;
             zSig0 += roundIncrement;
             if ( (sbits64) zSig0 < 0 ) zExp = 1;
             roundIncrement = roundMask + 1;
@@ -635,7 +626,7 @@ static floatx80
             return packFloatx80( zSign, zExp, zSig0 );
         }
     }
-    if ( roundBits ) float_exception_flags |= float_flag_inexact;
+    if ( roundBits ) roundData->exception |= float_flag_inexact;
     zSig0 += roundIncrement;
     if ( zSig0 < roundIncrement ) {
         ++zExp;
@@ -672,7 +663,7 @@ static floatx80
            ) {
             roundMask = 0;
  overflow:
-            float_raise( float_flag_overflow | float_flag_inexact );
+            roundData->exception |= float_flag_overflow | float_flag_inexact;
             if (    ( roundingMode == float_round_to_zero )
                  || ( zSign && ( roundingMode == float_round_up ) )
                  || ( ! zSign && ( roundingMode == float_round_down ) )
@@ -689,8 +680,8 @@ static floatx80
                 || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) );
             shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 );
             zExp = 0;
-            if ( isTiny && zSig1 ) float_raise( float_flag_underflow );
-            if ( zSig1 ) float_exception_flags |= float_flag_inexact;
+            if ( isTiny && zSig1 ) roundData->exception |= float_flag_underflow;
+            if ( zSig1 ) roundData->exception |= float_flag_inexact;
             if ( roundNearestEven ) {
                 increment = ( (sbits64) zSig1 < 0 );
             }
@@ -710,7 +701,7 @@ static floatx80
             return packFloatx80( zSign, zExp, zSig0 );
         }
     }
-    if ( zSig1 ) float_exception_flags |= float_flag_inexact;
+    if ( zSig1 ) roundData->exception |= float_flag_inexact;
     if ( increment ) {
         ++zSig0;
         if ( zSig0 == 0 ) {
@@ -740,7 +731,7 @@ normalized.
 */
 static floatx80
  normalizeRoundAndPackFloatx80(
-     int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
+     struct roundingData *roundData, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
  )
 {
     int8 shiftCount;
@@ -754,7 +745,7 @@ static floatx80
     shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
     zExp -= shiftCount;
     return
-        roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 );
+        roundAndPackFloatx80( roundData, zSign, zExp, zSig0, zSig1 );
 
 }
 
@@ -767,14 +758,14 @@ the single-precision floating-point format.  The conversion is performed
 according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-float32 int32_to_float32( int32 a )
+float32 int32_to_float32(struct roundingData *roundData, int32 a)
 {
     flag zSign;
 
     if ( a == 0 ) return 0;
     if ( a == 0x80000000 ) return packFloat32( 1, 0x9E, 0 );
     zSign = ( a < 0 );
-    return normalizeRoundAndPackFloat32( zSign, 0x9C, zSign ? - a : a );
+    return normalizeRoundAndPackFloat32( roundData, zSign, 0x9C, zSign ? - a : a );
 
 }
 
@@ -840,7 +831,7 @@ positive integer is returned.  Otherwise, if the conversion overflows, the
 largest integer with the same sign as `a' is returned.
 -------------------------------------------------------------------------------
 */
-int32 float32_to_int32( float32 a )
+int32 float32_to_int32( struct roundingData *roundData, float32 a )
 {
     flag aSign;
     int16 aExp, shiftCount;
@@ -856,7 +847,7 @@ int32 float32_to_int32( float32 a )
     zSig = aSig;
     zSig <<= 32;
     if ( 0 < shiftCount ) shift64RightJamming( zSig, shiftCount, &zSig );
-    return roundAndPackInt32( aSign, zSig );
+    return roundAndPackInt32( roundData, aSign, zSig );
 
 }
 
@@ -889,13 +880,13 @@ int32 float32_to_int32_round_to_zero( float32 a )
         return 0x80000000;
     }
     else if ( aExp <= 0x7E ) {
-        if ( aExp | aSig ) float_exception_flags |= float_flag_inexact;
+        if ( aExp | aSig ) float_raise( float_flag_inexact );
         return 0;
     }
     aSig = ( aSig | 0x00800000 )<<8;
     z = aSig>>( - shiftCount );
     if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) {
-        float_exception_flags |= float_flag_inexact;
+        float_raise( float_flag_inexact );
     }
     return aSign ? - z : z;
 
@@ -973,7 +964,7 @@ operation is performed according to the IEC/IEEE Standard for Binary
 Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-float32 float32_round_to_int( float32 a )
+float32 float32_round_to_int( struct roundingData *roundData, float32 a )
 {
     flag aSign;
     int16 aExp;
@@ -988,11 +979,12 @@ float32 float32_round_to_int( float32 a )
         }
         return a;
     }
+    roundingMode = roundData->mode;
     if ( aExp <= 0x7E ) {
         if ( (bits32) ( a<<1 ) == 0 ) return a;
-        float_exception_flags |= float_flag_inexact;
+        roundData->exception |= float_flag_inexact;
         aSign = extractFloat32Sign( a );
-        switch ( float_rounding_mode ) {
+        switch ( roundingMode ) {
          case float_round_nearest_even:
             if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) {
                 return packFloat32( aSign, 0x7F, 0 );
@@ -1009,7 +1001,6 @@ float32 float32_round_to_int( float32 a )
     lastBitMask <<= 0x96 - aExp;
     roundBitsMask = lastBitMask - 1;
     z = a;
-    roundingMode = float_rounding_mode;
     if ( roundingMode == float_round_nearest_even ) {
         z += lastBitMask>>1;
         if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
@@ -1020,7 +1011,7 @@ float32 float32_round_to_int( float32 a )
         }
     }
     z &= ~ roundBitsMask;
-    if ( z != a ) float_exception_flags |= float_flag_inexact;
+    if ( z != a ) roundData->exception |= float_flag_inexact;
     return z;
 
 }
@@ -1034,7 +1025,7 @@ addition is performed according to the IEC/IEEE Standard for Binary
 Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-static float32 addFloat32Sigs( float32 a, float32 b, flag zSign )
+static float32 addFloat32Sigs( struct roundingData *roundData, float32 a, float32 b, flag zSign )
 {
     int16 aExp, bExp, zExp;
     bits32 aSig, bSig, zSig;
@@ -1093,7 +1084,7 @@ static float32 addFloat32Sigs( float32 a, float32 b, flag zSign )
         ++zExp;
     }
  roundAndPack:
-    return roundAndPackFloat32( zSign, zExp, zSig );
+    return roundAndPackFloat32( roundData, zSign, zExp, zSig );
 
 }
 
@@ -1106,7 +1097,7 @@ result is a NaN.  The subtraction is performed according to the IEC/IEEE
 Standard for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-static float32 subFloat32Sigs( float32 a, float32 b, flag zSign )
+static float32 subFloat32Sigs( struct roundingData *roundData, float32 a, float32 b, flag zSign )
 {
     int16 aExp, bExp, zExp;
     bits32 aSig, bSig, zSig;
@@ -1123,7 +1114,7 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign )
     if ( expDiff < 0 ) goto bExpBigger;
     if ( aExp == 0xFF ) {
         if ( aSig | bSig ) return propagateFloat32NaN( a, b );
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return float32_default_nan;
     }
     if ( aExp == 0 ) {
@@ -1132,7 +1123,7 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign )
     }
     if ( bSig < aSig ) goto aBigger;
     if ( aSig < bSig ) goto bBigger;
-    return packFloat32( float_rounding_mode == float_round_down, 0, 0 );
+    return packFloat32( roundData->mode == float_round_down, 0, 0 );
  bExpBigger:
     if ( bExp == 0xFF ) {
         if ( bSig ) return propagateFloat32NaN( a, b );
@@ -1169,7 +1160,7 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign )
     zExp = aExp;
  normalizeRoundAndPack:
     --zExp;
-    return normalizeRoundAndPackFloat32( zSign, zExp, zSig );
+    return normalizeRoundAndPackFloat32( roundData, zSign, zExp, zSig );
 
 }
 
@@ -1180,17 +1171,17 @@ and `b'.  The operation is performed according to the IEC/IEEE Standard for
 Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-float32 float32_add( float32 a, float32 b )
+float32 float32_add( struct roundingData *roundData, float32 a, float32 b )
 {
     flag aSign, bSign;
 
     aSign = extractFloat32Sign( a );
     bSign = extractFloat32Sign( b );
     if ( aSign == bSign ) {
-        return addFloat32Sigs( a, b, aSign );
+        return addFloat32Sigs( roundData, a, b, aSign );
     }
     else {
-        return subFloat32Sigs( a, b, aSign );
+        return subFloat32Sigs( roundData, a, b, aSign );
     }
 
 }
@@ -1202,17 +1193,17 @@ Returns the result of subtracting the single-precision floating-point values
 for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-float32 float32_sub( float32 a, float32 b )
+float32 float32_sub( struct roundingData *roundData, float32 a, float32 b )
 {
     flag aSign, bSign;
 
     aSign = extractFloat32Sign( a );
     bSign = extractFloat32Sign( b );
     if ( aSign == bSign ) {
-        return subFloat32Sigs( a, b, aSign );
+        return subFloat32Sigs( roundData, a, b, aSign );
     }
     else {
-        return addFloat32Sigs( a, b, aSign );
+        return addFloat32Sigs( roundData, a, b, aSign );
     }
 
 }
@@ -1224,7 +1215,7 @@ Returns the result of multiplying the single-precision floating-point values
 for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-float32 float32_mul( float32 a, float32 b )
+float32 float32_mul( struct roundingData *roundData, float32 a, float32 b )
 {
     flag aSign, bSign, zSign;
     int16 aExp, bExp, zExp;
@@ -1244,7 +1235,7 @@ float32 float32_mul( float32 a, float32 b )
             return propagateFloat32NaN( a, b );
         }
         if ( ( bExp | bSig ) == 0 ) {
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             return float32_default_nan;
         }
         return packFloat32( zSign, 0xFF, 0 );
@@ -1252,7 +1243,7 @@ float32 float32_mul( float32 a, float32 b )
     if ( bExp == 0xFF ) {
         if ( bSig ) return propagateFloat32NaN( a, b );
         if ( ( aExp | aSig ) == 0 ) {
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             return float32_default_nan;
         }
         return packFloat32( zSign, 0xFF, 0 );
@@ -1274,7 +1265,7 @@ float32 float32_mul( float32 a, float32 b )
         zSig <<= 1;
         --zExp;
     }
-    return roundAndPackFloat32( zSign, zExp, zSig );
+    return roundAndPackFloat32( roundData, zSign, zExp, zSig );
 
 }
 
@@ -1285,7 +1276,7 @@ by the corresponding value `b'.  The operation is performed according to the
 IEC/IEEE Standard for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-float32 float32_div( float32 a, float32 b )
+float32 float32_div( struct roundingData *roundData, float32 a, float32 b )
 {
     flag aSign, bSign, zSign;
     int16 aExp, bExp, zExp;
@@ -1302,7 +1293,7 @@ float32 float32_div( float32 a, float32 b )
         if ( aSig ) return propagateFloat32NaN( a, b );
         if ( bExp == 0xFF ) {
             if ( bSig ) return propagateFloat32NaN( a, b );
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             return float32_default_nan;
         }
         return packFloat32( zSign, 0xFF, 0 );
@@ -1314,10 +1305,10 @@ float32 float32_div( float32 a, float32 b )
     if ( bExp == 0 ) {
         if ( bSig == 0 ) {
             if ( ( aExp | aSig ) == 0 ) {
-                float_raise( float_flag_invalid );
+                roundData->exception |= float_flag_invalid;
                 return float32_default_nan;
             }
-            float_raise( float_flag_divbyzero );
+            roundData->exception |= float_flag_divbyzero;
             return packFloat32( zSign, 0xFF, 0 );
         }
         normalizeFloat32Subnormal( bSig, &bExp, &bSig );
@@ -1341,7 +1332,7 @@ float32 float32_div( float32 a, float32 b )
     if ( ( zSig & 0x3F ) == 0 ) {
         zSig |= ( ( (bits64) bSig ) * zSig != ( (bits64) aSig )<<32 );
     }
-    return roundAndPackFloat32( zSign, zExp, zSig );
+    return roundAndPackFloat32( roundData, zSign, zExp, zSig );
 
 }
 
@@ -1352,7 +1343,7 @@ with respect to the corresponding value `b'.  The operation is performed
 according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-float32 float32_rem( float32 a, float32 b )
+float32 float32_rem( struct roundingData *roundData, float32 a, float32 b )
 {
     flag aSign, bSign, zSign;
     int16 aExp, bExp, expDiff;
@@ -1372,7 +1363,7 @@ float32 float32_rem( float32 a, float32 b )
         if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
             return propagateFloat32NaN( a, b );
         }
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return float32_default_nan;
     }
     if ( bExp == 0xFF ) {
@@ -1381,7 +1372,7 @@ float32 float32_rem( float32 a, float32 b )
     }
     if ( bExp == 0 ) {
         if ( bSig == 0 ) {
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             return float32_default_nan;
         }
         normalizeFloat32Subnormal( bSig, &bExp, &bSig );
@@ -1444,7 +1435,7 @@ float32 float32_rem( float32 a, float32 b )
     }
     zSign = ( (sbits32) aSig < 0 );
     if ( zSign ) aSig = - aSig;
-    return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig );
+    return normalizeRoundAndPackFloat32( roundData, aSign ^ zSign, bExp, aSig );
 
 }
 
@@ -1455,7 +1446,7 @@ The operation is performed according to the IEC/IEEE Standard for Binary
 Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-float32 float32_sqrt( float32 a )
+float32 float32_sqrt( struct roundingData *roundData, float32 a )
 {
     flag aSign;
     int16 aExp, zExp;
@@ -1468,12 +1459,12 @@ float32 float32_sqrt( float32 a )
     if ( aExp == 0xFF ) {
         if ( aSig ) return propagateFloat32NaN( a, 0 );
         if ( ! aSign ) return a;
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return float32_default_nan;
     }
     if ( aSign ) {
         if ( ( aExp | aSig ) == 0 ) return a;
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return float32_default_nan;
     }
     if ( aExp == 0 ) {
@@ -1499,7 +1490,7 @@ float32 float32_sqrt( float32 a )
         }
     }
     shift32RightJamming( zSig, 1, &zSig );
-    return roundAndPackFloat32( 0, zExp, zSig );
+    return roundAndPackFloat32( roundData, 0, zExp, zSig );
 
 }
 
@@ -1611,9 +1602,7 @@ flag float32_le_quiet( float32 a, float32 b )
     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
        ) {
-        if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid );
-        }
+        /* Do nothing, even if NaN as we're quiet */
         return 0;
     }
     aSign = extractFloat32Sign( a );
@@ -1638,9 +1627,7 @@ flag float32_lt_quiet( float32 a, float32 b )
     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
        ) {
-        if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid );
-        }
+        /* Do nothing, even if NaN as we're quiet */
         return 0;
     }
     aSign = extractFloat32Sign( a );
@@ -1661,7 +1648,7 @@ positive integer is returned.  Otherwise, if the conversion overflows, the
 largest integer with the same sign as `a' is returned.
 -------------------------------------------------------------------------------
 */
-int32 float64_to_int32( float64 a )
+int32 float64_to_int32( struct roundingData *roundData, float64 a )
 {
     flag aSign;
     int16 aExp, shiftCount;
@@ -1674,7 +1661,7 @@ int32 float64_to_int32( float64 a )
     if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
     shiftCount = 0x42C - aExp;
     if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig );
-    return roundAndPackInt32( aSign, aSig );
+    return roundAndPackInt32( roundData, aSign, aSig );
 
 }
 
@@ -1705,7 +1692,7 @@ int32 float64_to_int32_round_to_zero( float64 a )
         goto invalid;
     }
     else if ( 52 < shiftCount ) {
-        if ( aExp || aSig ) float_exception_flags |= float_flag_inexact;
+        if ( aExp || aSig ) float_raise( float_flag_inexact );
         return 0;
     }
     aSig |= LIT64( 0x0010000000000000 );
@@ -1715,11 +1702,11 @@ int32 float64_to_int32_round_to_zero( float64 a )
     if ( aSign ) z = - z;
     if ( ( z < 0 ) ^ aSign ) {
  invalid:
-        float_exception_flags |= float_flag_invalid;
+        float_raise( float_flag_invalid );
         return aSign ? 0x80000000 : 0x7FFFFFFF;
     }
     if ( ( aSig<<shiftCount ) != savedASig ) {
-        float_exception_flags |= float_flag_inexact;
+        float_raise( float_flag_inexact );
     }
     return z;
 
@@ -1736,7 +1723,7 @@ positive integer is returned.  Otherwise, if the conversion overflows, the
 largest positive integer is returned.
 -------------------------------------------------------------------------------
 */
-int32 float64_to_uint32( float64 a )
+int32 float64_to_uint32( struct roundingData *roundData, float64 a )
 {
     flag aSign;
     int16 aExp, shiftCount;
@@ -1749,7 +1736,7 @@ int32 float64_to_uint32( float64 a )
     if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
     shiftCount = 0x42C - aExp;
     if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig );
-    return roundAndPackInt32( aSign, aSig );
+    return roundAndPackInt32( roundData, aSign, aSig );
 }
 
 /*
@@ -1778,7 +1765,7 @@ int32 float64_to_uint32_round_to_zero( float64 a )
         goto invalid;
     }
     else if ( 52 < shiftCount ) {
-        if ( aExp || aSig ) float_exception_flags |= float_flag_inexact;
+        if ( aExp || aSig ) float_raise( float_flag_inexact );
         return 0;
     }
     aSig |= LIT64( 0x0010000000000000 );
@@ -1788,11 +1775,11 @@ int32 float64_to_uint32_round_to_zero( float64 a )
     if ( aSign ) z = - z;
     if ( ( z < 0 ) ^ aSign ) {
  invalid:
-        float_exception_flags |= float_flag_invalid;
+        float_raise( float_flag_invalid );
         return aSign ? 0x80000000 : 0x7FFFFFFF;
     }
     if ( ( aSig<<shiftCount ) != savedASig ) {
-        float_exception_flags |= float_flag_inexact;
+        float_raise( float_flag_inexact );
     }
     return z;
 }
@@ -1805,7 +1792,7 @@ performed according to the IEC/IEEE Standard for Binary Floating-point
 Arithmetic.
 -------------------------------------------------------------------------------
 */
-float32 float64_to_float32( float64 a )
+float32 float64_to_float32( struct roundingData *roundData, float64 a )
 {
     flag aSign;
     int16 aExp;
@@ -1825,7 +1812,7 @@ float32 float64_to_float32( float64 a )
         zSig |= 0x40000000;
         aExp -= 0x381;
     }
-    return roundAndPackFloat32( aSign, aExp, zSig );
+    return roundAndPackFloat32( roundData, aSign, aExp, zSig );
 
 }
 
@@ -1872,7 +1859,7 @@ operation is performed according to the IEC/IEEE Standard for Binary
 Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-float64 float64_round_to_int( float64 a )
+float64 float64_round_to_int( struct roundingData *roundData, float64 a )
 {
     flag aSign;
     int16 aExp;
@@ -1889,9 +1876,9 @@ float64 float64_round_to_int( float64 a )
     }
     if ( aExp <= 0x3FE ) {
         if ( (bits64) ( a<<1 ) == 0 ) return a;
-        float_exception_flags |= float_flag_inexact;
+        roundData->exception |= float_flag_inexact;
         aSign = extractFloat64Sign( a );
-        switch ( float_rounding_mode ) {
+        switch ( roundData->mode ) {
          case float_round_nearest_even:
             if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) {
                 return packFloat64( aSign, 0x3FF, 0 );
@@ -1909,7 +1896,7 @@ float64 float64_round_to_int( float64 a )
     lastBitMask <<= 0x433 - aExp;
     roundBitsMask = lastBitMask - 1;
     z = a;
-    roundingMode = float_rounding_mode;
+    roundingMode = roundData->mode;
     if ( roundingMode == float_round_nearest_even ) {
         z += lastBitMask>>1;
         if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
@@ -1920,7 +1907,7 @@ float64 float64_round_to_int( float64 a )
         }
     }
     z &= ~ roundBitsMask;
-    if ( z != a ) float_exception_flags |= float_flag_inexact;
+    if ( z != a ) roundData->exception |= float_flag_inexact;
     return z;
 
 }
@@ -1934,7 +1921,7 @@ addition is performed according to the IEC/IEEE Standard for Binary
 Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-static float64 addFloat64Sigs( float64 a, float64 b, flag zSign )
+static float64 addFloat64Sigs( struct roundingData *roundData, float64 a, float64 b, flag zSign )
 {
     int16 aExp, bExp, zExp;
     bits64 aSig, bSig, zSig;
@@ -1993,7 +1980,7 @@ static float64 addFloat64Sigs( float64 a, float64 b, flag zSign )
         ++zExp;
     }
  roundAndPack:
-    return roundAndPackFloat64( zSign, zExp, zSig );
+    return roundAndPackFloat64( roundData, zSign, zExp, zSig );
 
 }
 
@@ -2006,7 +1993,7 @@ result is a NaN.  The subtraction is performed according to the IEC/IEEE
 Standard for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-static float64 subFloat64Sigs( float64 a, float64 b, flag zSign )
+static float64 subFloat64Sigs( struct roundingData *roundData, float64 a, float64 b, flag zSign )
 {
     int16 aExp, bExp, zExp;
     bits64 aSig, bSig, zSig;
@@ -2023,7 +2010,7 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign )
     if ( expDiff < 0 ) goto bExpBigger;
     if ( aExp == 0x7FF ) {
         if ( aSig | bSig ) return propagateFloat64NaN( a, b );
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return float64_default_nan;
     }
     if ( aExp == 0 ) {
@@ -2032,7 +2019,7 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign )
     }
     if ( bSig < aSig ) goto aBigger;
     if ( aSig < bSig ) goto bBigger;
-    return packFloat64( float_rounding_mode == float_round_down, 0, 0 );
+    return packFloat64( roundData->mode == float_round_down, 0, 0 );
  bExpBigger:
     if ( bExp == 0x7FF ) {
         if ( bSig ) return propagateFloat64NaN( a, b );
@@ -2069,7 +2056,7 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign )
     zExp = aExp;
  normalizeRoundAndPack:
     --zExp;
-    return normalizeRoundAndPackFloat64( zSign, zExp, zSig );
+    return normalizeRoundAndPackFloat64( roundData, zSign, zExp, zSig );
 
 }
 
@@ -2080,17 +2067,17 @@ and `b'.  The operation is performed according to the IEC/IEEE Standard for
 Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-float64 float64_add( float64 a, float64 b )
+float64 float64_add( struct roundingData *roundData, float64 a, float64 b )
 {
     flag aSign, bSign;
 
     aSign = extractFloat64Sign( a );
     bSign = extractFloat64Sign( b );
     if ( aSign == bSign ) {
-        return addFloat64Sigs( a, b, aSign );
+        return addFloat64Sigs( roundData, a, b, aSign );
     }
     else {
-        return subFloat64Sigs( a, b, aSign );
+        return subFloat64Sigs( roundData, a, b, aSign );
     }
 
 }
@@ -2102,17 +2089,17 @@ Returns the result of subtracting the double-precision floating-point values
 for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-float64 float64_sub( float64 a, float64 b )
+float64 float64_sub( struct roundingData *roundData, float64 a, float64 b )
 {
     flag aSign, bSign;
 
     aSign = extractFloat64Sign( a );
     bSign = extractFloat64Sign( b );
     if ( aSign == bSign ) {
-        return subFloat64Sigs( a, b, aSign );
+        return subFloat64Sigs( roundData, a, b, aSign );
     }
     else {
-        return addFloat64Sigs( a, b, aSign );
+        return addFloat64Sigs( roundData, a, b, aSign );
     }
 
 }
@@ -2124,7 +2111,7 @@ Returns the result of multiplying the double-precision floating-point values
 for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-float64 float64_mul( float64 a, float64 b )
+float64 float64_mul( struct roundingData *roundData, float64 a, float64 b )
 {
     flag aSign, bSign, zSign;
     int16 aExp, bExp, zExp;
@@ -2142,7 +2129,7 @@ float64 float64_mul( float64 a, float64 b )
             return propagateFloat64NaN( a, b );
         }
         if ( ( bExp | bSig ) == 0 ) {
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             return float64_default_nan;
         }
         return packFloat64( zSign, 0x7FF, 0 );
@@ -2150,7 +2137,7 @@ float64 float64_mul( float64 a, float64 b )
     if ( bExp == 0x7FF ) {
         if ( bSig ) return propagateFloat64NaN( a, b );
         if ( ( aExp | aSig ) == 0 ) {
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             return float64_default_nan;
         }
         return packFloat64( zSign, 0x7FF, 0 );
@@ -2172,7 +2159,7 @@ float64 float64_mul( float64 a, float64 b )
         zSig0 <<= 1;
         --zExp;
     }
-    return roundAndPackFloat64( zSign, zExp, zSig0 );
+    return roundAndPackFloat64( roundData, zSign, zExp, zSig0 );
 
 }
 
@@ -2183,7 +2170,7 @@ by the corresponding value `b'.  The operation is performed according to
 the IEC/IEEE Standard for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-float64 float64_div( float64 a, float64 b )
+float64 float64_div( struct roundingData *roundData, float64 a, float64 b )
 {
     flag aSign, bSign, zSign;
     int16 aExp, bExp, zExp;
@@ -2202,7 +2189,7 @@ float64 float64_div( float64 a, float64 b )
         if ( aSig ) return propagateFloat64NaN( a, b );
         if ( bExp == 0x7FF ) {
             if ( bSig ) return propagateFloat64NaN( a, b );
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             return float64_default_nan;
         }
         return packFloat64( zSign, 0x7FF, 0 );
@@ -2214,10 +2201,10 @@ float64 float64_div( float64 a, float64 b )
     if ( bExp == 0 ) {
         if ( bSig == 0 ) {
             if ( ( aExp | aSig ) == 0 ) {
-                float_raise( float_flag_invalid );
+                roundData->exception |= float_flag_invalid;
                 return float64_default_nan;
             }
-            float_raise( float_flag_divbyzero );
+            roundData->exception |= float_flag_divbyzero;
             return packFloat64( zSign, 0x7FF, 0 );
         }
         normalizeFloat64Subnormal( bSig, &bExp, &bSig );
@@ -2243,7 +2230,7 @@ float64 float64_div( float64 a, float64 b )
         }
         zSig |= ( rem1 != 0 );
     }
-    return roundAndPackFloat64( zSign, zExp, zSig );
+    return roundAndPackFloat64( roundData, zSign, zExp, zSig );
 
 }
 
@@ -2254,7 +2241,7 @@ with respect to the corresponding value `b'.  The operation is performed
 according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-float64 float64_rem( float64 a, float64 b )
+float64 float64_rem( struct roundingData *roundData, float64 a, float64 b )
 {
     flag aSign, bSign, zSign;
     int16 aExp, bExp, expDiff;
@@ -2272,7 +2259,7 @@ float64 float64_rem( float64 a, float64 b )
         if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
             return propagateFloat64NaN( a, b );
         }
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return float64_default_nan;
     }
     if ( bExp == 0x7FF ) {
@@ -2281,7 +2268,7 @@ float64 float64_rem( float64 a, float64 b )
     }
     if ( bExp == 0 ) {
         if ( bSig == 0 ) {
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             return float64_default_nan;
         }
         normalizeFloat64Subnormal( bSig, &bExp, &bSig );
@@ -2329,7 +2316,7 @@ float64 float64_rem( float64 a, float64 b )
     }
     zSign = ( (sbits64) aSig < 0 );
     if ( zSign ) aSig = - aSig;
-    return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig );
+    return normalizeRoundAndPackFloat64( roundData, aSign ^ zSign, bExp, aSig );
 
 }
 
@@ -2340,7 +2327,7 @@ The operation is performed according to the IEC/IEEE Standard for Binary
 Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-float64 float64_sqrt( float64 a )
+float64 float64_sqrt( struct roundingData *roundData, float64 a )
 {
     flag aSign;
     int16 aExp, zExp;
@@ -2354,12 +2341,12 @@ float64 float64_sqrt( float64 a )
     if ( aExp == 0x7FF ) {
         if ( aSig ) return propagateFloat64NaN( a, a );
         if ( ! aSign ) return a;
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return float64_default_nan;
     }
     if ( aSign ) {
         if ( ( aExp | aSig ) == 0 ) return a;
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return float64_default_nan;
     }
     if ( aExp == 0 ) {
@@ -2390,7 +2377,7 @@ float64 float64_sqrt( float64 a )
         }
     }
     shift64RightJamming( zSig, 1, &zSig );
-    return roundAndPackFloat64( 0, zExp, zSig );
+    return roundAndPackFloat64( roundData, 0, zExp, zSig );
 
 }
 
@@ -2502,9 +2489,7 @@ flag float64_le_quiet( float64 a, float64 b )
     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
        ) {
-        if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid );
-        }
+        /* Do nothing, even if NaN as we're quiet */
         return 0;
     }
     aSign = extractFloat64Sign( a );
@@ -2529,9 +2514,7 @@ flag float64_lt_quiet( float64 a, float64 b )
     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
        ) {
-        if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid );
-        }
+        /* Do nothing, even if NaN as we're quiet */
         return 0;
     }
     aSign = extractFloat64Sign( a );
@@ -2554,7 +2537,7 @@ largest positive integer is returned.  Otherwise, if the conversion
 overflows, the largest integer with the same sign as `a' is returned.
 -------------------------------------------------------------------------------
 */
-int32 floatx80_to_int32( floatx80 a )
+int32 floatx80_to_int32( struct roundingData *roundData, floatx80 a )
 {
     flag aSign;
     int32 aExp, shiftCount;
@@ -2567,7 +2550,7 @@ int32 floatx80_to_int32( floatx80 a )
     shiftCount = 0x4037 - aExp;
     if ( shiftCount <= 0 ) shiftCount = 1;
     shift64RightJamming( aSig, shiftCount, &aSig );
-    return roundAndPackInt32( aSign, aSig );
+    return roundAndPackInt32( roundData, aSign, aSig );
 
 }
 
@@ -2598,7 +2581,7 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a )
         goto invalid;
     }
     else if ( 63 < shiftCount ) {
-        if ( aExp || aSig ) float_exception_flags |= float_flag_inexact;
+        if ( aExp || aSig ) float_raise( float_flag_inexact );
         return 0;
     }
     savedASig = aSig;
@@ -2607,11 +2590,11 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a )
     if ( aSign ) z = - z;
     if ( ( z < 0 ) ^ aSign ) {
  invalid:
-        float_exception_flags |= float_flag_invalid;
+        float_raise( float_flag_invalid );
         return aSign ? 0x80000000 : 0x7FFFFFFF;
     }
     if ( ( aSig<<shiftCount ) != savedASig ) {
-        float_exception_flags |= float_flag_inexact;
+        float_raise( float_flag_inexact );
     }
     return z;
 
@@ -2625,7 +2608,7 @@ conversion is performed according to the IEC/IEEE Standard for Binary
 Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-float32 floatx80_to_float32( floatx80 a )
+float32 floatx80_to_float32( struct roundingData *roundData, floatx80 a )
 {
     flag aSign;
     int32 aExp;
@@ -2642,7 +2625,7 @@ float32 floatx80_to_float32( floatx80 a )
     }
     shift64RightJamming( aSig, 33, &aSig );
     if ( aExp || aSig ) aExp -= 0x3F81;
-    return roundAndPackFloat32( aSign, aExp, aSig );
+    return roundAndPackFloat32( roundData, aSign, aExp, aSig );
 
 }
 
@@ -2654,7 +2637,7 @@ conversion is performed according to the IEC/IEEE Standard for Binary
 Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-float64 floatx80_to_float64( floatx80 a )
+float64 floatx80_to_float64( struct roundingData *roundData, floatx80 a )
 {
     flag aSign;
     int32 aExp;
@@ -2671,7 +2654,7 @@ float64 floatx80_to_float64( floatx80 a )
     }
     shift64RightJamming( aSig, 1, &zSig );
     if ( aExp || aSig ) aExp -= 0x3C01;
-    return roundAndPackFloat64( aSign, aExp, zSig );
+    return roundAndPackFloat64( roundData, aSign, aExp, zSig );
 
 }
 
@@ -2683,7 +2666,7 @@ value.  The operation is performed according to the IEC/IEEE Standard for
 Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-floatx80 floatx80_round_to_int( floatx80 a )
+floatx80 floatx80_round_to_int( struct roundingData *roundData, floatx80 a )
 {
     flag aSign;
     int32 aExp;
@@ -2703,9 +2686,9 @@ floatx80 floatx80_round_to_int( floatx80 a )
              && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) {
             return a;
         }
-        float_exception_flags |= float_flag_inexact;
+        roundData->exception |= float_flag_inexact;
         aSign = extractFloatx80Sign( a );
-        switch ( float_rounding_mode ) {
+        switch ( roundData->mode ) {
          case float_round_nearest_even:
             if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 )
                ) {
@@ -2729,7 +2712,7 @@ floatx80 floatx80_round_to_int( floatx80 a )
     lastBitMask <<= 0x403E - aExp;
     roundBitsMask = lastBitMask - 1;
     z = a;
-    roundingMode = float_rounding_mode;
+    roundingMode = roundData->mode;
     if ( roundingMode == float_round_nearest_even ) {
         z.low += lastBitMask>>1;
         if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
@@ -2744,7 +2727,7 @@ floatx80 floatx80_round_to_int( floatx80 a )
         ++z.high;
         z.low = LIT64( 0x8000000000000000 );
     }
-    if ( z.low != a.low ) float_exception_flags |= float_flag_inexact;
+    if ( z.low != a.low ) roundData->exception |= float_flag_inexact;
     return z;
 
 }
@@ -2758,7 +2741,7 @@ The addition is performed according to the IEC/IEEE Standard for Binary
 Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
+static floatx80 addFloatx80Sigs( struct roundingData *roundData, floatx80 a, floatx80 b, flag zSign )
 {
     int32 aExp, bExp, zExp;
     bits64 aSig, bSig, zSig0, zSig1;
@@ -2814,7 +2797,7 @@ static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
  roundAndPack:
     return
         roundAndPackFloatx80(
-            floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
+            roundData, zSign, zExp, zSig0, zSig1 );
 
 }
 
@@ -2827,7 +2810,7 @@ result is a NaN.  The subtraction is performed according to the IEC/IEEE
 Standard for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
+static floatx80 subFloatx80Sigs( struct roundingData *roundData, floatx80 a, floatx80 b, flag zSign )
 {
     int32 aExp, bExp, zExp;
     bits64 aSig, bSig, zSig0, zSig1;
@@ -2845,7 +2828,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
         if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
             return propagateFloatx80NaN( a, b );
         }
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         z.low = floatx80_default_nan_low;
         z.high = floatx80_default_nan_high;
         return z;
@@ -2857,7 +2840,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
     zSig1 = 0;
     if ( bSig < aSig ) goto aBigger;
     if ( aSig < bSig ) goto bBigger;
-    return packFloatx80( float_rounding_mode == float_round_down, 0, 0 );
+    return packFloatx80( roundData->mode == float_round_down, 0, 0 );
  bExpBigger:
     if ( bExp == 0x7FFF ) {
         if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
@@ -2883,7 +2866,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
  normalizeRoundAndPack:
     return
         normalizeRoundAndPackFloatx80(
-            floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
+            roundData, zSign, zExp, zSig0, zSig1 );
 
 }
 
@@ -2894,17 +2877,17 @@ values `a' and `b'.  The operation is performed according to the IEC/IEEE
 Standard for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-floatx80 floatx80_add( floatx80 a, floatx80 b )
+floatx80 floatx80_add( struct roundingData *roundData, floatx80 a, floatx80 b )
 {
     flag aSign, bSign;
     
     aSign = extractFloatx80Sign( a );
     bSign = extractFloatx80Sign( b );
     if ( aSign == bSign ) {
-        return addFloatx80Sigs( a, b, aSign );
+        return addFloatx80Sigs( roundData, a, b, aSign );
     }
     else {
-        return subFloatx80Sigs( a, b, aSign );
+        return subFloatx80Sigs( roundData, a, b, aSign );
     }
     
 }
@@ -2916,17 +2899,17 @@ point values `a' and `b'.  The operation is performed according to the
 IEC/IEEE Standard for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-floatx80 floatx80_sub( floatx80 a, floatx80 b )
+floatx80 floatx80_sub( struct roundingData *roundData, floatx80 a, floatx80 b )
 {
     flag aSign, bSign;
 
     aSign = extractFloatx80Sign( a );
     bSign = extractFloatx80Sign( b );
     if ( aSign == bSign ) {
-        return subFloatx80Sigs( a, b, aSign );
+        return subFloatx80Sigs( roundData, a, b, aSign );
     }
     else {
-        return addFloatx80Sigs( a, b, aSign );
+        return addFloatx80Sigs( roundData, a, b, aSign );
     }
 
 }
@@ -2938,7 +2921,7 @@ point values `a' and `b'.  The operation is performed according to the
 IEC/IEEE Standard for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-floatx80 floatx80_mul( floatx80 a, floatx80 b )
+floatx80 floatx80_mul( struct roundingData *roundData, floatx80 a, floatx80 b )
 {
     flag aSign, bSign, zSign;
     int32 aExp, bExp, zExp;
@@ -2964,7 +2947,7 @@ floatx80 floatx80_mul( floatx80 a, floatx80 b )
         if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
         if ( ( aExp | aSig ) == 0 ) {
  invalid:
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             z.low = floatx80_default_nan_low;
             z.high = floatx80_default_nan_high;
             return z;
@@ -2987,7 +2970,7 @@ floatx80 floatx80_mul( floatx80 a, floatx80 b )
     }
     return
         roundAndPackFloatx80(
-            floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
+            roundData, zSign, zExp, zSig0, zSig1 );
 
 }
 
@@ -2998,7 +2981,7 @@ value `a' by the corresponding value `b'.  The operation is performed
 according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-floatx80 floatx80_div( floatx80 a, floatx80 b )
+floatx80 floatx80_div( struct roundingData *roundData, floatx80 a, floatx80 b )
 {
     flag aSign, bSign, zSign;
     int32 aExp, bExp, zExp;
@@ -3029,12 +3012,12 @@ floatx80 floatx80_div( floatx80 a, floatx80 b )
         if ( bSig == 0 ) {
             if ( ( aExp | aSig ) == 0 ) {
  invalid:
-                float_raise( float_flag_invalid );
+                roundData->exception |= float_flag_invalid;
                 z.low = floatx80_default_nan_low;
                 z.high = floatx80_default_nan_high;
                 return z;
             }
-            float_raise( float_flag_divbyzero );
+            roundData->exception |= float_flag_divbyzero;
             return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
         }
         normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
@@ -3068,7 +3051,7 @@ floatx80 floatx80_div( floatx80 a, floatx80 b )
     }
     return
         roundAndPackFloatx80(
-            floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
+            roundData, zSign, zExp, zSig0, zSig1 );
 
 }
 
@@ -3079,7 +3062,7 @@ Returns the remainder of the extended double-precision floating-point value
 according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-floatx80 floatx80_rem( floatx80 a, floatx80 b )
+floatx80 floatx80_rem( struct roundingData *roundData, floatx80 a, floatx80 b )
 {
     flag aSign, bSign, zSign;
     int32 aExp, bExp, expDiff;
@@ -3107,7 +3090,7 @@ floatx80 floatx80_rem( floatx80 a, floatx80 b )
     if ( bExp == 0 ) {
         if ( bSig == 0 ) {
  invalid:
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             z.low = floatx80_default_nan_low;
             z.high = floatx80_default_nan_high;
             return z;
@@ -3164,9 +3147,10 @@ floatx80 floatx80_rem( floatx80 a, floatx80 b )
         aSig1 = alternateASig1;
         zSign = ! zSign;
     }
+
     return
         normalizeRoundAndPackFloatx80(
-            80, zSign, bExp + expDiff, aSig0, aSig1 );
+            roundData, zSign, bExp + expDiff, aSig0, aSig1 );
 
 }
 
@@ -3177,7 +3161,7 @@ value `a'.  The operation is performed according to the IEC/IEEE Standard
 for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 */
-floatx80 floatx80_sqrt( floatx80 a )
+floatx80 floatx80_sqrt( struct roundingData *roundData, floatx80 a )
 {
     flag aSign;
     int32 aExp, zExp;
@@ -3197,7 +3181,7 @@ floatx80 floatx80_sqrt( floatx80 a )
     if ( aSign ) {
         if ( ( aExp | aSig0 ) == 0 ) return a;
  invalid:
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         z.low = floatx80_default_nan_low;
         z.high = floatx80_default_nan_high;
         return z;
@@ -3242,7 +3226,7 @@ floatx80 floatx80_sqrt( floatx80 a )
     }
     return
         roundAndPackFloatx80(
-            floatx80_rounding_precision, 0, zExp, zSig0, zSig1 );
+            roundData, 0, zExp, zSig0, zSig1 );
 
 }
 
@@ -3390,10 +3374,7 @@ flag floatx80_le_quiet( floatx80 a, floatx80 b )
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
               && (bits64) ( extractFloatx80Frac( b )<<1 ) )
        ) {
-        if (    floatx80_is_signaling_nan( a )
-             || floatx80_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid );
-        }
+        /* Do nothing, even if NaN as we're quiet */
         return 0;
     }
     aSign = extractFloatx80Sign( a );
@@ -3427,10 +3408,7 @@ flag floatx80_lt_quiet( floatx80 a, floatx80 b )
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
               && (bits64) ( extractFloatx80Frac( b )<<1 ) )
        ) {
-        if (    floatx80_is_signaling_nan( a )
-             || floatx80_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid );
-        }
+        /* Do nothing, even if NaN as we're quiet */
         return 0;
     }
     aSign = extractFloatx80Sign( a );
index 1e17431..1c8799b 100644 (file)
@@ -74,7 +74,7 @@ enum {
 Software IEC/IEEE floating-point rounding mode.
 -------------------------------------------------------------------------------
 */
-extern signed char float_rounding_mode;
+//extern int8 float_rounding_mode;
 enum {
     float_round_nearest_even = 0,
     float_round_to_zero      = 1,
@@ -86,7 +86,6 @@ enum {
 -------------------------------------------------------------------------------
 Software IEC/IEEE floating-point exception flags.
 -------------------------------------------------------------------------------
-extern signed char float_exception_flags;
 enum {
     float_flag_inexact   =  1,
     float_flag_underflow =  2,
@@ -99,7 +98,6 @@ ScottB: November 4, 1998
 Changed the enumeration to match the bit order in the FPA11.
 */
 
-extern signed char float_exception_flags;
 enum {
     float_flag_invalid   =  1,
     float_flag_divbyzero =  2,
@@ -121,7 +119,7 @@ void float_raise( signed char );
 Software IEC/IEEE integer-to-floating-point conversion routines.
 -------------------------------------------------------------------------------
 */
-float32 int32_to_float32( signed int );
+float32 int32_to_float32( struct roundingData *, signed int );
 float64 int32_to_float64( signed int );
 #ifdef FLOATX80
 floatx80 int32_to_floatx80( signed int );
@@ -132,7 +130,7 @@ floatx80 int32_to_floatx80( signed int );
 Software IEC/IEEE single-precision conversion routines.
 -------------------------------------------------------------------------------
 */
-signed int float32_to_int32( float32 );
+signed int float32_to_int32( struct roundingData *, float32 );
 signed int float32_to_int32_round_to_zero( float32 );
 float64 float32_to_float64( float32 );
 #ifdef FLOATX80
@@ -144,13 +142,13 @@ floatx80 float32_to_floatx80( float32 );
 Software IEC/IEEE single-precision operations.
 -------------------------------------------------------------------------------
 */
-float32 float32_round_to_int( float32 );
-float32 float32_add( float32, float32 );
-float32 float32_sub( float32, float32 );
-float32 float32_mul( float32, float32 );
-float32 float32_div( float32, float32 );
-float32 float32_rem( float32, float32 );
-float32 float32_sqrt( float32 );
+float32 float32_round_to_int( struct roundingData*, float32 );
+float32 float32_add( struct roundingData *, float32, float32 );
+float32 float32_sub( struct roundingData *, float32, float32 );
+float32 float32_mul( struct roundingData *, float32, float32 );
+float32 float32_div( struct roundingData *, float32, float32 );
+float32 float32_rem( struct roundingData *, float32, float32 );
+float32 float32_sqrt( struct roundingData*, float32 );
 char float32_eq( float32, float32 );
 char float32_le( float32, float32 );
 char float32_lt( float32, float32 );
@@ -164,9 +162,9 @@ char float32_is_signaling_nan( float32 );
 Software IEC/IEEE double-precision conversion routines.
 -------------------------------------------------------------------------------
 */
-signed int float64_to_int32( float64 );
+signed int float64_to_int32( struct roundingData *, float64 );
 signed int float64_to_int32_round_to_zero( float64 );
-float32 float64_to_float32( float64 );
+float32 float64_to_float32( struct roundingData *, float64 );
 #ifdef FLOATX80
 floatx80 float64_to_floatx80( float64 );
 #endif
@@ -176,13 +174,13 @@ floatx80 float64_to_floatx80( float64 );
 Software IEC/IEEE double-precision operations.
 -------------------------------------------------------------------------------
 */
-float64 float64_round_to_int( float64 );
-float64 float64_add( float64, float64 );
-float64 float64_sub( float64, float64 );
-float64 float64_mul( float64, float64 );
-float64 float64_div( float64, float64 );
-float64 float64_rem( float64, float64 );
-float64 float64_sqrt( float64 );
+float64 float64_round_to_int( struct roundingData *, float64 );
+float64 float64_add( struct roundingData *, float64, float64 );
+float64 float64_sub( struct roundingData *, float64, float64 );
+float64 float64_mul( struct roundingData *, float64, float64 );
+float64 float64_div( struct roundingData *, float64, float64 );
+float64 float64_rem( struct roundingData *, float64, float64 );
+float64 float64_sqrt( struct roundingData *, float64 );
 char float64_eq( float64, float64 );
 char float64_le( float64, float64 );
 char float64_lt( float64, float64 );
@@ -198,31 +196,23 @@ char float64_is_signaling_nan( float64 );
 Software IEC/IEEE extended double-precision conversion routines.
 -------------------------------------------------------------------------------
 */
-signed int floatx80_to_int32( floatx80 );
+signed int floatx80_to_int32( struct roundingData *, floatx80 );
 signed int floatx80_to_int32_round_to_zero( floatx80 );
-float32 floatx80_to_float32( floatx80 );
-float64 floatx80_to_float64( floatx80 );
-
-/*
--------------------------------------------------------------------------------
-Software IEC/IEEE extended double-precision rounding precision.  Valid
-values are 32, 64, and 80.
--------------------------------------------------------------------------------
-*/
-extern signed char floatx80_rounding_precision;
+float32 floatx80_to_float32( struct roundingData *, floatx80 );
+float64 floatx80_to_float64( struct roundingData *, floatx80 );
 
 /*
 -------------------------------------------------------------------------------
 Software IEC/IEEE extended double-precision operations.
 -------------------------------------------------------------------------------
 */
-floatx80 floatx80_round_to_int( floatx80 );
-floatx80 floatx80_add( floatx80, floatx80 );
-floatx80 floatx80_sub( floatx80, floatx80 );
-floatx80 floatx80_mul( floatx80, floatx80 );
-floatx80 floatx80_div( floatx80, floatx80 );
-floatx80 floatx80_rem( floatx80, floatx80 );
-floatx80 floatx80_sqrt( floatx80 );
+floatx80 floatx80_round_to_int( struct roundingData *, floatx80 );
+floatx80 floatx80_add( struct roundingData *, floatx80, floatx80 );
+floatx80 floatx80_sub( struct roundingData *, floatx80, floatx80 );
+floatx80 floatx80_mul( struct roundingData *, floatx80, floatx80 );
+floatx80 floatx80_div( struct roundingData *, floatx80, floatx80 );
+floatx80 floatx80_rem( struct roundingData *, floatx80, floatx80 );
+floatx80 floatx80_sqrt( struct roundingData *, floatx80 );
 char floatx80_eq( floatx80, floatx80 );
 char floatx80_le( floatx80, floatx80 );
 char floatx80_lt( floatx80, floatx80 );
index ec58d3e..df35c45 100644 (file)
@@ -115,7 +115,7 @@ static int valid_kernel_stack(struct frame_tail *tail, struct pt_regs *regs)
        return (tailaddr > stack) && (tailaddr < stack_base);
 }
 
-void arm_backtrace(struct pt_regs const *regs, unsigned int depth)
+void arm_backtrace(struct pt_regs * const regs, unsigned int depth)
 {
        struct frame_tail *tail;
        unsigned long last_address = 0;
index b801cd6..9b367a6 100644 (file)
@@ -770,6 +770,9 @@ vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,
                if ((s64)m_sig < 0) {
                        vdd->sign = vfp_sign_negate(vdd->sign);
                        m_sig = -m_sig;
+               } else if (m_sig == 0) {
+                       vdd->sign = (fpscr & FPSCR_RMODE_MASK) ==
+                                     FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
                }
        } else {
                m_sig += vdn->significand;
index 356d980..ce2055b 100644 (file)
@@ -454,14 +454,13 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
                if (ka->sa.sa_flags & SA_ONESHOT)
                        ka->sa.sa_handler = SIG_DFL;
 
-               if (!(ka->sa.sa_flags & SA_NODEFER)) {
-                       spin_lock_irq(&tsk->sighand->siglock);
-                       sigorsets(&tsk->blocked, &tsk->blocked,
-                                 &ka->sa.sa_mask);
+               spin_lock_irq(&tsk->sighand->siglock);
+               sigorsets(&tsk->blocked, &tsk->blocked,
+                         &ka->sa.sa_mask);
+               if (!(ka->sa.sa_flags & SA_NODEFER))
                        sigaddset(&tsk->blocked, sig);
-                       recalc_sigpending();
-                       spin_unlock_irq(&tsk->sighand->siglock);
-               }
+               recalc_sigpending();
+               spin_unlock_irq(&tsk->sighand->siglock);
                return;
        }
 
index dacca8b..bd6f2db 100644 (file)
@@ -176,12 +176,12 @@ survive:
         * Handle the "normal" cases first - successful and sigbus
         */
        switch (fault) {
-       case 2:
+       case VM_FAULT_MAJOR:
                tsk->maj_flt++;
                return fault;
-       case 1:
+       case VM_FAULT_MINOR:
                tsk->min_flt++;
-       case 0:
+       case VM_FAULT_SIGBUS:
                return fault;
        }
 
@@ -226,14 +226,11 @@ int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        /*
         * Handle the "normal" case first
         */
-       if (fault > 0)
+       switch (fault) {
+       case VM_FAULT_MINOR:
+       case VM_FAULT_MAJOR:
                return 0;
-
-       /*
-        * We had some memory, but were unable to
-        * successfully fix up this page fault.
-        */
-       if (fault == 0){
+       case VM_FAULT_SIGBUS:
                goto do_sigbus;
        }
 
index 85e0032..6937719 100644 (file)
@@ -517,13 +517,12 @@ handle_signal(int canrestart, unsigned long sig,
        if (ka->sa.sa_flags & SA_ONESHOT)
                ka->sa.sa_handler = SIG_DFL;
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 }
 
 /*
index fb4c79d..0a3614d 100644 (file)
@@ -568,13 +568,12 @@ handle_signal(int canrestart, unsigned long sig,
        if (ka->sa.sa_flags & SA_ONESHOT)
                ka->sa.sa_handler = SIG_DFL;
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 }
 
 /*
index fe1cc36..934c510 100644 (file)
@@ -284,13 +284,13 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
         */
 
        switch (handle_mm_fault(mm, vma, address, writeaccess & 1)) {
-       case 1:
+       case VM_FAULT_MINOR:
                tsk->min_flt++;
                break;
-       case 2:
+       case VM_FAULT_MAJOR:
                tsk->maj_flt++;
                break;
-       case 0:
+       case VM_FAULT_SIGBUS:
                goto do_sigbus;
        default:
                goto out_of_memory;
index 36a2dff..d4ccc07 100644 (file)
@@ -506,13 +506,12 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
        else
                setup_frame(sig, ka, oldset, regs);
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked, sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 } /* end handle_signal() */
 
 /*****************************************************************************/
index 41d02ac..8b3eb50 100644 (file)
@@ -163,13 +163,13 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
         * the fault.
         */
        switch (handle_mm_fault(mm, vma, ear0, write)) {
-       case 1:
+       case VM_FAULT_MINOR:
                current->min_flt++;
                break;
-       case 2:
+       case VM_FAULT_MAJOR:
                current->maj_flt++;
                break;
-       case 0:
+       case VM_FAULT_SIGBUS:
                goto do_sigbus;
        default:
                goto out_of_memory;
index 5aab87e..f13d5e8 100644 (file)
@@ -488,13 +488,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
        else
                setup_frame(sig, ka, oldset, regs);
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 }
 
 /*
index a801d9d..619d843 100644 (file)
@@ -454,8 +454,9 @@ config HPET_TIMER
          Choose N to continue using the legacy 8254 timer.
 
 config HPET_EMULATE_RTC
-       bool "Provide RTC interrupt"
+       bool
        depends on HPET_TIMER && RTC=y
+       default y
 
 config SMP
        bool "Symmetric multi-processing support"
index bd1dbf3..a22a866 100644 (file)
@@ -726,15 +726,11 @@ __setup("apic=", apic_set_verbosity);
 static int __init detect_init_APIC (void)
 {
        u32 h, l, features;
-       extern void get_cpu_vendor(struct cpuinfo_x86*);
 
        /* Disabled by kernel option? */
        if (enable_local_apic < 0)
                return -1;
 
-       /* Workaround for us being called before identify_cpu(). */
-       get_cpu_vendor(&boot_cpu_data);
-
        switch (boot_cpu_data.x86_vendor) {
        case X86_VENDOR_AMD:
                if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||
index 963e17a..60a9e54 100644 (file)
@@ -442,6 +442,13 @@ acpi_cpufreq_cpu_init (
                        (u32) data->acpi_data.states[i].transition_latency);
 
        cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
+       
+       /*
+        * the first call to ->target() should result in us actually
+        * writing something to the appropriate registers.
+        */
+       data->resume = 1;
+       
        return (result);
 
  err_freqfree:
index f57e5ee..fc42638 100644 (file)
@@ -76,6 +76,12 @@ static void __init init_transmeta(struct cpuinfo_x86 *c)
 #define USER686 (X86_FEATURE_TSC|X86_FEATURE_CX8|X86_FEATURE_CMOV)
         if ( c->x86 == 5 && (c->x86_capability[0] & USER686) == USER686 )
                c->x86 = 6;
+
+#ifdef CONFIG_SYSCTL
+       /* randomize_va_space slows us down enormously;
+          it probably triggers retranslation of x86->native bytecode */
+       randomize_va_space = 0;
+#endif
 }
 
 static void transmeta_identify(struct cpuinfo_x86 * c)
index da6c46d..8c242bb 100644 (file)
@@ -195,7 +195,7 @@ static void disable_lapic_nmi_watchdog(void)
                        wrmsr(MSR_P6_EVNTSEL0, 0, 0);
                        break;
                case 15:
-                       if (boot_cpu_data.x86_model > 0x3)
+                       if (boot_cpu_data.x86_model > 0x4)
                                break;
 
                        wrmsr(MSR_P4_IQ_CCCR0, 0, 0);
@@ -432,7 +432,7 @@ void setup_apic_nmi_watchdog (void)
                        setup_p6_watchdog();
                        break;
                case 15:
-                       if (boot_cpu_data.x86_model > 0x3)
+                       if (boot_cpu_data.x86_model > 0x4)
                                return;
 
                        if (!setup_p4_watchdog())
index 89ef7ad..140e340 100644 (file)
@@ -577,10 +577,11 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
        else
                ret = setup_frame(sig, ka, oldset, regs);
 
-       if (ret && !(ka->sa.sa_flags & SA_NODEFER)) {
+       if (ret) {
                spin_lock_irq(&current->sighand->siglock);
                sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-               sigaddset(&current->blocked,sig);
+               if (!(ka->sa.sa_flags & SA_NODEFER))
+                       sigaddset(&current->blocked,sig);
                recalc_sigpending();
                spin_unlock_irq(&current->sighand->siglock);
        }
index 468500a..9b21a31 100644 (file)
@@ -251,7 +251,7 @@ ENTRY(sys_call_table)
        .long sys_io_submit
        .long sys_io_cancel
        .long sys_fadvise64     /* 250 */
-       .long sys_set_zone_reclaim
+       .long sys_ni_syscall
        .long sys_exit_group
        .long sys_lookup_dcookie
        .long sys_epoll_create
index a61f33d..cd2d5d5 100644 (file)
@@ -803,15 +803,17 @@ void math_error(void __user *eip)
         */
        cwd = get_fpu_cwd(task);
        swd = get_fpu_swd(task);
-       switch (((~cwd) & swd & 0x3f) | (swd & 0x240)) {
+       switch (swd & ~cwd & 0x3f) {
                case 0x000:
                default:
                        break;
                case 0x001: /* Invalid Op */
-               case 0x041: /* Stack Fault */
-               case 0x241: /* Stack Fault | Direction */
+                       /*
+                        * swd & 0x240 == 0x040: Stack Underflow
+                        * swd & 0x240 == 0x240: Stack Overflow
+                        * User must clear the SF bit (0x40) if set
+                        */
                        info.si_code = FPE_FLTINV;
-                       /* Should we clear the SF or let user space do it ???? */
                        break;
                case 0x002: /* Denormalize */
                case 0x010: /* Underflow */
index 9e92966..5d73e04 100644 (file)
@@ -9,12 +9,15 @@
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
 
-void machine_restart(char * __unused)
+void machine_shutdown(void)
 {
 #ifdef CONFIG_SMP
        smp_send_stop();
 #endif
+}
 
+void machine_emergency_restart(void)
+{
        /*
         * Visual Workstations restart after this
         * register is poked on the PIIX4
@@ -22,6 +25,12 @@ void machine_restart(char * __unused)
        outb(PIIX4_RESET_VAL, PIIX4_RESET_PORT);
 }
 
+void machine_restart(char * __unused)
+{
+       machine_shutdown();
+       machine_emergency_restart();
+}
+
 void machine_power_off(void)
 {
        unsigned short pm_status;
index 9f6d2d9..26ada6f 100644 (file)
@@ -14,6 +14,8 @@
 #include "cobalt.h"
 #include "piix4.h"
 
+int no_broadcast;
+
 char visws_board_type = -1;
 char visws_board_rev = -1;
 
index b3eda46..c638406 100644 (file)
@@ -251,6 +251,12 @@ kb_wait(void)
                        break;
 }
 
+void
+machine_shutdown(void)
+{
+       /* Architecture specific shutdown needed before a kexec */
+}
+
 void
 machine_restart(char *cmd)
 {
@@ -278,6 +284,13 @@ machine_restart(char *cmd)
        }
 }
 
+void
+machine_emergency_restart(void)
+{
+       /*for now, just hook this to a warm restart */
+       machine_restart(NULL);
+}
+
 void
 mca_nmi_hook(void)
 {
index c369a8b..6711ce3 100644 (file)
@@ -243,14 +243,6 @@ static unsigned long calculate_numa_remap_pages(void)
                /* now the roundup is correct, convert to PAGE_SIZE pages */
                size = size * PTRS_PER_PTE;
 
-               if (node_end_pfn[nid] & (PTRS_PER_PTE-1)) {
-                       /*
-                        * Adjust size if node_end_pfn is not on a proper
-                        * pmd boundary. remap_numa_kva will barf otherwise.
-                        */
-                       size +=  node_end_pfn[nid] & (PTRS_PER_PTE-1);
-               }
-
                /*
                 * Validate the region we are allocating only contains valid
                 * pages.
@@ -270,6 +262,17 @@ static unsigned long calculate_numa_remap_pages(void)
                reserve_pages += size;
                printk("Shrinking node %d from %ld pages to %ld pages\n",
                        nid, node_end_pfn[nid], node_end_pfn[nid] - size);
+
+               if (node_end_pfn[nid] & (PTRS_PER_PTE-1)) {
+                       /*
+                        * Align node_end_pfn[] and node_remap_start_pfn[] to
+                        * pmd boundary. remap_numa_kva will barf otherwise.
+                        */
+                       printk("Shrinking node %d further by %ld pages for proper alignment\n",
+                               nid, node_end_pfn[nid] & (PTRS_PER_PTE-1));
+                       size +=  node_end_pfn[nid] & (PTRS_PER_PTE-1);
+               }
+
                node_end_pfn[nid] -= size;
                node_remap_start_pfn[nid] = node_end_pfn[nid];
        }
index 2db65ec..42913f4 100644 (file)
@@ -30,6 +30,7 @@ static int __init pci_acpi_init(void)
        acpi_irq_penalty_init();
        pcibios_scanned++;
        pcibios_enable_irq = acpi_pci_irq_enable;
+       pcibios_disable_irq = acpi_pci_irq_disable;
 
        if (pci_routeirq) {
                /*
index 70bcd53..ade5bc5 100644 (file)
@@ -254,3 +254,9 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 
        return pcibios_enable_irq(dev);
 }
+
+void pcibios_disable_device (struct pci_dev *dev)
+{
+       if (pcibios_disable_irq)
+               pcibios_disable_irq(dev);
+}
index d291fb7..86348b6 100644 (file)
@@ -56,6 +56,7 @@ struct irq_router_handler {
 };
 
 int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
+void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL;
 
 /*
  *  Check passed address for the PCI IRQ Routing Table signature
index a80f0f5..127d53a 100644 (file)
@@ -73,3 +73,4 @@ extern int pcibios_scanned;
 extern spinlock_t pci_config_lock;
 
 extern int (*pcibios_enable_irq)(struct pci_dev *dev);
+extern void (*pcibios_disable_irq)(struct pci_dev *dev);
index 314c933..6c17433 100644 (file)
 extern struct pci_raw_ops pci_direct_conf1;
 
 static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; }
+static void pci_visws_disable_irq(struct pci_dev *dev) { }
 
 int (*pcibios_enable_irq)(struct pci_dev *dev) = &pci_visws_enable_irq;
+void (*pcibios_disable_irq)(struct pci_dev *dev) = &pci_visws_disable_irq;
 
 void __init pcibios_penalize_isa_irq(int irq, int active) {}
 
index cbb3e0c..8098813 100644 (file)
@@ -392,15 +392,8 @@ menu "Bus options (PCI, PCMCIA)"
 config PCI
        bool "PCI support"
        help
-         Find out whether you have a PCI motherboard. PCI is the name of a
-         bus system, i.e. the way the CPU talks to the other stuff inside
-         your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
-         VESA. If you have PCI, say Y, otherwise N.
-
-         The PCI-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>, contains valuable
-         information about which PCI hardware does work under Linux and which
-         doesn't.
+         Real IA-64 machines all have PCI/PCI-X/PCI Express busses.  Say Y
+         here unless you are using a simulator without PCI support.
 
 config PCI_DOMAINS
        bool
index 04d0b00..dccf35c 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10
-# Mon Jan 10 13:57:35 2005
+# Linux kernel version: 2.6.13-rc6
+# Tue Aug 16 14:40:41 2005
 #
 
 #
@@ -10,6 +10,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -21,24 +22,26 @@ CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=20
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_CPUSETS=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -63,9 +66,12 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_TIME_INTERPOLATION=y
 CONFIG_EFI=y
 CONFIG_GENERIC_IOMAP=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_IA64_UNCACHED_ALLOCATOR=y
 # CONFIG_IA64_GENERIC is not set
 # CONFIG_IA64_DIG is not set
 # CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
 CONFIG_IA64_SGI_SN2=y
 # CONFIG_IA64_HP_SIM is not set
 # CONFIG_ITANIUM is not set
@@ -74,6 +80,10 @@ CONFIG_MCKINLEY=y
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
 CONFIG_IA64_PAGE_SIZE_16KB=y
 # CONFIG_IA64_PAGE_SIZE_64KB is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
 CONFIG_IA64_L1_CACHE_SHIFT=7
 CONFIG_NUMA=y
 CONFIG_VIRTUAL_MEM_MAP=y
@@ -81,11 +91,20 @@ CONFIG_HOLES_IN_ZONE=y
 CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
 # CONFIG_IA64_CYCLONE is not set
 CONFIG_IOSAPIC=y
+CONFIG_IA64_SGI_SN_XP=m
 CONFIG_FORCE_MAX_ZONEORDER=18
 CONFIG_SMP=y
 CONFIG_NR_CPUS=512
 # CONFIG_HOTPLUG_CPU is not set
+CONFIG_SCHED_SMT=y
 CONFIG_PREEMPT=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
@@ -105,6 +124,7 @@ CONFIG_BINFMT_ELF=y
 #
 # Power management and ACPI
 #
+CONFIG_PM=y
 CONFIG_ACPI=y
 
 #
@@ -114,6 +134,7 @@ CONFIG_ACPI_BOOT=y
 CONFIG_ACPI_INTERPRETER=y
 # CONFIG_ACPI_BUTTON is not set
 CONFIG_ACPI_VIDEO=m
+CONFIG_ACPI_HOTKEY=m
 # CONFIG_ACPI_FAN is not set
 # CONFIG_ACPI_PROCESSOR is not set
 CONFIG_ACPI_NUMA=y
@@ -133,6 +154,7 @@ CONFIG_PCI_DOMAINS=y
 # CONFIG_PCI_MSI is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCI Hotplug Support
@@ -141,7 +163,6 @@ CONFIG_HOTPLUG_PCI=y
 # CONFIG_HOTPLUG_PCI_FAKE is not set
 # CONFIG_HOTPLUG_PCI_ACPI is not set
 # CONFIG_HOTPLUG_PCI_CPCI is not set
-# CONFIG_HOTPLUG_PCI_PCIE is not set
 # CONFIG_HOTPLUG_PCI_SHPC is not set
 CONFIG_HOTPLUG_PCI_SGI=y
 
@@ -151,8 +172,70 @@ CONFIG_HOTPLUG_PCI_SGI=y
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
 #
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 
 #
 # Device Drivers
@@ -163,7 +246,7 @@ CONFIG_HOTPLUG_PCI_SGI=y
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
+CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
 
 #
@@ -188,6 +271,7 @@ CONFIG_FW_LOADER=m
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_NBD=m
@@ -252,6 +336,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_BLK_DEV_HPT366 is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
 # CONFIG_BLK_DEV_PDC202XX_NEW is not set
@@ -282,6 +367,7 @@ CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=m
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -315,24 +401,20 @@ CONFIG_SCSI_SATA=y
 # CONFIG_SCSI_ATA_PIIX is not set
 # CONFIG_SCSI_SATA_NV is not set
 # CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_QSTOR is not set
 # CONFIG_SCSI_SATA_SX4 is not set
 # CONFIG_SCSI_SATA_SIL is not set
 # CONFIG_SCSI_SATA_SIS is not set
 # CONFIG_SCSI_SATA_ULI is not set
 # CONFIG_SCSI_SATA_VIA is not set
 CONFIG_SCSI_SATA_VITESSE=y
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 CONFIG_SCSI_QLOGIC_1280=y
 # CONFIG_SCSI_QLOGIC_1280_1040 is not set
@@ -342,6 +424,8 @@ CONFIG_SCSI_QLA22XX=y
 CONFIG_SCSI_QLA2300=y
 CONFIG_SCSI_QLA2322=y
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -364,11 +448,15 @@ CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
 
 #
 # Fusion MPT device support
 #
 CONFIG_FUSION=y
+CONFIG_FUSION_SPI=y
+CONFIG_FUSION_FC=y
 CONFIG_FUSION_MAX_SGE=128
 CONFIG_FUSION_CTL=m
 
@@ -383,82 +471,13 @@ CONFIG_FUSION_CTL=m
 # CONFIG_I2O is not set
 
 #
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-CONFIG_IPV6=m
-# CONFIG_IPV6_PRIVACY is not set
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-# CONFIG_INET6_TUNNEL is not set
-# CONFIG_IPV6_TUNNEL is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
+# Network device support
 #
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETPOLL=y
-# CONFIG_NETPOLL_RX is not set
-# CONFIG_NETPOLL_TRAP is not set
-CONFIG_NET_POLL_CONTROLLER=y
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -480,8 +499,10 @@ CONFIG_NETDEVICES=y
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SKGE is not set
 # CONFIG_SK98LIN is not set
 CONFIG_TIGON3=y
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -512,6 +533,10 @@ CONFIG_S2IO=m
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 CONFIG_NETCONSOLE=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
 
 #
 # ISDN subsystem
@@ -540,14 +565,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_EVDEV is not set
 # CONFIG_INPUT_EVBUG is not set
 
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
 #
 # Input Device Drivers
 #
@@ -557,6 +574,12 @@ CONFIG_SOUND_GAMEPORT=y
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
 #
 # Character devices
 #
@@ -568,9 +591,10 @@ CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_CYCLADES is not set
 # CONFIG_MOXA_SMARTIO is not set
 # CONFIG_ISI is not set
-# CONFIG_SYNCLINK is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
 # CONFIG_STALDRV is not set
 CONFIG_SGI_SNSC=y
 CONFIG_SGI_TIOCX=y
@@ -587,6 +611,7 @@ CONFIG_SGI_MBCS=m
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_SGI_L1_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_SERIAL_SGI_IOC4=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
@@ -615,18 +640,30 @@ CONFIG_EFI_RTC=y
 CONFIG_RAW_DRIVER=m
 # CONFIG_HPET is not set
 CONFIG_MAX_RAW_DEVS=256
+# CONFIG_HANGCHECK_TIMER is not set
 CONFIG_MMTIMER=y
 
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
 #
 # I2C support
 #
 # CONFIG_I2C is not set
+# CONFIG_I2C_SENSOR is not set
 
 #
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
 
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+
 #
 # Misc devices
 #
@@ -660,6 +697,8 @@ CONFIG_DUMMY_CONSOLE=y
 #
 # USB support
 #
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB=m
 # CONFIG_USB_DEBUG is not set
 
@@ -669,9 +708,8 @@ CONFIG_USB=m
 # CONFIG_USB_DEVICEFS is not set
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
@@ -679,7 +717,10 @@ CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB_EHCI_HCD=m
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=m
 # CONFIG_USB_SL811_HCD is not set
 
@@ -710,12 +751,15 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_MOUSE is not set
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
 # CONFIG_USB_EGALAX is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
 
 #
 # USB Imaging devices
@@ -740,6 +784,7 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
 
 #
 # USB port drivers
@@ -763,9 +808,12 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
 
 #
-# USB ATM/DSL drivers
+# USB DSL modem support
 #
 
 #
@@ -782,6 +830,7 @@ CONFIG_USB_HIDINPUT=y
 # InfiniBand support
 #
 CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_VERBS=m
 CONFIG_INFINIBAND_MTHCA=m
 # CONFIG_INFINIBAND_MTHCA_DEBUG is not set
 CONFIG_INFINIBAND_IPOIB=m
@@ -799,6 +848,7 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
@@ -814,13 +864,19 @@ CONFIG_REISERFS_FS_POSIX_ACL=y
 CONFIG_REISERFS_FS_SECURITY=y
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
 CONFIG_XFS_FS=y
+CONFIG_XFS_EXPORT=y
 CONFIG_XFS_RT=y
 CONFIG_XFS_QUOTA=y
 # CONFIG_XFS_SECURITY is not set
 CONFIG_XFS_POSIX_ACL=y
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 CONFIG_QUOTA=y
 # CONFIG_QFMT_V1 is not set
 # CONFIG_QFMT_V2 is not set
@@ -854,7 +910,6 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
 CONFIG_TMPFS_XATTR=y
@@ -885,15 +940,18 @@ CONFIG_RAMFS=y
 #
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
 CONFIG_NFS_DIRECTIO=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
@@ -980,6 +1038,9 @@ CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
 
 #
 # Profiling support
@@ -989,15 +1050,19 @@ CONFIG_ZLIB_DEFLATE=m
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=20
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_FS is not set
+# CONFIG_KPROBES is not set
 CONFIG_IA64_GRANULE_16MB=y
 # CONFIG_IA64_GRANULE_64MB is not set
 # CONFIG_IA64_PRINT_HAZARDS is not set
@@ -1019,11 +1084,12 @@ CONFIG_CRYPTO=y
 CONFIG_CRYPTO_HMAC=y
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
 CONFIG_CRYPTO_DES=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
index 73454ee..c853cfc 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc1-20050629
-# Wed Jun 29 15:28:12 2005
+# Linux kernel version: 2.6.13-rc6-tiger-smp
+# Wed Aug 17 10:19:51 2005
 #
 
 #
@@ -132,6 +132,7 @@ CONFIG_ACPI_BOOT=y
 CONFIG_ACPI_INTERPRETER=y
 CONFIG_ACPI_BUTTON=m
 # CONFIG_ACPI_VIDEO is not set
+# CONFIG_ACPI_HOTKEY is not set
 CONFIG_ACPI_FAN=m
 CONFIG_ACPI_PROCESSOR=m
 # CONFIG_ACPI_HOTPLUG_CPU is not set
@@ -169,6 +170,66 @@ CONFIG_HOTPLUG_PCI_ACPI=m
 #
 # CONFIG_PCCARD is not set
 
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+
 #
 # Device Drivers
 #
@@ -178,7 +239,7 @@ CONFIG_HOTPLUG_PCI_ACPI=m
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
 # CONFIG_DEBUG_DRIVER is not set
 
 #
@@ -348,6 +409,7 @@ CONFIG_SCSI_QLA22XX=m
 CONFIG_SCSI_QLA2300=m
 CONFIG_SCSI_QLA2322=m
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -393,72 +455,8 @@ CONFIG_FUSION_CTL=y
 # CONFIG_I2O is not set
 
 #
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
+# Network device support
 #
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-CONFIG_ARPD=y
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETPOLL=y
-# CONFIG_NETPOLL_RX is not set
-# CONFIG_NETPOLL_TRAP is not set
-CONFIG_NET_POLL_CONTROLLER=y
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
@@ -555,6 +553,10 @@ CONFIG_TIGON3=y
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 CONFIG_NETCONSOLE=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
 
 #
 # ISDN subsystem
@@ -680,6 +682,7 @@ CONFIG_DRM_R128=m
 CONFIG_DRM_RADEON=m
 CONFIG_DRM_MGA=m
 CONFIG_DRM_SIS=m
+# CONFIG_DRM_VIA is not set
 CONFIG_RAW_DRIVER=m
 CONFIG_HPET=y
 # CONFIG_HPET_RTC_IRQ is not set
@@ -696,12 +699,19 @@ CONFIG_MAX_RAW_DEVS=256
 # I2C support
 #
 # CONFIG_I2C is not set
+# CONFIG_I2C_SENSOR is not set
 
 #
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
 
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
 #
 # Misc devices
 #
@@ -800,6 +810,7 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_EGALAX is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
 
 #
 # USB Imaging devices
@@ -850,6 +861,7 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -910,6 +922,7 @@ CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_POSIX_ACL is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
index b7755e4..88e8867 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc1-20050629
-# Wed Jun 29 15:31:11 2005
+# Linux kernel version: 2.6.13-rc6
+# Wed Aug 17 10:02:43 2005
 #
 
 #
@@ -132,6 +132,7 @@ CONFIG_ACPI_BOOT=y
 CONFIG_ACPI_INTERPRETER=y
 CONFIG_ACPI_BUTTON=y
 CONFIG_ACPI_VIDEO=m
+CONFIG_ACPI_HOTKEY=m
 CONFIG_ACPI_FAN=y
 CONFIG_ACPI_PROCESSOR=y
 CONFIG_ACPI_THERMAL=y
@@ -168,6 +169,83 @@ CONFIG_HOTPLUG_PCI_ACPI=y
 #
 # CONFIG_PCCARD is not set
 
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+CONFIG_IP_NF_ARPTABLES=y
+# CONFIG_IP_NF_ARPFILTER is not set
+# CONFIG_IP_NF_ARP_MANGLE is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+
 #
 # Device Drivers
 #
@@ -349,6 +427,7 @@ CONFIG_SCSI_QLA2XXX=y
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -362,9 +441,11 @@ CONFIG_SCSI_QLA2XXX=y
 #
 # Fusion MPT device support
 #
-# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=y
+CONFIG_FUSION_FC=y
+CONFIG_FUSION_MAX_SGE=128
+CONFIG_FUSION_CTL=m
 
 #
 # IEEE 1394 (FireWire) support
@@ -377,87 +458,8 @@ CONFIG_SCSI_QLA2XXX=y
 # CONFIG_I2O is not set
 
 #
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
+# Network device support
 #
-# CONFIG_IP_NF_CONNTRACK is not set
-# CONFIG_IP_NF_CONNTRACK_MARK is not set
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-CONFIG_IP_NF_ARPTABLES=y
-# CONFIG_IP_NF_ARPFILTER is not set
-# CONFIG_IP_NF_ARP_MANGLE is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
@@ -555,6 +557,8 @@ CONFIG_TIGON3=y
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -659,6 +663,7 @@ CONFIG_DRM=y
 CONFIG_DRM_RADEON=y
 # CONFIG_DRM_MGA is not set
 # CONFIG_DRM_SIS is not set
+# CONFIG_DRM_VIA is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_HPET is not set
 # CONFIG_HANGCHECK_TIMER is not set
@@ -706,47 +711,10 @@ CONFIG_I2C_ALGOPCF=y
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
 # CONFIG_I2C_PCA_ISA is not set
+# CONFIG_I2C_SENSOR is not set
 
 #
-# Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-
-#
-# Other I2C Chip support
+# Miscellaneous I2C Chip support
 #
 # CONFIG_SENSORS_DS1337 is not set
 # CONFIG_SENSORS_DS1374 is not set
@@ -766,6 +734,11 @@ CONFIG_I2C_ALGOPCF=y
 #
 # CONFIG_W1 is not set
 
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+
 #
 # Misc devices
 #
@@ -782,7 +755,6 @@ CONFIG_VIDEO_DEV=y
 #
 # Video Adapters
 #
-# CONFIG_TUNER_MULTI_I2C is not set
 # CONFIG_VIDEO_BT848 is not set
 # CONFIG_VIDEO_CPIA is not set
 # CONFIG_VIDEO_SAA5246A is not set
@@ -1025,6 +997,7 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_EGALAX is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
 
 #
 # USB Imaging devices
@@ -1080,6 +1053,7 @@ CONFIG_USB_MON=y
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
 
 #
 # USB DSL modem support
@@ -1121,6 +1095,7 @@ CONFIG_JBD=y
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 
 #
 # XFS support
@@ -1128,6 +1103,7 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
index 9364199..1c8c7e6 100644 (file)
@@ -22,7 +22,7 @@ GLOBAL_ENTRY(_start)
        .save rp, r0
        .body
        movl gp = __gp
-       movl sp = stack_mem
+       movl sp = stack_mem+16384-16
        bsw.1
        br.call.sptk.many rp=start_bootloader
 END(_start)
index d65e87b..bbb8efe 100644 (file)
@@ -341,7 +341,7 @@ next_sg:
 #endif
 
        /* Attach the domains */
-       for_each_online_cpu(i) {
+       for_each_cpu_mask(i, *cpu_map) {
                struct sched_domain *sd;
 #ifdef CONFIG_SCHED_SMT
                sd = &per_cpu(cpu_domains, i);
index 66946f3..9be53e1 100644 (file)
@@ -1573,7 +1573,7 @@ sys_call_table:
        data8 sys_keyctl
        data8 sys_ioprio_set
        data8 sys_ioprio_get                    // 1275
-       data8 sys_set_zone_reclaim
+       data8 sys_ni_syscall
        data8 sys_inotify_init
        data8 sys_inotify_add_watch
        data8 sys_inotify_rm_watch
index b8ebb8e..f1201ac 100644 (file)
@@ -4312,6 +4312,7 @@ pfm_context_load(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
        DPRINT(("before cmpxchg() old_ctx=%p new_ctx=%p\n",
                thread->pfm_context, ctx));
 
+       ret = -EBUSY;
        old = ia64_cmpxchg(acq, &thread->pfm_context, NULL, ctx, sizeof(pfm_context_t *));
        if (old != NULL) {
                DPRINT(("load_pid [%d] already has a context\n", req->load_pid));
index 66e8406..051e050 100644 (file)
@@ -179,7 +179,7 @@ static int can_do_pal_halt = 1;
 
 static int __init nohalt_setup(char * str)
 {
-       pal_halt = 0;
+       pal_halt = can_do_pal_halt = 0;
        return 1;
 }
 __setup("nohalt", nohalt_setup);
index d227fab..6f0cc7a 100644 (file)
@@ -143,7 +143,8 @@ struct salinfo_data {
 
 static struct salinfo_data salinfo_data[ARRAY_SIZE(salinfo_log_name)];
 
-static spinlock_t data_lock, data_saved_lock;
+static DEFINE_SPINLOCK(data_lock);
+static DEFINE_SPINLOCK(data_saved_lock);
 
 /** salinfo_platform_oemdata - optional callback to decode oemdata from an error
  * record.
index b8a0a7d..774f34b 100644 (file)
@@ -467,15 +467,12 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse
                if (!setup_frame(sig, ka, info, oldset, scr))
                        return 0;
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               {
-                       sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
-                       sigaddset(&current->blocked, sig);
-                       recalc_sigpending();
-               }
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
+               sigaddset(&current->blocked, sig);
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
        return 1;
 }
 
index 54d9ed4..f9472c5 100644 (file)
@@ -380,6 +380,7 @@ void pcibios_bus_to_resource(struct pci_dev *dev,
        res->start = region->start + offset;
        res->end = region->end + offset;
 }
+EXPORT_SYMBOL(pcibios_bus_to_resource);
 
 static int __devinit is_valid_resource(struct pci_dev *dev, int idx)
 {
index a6649ba..414cdf2 100644 (file)
@@ -203,6 +203,7 @@ static void sn_fixup_ionodes(void)
                                continue;
                        }
 
+                       spin_lock_init(&sn_flush_device_list->sfdl_flush_lock);
                        hubdev->hdi_flush_nasid_list.widget_p[widget] =
                            sn_flush_device_list;
                }
@@ -322,7 +323,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
        struct pci_controller *controller;
        struct pcibus_bussoft *prom_bussoft_ptr;
        struct hubdev_info *hubdev_info;
-       void *provider_soft;
+       void *provider_soft = NULL;
        struct sn_pcibus_provider *provider;
 
        status = sal_get_pcibus_info((u64) segment, (u64) busnum,
@@ -338,7 +339,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
        if (bus == NULL) {
                bus = pci_scan_bus(busnum, &pci_root_ops, controller);
                if (bus == NULL)
-                       return; /* error, or bus already scanned */
+                       goto error_return; /* error, or bus already scanned */
                bus->sysdata = NULL;
        }
 
@@ -351,28 +352,30 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
         */
 
        if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES)
-               return;         /* unsupported asic type */
+               goto error_return; /* unsupported asic type */
 
        if (prom_bussoft_ptr->bs_asic_type == PCIIO_ASIC_TYPE_PPB)
                goto error_return; /* no further fixup necessary */
 
        provider = sn_pci_provider[prom_bussoft_ptr->bs_asic_type];
        if (provider == NULL)
-               return;         /* no provider registerd for this asic */
+               goto error_return; /* no provider registerd for this asic */
 
-       provider_soft = NULL;
+       bus->sysdata = controller;
        if (provider->bus_fixup)
                provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr, controller);
 
-       if (provider_soft == NULL)
-               return;         /* fixup failed or not applicable */
+       if (provider_soft == NULL) {
+               /* fixup failed or not applicable */
+               bus->sysdata = NULL;
+               goto error_return;
+       }
 
        /*
         * Generic bus fixup goes here.  Don't reference prom_bussoft_ptr
         * after this point.
         */
 
-       bus->sysdata = controller;
        PCI_CONTROLLER(bus)->platform_data = provider_soft;
        nasid = NASID_GET(SN_PCIBUS_BUSSOFT(bus)->bs_base);
        cnode = nasid_to_cnodeid(nasid);
index 7772951..7622d4e 100644 (file)
@@ -269,7 +269,7 @@ config NR_CPUS
 # Common NUMA Features
 config NUMA
        bool "Numa Memory Allocation Support"
-       depends on SMP
+       depends on SMP && BROKEN
        default n
 
 # turning this on wastes a bunch of space.
@@ -286,6 +286,7 @@ menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
 
 config PCI
        bool "PCI support"
+       depends on BROKEN
        default n
        help
          Find out whether you have a PCI motherboard. PCI is the name of a
index 3103972..bbf711b 100644 (file)
@@ -20,7 +20,7 @@ config DEBUG_STACK_USAGE
 
 config DEBUG_PAGEALLOC
        bool "Page alloc debugging"
-       depends on DEBUG_KERNEL
+       depends on DEBUG_KERNEL && BROKEN
        help
          Unmap pages from the kernel linear mapping after free_pages().
          This results in a large slowdown, but helps to find certain types
index a146b24..708634b 100644 (file)
 typedef struct {
        unsigned long icucr;  /* ICU Control Register */
 } icu_data_t;
+static icu_data_t icu_data[M32700UT_NUM_CPU_IRQ];
+#else
+icu_data_t icu_data[M32700UT_NUM_CPU_IRQ];
 #endif /* CONFIG_SMP */
 
-static icu_data_t icu_data[M32700UT_NUM_CPU_IRQ];
 
 static void disable_m32700ut_irq(unsigned int irq)
 {
index f0301f5..d7b7ec6 100644 (file)
 typedef struct {
        unsigned long icucr;  /* ICU Control Register */
 } icu_data_t;
+static icu_data_t icu_data[OPSPUT_NUM_CPU_IRQ];
+#else
+icu_data_t icu_data[OPSPUT_NUM_CPU_IRQ];
 #endif /* CONFIG_SMP */
 
-static icu_data_t icu_data[OPSPUT_NUM_CPU_IRQ];
 
 static void disable_opsput_irq(unsigned int irq)
 {
index 5aef7e4..71763f7 100644 (file)
@@ -341,13 +341,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
        /* Set up the stack frame */
        setup_rt_frame(sig, ka, info, oldset, regs);
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 }
 
 /*
index f9a0e72..640d592 100644 (file)
@@ -91,6 +91,7 @@ extern struct {
 
 /* which physical physical ID maps to which logical CPU number */
 static volatile int physid_2_cpu[NR_CPUS];
+#define physid_to_cpu(physid)  physid_2_cpu[physid]
 
 /* which logical CPU number maps to which physical ID */
 volatile int cpu_2_physid[NR_CPUS];
index 3c47072..8a2b77b 100644 (file)
@@ -205,8 +205,7 @@ static long last_rtc_update = 0;
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-static inline void
-do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 #ifndef CONFIG_SMP
        profile_tick(CPU_PROFILING, regs);
@@ -221,6 +220,7 @@ do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
         * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
         * called as close as possible to 500 ms before the new second starts.
         */
+       write_seqlock(&xtime_lock);
        if ((time_status & STA_UNSYNC) == 0
                && xtime.tv_sec > last_rtc_update + 660
                && (xtime.tv_nsec / 1000) >= 500000 - ((unsigned)TICK_SIZE) / 2
@@ -231,6 +231,7 @@ do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                else    /* do it again in 60 s */
                        last_rtc_update = xtime.tv_sec - 600;
        }
+       write_sequnlock(&xtime_lock);
        /* As we return to user mode fire off the other CPU schedulers..
           this is basically because we don't yet share IRQ's around.
           This message is rigged to be safe on the 386 - basically it's
@@ -238,14 +239,8 @@ do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 
 #ifdef CONFIG_SMP
        smp_local_timer_interrupt(regs);
+       smp_send_timer();
 #endif
-}
-
-irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       write_seqlock(&xtime_lock);
-       do_timer_interrupt(irq, NULL, regs);
-       write_sequnlock(&xtime_lock);
 
        return IRQ_HANDLED;
 }
index c871b46..ddb16a8 100644 (file)
@@ -58,3 +58,4 @@ csum_partial_copy_from_user (const unsigned char __user *src,
        return csum_partial(dst, len-missing, sum);
 }
 EXPORT_SYMBOL(csum_partial_copy_from_user);
+EXPORT_SYMBOL(csum_partial);
index 1d1a01e..08e7279 100644 (file)
 #include <linux/mmzone.h>
 #include <linux/initrd.h>
 #include <linux/nodemask.h>
+#include <linux/module.h>
 
 #include <asm/setup.h>
 
 extern char _end[];
 
 struct pglist_data *node_data[MAX_NUMNODES];
+EXPORT_SYMBOL(node_data);
 static bootmem_data_t node_bdata[MAX_NUMNODES] __initdata;
 
 pg_data_t m32r_node_data[MAX_NUMNODES];
index ac48b6d..aec1527 100644 (file)
@@ -160,13 +160,13 @@ good_area:
        printk("handle_mm_fault returns %d\n",fault);
 #endif
        switch (fault) {
-       case 1:
+       case VM_FAULT_MINOR:
                current->min_flt++;
                break;
-       case 2:
+       case VM_FAULT_MAJOR:
                current->maj_flt++;
                break;
-       case 0:
+       case VM_FAULT_SIGBUS:
                goto bus_err;
        default:
                goto out_of_memory;
index 30dceb5..43a2726 100644 (file)
@@ -732,13 +732,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
        if (ka->sa.sa_flags & SA_ONESHOT)
                ka->sa.sa_handler = SIG_DFL;
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 }
 
 /*
index 4024478..4c114ae 100644 (file)
@@ -155,13 +155,12 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
        else
                setup_irix_frame(ka, regs, sig, oldset);
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 }
 
 asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
index 65ee153..0209c1d 100644 (file)
@@ -425,13 +425,12 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
                setup_frame(ka, regs, sig, oldset);
 #endif
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 }
 
 extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
index c1a69cf..f6875f0 100644 (file)
@@ -751,13 +751,12 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
        else
                setup_frame(ka, regs, sig, oldset);
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 }
 
 int do_signal32(sigset_t *oldset, struct pt_regs *regs)
index 9421bb9..55d71c1 100644 (file)
@@ -517,13 +517,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
        if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
                return 0;
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
        return 1;
 }
 
index eaa7014..0ad945d 100644 (file)
@@ -178,17 +178,17 @@ good_area:
         */
 
        switch (handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) != 0)) {
-             case 1:
+             case VM_FAULT_MINOR:
                ++current->min_flt;
                break;
-             case 2:
+             case VM_FAULT_MAJOR:
                ++current->maj_flt;
                break;
-             case 0:
+             case VM_FAULT_SIGBUS:
                /*
-                * We ran out of memory, or some other thing happened
-                * to us that made us unable to handle the page fault
-                * gracefully.
+                * We hit a hared mapping outside of the file, or some
+                * other thing happened to us that made us unable to
+                * handle the page fault gracefully.
                 */
                goto bad_area;
              default:
index 9e2227e..57dacf9 100644 (file)
@@ -69,9 +69,9 @@ config FEC_QS6612
        
 config ENET_BIG_BUFFERS
        bool "Use Big CPM Ethernet Buffers"
-       depends on NET_ETHERNET
+       depends on SCC_ENET || FEC_ENET
        help
-         Allocate large buffers for MPC8xx Etherenet.  Increases throughput
+         Allocate large buffers for MPC8xx Ethernet. Increases throughput
          and decreases the likelihood of dropped packets, but costs memory.
 
 config HTDMSOUND
index 0cc2e7a..11726e2 100644 (file)
@@ -39,8 +39,6 @@
 #include <asm/tlbflush.h>
 #include <asm/rheap.h>
 
-extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep);
-
 static void m8xx_cpm_dpinit(void);
 static uint    host_buffer;    /* One page of host buffer */
 static uint    host_end;       /* end + 1 */
@@ -108,14 +106,11 @@ struct hw_interrupt_type cpm_pic = {
        .end            = cpm_eoi,
 };
 
-extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
-
 void
-m8xx_cpm_reset(uint bootpage)
+m8xx_cpm_reset(void)
 {
        volatile immap_t         *imp;
        volatile cpm8xx_t       *commproc;
-       pte_t *pte;
 
        imp = (immap_t *)IMAP_ADDR;
        commproc = (cpm8xx_t *)&imp->im_cpm;
@@ -143,17 +138,6 @@ m8xx_cpm_reset(uint bootpage)
        /* Reclaim the DP memory for our use. */
        m8xx_cpm_dpinit();
 
-       /* get the PTE for the bootpage */
-       if (!get_pteptr(&init_mm, bootpage, &pte))
-              panic("get_pteptr failed\n");
-                                                                                                                                                                                       
-       /* and make it uncachable */
-       pte_val(*pte) |= _PAGE_NO_CACHE;
-       _tlbie(bootpage);
-
-       host_buffer = bootpage;
-       host_end = host_buffer + PAGE_SIZE;
-
        /* Tell everyone where the comm processor resides.
        */
        cpmp = (cpm8xx_t *)commproc;
@@ -384,8 +368,6 @@ static rh_info_t cpm_dpmem_info;
 
 void m8xx_cpm_dpinit(void)
 {
-       cpm8xx_t *cp = &((immap_t *)IMAP_ADDR)->im_cpm;
-
        spin_lock_init(&cpm_dpmem_lock);
 
        /* Initialize the info header */
index 0730392..62f68d6 100644 (file)
@@ -173,7 +173,7 @@ struct fec_enet_private {
        uint    phy_status;
        uint    phy_speed;
        phy_info_t      *phy;
-       struct tq_struct phy_task;
+       struct work_struct phy_task;
 
        uint    sequence_done;
 
@@ -199,7 +199,8 @@ static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
 #ifdef CONFIG_USE_MDIO
 static void fec_enet_mii(struct net_device *dev);
 #endif /* CONFIG_USE_MDIO */
-static void fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+static irqreturn_t fec_enet_interrupt(int irq, void * dev_id,
+                                                       struct pt_regs * regs);
 #ifdef CONFIG_FEC_PACKETHOOK
 static void  fec_enet_tx(struct net_device *dev, __u32 regval);
 static void  fec_enet_rx(struct net_device *dev, __u32 regval);
@@ -471,7 +472,7 @@ fec_timeout(struct net_device *dev)
 /* The interrupt handler.
  * This is called from the MPC core interrupt.
  */
-static void
+static irqreturn_t
 fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
 {
        struct  net_device *dev = dev_id;
@@ -525,6 +526,7 @@ printk("%s[%d] %s: unexpected FEC_ENET_MII event\n", __FILE__,__LINE__,__FUNCTIO
                }
 
        }
+       return IRQ_RETVAL(IRQ_HANDLED);
 }
 
 
@@ -1263,8 +1265,9 @@ static void mii_display_status(struct net_device *dev)
        printk(".\n");
 }
 
-static void mii_display_config(struct net_device *dev)
+static void mii_display_config(void *priv)
 {
+       struct net_device *dev = (struct net_device *)priv;
        struct fec_enet_private *fep = dev->priv;
        volatile uint *s = &(fep->phy_status);
 
@@ -1294,8 +1297,9 @@ static void mii_display_config(struct net_device *dev)
        fep->sequence_done = 1;
 }
 
-static void mii_relink(struct net_device *dev)
+static void mii_relink(void *priv)
 {
+       struct net_device *dev = (struct net_device *)priv;
        struct fec_enet_private *fep = dev->priv;
        int duplex;
 
@@ -1323,18 +1327,16 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = dev->priv;
 
-       fep->phy_task.routine = (void *)mii_relink;
-       fep->phy_task.data = dev;
-       schedule_task(&fep->phy_task);
+       INIT_WORK(&fep->phy_task, mii_relink, (void *)dev);
+       schedule_work(&fep->phy_task);
 }
 
 static void mii_queue_config(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = dev->priv;
 
-       fep->phy_task.routine = (void *)mii_display_config;
-       fep->phy_task.data = dev;
-       schedule_task(&fep->phy_task);
+       INIT_WORK(&fep->phy_task, mii_display_config, (void *)dev);
+       schedule_work(&fep->phy_task);
 }
 
 
@@ -1403,11 +1405,11 @@ mii_discover_phy(uint mii_reg, struct net_device *dev)
 
 /* This interrupt occurs when the PHY detects a link change.
 */
-static void
+static
 #ifdef CONFIG_RPXCLASSIC
-mii_link_interrupt(void *dev_id)
+void mii_link_interrupt(void *dev_id)
 #else
-mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+irqreturn_t mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs)
 #endif
 {
 #ifdef CONFIG_USE_MDIO
@@ -1440,6 +1442,9 @@ mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs)
 printk("%s[%d] %s: unexpected Link interrupt\n", __FILE__,__LINE__,__FUNCTION__);
 #endif /* CONFIG_USE_MDIO */
 
+#ifndef CONFIG_RPXCLASSIC
+       return IRQ_RETVAL(IRQ_HANDLED);
+#endif /* CONFIG_RPXCLASSIC */
 }
 
 static int
@@ -1575,7 +1580,7 @@ static int __init fec_enet_init(void)
        struct fec_enet_private *fep;
        int i, j, k, err;
        unsigned char   *eap, *iap, *ba;
-       unsigned long   mem_addr;
+       dma_addr_t      mem_addr;
        volatile        cbd_t   *bdp;
        cbd_t           *cbd_base;
        volatile        immap_t *immap;
@@ -1640,7 +1645,8 @@ static int __init fec_enet_init(void)
                printk("FEC initialization failed.\n");
                return 1;
        }
-       cbd_base = (cbd_t *)consistent_alloc(GFP_KERNEL, PAGE_SIZE, &mem_addr);
+       cbd_base = (cbd_t *)dma_alloc_coherent(dev->class_dev.dev, PAGE_SIZE,
+                                              &mem_addr, GFP_KERNEL);
 
        /* Set receive and transmit descriptor base.
        */
@@ -1657,7 +1663,10 @@ static int __init fec_enet_init(void)
 
                /* Allocate a page.
                */
-               ba = (unsigned char *)consistent_alloc(GFP_KERNEL, PAGE_SIZE, &mem_addr);
+               ba = (unsigned char *)dma_alloc_coherent(dev->class_dev.dev,
+                                                        PAGE_SIZE,
+                                                        &mem_addr,
+                                                        GFP_KERNEL);
                /* BUG: no check for failure */
 
                /* Initialize the BD for every fragment in the page.
index 2c2da9b..e6fa1d1 100644 (file)
@@ -558,6 +558,7 @@ config PPC_MULTIPLATFORM
 
 config APUS
        bool "Amiga-APUS"
+       depends on BROKEN
        help
          Select APUS if configuring for a PowerUP Amiga.
          More information is available at:
@@ -647,6 +648,7 @@ config PAL4
 
 config GEMINI
        bool "Synergy-Gemini"
+       depends on BROKEN
        help
          Select Gemini if configuring for a Synergy Microsystems' Gemini
          series Single Board Computer.  More information is available at:
@@ -909,6 +911,7 @@ config PPCBUG_NVRAM
        default y if PPC_PREP
 
 config SMP
+       depends on PPC_STD_MMU
        bool "Symmetric multi-processing support"
        ---help---
          This enables support for systems with more than one CPU. If you have
@@ -928,7 +931,7 @@ config SMP
 
 config IRQ_ALL_CPUS
        bool "Distribute interrupts on all CPUs by default"
-       depends on SMP
+       depends on SMP && !MV64360
        help
          This option gives the kernel permission to distribute IRQs across
          multiple CPUs.  Saying N here will route all IRQs to the first
@@ -1119,7 +1122,9 @@ config PROC_HARDWARE
 
 source "drivers/zorro/Kconfig"
 
+if !44x || BROKEN
 source kernel/power/Kconfig
+endif
 
 config SECCOMP
        bool "Enable seccomp to safely compute untrusted bytecode"
index 991b4cb..d4dc4fa 100644 (file)
@@ -61,6 +61,12 @@ zimageinitrd-$(CONFIG_IBM_OPENBIOS)  := zImage.initrd-TREE
          end-$(CONFIG_EMBEDDEDBOOT)    := embedded
         misc-$(CONFIG_EMBEDDEDBOOT)    := misc-embedded.o
 
+      zimage-$(CONFIG_BAMBOO)          := zImage-TREE
+zimageinitrd-$(CONFIG_BAMBOO)          := zImage.initrd-TREE
+         end-$(CONFIG_BAMBOO)          := bamboo
+  entrypoint-$(CONFIG_BAMBOO)          := 0x01000000
+     extra.o-$(CONFIG_BAMBOO)          := pibs.o
+
       zimage-$(CONFIG_EBONY)           := zImage-TREE
 zimageinitrd-$(CONFIG_EBONY)           := zImage.initrd-TREE
          end-$(CONFIG_EBONY)           := ebony
index 1348740..67222d5 100644 (file)
@@ -91,9 +91,11 @@ load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
 
        mac64 = simple_strtoull((char *)PIBS_MAC_BASE, 0, 16);
        memcpy(hold_residual->bi_enetaddr, (char *)&mac64+2, 6);
-#ifdef CONFIG_440GX
+#if defined(CONFIG_440GX) || defined(CONFIG_440EP)
        mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET), 0, 16);
        memcpy(hold_residual->bi_enet1addr, (char *)&mac64+2, 6);
+#endif
+#ifdef CONFIG_440GX
        mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET*2), 0, 16);
        memcpy(hold_residual->bi_enet2addr, (char *)&mac64+2, 6);
        mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET*3), 0, 16);
diff --git a/arch/ppc/configs/bamboo_defconfig b/arch/ppc/configs/bamboo_defconfig
new file mode 100644 (file)
index 0000000..0ba4e70
--- /dev/null
@@ -0,0 +1,943 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12
+# Tue Jun 28 15:24:25 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+CONFIG_44x=y
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+# CONFIG_E500 is not set
+CONFIG_PPC_FPU=y
+CONFIG_BOOKE=y
+CONFIG_PTE_64BIT=y
+CONFIG_PHYS_64BIT=y
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_4xx=y
+
+#
+# IBM 4xx options
+#
+CONFIG_BAMBOO=y
+# CONFIG_EBONY is not set
+# CONFIG_LUAN is not set
+# CONFIG_OCOTEA is not set
+CONFIG_440EP=y
+CONFIG_440=y
+CONFIG_IBM440EP_ERR42=y
+CONFIG_IBM_OCP=y
+# CONFIG_PPC4xx_DMA is not set
+CONFIG_PPC_GEN550=y
+# CONFIG_PM is not set
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_START=0xff100000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_BOOT_LOAD=0x01000000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+# CONFIG_BLK_DEV_SD is not set
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_IBM_EMAC=y
+# CONFIG_IBM_EMAC_ERRMSG is not set
+CONFIG_IBM_EMAC_RXB=64
+CONFIG_IBM_EMAC_TXB=8
+CONFIG_IBM_EMAC_FGAP=8
+CONFIG_IBM_EMAC_SKBRES=0
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=y
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+CONFIG_NATSEMI=y
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+CONFIG_USB_PEGASUS=y
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_KGDB is not set
+# CONFIG_XMON is not set
+CONFIG_BDI_SWITCH=y
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_PPC_OCP=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
index 50936cd..8a3d74f 100644 (file)
@@ -852,6 +852,26 @@ struct cpu_spec    cpu_specs[] = {
 
 #endif /* CONFIG_40x */
 #ifdef CONFIG_44x
+       {
+               .pvr_mask               = 0xf0000fff,
+               .pvr_value              = 0x40000850,
+               .cpu_name               = "440EP Rev. A",
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB,
+               .cpu_user_features      = COMMON_PPC, /* 440EP has an FPU */
+               .icache_bsize           = 32,
+               .dcache_bsize           = 32,
+       },
+       {
+               .pvr_mask               = 0xf0000fff,
+               .pvr_value              = 0x400008d3,
+               .cpu_name               = "440EP Rev. B",
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB,
+               .cpu_user_features      = COMMON_PPC, /* 440EP has an FPU */
+               .icache_bsize           = 32,
+               .dcache_bsize           = 32,
+       },
        {       /* 440GP Rev. B */
                .pvr_mask               = 0xf0000fff,
                .pvr_value              = 0x40000440,
index d4df686..cb83045 100644 (file)
@@ -215,6 +215,7 @@ syscall_dotrace_cont:
        lwzx    r10,r10,r0      /* Fetch system call handler [ptr] */
        mtlr    r10
        addi    r9,r1,STACK_FRAME_OVERHEAD
+       PPC440EP_ERR42
        blrl                    /* Call handler */
        .globl  ret_from_syscall
 ret_from_syscall:
index 6c7ae60..69ff3a9 100644 (file)
@@ -179,24 +179,26 @@ skpinv:   addi    r4,r4,1                         /* Increment */
 4:
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
        /*
-        * Add temporary UART mapping for early debug.  This
-        * mapping must be identical to that used by the early
-        * bootloader code since the same asm/serial.h parameters
-        * are used for polled operation.
+        * Add temporary UART mapping for early debug.
+        * We can map UART registers wherever we want as long as they don't
+        * interfere with other system mappings (e.g. with pinned entries).
+        * For an example of how we handle this - see ocotea.h.       --ebs
         */
        /* pageid fields */
        lis     r3,UART0_IO_BASE@h
-       ori     r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M
+       ori     r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_4K
 
        /* xlat fields */
        lis     r4,UART0_PHYS_IO_BASE@h         /* RPN depends on SoC */
+#ifndef CONFIG_440EP
        ori     r4,r4,0x0001            /* ERPN is 1 for second 4GB page */
+#endif
 
        /* attrib fields */
        li      r5,0
        ori     r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_I | PPC44x_TLB_G)
 
-        li      r0,1                    /* TLB slot 1 */
+        li      r0,0                    /* TLB slot 0 */
 
        tlbwe   r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
        tlbwe   r4,r0,PPC44x_TLB_XLAT   /* Load the translation fields */
@@ -228,6 +230,16 @@ skpinv:    addi    r4,r4,1                         /* Increment */
        lis     r4,interrupt_base@h     /* IVPR only uses the high 16-bits */
        mtspr   SPRN_IVPR,r4
 
+#ifdef CONFIG_440EP
+       /* Clear DAPUIB flag in CCR0 (enable APU between CPU and FPU) */
+       mfspr   r2,SPRN_CCR0
+       lis     r3,0xffef
+       ori     r3,r3,0xffff
+       and     r2,r2,r3
+       mtspr   SPRN_CCR0,r2
+       isync
+#endif
+
        /*
         * This is where the main kernel code starts.
         */
index 191a8de..ce71b4a 100644 (file)
@@ -1145,6 +1145,7 @@ _GLOBAL(kernel_thread)
        stwu    r0,-16(r1)
        mtlr    r30             /* fn addr in lr */
        mr      r3,r31          /* load arg and call fn */
+       PPC440EP_ERR42
        blrl
        li      r0,__NR_exit    /* exit if function returns */
        li      r3,0
@@ -1451,3 +1452,6 @@ _GLOBAL(sys_call_table)
        .long sys_waitid
        .long sys_ioprio_set
        .long sys_ioprio_get
+       .long sys_inotify_init          /* 275 */
+       .long sys_inotify_add_watch
+       .long sys_inotify_rm_watch
index 70cfb6f..7b3586a 100644 (file)
@@ -160,6 +160,21 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
 }
 EXPORT_SYMBOL(pcibios_resource_to_bus);
 
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+                            struct pci_bus_region *region)
+{
+       unsigned long offset = 0;
+       struct pci_controller *hose = dev->sysdata;
+
+       if (hose && res->flags & IORESOURCE_IO)
+               offset = (unsigned long)hose->io_base_virt - isa_io_base;
+       else if (hose && res->flags & IORESOURCE_MEM)
+               offset = hose->pci_mem_offset;
+       res->start = region->start + offset;
+       res->end = region->end + offset;
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+
 /*
  * We need to avoid collisions with `mirrored' VGA ports
  * and other strange ISA hardware, so we always want the
index d59ad07..e7d40cc 100644 (file)
@@ -324,7 +324,7 @@ EXPORT_SYMBOL(__res);
 
 EXPORT_SYMBOL(next_mmu_context);
 EXPORT_SYMBOL(set_context);
-EXPORT_SYMBOL(handle_mm_fault); /* For MOL */
+EXPORT_SYMBOL_GPL(__handle_mm_fault); /* For MOL */
 EXPORT_SYMBOL(disarm_decr);
 #ifdef CONFIG_PPC_STD_MMU
 extern long mol_trampoline;
index 8aaeb6f..2244bf9 100644 (file)
@@ -759,13 +759,12 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
        else
                handle_signal(signr, &ka, &info, oldset, regs, newsp);
 
-       if (!(ka.sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka.sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka.sa.sa_mask);
+       if (!(ka.sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked, signr);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 
        return 1;
 }
index a0612a8..805dd98 100644 (file)
@@ -3,6 +3,11 @@ config 4xx
        depends on 40x || 44x
        default y
 
+config WANT_EARLY_SERIAL
+       bool
+       select SERIAL_8250
+       default n
+
 menu "IBM 4xx options"
        depends on 4xx
 
@@ -18,6 +23,7 @@ config ASH
 
 config BUBINGA
        bool "Bubinga"
+       select WANT_EARLY_SERIAL
        help
          This option enables support for the IBM 405EP evaluation board.
 
@@ -68,18 +74,27 @@ choice
        depends on 44x
        default EBONY
 
+config BAMBOO
+       bool "Bamboo"
+       select WANT_EARLY_SERIAL
+       help
+         This option enables support for the IBM PPC440EP evaluation board.
+
 config EBONY
        bool "Ebony"
+       select WANT_EARLY_SERIAL
        help
          This option enables support for the IBM PPC440GP evaluation board.
 
 config LUAN
        bool "Luan"
+       select WANT_EARLY_SERIAL
        help
          This option enables support for the IBM PPC440SP evaluation board.
 
 config OCOTEA
        bool "Ocotea"
+       select WANT_EARLY_SERIAL
        help
          This option enables support for the IBM PPC440GX evaluation board.
 
@@ -98,6 +113,12 @@ config NP405H
        depends on ASH
        default y
 
+config 440EP
+       bool
+       depends on BAMBOO
+       select PPC_FPU
+       default y
+
 config 440GP
        bool
        depends on EBONY
@@ -115,7 +136,7 @@ config 440SP
 
 config 440
        bool
-       depends on 440GP || 440SP
+       depends on 440GP || 440SP || 440EP
        default y
 
 config 440A
@@ -123,6 +144,11 @@ config 440A
        depends on 440GX
        default y
 
+config IBM440EP_ERR42
+       bool
+       depends on 440EP
+       default y
+
 # All 405-based cores up until the 405GPR and 405EP have this errata.
 config IBM405_ERR77
        bool
@@ -142,7 +168,7 @@ config BOOKE
 
 config IBM_OCP
        bool
-       depends on ASH || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
+       depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
        default y
 
 config XILINX_OCP
@@ -214,10 +240,6 @@ config PPC_GEN550
        depends on 4xx
        default y
 
-config PM
-       bool "Power Management support (EXPERIMENTAL)"
-       depends on 4xx && EXPERIMENTAL
-
 choice
        prompt "TTYS0 device and default console"
        depends on 40x
index ea470c6..844c3b5 100644 (file)
@@ -2,6 +2,7 @@
 # Makefile for the PowerPC 4xx linux kernel.
 
 obj-$(CONFIG_ASH)              += ash.o
+obj-$(CONFIG_BAMBOO)           += bamboo.o
 obj-$(CONFIG_CPCI405)          += cpci405.o
 obj-$(CONFIG_EBONY)            += ebony.o
 obj-$(CONFIG_EP405)            += ep405.o
@@ -19,6 +20,7 @@ obj-$(CONFIG_405GP)           += ibm405gp.o
 obj-$(CONFIG_REDWOOD_5)                += ibmstb4.o
 obj-$(CONFIG_NP405H)           += ibmnp405h.o
 obj-$(CONFIG_REDWOOD_6)                += ibmstbx25.o
+obj-$(CONFIG_440EP)            += ibm440ep.o
 obj-$(CONFIG_440GP)            += ibm440gp.o
 obj-$(CONFIG_440GX)            += ibm440gx.o
 obj-$(CONFIG_440SP)            += ibm440sp.o
diff --git a/arch/ppc/platforms/4xx/bamboo.c b/arch/ppc/platforms/4xx/bamboo.c
new file mode 100644 (file)
index 0000000..f116787
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * arch/ppc/platforms/4xx/bamboo.c
+ *
+ * Bamboo board specific routines
+ *
+ * Wade Farnsworth <wfarnsworth@mvista.com>
+ * Copyright 2004 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/blkdev.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/initrd.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/ethtool.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ocp.h>
+#include <asm/pci-bridge.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/ppc4xx_pic.h>
+#include <asm/ppcboot.h>
+
+#include <syslib/gen550.h>
+#include <syslib/ibm440gx_common.h>
+
+/*
+ * This is a horrible kludge, we eventually need to abstract this
+ * generic PHY stuff, so the  standard phy mode defines can be
+ * easily used from arch code.
+ */
+#include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
+
+bd_t __res;
+
+static struct ibm44x_clocks clocks __initdata;
+
+/*
+ * Bamboo external IRQ triggering/polarity settings
+ */
+unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = {
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ0: Ethernet transceiver */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ1: Expansion connector */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ2: PCI slot 0 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ3: PCI slot 1 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ4: PCI slot 2 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ5: PCI slot 3 */
+       (IRQ_SENSE_EDGE  | IRQ_POLARITY_NEGATIVE), /* IRQ6: SMI pushbutton */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ7: EXT */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ8: EXT */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ9: EXT */
+};
+
+static void __init
+bamboo_calibrate_decr(void)
+{
+       unsigned int freq;
+
+       if (mfspr(SPRN_CCR1) & CCR1_TCS)
+               freq = BAMBOO_TMRCLK;
+       else
+               freq = clocks.cpu;
+
+       ibm44x_calibrate_decr(freq);
+
+}
+
+static int
+bamboo_show_cpuinfo(struct seq_file *m)
+{
+       seq_printf(m, "vendor\t\t: IBM\n");
+       seq_printf(m, "machine\t\t: PPC440EP EVB (Bamboo)\n");
+
+       return 0;
+}
+
+static inline int
+bamboo_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+       static char pci_irq_table[][4] =
+       /*
+        *      PCI IDSEL/INTPIN->INTLINE
+        *         A   B   C   D
+        */
+       {
+               { 28, 28, 28, 28 },     /* IDSEL 1 - PCI Slot 0 */
+               { 27, 27, 27, 27 },     /* IDSEL 2 - PCI Slot 1 */
+               { 26, 26, 26, 26 },     /* IDSEL 3 - PCI Slot 2 */
+               { 25, 25, 25, 25 },     /* IDSEL 4 - PCI Slot 3 */
+       };
+
+       const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+       return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static void __init bamboo_set_emacdata(void)
+{
+       unsigned char * selection1_base;
+       struct ocp_def *def;
+       struct ocp_func_emac_data *emacdata;
+       u8 selection1_val;
+       int mode;
+
+       selection1_base = ioremap64(BAMBOO_FPGA_SELECTION1_REG_ADDR, 16);
+       selection1_val = readb(selection1_base);
+       iounmap((void *) selection1_base);
+       if (BAMBOO_SEL_MII(selection1_val))
+               mode = PHY_MODE_MII;
+       else if (BAMBOO_SEL_RMII(selection1_val))
+               mode = PHY_MODE_RMII;
+       else
+               mode = PHY_MODE_SMII;
+
+       /* Set mac_addr and phy mode for each EMAC */
+
+       def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0);
+       emacdata = def->additions;
+       memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
+       emacdata->phy_mode = mode;
+
+       def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 1);
+       emacdata = def->additions;
+       memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6);
+       emacdata->phy_mode = mode;
+}
+
+static int
+bamboo_exclude_device(unsigned char bus, unsigned char devfn)
+{
+       return (bus == 0 && devfn == 0);
+}
+
+#define PCI_READW(offset) \
+        (readw((void *)((u32)pci_reg_base+offset)))
+
+#define PCI_WRITEW(value, offset) \
+       (writew(value, (void *)((u32)pci_reg_base+offset)))
+
+#define PCI_WRITEL(value, offset) \
+       (writel(value, (void *)((u32)pci_reg_base+offset)))
+
+static void __init
+bamboo_setup_pci(void)
+{
+       void *pci_reg_base;
+       unsigned long memory_size;
+       memory_size = ppc_md.find_end_of_memory();
+
+       pci_reg_base = ioremap64(BAMBOO_PCIL0_BASE, BAMBOO_PCIL0_SIZE);
+
+       /* Enable PCI I/O, Mem, and Busmaster cycles */
+       PCI_WRITEW(PCI_READW(PCI_COMMAND) |
+                  PCI_COMMAND_MEMORY |
+                  PCI_COMMAND_MASTER, PCI_COMMAND);
+
+       /* Disable region first */
+       PCI_WRITEL(0, BAMBOO_PCIL0_PMM0MA);
+
+       /* PLB starting addr: 0x00000000A0000000 */
+       PCI_WRITEL(BAMBOO_PCI_PHY_MEM_BASE, BAMBOO_PCIL0_PMM0LA);
+
+       /* PCI start addr, 0xA0000000 (PCI Address) */
+       PCI_WRITEL(BAMBOO_PCI_MEM_BASE, BAMBOO_PCIL0_PMM0PCILA);
+       PCI_WRITEL(0, BAMBOO_PCIL0_PMM0PCIHA);
+
+       /* Enable no pre-fetch, enable region */
+       PCI_WRITEL(((0xffffffff -
+                    (BAMBOO_PCI_UPPER_MEM - BAMBOO_PCI_MEM_BASE)) | 0x01),
+                     BAMBOO_PCIL0_PMM0MA);
+
+       /* Disable region one */
+       PCI_WRITEL(0, BAMBOO_PCIL0_PMM1MA);
+       PCI_WRITEL(0, BAMBOO_PCIL0_PMM1LA);
+       PCI_WRITEL(0, BAMBOO_PCIL0_PMM1PCILA);
+       PCI_WRITEL(0, BAMBOO_PCIL0_PMM1PCIHA);
+       PCI_WRITEL(0, BAMBOO_PCIL0_PMM1MA);
+
+       /* Disable region two */
+       PCI_WRITEL(0, BAMBOO_PCIL0_PMM2MA);
+       PCI_WRITEL(0, BAMBOO_PCIL0_PMM2LA);
+       PCI_WRITEL(0, BAMBOO_PCIL0_PMM2PCILA);
+       PCI_WRITEL(0, BAMBOO_PCIL0_PMM2PCIHA);
+       PCI_WRITEL(0, BAMBOO_PCIL0_PMM2MA);
+
+       /* Now configure the PCI->PLB windows, we only use PTM1
+        *
+        * For Inbound flow, set the window size to all available memory
+        * This is required because if size is smaller,
+        * then Eth/PCI DD would fail as PCI card not able to access
+        * the memory allocated by DD.
+        */
+
+       PCI_WRITEL(0, BAMBOO_PCIL0_PTM1MS);     /* disabled region 1 */
+       PCI_WRITEL(0, BAMBOO_PCIL0_PTM1LA);     /* begin of address map */
+
+       memory_size = 1 << fls(memory_size - 1);
+
+       /* Size low + Enabled */
+       PCI_WRITEL((0xffffffff - (memory_size - 1)) | 0x1, BAMBOO_PCIL0_PTM1MS);
+
+       eieio();
+       iounmap(pci_reg_base);
+}
+
+static void __init
+bamboo_setup_hose(void)
+{
+       unsigned int bar_response, bar;
+       struct pci_controller *hose;
+
+       bamboo_setup_pci();
+
+       hose = pcibios_alloc_controller();
+
+       if (!hose)
+               return;
+
+       hose->first_busno = 0;
+       hose->last_busno = 0xff;
+
+       hose->pci_mem_offset = BAMBOO_PCI_MEM_OFFSET;
+
+       pci_init_resource(&hose->io_resource,
+                       BAMBOO_PCI_LOWER_IO,
+                       BAMBOO_PCI_UPPER_IO,
+                       IORESOURCE_IO,
+                       "PCI host bridge");
+
+       pci_init_resource(&hose->mem_resources[0],
+                       BAMBOO_PCI_LOWER_MEM,
+                       BAMBOO_PCI_UPPER_MEM,
+                       IORESOURCE_MEM,
+                       "PCI host bridge");
+
+       ppc_md.pci_exclude_device = bamboo_exclude_device;
+
+       hose->io_space.start = BAMBOO_PCI_LOWER_IO;
+       hose->io_space.end = BAMBOO_PCI_UPPER_IO;
+       hose->mem_space.start = BAMBOO_PCI_LOWER_MEM;
+       hose->mem_space.end = BAMBOO_PCI_UPPER_MEM;
+       isa_io_base =
+               (unsigned long)ioremap64(BAMBOO_PCI_IO_BASE, BAMBOO_PCI_IO_SIZE);
+       hose->io_base_virt = (void *)isa_io_base;
+
+       setup_indirect_pci(hose,
+                       BAMBOO_PCI_CFGA_PLB32,
+                       BAMBOO_PCI_CFGD_PLB32);
+       hose->set_cfg_type = 1;
+
+       /* Zero config bars */
+       for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
+               early_write_config_dword(hose, hose->first_busno,
+                                        PCI_FUNC(hose->first_busno), bar,
+                                        0x00000000);
+               early_read_config_dword(hose, hose->first_busno,
+                                       PCI_FUNC(hose->first_busno), bar,
+                                       &bar_response);
+       }
+
+       hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+       ppc_md.pci_swizzle = common_swizzle;
+       ppc_md.pci_map_irq = bamboo_map_irq;
+}
+
+TODC_ALLOC();
+
+static void __init
+bamboo_early_serial_map(void)
+{
+       struct uart_port port;
+
+       /* Setup ioremapped serial port access */
+       memset(&port, 0, sizeof(port));
+       port.membase = ioremap64(PPC440EP_UART0_ADDR, 8);
+       port.irq = 0;
+       port.uartclk = clocks.uart0;
+       port.regshift = 0;
+       port.iotype = SERIAL_IO_MEM;
+       port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+       port.line = 0;
+
+       if (early_serial_setup(&port) != 0) {
+               printk("Early serial init of port 0 failed\n");
+       }
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       /* Configure debug serial access */
+       gen550_init(0, &port);
+#endif
+
+       port.membase = ioremap64(PPC440EP_UART1_ADDR, 8);
+       port.irq = 1;
+       port.uartclk = clocks.uart1;
+       port.line = 1;
+
+       if (early_serial_setup(&port) != 0) {
+               printk("Early serial init of port 1 failed\n");
+       }
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       /* Configure debug serial access */
+       gen550_init(1, &port);
+#endif
+
+       port.membase = ioremap64(PPC440EP_UART2_ADDR, 8);
+       port.irq = 3;
+       port.uartclk = clocks.uart2;
+       port.line = 2;
+
+       if (early_serial_setup(&port) != 0) {
+               printk("Early serial init of port 2 failed\n");
+       }
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       /* Configure debug serial access */
+       gen550_init(2, &port);
+#endif
+
+       port.membase = ioremap64(PPC440EP_UART3_ADDR, 8);
+       port.irq = 4;
+       port.uartclk = clocks.uart3;
+       port.line = 3;
+
+       if (early_serial_setup(&port) != 0) {
+               printk("Early serial init of port 3 failed\n");
+       }
+}
+
+static void __init
+bamboo_setup_arch(void)
+{
+
+       bamboo_set_emacdata();
+
+       ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200);
+       ocp_sys_info.opb_bus_freq = clocks.opb;
+
+       /* Setup TODC access */
+       TODC_INIT(TODC_TYPE_DS1743,
+                       0,
+                       0,
+                       ioremap64(BAMBOO_RTC_ADDR, BAMBOO_RTC_SIZE),
+                       8);
+
+       /* init to some ~sane value until calibrate_delay() runs */
+        loops_per_jiffy = 50000000/HZ;
+
+       /* Setup PCI host bridge */
+       bamboo_setup_hose();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (initrd_start)
+               ROOT_DEV = Root_RAM0;
+       else
+#endif
+#ifdef CONFIG_ROOT_NFS
+               ROOT_DEV = Root_NFS;
+#else
+               ROOT_DEV = Root_HDA1;
+#endif
+
+       bamboo_early_serial_map();
+
+       /* Identify the system */
+       printk("IBM Bamboo port (MontaVista Software, Inc. (source@mvista.com))\n");
+}
+
+void __init platform_init(unsigned long r3, unsigned long r4,
+               unsigned long r5, unsigned long r6, unsigned long r7)
+{
+       parse_bootinfo(find_bootinfo());
+
+       /*
+        * If we were passed in a board information, copy it into the
+        * residual data area.
+        */
+       if (r3)
+               __res = *(bd_t *)(r3 + KERNELBASE);
+
+
+       ibm44x_platform_init();
+
+       ppc_md.setup_arch = bamboo_setup_arch;
+       ppc_md.show_cpuinfo = bamboo_show_cpuinfo;
+       ppc_md.get_irq = NULL;          /* Set in ppc4xx_pic_init() */
+
+       ppc_md.calibrate_decr = bamboo_calibrate_decr;
+       ppc_md.time_init = todc_time_init;
+       ppc_md.set_rtc_time = todc_set_rtc_time;
+       ppc_md.get_rtc_time = todc_get_rtc_time;
+
+       ppc_md.nvram_read_val = todc_direct_read_val;
+       ppc_md.nvram_write_val = todc_direct_write_val;
+#ifdef CONFIG_KGDB
+       ppc_md.early_serial_map = bamboo_early_serial_map;
+#endif
+}
+
diff --git a/arch/ppc/platforms/4xx/bamboo.h b/arch/ppc/platforms/4xx/bamboo.h
new file mode 100644 (file)
index 0000000..63d7145
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * arch/ppc/platforms/bamboo.h
+ *
+ * Bamboo board definitions
+ *
+ * Wade Farnsworth <wfarnsworth@mvista.com>
+ *
+ * Copyright 2004 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_BAMBOO_H__
+#define __ASM_BAMBOO_H__
+
+#include <linux/config.h>
+#include <platforms/4xx/ibm440ep.h>
+
+/* F/W TLB mapping used in bootloader glue to reset EMAC */
+#define PPC44x_EMAC0_MR0               0x0EF600E00
+
+/* Location of MAC addresses in PIBS image */
+#define PIBS_FLASH_BASE                        0xfff00000
+#define PIBS_MAC_BASE                  (PIBS_FLASH_BASE+0xc0400)
+#define PIBS_MAC_SIZE                  0x200
+#define PIBS_MAC_OFFSET                        0x100
+
+/* Default clock rate */
+#define BAMBOO_TMRCLK                  25000000
+
+/* RTC/NVRAM location */
+#define BAMBOO_RTC_ADDR                        0x080000000ULL
+#define BAMBOO_RTC_SIZE                        0x2000
+
+/* FPGA Registers */
+#define BAMBOO_FPGA_ADDR               0x080002000ULL
+
+#define BAMBOO_FPGA_CONFIG2_REG_ADDR   (BAMBOO_FPGA_ADDR + 0x1)
+#define BAMBOO_FULL_DUPLEX_EN(x)       (x & 0x08)
+#define BAMBOO_FORCE_100Mbps(x)                (x & 0x04)
+#define BAMBOO_AUTONEGOTIATE(x)                (x & 0x02)
+
+#define BAMBOO_FPGA_SETTING_REG_ADDR   (BAMBOO_FPGA_ADDR + 0x3)
+#define BAMBOO_BOOT_SMALL_FLASH(x)     (!(x & 0x80))
+#define BAMBOO_LARGE_FLASH_EN(x)       (!(x & 0x40))
+#define BAMBOO_BOOT_NAND_FLASH(x)      (!(x & 0x20))
+
+#define BAMBOO_FPGA_SELECTION1_REG_ADDR (BAMBOO_FPGA_ADDR + 0x4)
+#define BAMBOO_SEL_MII(x)              (x & 0x80)
+#define BAMBOO_SEL_RMII(x)             (x & 0x40)
+#define BAMBOO_SEL_SMII(x)             (x & 0x20)
+
+/* Flash */
+#define BAMBOO_SMALL_FLASH_LOW         0x087f00000ULL
+#define BAMBOO_SMALL_FLASH_HIGH                0x0fff00000ULL
+#define BAMBOO_SMALL_FLASH_SIZE                0x100000
+#define BAMBOO_LARGE_FLASH_LOW         0x087800000ULL
+#define BAMBOO_LARGE_FLASH_HIGH1       0x0ff800000ULL
+#define BAMBOO_LARGE_FLASH_HIGH2       0x0ffc00000ULL
+#define BAMBOO_LARGE_FLASH_SIZE                0x400000
+#define BAMBOO_SRAM_LOW                        0x087f00000ULL
+#define BAMBOO_SRAM_HIGH1              0x0fff00000ULL
+#define BAMBOO_SRAM_HIGH2              0x0ff800000ULL
+#define BAMBOO_SRAM_SIZE               0x100000
+#define BAMBOO_NAND_FLASH_REG_ADDR     0x090000000ULL
+#define BAMBOO_NAND_FLASH_REG_SIZE     0x2000
+
+/*
+ * Serial port defines
+ */
+#define RS_TABLE_SIZE                  4
+
+#define UART0_IO_BASE                  0xEF600300
+#define UART1_IO_BASE                  0xEF600400
+#define UART2_IO_BASE                  0xEF600500
+#define UART3_IO_BASE                  0xEF600600
+
+#define BASE_BAUD                      33177600/3/16
+#define UART0_INT                      0
+#define UART1_INT                      1
+#define UART2_INT                      3
+#define UART3_INT                      4
+
+#define STD_UART_OP(num)                                       \
+       { 0, BASE_BAUD, 0, UART##num##_INT,                     \
+               (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),        \
+               iomem_base: UART##num##_IO_BASE,                \
+               io_type: SERIAL_IO_MEM},
+
+#define SERIAL_PORT_DFNS       \
+       STD_UART_OP(0)          \
+       STD_UART_OP(1)          \
+       STD_UART_OP(2)          \
+       STD_UART_OP(3)
+
+/* PCI support */
+#define BAMBOO_PCI_CFGA_PLB32          0xeec00000
+#define BAMBOO_PCI_CFGD_PLB32          0xeec00004
+
+#define BAMBOO_PCI_IO_BASE             0x00000000e8000000ULL
+#define BAMBOO_PCI_IO_SIZE             0x00010000
+#define BAMBOO_PCI_MEM_OFFSET          0x00000000
+#define BAMBOO_PCI_PHY_MEM_BASE                0x00000000a0000000ULL
+
+#define BAMBOO_PCI_LOWER_IO            0x00000000
+#define BAMBOO_PCI_UPPER_IO            0x0000ffff
+#define BAMBOO_PCI_LOWER_MEM           0xa0000000
+#define BAMBOO_PCI_UPPER_MEM           0xafffffff
+#define BAMBOO_PCI_MEM_BASE            0xa0000000
+
+#define BAMBOO_PCIL0_BASE              0x00000000ef400000ULL
+#define BAMBOO_PCIL0_SIZE              0x40
+
+#define BAMBOO_PCIL0_PMM0LA            0x000
+#define BAMBOO_PCIL0_PMM0MA            0x004
+#define BAMBOO_PCIL0_PMM0PCILA         0x008
+#define BAMBOO_PCIL0_PMM0PCIHA         0x00C
+#define BAMBOO_PCIL0_PMM1LA            0x010
+#define BAMBOO_PCIL0_PMM1MA            0x014
+#define BAMBOO_PCIL0_PMM1PCILA         0x018
+#define BAMBOO_PCIL0_PMM1PCIHA         0x01C
+#define BAMBOO_PCIL0_PMM2LA            0x020
+#define BAMBOO_PCIL0_PMM2MA            0x024
+#define BAMBOO_PCIL0_PMM2PCILA         0x028
+#define BAMBOO_PCIL0_PMM2PCIHA         0x02C
+#define BAMBOO_PCIL0_PTM1MS            0x030
+#define BAMBOO_PCIL0_PTM1LA            0x034
+#define BAMBOO_PCIL0_PTM2MS            0x038
+#define BAMBOO_PCIL0_PTM2LA            0x03C
+
+#endif                          /* __ASM_BAMBOO_H__ */
+#endif                          /* __KERNEL__ */
index cd11734..509e69a 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright 2002-2005 MontaVista Software Inc.
  *
  * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
- * Copyright (c) 2003, 2004 Zultys Technologies
+ * Copyright (c) 2003-2005 Zultys Technologies
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -50,6 +50,7 @@
 #include <asm/bootinfo.h>
 #include <asm/ppc4xx_pic.h>
 #include <asm/ppcboot.h>
+#include <asm/tlbflush.h>
 
 #include <syslib/gen550.h>
 #include <syslib/ibm440gp_common.h>
@@ -248,6 +249,9 @@ ebony_early_serial_map(void)
 #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
        /* Configure debug serial access */
        gen550_init(0, &port);
+
+       /* Purge TLB entry added in head_44x.S for early serial access */
+       _tlbie(UART0_IO_BASE);
 #endif
 
        port.membase = ioremap64(PPC440GP_UART1_ADDR, 8);
index 47c391c..d08faa4 100644 (file)
  * Serial port defines
  */
 
-/* OpenBIOS defined UART mappings, used before early_serial_setup */
+#if defined(__BOOTER__)
+/* OpenBIOS defined UART mappings, used by bootloader shim */
 #define UART0_IO_BASE  0xE0000200
 #define UART1_IO_BASE  0xE0000300
+#else
+/* head_44x.S created UART mapping, used before early_serial_setup.
+ * We cannot use default OpenBIOS UART mappings because they
+ * don't work for configurations with more than 512M RAM.    --ebs
+ */
+#define UART0_IO_BASE  0xF0000200
+#define UART1_IO_BASE  0xF0000300
+#endif
 
 /* external Epson SG-615P */
 #define BASE_BAUD      691200
@@ -66,7 +75,7 @@
 #define STD_UART_OP(num)                                       \
        { 0, BASE_BAUD, 0, UART##num##_INT,                     \
                (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),        \
-               iomem_base: UART##num##_IO_BASE,                \
+               iomem_base: (void*)UART##num##_IO_BASE,         \
                io_type: SERIAL_IO_MEM},
 
 #define SERIAL_PORT_DFNS       \
diff --git a/arch/ppc/platforms/4xx/ibm440ep.c b/arch/ppc/platforms/4xx/ibm440ep.c
new file mode 100644 (file)
index 0000000..284da01
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * arch/ppc/platforms/4xx/ibm440ep.c
+ *
+ * PPC440EP I/O descriptions
+ *
+ * Wade Farnsworth <wfarnsworth@mvista.com>
+ * Copyright 2004 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <platforms/4xx/ibm440ep.h>
+#include <asm/ocp.h>
+#include <asm/ppc4xx_pic.h>
+
+static struct ocp_func_emac_data ibm440ep_emac0_def = {
+       .rgmii_idx      = -1,           /* No RGMII */
+       .rgmii_mux      = -1,           /* No RGMII */
+       .zmii_idx       = 0,            /* ZMII device index */
+       .zmii_mux       = 0,            /* ZMII input of this EMAC */
+       .mal_idx        = 0,            /* MAL device index */
+       .mal_rx_chan    = 0,            /* MAL rx channel number */
+       .mal_tx_chan    = 0,            /* MAL tx channel number */
+       .wol_irq        = 61,           /* WOL interrupt number */
+       .mdio_idx       = -1,           /* No shared MDIO */
+       .tah_idx        = -1,           /* No TAH */
+};
+
+static struct ocp_func_emac_data ibm440ep_emac1_def = {
+       .rgmii_idx      = -1,           /* No RGMII */
+       .rgmii_mux      = -1,           /* No RGMII */
+       .zmii_idx       = 0,            /* ZMII device index */
+       .zmii_mux       = 1,            /* ZMII input of this EMAC */
+       .mal_idx        = 0,            /* MAL device index */
+       .mal_rx_chan    = 1,            /* MAL rx channel number */
+       .mal_tx_chan    = 2,            /* MAL tx channel number */
+       .wol_irq        = 63,           /* WOL interrupt number */
+       .mdio_idx       = -1,           /* No shared MDIO */
+       .tah_idx        = -1,           /* No TAH */
+};
+OCP_SYSFS_EMAC_DATA()
+
+static struct ocp_func_mal_data ibm440ep_mal0_def = {
+       .num_tx_chans   = 4,            /* Number of TX channels */
+       .num_rx_chans   = 2,            /* Number of RX channels */
+       .txeob_irq      = 10,           /* TX End Of Buffer IRQ  */
+       .rxeob_irq      = 11,           /* RX End Of Buffer IRQ  */
+       .txde_irq       = 33,           /* TX Descriptor Error IRQ */
+       .rxde_irq       = 34,           /* RX Descriptor Error IRQ */
+       .serr_irq       = 32,           /* MAL System Error IRQ    */
+};
+OCP_SYSFS_MAL_DATA()
+
+static struct ocp_func_iic_data ibm440ep_iic0_def = {
+       .fast_mode      = 0,            /* Use standad mode (100Khz) */
+};
+
+static struct ocp_func_iic_data ibm440ep_iic1_def = {
+       .fast_mode      = 0,            /* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] = {
+       { .vendor       = OCP_VENDOR_IBM,
+         .function     = OCP_FUNC_OPB,
+         .index        = 0,
+         .paddr        = 0x0EF600000ULL,
+         .irq          = OCP_IRQ_NA,
+         .pm           = OCP_CPM_NA,
+       },
+       { .vendor       = OCP_VENDOR_IBM,
+         .function     = OCP_FUNC_16550,
+         .index        = 0,
+         .paddr        = PPC440EP_UART0_ADDR,
+         .irq          = UART0_INT,
+         .pm           = IBM_CPM_UART0,
+       },
+       { .vendor       = OCP_VENDOR_IBM,
+         .function     = OCP_FUNC_16550,
+         .index        = 1,
+         .paddr        = PPC440EP_UART1_ADDR,
+         .irq          = UART1_INT,
+         .pm           = IBM_CPM_UART1,
+       },
+       { .vendor       = OCP_VENDOR_IBM,
+         .function     = OCP_FUNC_16550,
+         .index        = 2,
+         .paddr        = PPC440EP_UART2_ADDR,
+         .irq          = UART2_INT,
+         .pm           = IBM_CPM_UART2,
+       },
+       { .vendor       = OCP_VENDOR_IBM,
+         .function     = OCP_FUNC_16550,
+         .index        = 3,
+         .paddr        = PPC440EP_UART3_ADDR,
+         .irq          = UART3_INT,
+         .pm           = IBM_CPM_UART3,
+       },
+       { .vendor       = OCP_VENDOR_IBM,
+         .function     = OCP_FUNC_IIC,
+         .index        = 0,
+         .paddr        = 0x0EF600700ULL,
+         .irq          = 2,
+         .pm           = IBM_CPM_IIC0,
+         .additions    = &ibm440ep_iic0_def,
+         .show         = &ocp_show_iic_data
+       },
+       { .vendor       = OCP_VENDOR_IBM,
+         .function     = OCP_FUNC_IIC,
+         .index        = 1,
+         .paddr        = 0x0EF600800ULL,
+         .irq          = 7,
+         .pm           = IBM_CPM_IIC1,
+         .additions    = &ibm440ep_iic1_def,
+         .show         = &ocp_show_iic_data
+       },
+       { .vendor       = OCP_VENDOR_IBM,
+         .function     = OCP_FUNC_GPIO,
+         .index        = 0,
+         .paddr        = 0x0EF600B00ULL,
+         .irq          = OCP_IRQ_NA,
+         .pm           = IBM_CPM_GPIO0,
+       },
+       { .vendor       = OCP_VENDOR_IBM,
+         .function     = OCP_FUNC_GPIO,
+         .index        = 1,
+         .paddr        = 0x0EF600C00ULL,
+         .irq          = OCP_IRQ_NA,
+         .pm           = OCP_CPM_NA,
+       },
+       { .vendor       = OCP_VENDOR_IBM,
+         .function     = OCP_FUNC_MAL,
+         .paddr        = OCP_PADDR_NA,
+         .irq          = OCP_IRQ_NA,
+         .pm           = OCP_CPM_NA,
+         .additions    = &ibm440ep_mal0_def,
+         .show         = &ocp_show_mal_data,
+       },
+       { .vendor       = OCP_VENDOR_IBM,
+         .function     = OCP_FUNC_EMAC,
+         .index        = 0,
+         .paddr        = 0x0EF600E00ULL,
+         .irq          = 60,
+         .pm           = OCP_CPM_NA,
+         .additions    = &ibm440ep_emac0_def,
+         .show         = &ocp_show_emac_data,
+       },
+       { .vendor       = OCP_VENDOR_IBM,
+         .function     = OCP_FUNC_EMAC,
+         .index        = 1,
+         .paddr        = 0x0EF600F00ULL,
+         .irq          = 62,
+         .pm           = OCP_CPM_NA,
+         .additions    = &ibm440ep_emac1_def,
+         .show         = &ocp_show_emac_data,
+       },
+       { .vendor       = OCP_VENDOR_IBM,
+         .function     = OCP_FUNC_ZMII,
+         .paddr        = 0x0EF600D00ULL,
+         .irq          = OCP_IRQ_NA,
+         .pm           = OCP_CPM_NA,
+       },
+       { .vendor       = OCP_VENDOR_INVALID
+       }
+};
+
+/* Polarity and triggering settings for internal interrupt sources */
+struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = {
+       { .polarity     = 0xffbffe03,
+         .triggering   = 0xfffffe00,
+         .ext_irq_mask = 0x000001fc,   /* IRQ0 - IRQ6 */
+       },
+       { .polarity     = 0xffffc6ef,
+         .triggering   = 0xffffc7ff,
+         .ext_irq_mask = 0x00003800,   /* IRQ7 - IRQ9 */
+       },
+};
+
+static struct resource usb_gadget_resources[] = {
+       [0] = {
+               .start  = 0x050000100ULL,
+               .end    = 0x05000017FULL,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 55,
+               .end    = 55,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static u64 dma_mask = 0xffffffffULL;
+
+static struct platform_device usb_gadget_device = {
+       .name           = "musbhsfc",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(usb_gadget_resources),
+       .resource       = usb_gadget_resources,
+       .dev            = {
+               .dma_mask = &dma_mask,
+               .coherent_dma_mask = 0xffffffffULL,
+       }
+};
+
+static struct platform_device *ibm440ep_devs[] __initdata = {
+       &usb_gadget_device,
+};
+
+static int __init
+ibm440ep_platform_add_devices(void)
+{
+       return platform_add_devices(ibm440ep_devs, ARRAY_SIZE(ibm440ep_devs));
+}
+arch_initcall(ibm440ep_platform_add_devices);
+
diff --git a/arch/ppc/platforms/4xx/ibm440ep.h b/arch/ppc/platforms/4xx/ibm440ep.h
new file mode 100644 (file)
index 0000000..97c80b8
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * arch/ppc/platforms/4xx/ibm440ep.h
+ *
+ * PPC440EP definitions
+ *
+ * Wade Farnsworth <wfarnsworth@mvista.com>
+ *
+ * Copyright 2002 Roland Dreier
+ * Copyright 2004 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifdef __KERNEL__
+#ifndef __PPC_PLATFORMS_IBM440EP_H
+#define __PPC_PLATFORMS_IBM440EP_H
+
+#include <linux/config.h>
+#include <asm/ibm44x.h>
+
+/* UART */
+#define PPC440EP_UART0_ADDR            0x0EF600300
+#define PPC440EP_UART1_ADDR            0x0EF600400
+#define PPC440EP_UART2_ADDR            0x0EF600500
+#define PPC440EP_UART3_ADDR            0x0EF600600
+#define UART0_INT                      0
+#define UART1_INT                      1
+#define UART2_INT                      3
+#define UART3_INT                      4
+
+/* Clock and Power Management */
+#define IBM_CPM_IIC0           0x80000000      /* IIC interface */
+#define IBM_CPM_IIC1           0x40000000      /* IIC interface */
+#define IBM_CPM_PCI            0x20000000      /* PCI bridge */
+#define IBM_CPM_USB1H          0x08000000      /* USB 1.1 Host */
+#define IBM_CPM_FPU            0x04000000      /* floating point unit */
+#define IBM_CPM_CPU            0x02000000      /* processor core */
+#define IBM_CPM_DMA            0x01000000      /* DMA controller */
+#define IBM_CPM_BGO            0x00800000      /* PLB to OPB bus arbiter */
+#define IBM_CPM_BGI            0x00400000      /* OPB to PLB bridge */
+#define IBM_CPM_EBC            0x00200000      /* External Bus Controller */
+#define IBM_CPM_EBM            0x00100000      /* Ext Bus Master Interface */
+#define IBM_CPM_DMC            0x00080000      /* SDRAM peripheral controller */
+#define IBM_CPM_PLB4           0x00040000      /* PLB4 bus arbiter */
+#define IBM_CPM_PLB4x3         0x00020000      /* PLB4 to PLB3 bridge controller */
+#define IBM_CPM_PLB3x4         0x00010000      /* PLB3 to PLB4 bridge controller */
+#define IBM_CPM_PLB3           0x00008000      /* PLB3 bus arbiter */
+#define IBM_CPM_PPM            0x00002000      /* PLB Performance Monitor */
+#define IBM_CPM_UIC1           0x00001000      /* Universal Interrupt Controller */
+#define IBM_CPM_GPIO0          0x00000800      /* General Purpose IO (??) */
+#define IBM_CPM_GPT            0x00000400      /* General Purpose Timers  */
+#define IBM_CPM_UART0          0x00000200      /* serial port 0 */
+#define IBM_CPM_UART1          0x00000100      /* serial port 1 */
+#define IBM_CPM_UIC0           0x00000080      /* Universal Interrupt Controller */
+#define IBM_CPM_TMRCLK         0x00000040      /* CPU timers */
+#define IBM_CPM_EMAC0          0x00000020      /* ethernet port 0 */
+#define IBM_CPM_EMAC1          0x00000010      /* ethernet port 1 */
+#define IBM_CPM_UART2          0x00000008      /* serial port 2 */
+#define IBM_CPM_UART3          0x00000004      /* serial port 3 */
+#define IBM_CPM_USB2D          0x00000002      /* USB 2.0 Device */
+#define IBM_CPM_USB2H          0x00000001      /* USB 2.0 Host */
+
+#define DFLT_IBM4xx_PM         ~(IBM_CPM_UIC0 | IBM_CPM_UIC1 | IBM_CPM_CPU \
+                               | IBM_CPM_EBC | IBM_CPM_BGO | IBM_CPM_FPU \
+                               | IBM_CPM_EBM | IBM_CPM_PLB4 | IBM_CPM_3x4 \
+                               | IBM_CPM_PLB3 | IBM_CPM_PLB4x3 \
+                               | IBM_CPM_EMAC0 | IBM_CPM_TMRCLK \
+                               | IBM_CPM_DMA | IBM_CPM_PCI | IBM_CPM_EMAC1)
+
+
+#endif /* __PPC_PLATFORMS_IBM440EP_H */
+#endif /* __KERNEL__ */
index 5f82a6b..8fc34a3 100644 (file)
@@ -48,6 +48,7 @@
 #include <asm/bootinfo.h>
 #include <asm/ppc4xx_pic.h>
 #include <asm/ppcboot.h>
+#include <asm/tlbflush.h>
 
 #include <syslib/gen550.h>
 #include <syslib/ibm440gx_common.h>
@@ -266,6 +267,9 @@ ocotea_early_serial_map(void)
 #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
        /* Configure debug serial access */
        gen550_init(0, &port);
+
+       /* Purge TLB entry added in head_44x.S for early serial access */
+       _tlbie(UART0_IO_BASE);
 #endif
 
        port.membase = ioremap64(PPC440GX_UART1_ADDR, 8);
index 202dc82..3325115 100644 (file)
  */
 #define RS_TABLE_SIZE  2
 
-/* OpenBIOS defined UART mappings, used before early_serial_setup */
+#if defined(__BOOTER__)
+/* OpenBIOS defined UART mappings, used by bootloader shim */
 #define UART0_IO_BASE  0xE0000200
 #define UART1_IO_BASE  0xE0000300
+#else
+/* head_44x.S created UART mapping, used before early_serial_setup.
+ * We cannot use default OpenBIOS UART mappings because they
+ * don't work for configurations with more than 512M RAM.    --ebs
+ */
+#define UART0_IO_BASE  0xF0000200
+#define UART1_IO_BASE  0xF0000300
+#endif
 
 #define BASE_BAUD      11059200/16
 #define STD_UART_OP(num)                                       \
        { 0, BASE_BAUD, 0, UART##num##_INT,                     \
                (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),        \
-               iomem_base: UART##num##_IO_BASE,                \
+               iomem_base: (void*)UART##num##_IO_BASE,         \
                io_type: SERIAL_IO_MEM},
 
 #define SERIAL_PORT_DFNS       \
index dec5bf4..220a65a 100644 (file)
@@ -11,6 +11,7 @@ obj-$(CONFIG_PPCBUG_NVRAM)    += prep_nvram.o
 obj-$(CONFIG_PPC_OCP)          += ocp.o
 obj-$(CONFIG_IBM_OCP)          += ibm_ocp.o
 obj-$(CONFIG_44x)              += ibm44x_common.o
+obj-$(CONFIG_440EP)            += ibm440gx_common.o
 obj-$(CONFIG_440GP)            += ibm440gp_common.o
 obj-$(CONFIG_440GX)            += ibm440gx_common.o
 obj-$(CONFIG_440SP)            += ibm440gx_common.o ibm440sp_common.o
@@ -44,6 +45,7 @@ obj-$(CONFIG_PPC_CHRP)                += open_pic.o indirect_pci.o i8259.o
 obj-$(CONFIG_PPC_PREP)         += open_pic.o indirect_pci.o i8259.o todc_time.o
 obj-$(CONFIG_ADIR)             += i8259.o indirect_pci.o pci_auto.o \
                                        todc_time.o
+obj-$(CONFIG_BAMBOO)           += indirect_pci.o pci_auto.o todc_time.o
 obj-$(CONFIG_CPCI690)          += todc_time.o pci_auto.o
 obj-$(CONFIG_EBONY)            += indirect_pci.o pci_auto.o todc_time.o
 obj-$(CONFIG_EV64260)          += todc_time.o pci_auto.o
index 4ad85e0..d4776af 100644 (file)
@@ -34,6 +34,10 @@ void __init ibm440gx_get_clocks(struct ibm44x_clocks* p, unsigned int sys_clk,
        u32 plld  = CPR_READ(DCRN_CPR_PLLD);
        u32 uart0 = SDR_READ(DCRN_SDR_UART0);
        u32 uart1 = SDR_READ(DCRN_SDR_UART1);
+#ifdef CONFIG_440EP
+       u32 uart2 = SDR_READ(DCRN_SDR_UART2);
+       u32 uart3 = SDR_READ(DCRN_SDR_UART3);
+#endif
 
        /* Dividers */
        u32 fbdv   = __fix_zero((plld >> 24) & 0x1f, 32);
@@ -96,6 +100,17 @@ bypass:
                p->uart1 = ser_clk;
        else
                p->uart1 = p->plb / __fix_zero(uart1 & 0xff, 256);
+#ifdef CONFIG_440EP
+       if (uart2 & 0x00800000)
+               p->uart2 = ser_clk;
+       else
+               p->uart2 = p->plb / __fix_zero(uart2 & 0xff, 256);
+
+       if (uart3 & 0x00800000)
+               p->uart3 = ser_clk;
+       else
+               p->uart3 = p->plb / __fix_zero(uart3 & 0xff, 256);
+#endif
 }
 
 /* Issue L2C diagnostic command */
index b14eb60..c16b6a5 100644 (file)
@@ -29,6 +29,10 @@ struct ibm44x_clocks {
        unsigned int ebc;       /* PerClk */
        unsigned int uart0;
        unsigned int uart1;
+#ifdef CONFIG_440EP
+       unsigned int uart2;
+       unsigned int uart3;
+#endif
 };
 
 /* common 44x platform init */
index c1db2ab..a3702cf 100644 (file)
@@ -57,7 +57,7 @@ unsigned char __res[sizeof(bd_t)];
 extern void m8xx_ide_init(void);
 
 extern unsigned long find_available_memory(void);
-extern void m8xx_cpm_reset(uint cpm_page);
+extern void m8xx_cpm_reset();
 extern void m8xx_wdt_handler_install(bd_t *bp);
 extern void rpxfb_alloc_pages(void);
 extern void cpm_interrupt_init(void);
@@ -70,13 +70,9 @@ board_init(void)
 void __init
 m8xx_setup_arch(void)
 {
-       int     cpm_page;
-
-       cpm_page = (int) alloc_bootmem_pages(PAGE_SIZE);
-
        /* Reset the Communication Processor Module.
        */
-       m8xx_cpm_reset(cpm_page);
+       m8xx_cpm_reset();
 
 #ifdef CONFIG_FB_RPX
        rpxfb_alloc_pages();
@@ -427,7 +423,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
        ppc_md.find_end_of_memory       = m8xx_find_end_of_memory;
        ppc_md.setup_io_mappings        = m8xx_map_io;
 
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+#if defined(CONFIG_BLK_DEV_MPC8xx_IDE)
        m8xx_ide_init();
 #endif
 }
index 75c8e98..5aaf0e5 100644 (file)
@@ -191,8 +191,8 @@ struct platform_device ppc_sys_platform_devices[] = {
                .num_resources   = 2,
                .resource = (struct resource[]) {
                        {
-                               .start  = 0x22000,
-                               .end    = 0x22fff,
+                               .start  = 0x23000,
+                               .end    = 0x23fff,
                                .flags  = IORESOURCE_MEM,
                        },
                        {
@@ -208,8 +208,8 @@ struct platform_device ppc_sys_platform_devices[] = {
                .num_resources   = 2,
                .resource = (struct resource[]) {
                        {
-                               .start  = 0x23000,
-                               .end    = 0x23fff,
+                               .start  = 0x22000,
+                               .end    = 0x22fff,
                                .flags  = IORESOURCE_MEM,
                        },
                        {
index 5015ab9..f15e642 100644 (file)
@@ -620,6 +620,7 @@ ppc4xx_clr_dma_status(unsigned int dmanr)
        return DMA_STATUS_GOOD;
 }
 
+#ifdef CONFIG_PPC4xx_EDMA
 /*
  * Enables the burst on the channel (BTEN bit in the control/count register)
  * Note:
@@ -685,6 +686,11 @@ ppc4xx_set_burst_size(unsigned int dmanr, unsigned int bsize)
        return DMA_STATUS_GOOD;
 }
 
+EXPORT_SYMBOL(ppc4xx_enable_burst);
+EXPORT_SYMBOL(ppc4xx_disable_burst);
+EXPORT_SYMBOL(ppc4xx_set_burst_size);
+#endif /* CONFIG_PPC4xx_EDMA */
+
 EXPORT_SYMBOL(ppc4xx_init_dma_channel);
 EXPORT_SYMBOL(ppc4xx_get_channel_config);
 EXPORT_SYMBOL(ppc4xx_set_channel_priority);
@@ -703,6 +709,4 @@ EXPORT_SYMBOL(ppc4xx_enable_dma_interrupt);
 EXPORT_SYMBOL(ppc4xx_disable_dma_interrupt);
 EXPORT_SYMBOL(ppc4xx_get_dma_status);
 EXPORT_SYMBOL(ppc4xx_clr_dma_status);
-EXPORT_SYMBOL(ppc4xx_enable_burst);
-EXPORT_SYMBOL(ppc4xx_disable_burst);
-EXPORT_SYMBOL(ppc4xx_set_burst_size);
+
index 9d5e4e9..78837e8 100644 (file)
@@ -1307,7 +1307,7 @@ local int huft_build(
   {
     *t = (inflate_huft *)Z_NULL;
     *m = 0;
-    return Z_OK;
+    return Z_DATA_ERROR;
   }
 
 
@@ -1351,6 +1351,7 @@ local int huft_build(
     if ((j = *p++) != 0)
       v[x[j]++] = i;
   } while (++i < n);
+  n = x[g];                    /* set n to length of v */
 
 
   /* Generate the Huffman codes and for each, make the table entries */
diff --git a/arch/ppc64/configs/bpa_defconfig b/arch/ppc64/configs/bpa_defconfig
new file mode 100644 (file)
index 0000000..46c5da4
--- /dev/null
@@ -0,0 +1,987 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.13-rc6
+# Mon Aug  8 14:12:19 2005
+#
+CONFIG_64BIT=y
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_COMPAT=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_FORCE_MAX_ZONEORDER=13
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_CPUSETS is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_SYSVIPC_COMPAT=y
+
+#
+# Platform support
+#
+# CONFIG_PPC_ISERIES is not set
+CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_PPC_PSERIES is not set
+CONFIG_PPC_BPA=y
+# CONFIG_PPC_PMAC is not set
+# CONFIG_PPC_MAPLE is not set
+CONFIG_PPC=y
+CONFIG_PPC64=y
+CONFIG_PPC_OF=y
+CONFIG_BPA_IIC=y
+CONFIG_ALTIVEC=y
+CONFIG_KEXEC=y
+# CONFIG_U3_DART is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_POWER4_ONLY is not set
+# CONFIG_IOMMU_VMERGE is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=4
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_NUMA is not set
+CONFIG_SCHED_SMT=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_PPC_RTAS=y
+CONFIG_RTAS_PROC=y
+CONFIG_RTAS_FLASH=y
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# General setup
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=y
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_IP_TCPDIAG=y
+CONFIG_IP_TCPDIAG_IPV6=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=y
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=m
+# CONFIG_E1000_NAPI is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+CONFIG_SKGE=m
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_MV643XX_ETH is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_SYNCLINK is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_WATCHDOG_RTAS=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+# CONFIG_TMPFS_SECURITY is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_KPROBES is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUGGER=y
+# CONFIG_XMON is not set
+# CONFIG_PPCDBG is not set
+CONFIG_IRQSTACKS=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
index 9e0abe8..ab56774 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc3
-# Wed Jul 13 14:40:34 2005
+# Linux kernel version: 2.6.13-rc6
+# Mon Aug  8 14:16:59 2005
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -267,8 +267,6 @@ CONFIG_NET_CLS_ROUTE=y
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -468,6 +466,7 @@ CONFIG_SCSI_QLA2XXX=y
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -539,11 +538,9 @@ CONFIG_IEEE1394_RAWIO=y
 #
 # Macintosh device drivers
 #
-CONFIG_ADB=y
 CONFIG_ADB_PMU=y
 CONFIG_PMAC_SMU=y
 # CONFIG_PMAC_BACKLIGHT is not set
-# CONFIG_INPUT_ADBHID is not set
 CONFIG_THERM_PM72=y
 
 #
@@ -631,6 +628,8 @@ CONFIG_PPPOE=m
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -718,7 +717,6 @@ CONFIG_LEGACY_PTY_COUNT=256
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
index dbd54d1..394ba18 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc3
-# Wed Jul 13 14:43:39 2005
+# Linux kernel version: 2.6.13-rc6
+# Mon Aug  8 14:17:02 2005
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -257,10 +257,6 @@ CONFIG_NET_CLS_ROUTE=y
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
-CONFIG_NETPOLL=y
-CONFIG_NETPOLL_RX=y
-CONFIG_NETPOLL_TRAP=y
-CONFIG_NET_POLL_CONTROLLER=y
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -388,6 +384,7 @@ CONFIG_SCSI_QLA2XXX=y
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -537,6 +534,10 @@ CONFIG_PPPOE=m
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 CONFIG_NETCONSOLE=y
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_RX=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
 
 #
 # ISDN subsystem
@@ -610,7 +611,6 @@ CONFIG_LEGACY_PTY_COUNT=256
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
index cda8e8c..2033fe6 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc3
-# Wed Jul 13 14:46:18 2005
+# Linux kernel version: 2.6.13-rc6
+# Mon Aug  8 14:17:04 2005
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -193,8 +193,6 @@ CONFIG_TCP_CONG_BIC=y
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -433,6 +431,8 @@ CONFIG_E1000=y
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -512,7 +512,6 @@ CONFIG_LEGACY_PTY_COUNT=256
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
index 5112edf..297fd52 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc3
-# Wed Jul 13 14:47:54 2005
+# Linux kernel version: 2.6.13-rc6
+# Mon Aug  8 14:17:07 2005
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -287,10 +287,6 @@ CONFIG_NET_CLS_ROUTE=y
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
-CONFIG_NETPOLL=y
-CONFIG_NETPOLL_RX=y
-CONFIG_NETPOLL_TRAP=y
-CONFIG_NET_POLL_CONTROLLER=y
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -488,6 +484,7 @@ CONFIG_SCSI_QLA22XX=m
 CONFIG_SCSI_QLA2300=m
 CONFIG_SCSI_QLA2322=m
 CONFIG_SCSI_QLA6312=m
+CONFIG_SCSI_QLA24XX=m
 CONFIG_SCSI_LPFC=m
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -645,6 +642,10 @@ CONFIG_PPPOE=m
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 CONFIG_NETCONSOLE=y
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_RX=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
 
 #
 # ISDN subsystem
@@ -746,7 +747,6 @@ CONFIG_HVCS=m
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
index fbf1f42..c361e77 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc3
-# Wed Jul 13 14:37:07 2005
+# Linux kernel version: 2.6.13-rc6
+# Mon Aug  8 14:16:54 2005
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -289,10 +289,6 @@ CONFIG_NET_CLS_ROUTE=y
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
-CONFIG_NETPOLL=y
-CONFIG_NETPOLL_RX=y
-CONFIG_NETPOLL_TRAP=y
-CONFIG_NET_POLL_CONTROLLER=y
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -506,6 +502,7 @@ CONFIG_SCSI_QLA22XX=m
 CONFIG_SCSI_QLA2300=m
 CONFIG_SCSI_QLA2322=m
 CONFIG_SCSI_QLA6312=m
+CONFIG_SCSI_QLA24XX=m
 CONFIG_SCSI_LPFC=m
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -579,11 +576,9 @@ CONFIG_IEEE1394_AMDTP=m
 #
 # Macintosh device drivers
 #
-CONFIG_ADB=y
 CONFIG_ADB_PMU=y
 CONFIG_PMAC_SMU=y
 # CONFIG_PMAC_BACKLIGHT is not set
-# CONFIG_INPUT_ADBHID is not set
 CONFIG_THERM_PM72=y
 
 #
@@ -694,6 +689,10 @@ CONFIG_PPPOE=m
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 CONFIG_NETCONSOLE=y
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_RX=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
 
 #
 # ISDN subsystem
@@ -797,7 +796,6 @@ CONFIG_HVCS=m
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
index 76cfd14..1c11031 100644 (file)
 /* The HvReleaseData is the root of the information shared between 
  * the hypervisor and Linux.  
  */
-
-/*
- * WARNING - magic here
- *
- * Ok, this is a horrid hack below, but marginally better than the
- * alternatives.  What we really want is just to initialize
- * hvReleaseData in C as in the #if 0 section here.  However, gcc
- * refuses to believe that (u32)&x is a constant expression, so will
- * not allow the xMsNucDataOffset field to be properly initialized.
- * So, we declare hvReleaseData in inline asm instead.  We use inline
- * asm, rather than a .S file, because the assembler won't generate
- * the necessary relocation for the LparMap either, unless that symbol
- * is declared in the same source file.  Finally, we put the asm in a
- * dummy, attribute-used function, instead of at file scope, because
- * file scope asms don't allow contraints.  We want to use the "i"
- * constraints to put sizeof() and offsetof() expressions in there,
- * because including asm/offsets.h in C code then stringifying causes
- * all manner of warnings.
- */
-#if 0
 struct HvReleaseData hvReleaseData = {
        .xDesc = 0xc8a5d9c4,    /* "HvRD" ebcdic */
        .xSize = sizeof(struct HvReleaseData),
        .xVpdAreasPtrOffset = offsetof(struct naca_struct, xItVpdAreas),
        .xSlicNacaAddr = &naca,         /* 64-bit Naca address */
-       .xMsNucDataOffset = (u32)((unsigned long)&xLparMap - KERNELBASE),
+       .xMsNucDataOffset = LPARMAP_PHYS,
        .xFlags = HVREL_TAGSINACTIVE    /* tags inactive       */
                                        /* 64 bit              */
                                        /* shared processors   */
@@ -70,63 +50,6 @@ struct HvReleaseData hvReleaseData = {
                0xa7, 0x40, 0xf2, 0x4b,
                0xf4, 0x4b, 0xf6, 0xf4 },
 };
-#endif
-
-
-extern struct HvReleaseData hvReleaseData;
-
-static void __attribute_used__ hvReleaseData_wrapper(void)
-{
-       /* This doesn't appear to need any alignment (even 4 byte) */
-       asm volatile (
-               "       lparMapPhys = xLparMap - %3\n"
-               "       .data\n"
-               "       .globl  hvReleaseData\n"
-               "hvReleaseData:\n"
-               "       .long   0xc8a5d9c4\n"   /* xDesc */
-                                               /* "HvRD" in ebcdic */
-               "       .short  %0\n"           /* xSize */
-               "       .short  %1\n"           /* xVpdAreasPtrOffset */
-               "       .llong  naca\n"         /* xSlicNacaAddr */
-               "       .long   lparMapPhys\n"  /* xMsNucDataOffset */
-               "       .long   0\n"            /* xRsvd1 */
-               "       .short  %2\n"           /* xFlags */
-               "       .short  4\n"    /* xVrmIndex  - v5r2m0 */
-               "       .short  3\n"    /* xMinSupportedPlicVrmIndex - v5r1m0 */
-               "       .short  3\n"    /* xMinCompatablePlicVrmIndex - v5r1m0 */
-               "       .long   0xd38995a4\n"   /* xVrmName */
-               "       .long   0xa740f24b\n"   /*   "Linux 2.4.64" ebcdic */
-               "       .long   0xf44bf6f4\n"
-               "       . = hvReleaseData + %0\n"
-               "       .previous\n"
-               : : "i"(sizeof(hvReleaseData)),
-               "i"(offsetof(struct naca_struct, xItVpdAreas)),
-               "i"(HVREL_TAGSINACTIVE /* tags inactive, 64 bit, */
-                                      /* shared processors, HMT allowed */
-                   | 6), /* TEMP: This allows non-GA drivers */
-               "i"(KERNELBASE)
-               );
-}
-
-struct LparMap __attribute__((aligned (16))) xLparMap = {
-       .xNumberEsids = HvEsidsToMap,
-       .xNumberRanges = HvRangesToMap,
-       .xSegmentTableOffs = STAB0_PAGE,
-
-       .xEsids = {
-               { .xKernelEsid = GET_ESID(KERNELBASE),
-                 .xKernelVsid = KERNEL_VSID(KERNELBASE), },
-               { .xKernelEsid = GET_ESID(VMALLOCBASE),
-                 .xKernelVsid = KERNEL_VSID(VMALLOCBASE), },
-       },
-
-       .xRanges = {
-               { .xPages = HvPagesToMap,
-                 .xOffset = 0,
-                 .xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - PAGE_SHIFT),
-               },
-       },
-};
 
 extern void system_reset_iSeries(void);
 extern void machine_check_iSeries(void);
index d9b2660..2ecccb6 100644 (file)
@@ -73,3 +73,8 @@ obj-$(CONFIG_ALTIVEC)         += vecemu.o vector.o
 obj-$(CONFIG_KPROBES)          += kprobes.o
 
 CFLAGS_ioctl32.o += -Ifs/
+
+ifeq ($(CONFIG_PPC_ISERIES),y)
+arch/ppc64/kernel/head.o: arch/ppc64/kernel/lparmap.s
+AFLAGS_head.o += -Iarch/ppc64/kernel
+endif
index 74fc3bc..accaa05 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/cputable.h>
 #include <asm/setup.h>
 #include <asm/hvcall.h>
+#include <asm/iSeries/LparMap.h>
 
 #ifdef CONFIG_PPC_ISERIES
 #define DO_SOFT_DISABLE
@@ -679,6 +680,11 @@ hardware_interrupt_iSeries_masked:
        .globl fwnmi_data_area
 fwnmi_data_area:
 
+#ifdef CONFIG_PPC_ISERIES
+       . = LPARMAP_PHYS
+#include "lparmap.s"
+#endif /* CONFIG_PPC_ISERIES */
+
 /*
  * Vectors for the FWNMI option.  Share common code.
  */
@@ -2071,7 +2077,7 @@ _GLOBAL(hmt_start_secondary)
        blr
 #endif
 
-#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES)
+#if defined(CONFIG_KEXEC) || (defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES))
 _GLOBAL(smp_release_cpus)
        /* All secondary cpus are spinning on a common
         * spinloop, release them all now so they can start
index 8316426..845eebd 100644 (file)
@@ -242,7 +242,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
        dma_addr_t dma_next = 0, dma_addr;
        unsigned long flags;
        struct scatterlist *s, *outs, *segstart;
-       int outcount;
+       int outcount, incount;
        unsigned long handle;
 
        BUG_ON(direction == DMA_NONE);
@@ -252,6 +252,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
 
        outs = s = segstart = &sglist[0];
        outcount = 1;
+       incount = nelems;
        handle = 0;
 
        /* Init first segment length for backout at failure */
@@ -338,10 +339,10 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
 
        DBG("mapped %d elements:\n", outcount);
 
-       /* For the sake of iommu_free_sg, we clear out the length in the
+       /* For the sake of iommu_unmap_sg, we clear out the length in the
         * next entry of the sglist if we didn't fill the list completely
         */
-       if (outcount < nelems) {
+       if (outcount < incount) {
                outs++;
                outs->dma_address = DMA_ERROR_CODE;
                outs->dma_length = 0;
diff --git a/arch/ppc64/kernel/lparmap.c b/arch/ppc64/kernel/lparmap.c
new file mode 100644 (file)
index 0000000..b81de28
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2005  Stephen Rothwell  IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <asm/mmu.h>
+#include <asm/page.h>
+#include <asm/iSeries/LparMap.h>
+
+const struct LparMap __attribute__((__section__(".text"))) xLparMap = {
+       .xNumberEsids = HvEsidsToMap,
+       .xNumberRanges = HvRangesToMap,
+       .xSegmentTableOffs = STAB0_PAGE,
+
+       .xEsids = {
+               { .xKernelEsid = GET_ESID(KERNELBASE),
+                 .xKernelVsid = KERNEL_VSID(KERNELBASE), },
+               { .xKernelEsid = GET_ESID(VMALLOCBASE),
+                 .xKernelVsid = KERNEL_VSID(VMALLOCBASE), },
+       },
+
+       .xRanges = {
+               { .xPages = HvPagesToMap,
+                 .xOffset = 0,
+                 .xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - PAGE_SHIFT),
+               },
+       },
+};
index fdb2fc6..4775f12 100644 (file)
@@ -185,7 +185,7 @@ void kexec_copy_flush(struct kimage *image)
 void kexec_smp_down(void *arg)
 {
        if (ppc_md.cpu_irq_down)
-               ppc_md.cpu_irq_down();
+               ppc_md.cpu_irq_down(1);
 
        local_irq_disable();
        kexec_smp_wait();
@@ -232,7 +232,7 @@ static void kexec_prepare_cpus(void)
 
        /* after we tell the others to go down */
        if (ppc_md.cpu_irq_down)
-               ppc_md.cpu_irq_down();
+               ppc_md.cpu_irq_down(0);
 
        put_cpu();
 
@@ -243,15 +243,19 @@ static void kexec_prepare_cpus(void)
 
 static void kexec_prepare_cpus(void)
 {
+       extern void smp_release_cpus(void);
        /*
         * move the secondarys to us so that we can copy
         * the new kernel 0-0x100 safely
         *
         * do this if kexec in setup.c ?
+        *
+        * We need to release the cpus if we are ever going from an
+        * UP to an SMP kernel.
         */
-       smp_relase_cpus();
+       smp_release_cpus();
        if (ppc_md.cpu_irq_down)
-               ppc_md.cpu_irq_down();
+               ppc_md.cpu_irq_down(0);
        local_irq_disable();
 }
 
index 59f4f99..a05b50b 100644 (file)
@@ -1129,6 +1129,9 @@ _GLOBAL(sys_call_table32)
        .llong .compat_sys_waitid
        .llong .sys32_ioprio_set
        .llong .sys32_ioprio_get
+       .llong .sys_inotify_init        /* 275 */
+       .llong .sys_inotify_add_watch
+       .llong .sys_inotify_rm_watch
 
        .balign 8
 _GLOBAL(sys_call_table)
@@ -1407,3 +1410,6 @@ _GLOBAL(sys_call_table)
        .llong .sys_waitid
        .llong .sys_ioprio_set
        .llong .sys_ioprio_get
+       .llong .sys_inotify_init        /* 275 */
+       .llong .sys_inotify_add_watch
+       .llong .sys_inotify_rm_watch
index e8fbab1..cc262a0 100644 (file)
@@ -794,10 +794,10 @@ void mpic_setup_this_cpu(void)
 
 /*
  * XXX: someone who knows mpic should check this.
- * do we need to eoi the ipi here (see xics comments)?
+ * do we need to eoi the ipi including for kexec cpu here (see xics comments)?
  * or can we reset the mpic in the new kernel?
  */
-void mpic_teardown_this_cpu(void)
+void mpic_teardown_this_cpu(int secondary)
 {
        struct mpic *mpic = mpic_primary;
        unsigned long flags;
index 99fbbc9..ca78a7f 100644 (file)
@@ -256,7 +256,7 @@ extern unsigned int mpic_irq_get_priority(unsigned int irq);
 extern void mpic_setup_this_cpu(void);
 
 /* Clean up for kexec (or cpu offline or ...) */
-extern void mpic_teardown_this_cpu(void);
+extern void mpic_teardown_this_cpu(int secondary);
 
 /* Request IPIs on primary mpic */
 extern void mpic_request_ipis(void);
index ae6f579..d0d55c7 100644 (file)
@@ -108,8 +108,28 @@ void  pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region
        region->end = res->end - offset;
 }
 
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+                             struct pci_bus_region *region)
+{
+       unsigned long offset = 0;
+       struct pci_controller *hose = pci_bus_to_host(dev->bus);
+
+       if (!hose)
+               return;
+
+       if (res->flags & IORESOURCE_IO)
+               offset = (unsigned long)hose->io_base_virt - pci_io_base;
+
+       if (res->flags & IORESOURCE_MEM)
+               offset = hose->pci_mem_offset;
+
+       res->start = region->start + offset;
+       res->end = region->end + offset;
+}
+
 #ifdef CONFIG_HOTPLUG
 EXPORT_SYMBOL(pcibios_resource_to_bus);
+EXPORT_SYMBOL(pcibios_bus_to_resource);
 #endif
 
 /*
index 47727a6..5aca01d 100644 (file)
@@ -916,6 +916,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
                }
        }
 
+#ifdef CONFIG_ALTIVEC
        /* Check if we have a VMX and eventually update CPU features */
        prop = (u32 *)get_flat_dt_prop(node, "ibm,vmx", NULL);
        if (prop && (*prop) > 0) {
@@ -929,6 +930,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
                cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC;
                cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
        }
+#endif /* CONFIG_ALTIVEC */
 
        /*
         * Check for an SMT capable CPU and set the CPU feature. We do
index e248a79..dbbe6c7 100644 (file)
@@ -1803,7 +1803,7 @@ static void __init fixup_device_tree(void)
        if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
            == PROM_ERROR)
                return;
-       if (u3_rev != 0x35)
+       if (u3_rev != 0x35 && u3_rev != 0x37)
                return;
        /* does it need fixup ? */
        if (prom_getproplen(i2c, "interrupts") > 0)
index 687e855..e9c24d2 100644 (file)
@@ -706,6 +706,8 @@ void machine_power_off(void)
        local_irq_disable();
        while (1) ;
 }
+/* Used by the G5 thermal driver */
+EXPORT_SYMBOL_GPL(machine_power_off);
 
 void machine_halt(void)
 {
index bf78227..49a79a5 100644 (file)
@@ -481,10 +481,11 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
        /* Set up Signal Frame */
        ret = setup_rt_frame(sig, ka, info, oldset, regs);
 
-       if (ret && !(ka->sa.sa_flags & SA_NODEFER)) {
+       if (ret) {
                spin_lock_irq(&current->sighand->siglock);
                sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
-               sigaddset(&current->blocked,sig);
+               if (!(ka->sa.sa_flags & SA_NODEFER))
+                       sigaddset(&current->blocked,sig);
                recalc_sigpending();
                spin_unlock_irq(&current->sighand->siglock);
        }
index 3c2fa5c..46f4d6c 100644 (file)
@@ -976,11 +976,12 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
        else
                ret = handle_signal32(signr, &ka, &info, oldset, regs, newsp);
 
-       if (ret && !(ka.sa.sa_flags & SA_NODEFER)) {
+       if (ret) {
                spin_lock_irq(&current->sighand->siglock);
                sigorsets(&current->blocked, &current->blocked,
                          &ka.sa.sa_mask);
-               sigaddset(&current->blocked, signr);
+               if (!(ka.sa.sa_flags & SA_NODEFER))
+                       sigaddset(&current->blocked, signr);
                recalc_sigpending();
                spin_unlock_irq(&current->sighand->siglock);
        }
index 677c445..d9dc6f2 100644 (file)
@@ -647,29 +647,30 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
        }
 }
 
-void xics_teardown_cpu(void)
+void xics_teardown_cpu(int secondary)
 {
        int cpu = smp_processor_id();
-       int status;
 
        ops->cppr_info(cpu, 0x00);
        iosync();
 
        /*
-        * we need to EOI the IPI if we got here from kexec down IPI
-        *
-        * xics doesn't care if we duplicate an EOI as long as we
-        * don't EOI and raise priority.
-        *
-        * probably need to check all the other interrupts too
-        * should we be flagging idle loop instead?
-        * or creating some task to be scheduled?
+        * Some machines need to have at least one cpu in the GIQ,
+        * so leave the master cpu in the group.
         */
-       ops->xirr_info_set(cpu, XICS_IPI);
-
-       status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
-               (1UL << interrupt_server_size) - 1 - default_distrib_server, 0);
-       WARN_ON(status != 0);
+       if (secondary) {
+               /*
+                * we need to EOI the IPI if we got here from kexec down IPI
+                *
+                * probably need to check all the other interrupts too
+                * should we be flagging idle loop instead?
+                * or creating some task to be scheduled?
+                */
+               ops->xirr_info_set(cpu, XICS_IPI);
+               rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
+                       (1UL << interrupt_server_size) - 1 -
+                       default_distrib_server, 0);
+       }
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
index cafd91a..0b191f2 100644 (file)
@@ -647,7 +647,12 @@ void __init do_init_bootmem(void)
 new_range:
                        mem_start = read_n_cells(addr_cells, &memcell_buf);
                        mem_size = read_n_cells(size_cells, &memcell_buf);
-                       numa_domain = numa_enabled ? of_node_numa_domain(memory) : 0;
+                       if (numa_enabled) {
+                               numa_domain = of_node_numa_domain(memory);
+                               if (numa_domain  >= MAX_NUMNODES)
+                                       numa_domain = 0;
+                       } else
+                               numa_domain =  0;
 
                        if (numa_domain != nid)
                                continue;
index 7f6e13a..0553943 100644 (file)
@@ -329,13 +329,16 @@ int xmon_core(struct pt_regs *regs, int fromipi)
                printf("cpu 0x%x: Exception %lx %s in xmon, "
                       "returning to main loop\n",
                       cpu, regs->trap, getvecname(TRAP(regs)));
+               release_output_lock();
                longjmp(xmon_fault_jmp[cpu], 1);
        }
 
        if (setjmp(recurse_jmp) != 0) {
                if (!in_xmon || !xmon_gate) {
+                       get_output_lock();
                        printf("xmon: WARNING: bad recursive fault "
                               "on cpu 0x%x\n", cpu);
+                       release_output_lock();
                        goto waiting;
                }
                secondary = !(xmon_taken && cpu == xmon_owner);
index d05d65a..7358cdb 100644 (file)
@@ -637,12 +637,11 @@ handle_signal32(unsigned long sig, struct k_sigaction *ka,
        else
                setup_frame32(sig, ka, oldset, regs);
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 }
 
index 799a98e..23fe94e 100644 (file)
@@ -1449,3 +1449,29 @@ compat_sys_kexec_load_wrapper:
        llgtr   %r4,%r4                 # struct kexec_segment *
        llgfr   %r5,%r5                 # unsigned long
        jg      compat_sys_kexec_load
+
+       .globl  sys_ioprio_set_wrapper
+sys_ioprio_set_wrapper:
+       lgfr    %r2,%r2                 # int
+       lgfr    %r3,%r3                 # int
+       lgfr    %r4,%r4                 # int
+       jg      sys_ioprio_set
+
+       .globl  sys_ioprio_get_wrapper
+sys_ioprio_get_wrapper:
+       lgfr    %r2,%r2                 # int
+       lgfr    %r3,%r3                 # int
+       jg      sys_ioprio_get
+
+       .globl  sys_inotify_add_watch_wrapper
+sys_inotify_add_watch_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgtr   %r3,%r3                 # const char *
+       llgfr   %r4,%r4                 # u32
+       jg      sys_inotify_add_watch
+
+       .globl  sys_inotify_rm_watch_wrapper
+sys_inotify_rm_watch_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgfr   %r3,%r3                 # u32
+       jg      sys_inotify_rm_watch
index 2006214..d47fecb 100644 (file)
@@ -46,9 +46,9 @@ int  __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
                                "lra    3,0(%4)\n"
                                "lr     5,%5\n"
                                "diag   2,4,0x8\n"
-                               "brc    8, .Litfits\n"
+                               "brc    8, 1f\n"
                                "ar     5, %5\n"
-                               ".Litfits: \n"
+                               "1: \n"
                                "lr     %0,4\n"
                                "lr     %1,5\n"
                                : "=d" (return_code), "=d" (return_len)
@@ -64,9 +64,9 @@ int  __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
                                "sam31\n"
                                "diag   2,4,0x8\n"
                                "sam64\n"
-                               "brc    8, .Litfits\n"
+                               "brc    8, 1f\n"
                                "agr    5, %5\n"
-                               ".Litfits: \n"
+                               "1: \n"
                                "lgr    %0,4\n"
                                "lgr    %1,5\n"
                                : "=d" (return_code), "=d" (return_len)
index 2721c3a..5aa71b0 100644 (file)
@@ -70,6 +70,8 @@ machine_kexec(struct kimage *image)
        for (;;);
 }
 
+extern void pfault_fini(void);
+
 static void
 kexec_halt_all_cpus(void *kernel_image)
 {
@@ -78,6 +80,11 @@ kexec_halt_all_cpus(void *kernel_image)
        struct kimage *image;
        relocate_kernel_t data_mover;
 
+#ifdef CONFIG_PFAULT
+       if (MACHINE_IS_VM)
+               pfault_fini();
+#endif
+
        if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid))
                signal_processor(smp_processor_id(), sigp_stop);
 
index d5e4a62..2a25ec7 100644 (file)
@@ -4,6 +4,7 @@
  * (C) Copyright IBM Corp. 2005
  *
  * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ *           Heiko Carstens <heiko.carstens@de.ibm.com>
  *
  */
 
        relocate_kernel:
                basr    %r13,0          #base address
        .base:
-               spx     zero64-.base(%r13)      #absolute addressing mode
                stnsm   sys_msk-.base(%r13),0xf8        #disable DAT and IRQ (external)
+               spx     zero64-.base(%r13)      #absolute addressing mode
+               stctl   %c0,%c15,ctlregs-.base(%r13)
+               stm     %r0,%r15,gprregs-.base(%r13)
+               la      %r1,load_psw-.base(%r13)
+               mvc     0(8,%r0),0(%r1)
+               la      %r0,.back-.base(%r13)
+               st      %r0,4(%r0)
+               oi      4(%r0),0x80
+               mvc     0x68(8,%r0),0(%r1)
+               la      %r0,.back_pgm-.base(%r13)
+               st      %r0,0x6c(%r0)
+               oi      0x6c(%r0),0x80
+               lhi     %r0,0
+               diag    %r0,%r0,0x308
+       .back:
+               basr    %r13,0
+       .back_base:
+               oi      have_diag308-.back_base(%r13),0x01
+               lctl    %c0,%c15,ctlregs-.back_base(%r13)
+               lm      %r0,%r15,gprregs-.back_base(%r13)
+               j       .start_reloc
+       .back_pgm:
+               lm      %r0,%r15,gprregs-.base(%r13)
+       .start_reloc:
                lhi     %r10,-1         #preparing the mask
                sll     %r10,12         #shift it such that it becomes 0xf000
        .top:
                o       %r3,4(%r4)      #or load address into psw
                st      %r3,4(%r4)
                mvc     0(8,%r0),0(%r4) #copy psw to absolute address 0
+               tm      have_diag308-.base(%r13),0x01
+               jno     .no_diag308
+               diag    %r0,%r0,0x308
+       .no_diag308:
                sr      %r1,%r1         #clear %r1
                sr      %r2,%r2         #clear %r2
                sigp    %r1,%r2,0x12    #set cpuid to zero
                .long   0x00080000,0x80000000
        sys_msk:
                .quad   0
+       ctlregs:
+               .rept   16
+               .long   0
+               .endr
+       gprregs:
+               .rept   16
+               .long   0
+               .endr
+       have_diag308:
+               .byte   0
+               .align  8
        relocate_kernel_end:
        .globl  relocate_kernel_len
        relocate_kernel_len:
index 96290cc..8cdb86e 100644 (file)
@@ -4,6 +4,7 @@
  * (C) Copyright IBM Corp. 2005
  *
  * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ *           Heiko Carstens <heiko.carstens@de.ibm.com>
  *
  */
 
        relocate_kernel:
                basr    %r13,0          #base address
        .base:
+               stnsm   sys_msk-.base(%r13),0xf8        #disable DAT and IRQs
                spx     zero64-.base(%r13)      #absolute addressing mode
-               stnsm   sys_msk-.base(%r13),0xf8        #disable DAT and IRQ (external)
+               stctg   %c0,%c15,ctlregs-.base(%r13)
+               stmg    %r0,%r15,gprregs-.base(%r13)
+               lghi    %r0,3
+               sllg    %r0,%r0,31
+               stg     %r0,0x1d0(%r0)
+               la      %r0,.back_pgm-.base(%r13)
+               stg     %r0,0x1d8(%r0)
+               la      %r1,load_psw-.base(%r13)
+               mvc     0(8,%r0),0(%r1)
+               la      %r0,.back-.base(%r13)
+               st      %r0,4(%r0)
+               oi      4(%r0),0x80
+               lghi    %r0,0
+               diag    %r0,%r0,0x308
+       .back:
+               lhi     %r1,1           #mode 1 = esame
+               sigp    %r1,%r0,0x12    #switch to esame mode
+               sam64                   #switch to 64 bit addressing mode
+               basr    %r13,0
+       .back_base:
+               oi      have_diag308-.back_base(%r13),0x01
+               lctlg   %c0,%c15,ctlregs-.back_base(%r13)
+               lmg     %r0,%r15,gprregs-.back_base(%r13)
+               j       .top
+       .back_pgm:
+               lmg     %r0,%r15,gprregs-.base(%r13)
        .top:
                lghi    %r7,4096        #load PAGE_SIZE in r7
                lghi    %r9,4096        #load PAGE_SIZE in r9
                o       %r3,4(%r4)      #or load address into psw
                st      %r3,4(%r4)
                mvc     0(8,%r0),0(%r4) #copy psw to absolute address 0
+               tm      have_diag308-.base(%r13),0x01
+               jno     .no_diag308
+               diag    %r0,%r0,0x308
+       .no_diag308:
                sam31                   #31 bit mode
                sr      %r1,%r1         #erase register r1
                sr      %r2,%r2         #erase register r2
                .long   0x00080000,0x80000000
        sys_msk:
                .quad   0
+       ctlregs:
+               .rept   16
+               .quad   0
+               .endr
+       gprregs:
+               .rept   16
+               .quad   0
+               .endr
+       have_diag308:
+               .byte   0
+               .align  8
        relocate_kernel_end:
        .globl  relocate_kernel_len
        relocate_kernel_len:
                .quad   relocate_kernel_end - relocate_kernel
-
index 610c1d0..6a3f5b7 100644 (file)
@@ -429,13 +429,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
        else
                setup_frame(sig, ka, oldset, regs);
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 }
 
 /*
index da77f00..85222fe 100644 (file)
@@ -537,7 +537,8 @@ int __devinit start_secondary(void *cpuvoid)
 #endif
 #ifdef CONFIG_PFAULT
        /* Enable pfault pseudo page faults on this cpu. */
-       pfault_init();
+       if (MACHINE_IS_VM)
+               pfault_init();
 #endif
        /* Mark this cpu as online */
        cpu_set(smp_processor_id(), cpu_online_map);
@@ -690,7 +691,8 @@ __cpu_disable(void)
 
 #ifdef CONFIG_PFAULT
        /* Disable pfault pseudo page faults on this cpu. */
-       pfault_fini();
+       if (MACHINE_IS_VM)
+               pfault_fini();
 #endif
 
        /* disable all external interrupts */
index a8668af..426d7ca 100644 (file)
@@ -290,3 +290,8 @@ SYSCALL(sys_add_key,sys_add_key,compat_sys_add_key_wrapper)
 SYSCALL(sys_request_key,sys_request_key,compat_sys_request_key_wrapper)
 SYSCALL(sys_keyctl,sys_keyctl,compat_sys_keyctl)               /* 280 */
 SYSCALL(sys_waitid,sys_waitid,compat_sys_waitid_wrapper)
+SYSCALL(sys_ioprio_set,sys_ioprio_set,sys_ioprio_set_wrapper)
+SYSCALL(sys_ioprio_get,sys_ioprio_get,sys_ioprio_get_wrapper)
+SYSCALL(sys_inotify_init,sys_inotify_init,sys_inotify_init)
+SYSCALL(sys_inotify_add_watch,sys_inotify_add_watch,sys_inotify_add_watch_wrapper)
+SYSCALL(sys_inotify_rm_watch,sys_inotify_rm_watch,sys_inotify_rm_watch_wrapper)
index bc7b7be..6b8703e 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/kallsyms.h>
+#include <linux/reboot.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -675,6 +676,19 @@ asmlinkage void kernel_stack_overflow(struct pt_regs * regs)
        panic("Corrupt kernel stack, can't continue.");
 }
 
+#ifndef CONFIG_ARCH_S390X
+static int
+pagex_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+       if (MACHINE_IS_VM)
+               cpcmd("SET PAGEX OFF", NULL, 0, NULL);
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block pagex_reboot_notifier = {
+       .notifier_call = &pagex_reboot_event,
+};
+#endif
 
 /* init is done in lowcore.S and head.S */
 
@@ -735,6 +749,7 @@ void __init trap_init(void)
                                                    &ext_int_pfault);
 #endif
 #ifndef CONFIG_ARCH_S390X
+               register_reboot_notifier(&pagex_reboot_notifier);
                cpcmd("SET PAGEX ON", NULL, 0, NULL);
 #endif
        }
index 6615e48..fb63681 100644 (file)
@@ -1145,5 +1145,10 @@ ENTRY(sys_call_table)
        .long sys_add_key               /* 285 */
        .long sys_request_key
        .long sys_keyctl
+       .long sys_ioprio_set
+       .long sys_ioprio_get
+       .long sys_inotify_init          /* 290 */
+       .long sys_inotify_add_watch
+       .long sys_inotify_rm_watch
 
 /* End of entry.S */
index 8022243..b475c4d 100644 (file)
@@ -546,13 +546,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
        if (ka->sa.sa_flags & SA_ONESHOT)
                ka->sa.sa_handler = SIG_DFL;
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 }
 
 /*
index c6a14a8..3ea8929 100644 (file)
@@ -664,13 +664,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
        else
                setup_frame(sig, ka, oldset, regs);
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 }
 
 /*
index 6aabc63..a3d0378 100644 (file)
@@ -342,4 +342,9 @@ sys_call_table:
        .long sys_add_key
        .long sys_request_key
        .long sys_keyctl                /* 315 */
+       .long sys_ioprio_set
+       .long sys_ioprio_get
+       .long sys_inotify_init
+       .long sys_inotify_add_watch
+       .long sys_inotify_rm_watch      /* 320 */
 
index a249328..f08d0ea 100644 (file)
@@ -223,13 +223,13 @@ good_area:
         */
 survive:
        switch (handle_mm_fault(mm, vma, address, writeaccess)) {
-       case 1:
+       case VM_FAULT_MINOR:
                tsk->min_flt++;
                break;
-       case 2:
+       case VM_FAULT_MAJOR:
                tsk->maj_flt++;
                break;
-       case 0:
+       case VM_FAULT_SIGBUS:
                goto do_sigbus;
        default:
                goto out_of_memory;
index 011ff35..5f34d7d 100644 (file)
@@ -1034,13 +1034,12 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,
                else
                        setup_frame(&ka->sa, regs, signr, oldset, info);
        }
-       if (!(ka->sa.sa_flags & SA_NOMASK)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NOMASK))
                sigaddset(&current->blocked, signr);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 }
 
 static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
index 1bd430d..8faa8dc 100644 (file)
@@ -98,8 +98,9 @@ extern void ___rw_write_enter(void);
  * The module references will be fixed up by module_frob_arch_sections.
  */
 #define DOT_ALIAS2(__ret, __x, __arg1, __arg2) \
-       extern __ret __x(__arg1, __arg2) \
-                    __attribute__((weak, alias("." # __x)));
+       extern __ret __x(__arg1, __arg2); \
+       asm(".weak " #__x);\
+       asm(#__x "=." #__x);
 
 DOT_ALIAS2(int, div, int, int)
 DOT_ALIAS2(int, mul, int, int)
index 093281b..6f00ab8 100644 (file)
@@ -8,7 +8,7 @@ EXTRA_CFLAGS := -Werror
 extra-y                := head.o init_task.o vmlinux.lds
 
 obj-y          := process.o setup.o cpu.o idprom.o \
-                  traps.o devices.o auxio.o \
+                  traps.o devices.o auxio.o una_asm.o \
                   irq.o ptrace.o time.o sys_sparc.o signal.o \
                   unaligned.o central.o pci.o starfire.o semaphore.o \
                   power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o
index bba140d..f21c993 100644 (file)
@@ -540,6 +540,7 @@ void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res,
 
        pbm->parent->resource_adjust(pdev, res, root);
 }
+EXPORT_SYMBOL(pcibios_bus_to_resource);
 
 char * __init pcibios_setup(char *str)
 {
index b279346..60f5dfa 100644 (file)
@@ -574,13 +574,12 @@ static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,
 {
        setup_rt_frame(ka, regs, signr, oldset,
                       (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
-       if (!(ka->sa.sa_flags & SA_NOMASK)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NOMASK))
                sigaddset(&current->blocked,signr);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 }
 
 static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
index f28428f..b1ed230 100644 (file)
@@ -1325,13 +1325,12 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
                else
                        setup_frame32(&ka->sa, regs, signr, oldset, info);
        }
-       if (!(ka->sa.sa_flags & SA_NOMASK)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NOMASK))
                sigaddset(&current->blocked,signr);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 }
 
 static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs,
index 100b010..0c9e54b 100644 (file)
@@ -2127,6 +2127,9 @@ void __init trap_init(void)
            TI_PRE_COUNT != offsetof(struct thread_info, preempt_count) ||
            TI_NEW_CHILD != offsetof(struct thread_info, new_child) ||
            TI_SYS_NOERROR != offsetof(struct thread_info, syscall_noerror) ||
+           TI_RESTART_BLOCK != offsetof(struct thread_info, restart_block) ||
+           TI_KUNA_REGS != offsetof(struct thread_info, kern_una_regs) ||
+           TI_KUNA_INSN != offsetof(struct thread_info, kern_una_insn) ||
            TI_FPREGS != offsetof(struct thread_info, fpregs) ||
            (TI_FPREGS & (64 - 1)))
                thread_info_offsets_are_bolixed_dave();
diff --git a/arch/sparc64/kernel/una_asm.S b/arch/sparc64/kernel/una_asm.S
new file mode 100644 (file)
index 0000000..cbb4058
--- /dev/null
@@ -0,0 +1,153 @@
+/* una_asm.S: Kernel unaligned trap assembler helpers.
+ *
+ * Copyright (C) 1996,2005 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+       .text
+
+kernel_unaligned_trap_fault:
+       call    kernel_mna_trap_fault
+        nop
+       retl
+        nop
+       .size   kern_unaligned_trap_fault, .-kern_unaligned_trap_fault
+
+       .globl  __do_int_store
+__do_int_store:
+       rd      %asi, %o4
+       wr      %o3, 0, %asi
+       ldx     [%o2], %g3
+       cmp     %o1, 2
+       be,pn   %icc, 2f
+        cmp    %o1, 4
+       be,pt   %icc, 1f
+        srlx   %g3, 24, %g2
+       srlx    %g3, 56, %g1
+       srlx    %g3, 48, %g7
+4:     stba    %g1, [%o0] %asi
+       srlx    %g3, 40, %g1
+5:     stba    %g7, [%o0 + 1] %asi
+       srlx    %g3, 32, %g7
+6:     stba    %g1, [%o0 + 2] %asi
+7:     stba    %g7, [%o0 + 3] %asi
+       srlx    %g3, 16, %g1
+8:     stba    %g2, [%o0 + 4] %asi
+       srlx    %g3, 8, %g7
+9:     stba    %g1, [%o0 + 5] %asi
+10:    stba    %g7, [%o0 + 6] %asi
+       ba,pt   %xcc, 0f
+11:     stba   %g3, [%o0 + 7] %asi
+1:     srl     %g3, 16, %g7
+12:    stba    %g2, [%o0] %asi
+       srl     %g3, 8, %g2
+13:    stba    %g7, [%o0 + 1] %asi
+14:    stba    %g2, [%o0 + 2] %asi
+       ba,pt   %xcc, 0f
+15:     stba   %g3, [%o0 + 3] %asi
+2:     srl     %g3, 8, %g2
+16:    stba    %g2, [%o0] %asi
+17:    stba    %g3, [%o0 + 1] %asi
+0:
+       wr      %o4, 0x0, %asi
+       retl
+        nop
+       .size   __do_int_store, .-__do_int_store
+
+       .section        __ex_table
+       .word           4b, kernel_unaligned_trap_fault
+       .word           5b, kernel_unaligned_trap_fault
+       .word           6b, kernel_unaligned_trap_fault
+       .word           7b, kernel_unaligned_trap_fault
+       .word           8b, kernel_unaligned_trap_fault
+       .word           9b, kernel_unaligned_trap_fault
+       .word           10b, kernel_unaligned_trap_fault
+       .word           11b, kernel_unaligned_trap_fault
+       .word           12b, kernel_unaligned_trap_fault
+       .word           13b, kernel_unaligned_trap_fault
+       .word           14b, kernel_unaligned_trap_fault
+       .word           15b, kernel_unaligned_trap_fault
+       .word           16b, kernel_unaligned_trap_fault
+       .word           17b, kernel_unaligned_trap_fault
+       .previous
+
+       .globl  do_int_load
+do_int_load:
+       rd      %asi, %o5
+       wr      %o4, 0, %asi
+       cmp     %o1, 8
+       bge,pn  %icc, 9f
+        cmp    %o1, 4
+       be,pt   %icc, 6f
+4:      lduba  [%o2] %asi, %g2
+5:     lduba   [%o2 + 1] %asi, %g3
+       sll     %g2, 8, %g2
+       brz,pt  %o3, 3f
+        add    %g2, %g3, %g2
+       sllx    %g2, 48, %g2
+       srax    %g2, 48, %g2
+3:     ba,pt   %xcc, 0f
+        stx    %g2, [%o0]
+6:     lduba   [%o2 + 1] %asi, %g3
+       sll     %g2, 24, %g2
+7:     lduba   [%o2 + 2] %asi, %g7
+       sll     %g3, 16, %g3
+8:     lduba   [%o2 + 3] %asi, %g1
+       sll     %g7, 8, %g7
+       or      %g2, %g3, %g2
+       or      %g7, %g1, %g7
+       or      %g2, %g7, %g2
+       brnz,a,pt %o3, 3f
+        sra    %g2, 0, %g2
+3:     ba,pt   %xcc, 0f
+        stx    %g2, [%o0]
+9:     lduba   [%o2] %asi, %g2
+10:    lduba   [%o2 + 1] %asi, %g3
+       sllx    %g2, 56, %g2
+11:    lduba   [%o2 + 2] %asi, %g7
+       sllx    %g3, 48, %g3
+12:    lduba   [%o2 + 3] %asi, %g1
+       sllx    %g7, 40, %g7
+       sllx    %g1, 32, %g1
+       or      %g2, %g3, %g2
+       or      %g7, %g1, %g7
+13:    lduba   [%o2 + 4] %asi, %g3
+       or      %g2, %g7, %g7
+14:    lduba   [%o2 + 5] %asi, %g1
+       sllx    %g3, 24, %g3
+15:    lduba   [%o2 + 6] %asi, %g2
+       sllx    %g1, 16, %g1
+       or      %g7, %g3, %g7
+16:    lduba   [%o2 + 7] %asi, %g3
+       sllx    %g2, 8, %g2
+       or      %g7, %g1, %g7
+       or      %g2, %g3, %g2
+       or      %g7, %g2, %g7
+       cmp     %o1, 8
+       be,a,pt %icc, 0f
+        stx    %g7, [%o0]
+       srlx    %g7, 32, %g2
+       sra     %g7, 0, %g7
+       stx     %g2, [%o0]
+       stx     %g7, [%o0 + 8]
+0:
+       wr      %o5, 0x0, %asi
+       retl
+        nop
+       .size   __do_int_load, .-__do_int_load
+
+       .section        __ex_table
+       .word           4b, kernel_unaligned_trap_fault
+       .word           5b, kernel_unaligned_trap_fault
+       .word           6b, kernel_unaligned_trap_fault
+       .word           7b, kernel_unaligned_trap_fault
+       .word           8b, kernel_unaligned_trap_fault
+       .word           9b, kernel_unaligned_trap_fault
+       .word           10b, kernel_unaligned_trap_fault
+       .word           11b, kernel_unaligned_trap_fault
+       .word           12b, kernel_unaligned_trap_fault
+       .word           13b, kernel_unaligned_trap_fault
+       .word           14b, kernel_unaligned_trap_fault
+       .word           15b, kernel_unaligned_trap_fault
+       .word           16b, kernel_unaligned_trap_fault
+       .previous
index 4372bf3..11c3e88 100644 (file)
@@ -180,169 +180,28 @@ static void __attribute_used__ unaligned_panic(char *str, struct pt_regs *regs)
        die_if_kernel(str, regs);
 }
 
-#define do_integer_load(dest_reg, size, saddr, is_signed, asi, errh) ({                \
-__asm__ __volatile__ (                                                         \
-       "wr     %4, 0, %%asi\n\t"                                               \
-       "cmp    %1, 8\n\t"                                                      \
-       "bge,pn %%icc, 9f\n\t"                                                  \
-       " cmp   %1, 4\n\t"                                                      \
-       "be,pt  %%icc, 6f\n"                                                    \
-"4:\t" " lduba [%2] %%asi, %%l1\n"                                             \
-"5:\t" "lduba  [%2 + 1] %%asi, %%l2\n\t"                                       \
-       "sll    %%l1, 8, %%l1\n\t"                                              \
-       "brz,pt %3, 3f\n\t"                                                     \
-       " add   %%l1, %%l2, %%l1\n\t"                                           \
-       "sllx   %%l1, 48, %%l1\n\t"                                             \
-       "srax   %%l1, 48, %%l1\n"                                               \
-"3:\t" "ba,pt  %%xcc, 0f\n\t"                                                  \
-       " stx   %%l1, [%0]\n"                                                   \
-"6:\t" "lduba  [%2 + 1] %%asi, %%l2\n\t"                                       \
-       "sll    %%l1, 24, %%l1\n"                                               \
-"7:\t" "lduba  [%2 + 2] %%asi, %%g7\n\t"                                       \
-       "sll    %%l2, 16, %%l2\n"                                               \
-"8:\t" "lduba  [%2 + 3] %%asi, %%g1\n\t"                                       \
-       "sll    %%g7, 8, %%g7\n\t"                                              \
-       "or     %%l1, %%l2, %%l1\n\t"                                           \
-       "or     %%g7, %%g1, %%g7\n\t"                                           \
-       "or     %%l1, %%g7, %%l1\n\t"                                           \
-       "brnz,a,pt %3, 3f\n\t"                                                  \
-       " sra   %%l1, 0, %%l1\n"                                                \
-"3:\t" "ba,pt  %%xcc, 0f\n\t"                                                  \
-       " stx   %%l1, [%0]\n"                                                   \
-"9:\t" "lduba  [%2] %%asi, %%l1\n"                                             \
-"10:\t"        "lduba  [%2 + 1] %%asi, %%l2\n\t"                                       \
-       "sllx   %%l1, 56, %%l1\n"                                               \
-"11:\t"        "lduba  [%2 + 2] %%asi, %%g7\n\t"                                       \
-       "sllx   %%l2, 48, %%l2\n"                                               \
-"12:\t"        "lduba  [%2 + 3] %%asi, %%g1\n\t"                                       \
-       "sllx   %%g7, 40, %%g7\n\t"                                             \
-       "sllx   %%g1, 32, %%g1\n\t"                                             \
-       "or     %%l1, %%l2, %%l1\n\t"                                           \
-       "or     %%g7, %%g1, %%g7\n"                                             \
-"13:\t"        "lduba  [%2 + 4] %%asi, %%l2\n\t"                                       \
-       "or     %%l1, %%g7, %%g7\n"                                             \
-"14:\t"        "lduba  [%2 + 5] %%asi, %%g1\n\t"                                       \
-       "sllx   %%l2, 24, %%l2\n"                                               \
-"15:\t"        "lduba  [%2 + 6] %%asi, %%l1\n\t"                                       \
-       "sllx   %%g1, 16, %%g1\n\t"                                             \
-       "or     %%g7, %%l2, %%g7\n"                                             \
-"16:\t"        "lduba  [%2 + 7] %%asi, %%l2\n\t"                                       \
-       "sllx   %%l1, 8, %%l1\n\t"                                              \
-       "or     %%g7, %%g1, %%g7\n\t"                                           \
-       "or     %%l1, %%l2, %%l1\n\t"                                           \
-       "or     %%g7, %%l1, %%g7\n\t"                                           \
-       "cmp    %1, 8\n\t"                                                      \
-       "be,a,pt %%icc, 0f\n\t"                                                 \
-       " stx   %%g7, [%0]\n\t"                                                 \
-       "srlx   %%g7, 32, %%l1\n\t"                                             \
-       "sra    %%g7, 0, %%g7\n\t"                                              \
-       "stx    %%l1, [%0]\n\t"                                                 \
-       "stx    %%g7, [%0 + 8]\n"                                               \
-"0:\n\t"                                                                       \
-       "wr     %%g0, %5, %%asi\n\n\t"                                          \
-       ".section __ex_table\n\t"                                               \
-       ".word  4b, " #errh "\n\t"                                              \
-       ".word  5b, " #errh "\n\t"                                              \
-       ".word  6b, " #errh "\n\t"                                              \
-       ".word  7b, " #errh "\n\t"                                              \
-       ".word  8b, " #errh "\n\t"                                              \
-       ".word  9b, " #errh "\n\t"                                              \
-       ".word  10b, " #errh "\n\t"                                             \
-       ".word  11b, " #errh "\n\t"                                             \
-       ".word  12b, " #errh "\n\t"                                             \
-       ".word  13b, " #errh "\n\t"                                             \
-       ".word  14b, " #errh "\n\t"                                             \
-       ".word  15b, " #errh "\n\t"                                             \
-       ".word  16b, " #errh "\n\n\t"                                           \
-       ".previous\n\t"                                                         \
-       : : "r" (dest_reg), "r" (size), "r" (saddr), "r" (is_signed),           \
-         "r" (asi), "i" (ASI_AIUS)                                             \
-       : "l1", "l2", "g7", "g1", "cc");                                        \
-})
+extern void do_int_load(unsigned long *dest_reg, int size,
+                       unsigned long *saddr, int is_signed, int asi);
        
-#define store_common(dst_addr, size, src_val, asi, errh) ({                    \
-__asm__ __volatile__ (                                                         \
-       "wr     %3, 0, %%asi\n\t"                                               \
-       "ldx    [%2], %%l1\n"                                                   \
-       "cmp    %1, 2\n\t"                                                      \
-       "be,pn  %%icc, 2f\n\t"                                                  \
-       " cmp   %1, 4\n\t"                                                      \
-       "be,pt  %%icc, 1f\n\t"                                                  \
-       " srlx  %%l1, 24, %%l2\n\t"                                             \
-       "srlx   %%l1, 56, %%g1\n\t"                                             \
-       "srlx   %%l1, 48, %%g7\n"                                               \
-"4:\t" "stba   %%g1, [%0] %%asi\n\t"                                           \
-       "srlx   %%l1, 40, %%g1\n"                                               \
-"5:\t" "stba   %%g7, [%0 + 1] %%asi\n\t"                                       \
-       "srlx   %%l1, 32, %%g7\n"                                               \
-"6:\t" "stba   %%g1, [%0 + 2] %%asi\n"                                         \
-"7:\t" "stba   %%g7, [%0 + 3] %%asi\n\t"                                       \
-       "srlx   %%l1, 16, %%g1\n"                                               \
-"8:\t" "stba   %%l2, [%0 + 4] %%asi\n\t"                                       \
-       "srlx   %%l1, 8, %%g7\n"                                                \
-"9:\t" "stba   %%g1, [%0 + 5] %%asi\n"                                         \
-"10:\t"        "stba   %%g7, [%0 + 6] %%asi\n\t"                                       \
-       "ba,pt  %%xcc, 0f\n"                                                    \
-"11:\t"        " stba  %%l1, [%0 + 7] %%asi\n"                                         \
-"1:\t" "srl    %%l1, 16, %%g7\n"                                               \
-"12:\t"        "stba   %%l2, [%0] %%asi\n\t"                                           \
-       "srl    %%l1, 8, %%l2\n"                                                \
-"13:\t"        "stba   %%g7, [%0 + 1] %%asi\n"                                         \
-"14:\t"        "stba   %%l2, [%0 + 2] %%asi\n\t"                                       \
-       "ba,pt  %%xcc, 0f\n"                                                    \
-"15:\t"        " stba  %%l1, [%0 + 3] %%asi\n"                                         \
-"2:\t" "srl    %%l1, 8, %%l2\n"                                                \
-"16:\t"        "stba   %%l2, [%0] %%asi\n"                                             \
-"17:\t"        "stba   %%l1, [%0 + 1] %%asi\n"                                         \
-"0:\n\t"                                                                       \
-       "wr     %%g0, %4, %%asi\n\n\t"                                          \
-       ".section __ex_table\n\t"                                               \
-       ".word  4b, " #errh "\n\t"                                              \
-       ".word  5b, " #errh "\n\t"                                              \
-       ".word  6b, " #errh "\n\t"                                              \
-       ".word  7b, " #errh "\n\t"                                              \
-       ".word  8b, " #errh "\n\t"                                              \
-       ".word  9b, " #errh "\n\t"                                              \
-       ".word  10b, " #errh "\n\t"                                             \
-       ".word  11b, " #errh "\n\t"                                             \
-       ".word  12b, " #errh "\n\t"                                             \
-       ".word  13b, " #errh "\n\t"                                             \
-       ".word  14b, " #errh "\n\t"                                             \
-       ".word  15b, " #errh "\n\t"                                             \
-       ".word  16b, " #errh "\n\t"                                             \
-       ".word  17b, " #errh "\n\n\t"                                           \
-       ".previous\n\t"                                                         \
-       : : "r" (dst_addr), "r" (size), "r" (src_val), "r" (asi), "i" (ASI_AIUS)\
-       : "l1", "l2", "g7", "g1", "cc");                                        \
-})
-
-#define do_integer_store(reg_num, size, dst_addr, regs, asi, errh) ({          \
-       unsigned long zero = 0;                                                 \
-       unsigned long *src_val = &zero;                                         \
-                                                                               \
-       if (size == 16) {                                                       \
-               size = 8;                                                       \
-               zero = (((long)(reg_num ?                                       \
-                       (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) |       \
-                       (unsigned)fetch_reg(reg_num + 1, regs);                 \
-       } else if (reg_num) src_val = fetch_reg_addr(reg_num, regs);            \
-       store_common(dst_addr, size, src_val, asi, errh);                       \
-})
-
-extern void smp_capture(void);
-extern void smp_release(void);
-
-#define do_atomic(srcdest_reg, mem, errh) ({                                   \
-       unsigned long flags, tmp;                                               \
-                                                                               \
-       smp_capture();                                                          \
-       local_irq_save(flags);                                                  \
-       tmp = *srcdest_reg;                                                     \
-       do_integer_load(srcdest_reg, 4, mem, 0, errh);                          \
-       store_common(mem, 4, &tmp, errh);                                       \
-       local_irq_restore(flags);                                               \
-       smp_release();                                                          \
-})
+extern void __do_int_store(unsigned long *dst_addr, int size,
+                          unsigned long *src_val, int asi);
+
+static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr,
+                               struct pt_regs *regs, int asi)
+{
+       unsigned long zero = 0;
+       unsigned long *src_val = &zero;
+
+       if (size == 16) {
+               size = 8;
+               zero = (((long)(reg_num ?
+                       (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) |
+                       (unsigned)fetch_reg(reg_num + 1, regs);
+       } else if (reg_num) {
+               src_val = fetch_reg_addr(reg_num, regs);
+       }
+       __do_int_store(dst_addr, size, src_val, asi);
+}
 
 static inline void advance(struct pt_regs *regs)
 {
@@ -364,24 +223,29 @@ static inline int ok_for_kernel(unsigned int insn)
        return !floating_point_load_or_store_p(insn);
 }
 
-void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn) __asm__ ("kernel_mna_trap_fault");
-
-void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
+void kernel_mna_trap_fault(void)
 {
-       unsigned long g2 = regs->u_regs [UREG_G2];
+       struct pt_regs *regs = current_thread_info()->kern_una_regs;
+       unsigned int insn = current_thread_info()->kern_una_insn;
+       unsigned long g2 = regs->u_regs[UREG_G2];
        unsigned long fixup = search_extables_range(regs->tpc, &g2);
 
        if (!fixup) {
-               unsigned long address = compute_effective_address(regs, insn, ((insn >> 25) & 0x1f));
+               unsigned long address;
+
+               address = compute_effective_address(regs, insn,
+                                                   ((insn >> 25) & 0x1f));
                if (address < PAGE_SIZE) {
-                       printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference in mna handler");
+                       printk(KERN_ALERT "Unable to handle kernel NULL "
+                              "pointer dereference in mna handler");
                } else
-                       printk(KERN_ALERT "Unable to handle kernel paging request in mna handler");
+                       printk(KERN_ALERT "Unable to handle kernel paging "
+                              "request in mna handler");
                printk(KERN_ALERT " at virtual address %016lx\n",address);
-               printk(KERN_ALERT "current->{mm,active_mm}->context = %016lx\n",
+               printk(KERN_ALERT "current->{active_,}mm->context = %016lx\n",
                        (current->mm ? CTX_HWBITS(current->mm->context) :
                        CTX_HWBITS(current->active_mm->context)));
-               printk(KERN_ALERT "current->{mm,active_mm}->pgd = %016lx\n",
+               printk(KERN_ALERT "current->{active_,}mm->pgd = %016lx\n",
                        (current->mm ? (unsigned long) current->mm->pgd :
                        (unsigned long) current->active_mm->pgd));
                die_if_kernel("Oops", regs);
@@ -400,48 +264,41 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
        enum direction dir = decode_direction(insn);
        int size = decode_access_size(insn);
 
+       current_thread_info()->kern_una_regs = regs;
+       current_thread_info()->kern_una_insn = insn;
+
        if (!ok_for_kernel(insn) || dir == both) {
-               printk("Unsupported unaligned load/store trap for kernel at <%016lx>.\n",
-                      regs->tpc);
-               unaligned_panic("Kernel does fpu/atomic unaligned load/store.", regs);
-
-               __asm__ __volatile__ ("\n"
-"kernel_unaligned_trap_fault:\n\t"
-               "mov    %0, %%o0\n\t"
-               "call   kernel_mna_trap_fault\n\t"
-               " mov   %1, %%o1\n\t"
-               :
-               : "r" (regs), "r" (insn)
-               : "o0", "o1", "o2", "o3", "o4", "o5", "o7",
-                 "g1", "g2", "g3", "g4", "g7", "cc");
+               printk("Unsupported unaligned load/store trap for kernel "
+                      "at <%016lx>.\n", regs->tpc);
+               unaligned_panic("Kernel does fpu/atomic "
+                               "unaligned load/store.", regs);
+
+               kernel_mna_trap_fault();
        } else {
-               unsigned long addr = compute_effective_address(regs, insn, ((insn >> 25) & 0x1f));
+               unsigned long addr;
 
+               addr = compute_effective_address(regs, insn,
+                                                ((insn >> 25) & 0x1f));
 #ifdef DEBUG_MNA
-               printk("KMNA: pc=%016lx [dir=%s addr=%016lx size=%d] retpc[%016lx]\n",
-                      regs->tpc, dirstrings[dir], addr, size, regs->u_regs[UREG_RETPC]);
+               printk("KMNA: pc=%016lx [dir=%s addr=%016lx size=%d] "
+                      "retpc[%016lx]\n",
+                      regs->tpc, dirstrings[dir], addr, size,
+                      regs->u_regs[UREG_RETPC]);
 #endif
                switch (dir) {
                case load:
-                       do_integer_load(fetch_reg_addr(((insn>>25)&0x1f), regs),
-                                       size, (unsigned long *) addr,
-                                       decode_signedness(insn), decode_asi(insn, regs),
-                                       kernel_unaligned_trap_fault);
+                       do_int_load(fetch_reg_addr(((insn>>25)&0x1f), regs),
+                                   size, (unsigned long *) addr,
+                                   decode_signedness(insn),
+                                   decode_asi(insn, regs));
                        break;
 
                case store:
-                       do_integer_store(((insn>>25)&0x1f), size,
-                                        (unsigned long *) addr, regs,
-                                        decode_asi(insn, regs),
-                                        kernel_unaligned_trap_fault);
-                       break;
-#if 0 /* unsupported */
-               case both:
-                       do_atomic(fetch_reg_addr(((insn>>25)&0x1f), regs),
-                                 (unsigned long *) addr,
-                                 kernel_unaligned_trap_fault);
+                       do_int_store(((insn>>25)&0x1f), size,
+                                    (unsigned long *) addr, regs,
+                                    decode_asi(insn, regs));
                        break;
-#endif
+
                default:
                        panic("Impossible kernel unaligned trap.");
                        /* Not reached... */
index 7aae0a1..686e526 100644 (file)
@@ -88,7 +88,6 @@ static void frob_mem_refresh(int cpu_slowing_down,
 {
        unsigned long old_refr_count, refr_count, mctrl;
 
-
        refr_count  = (clock_tick * MCTRL0_REFR_INTERVAL);
        refr_count /= (MCTRL0_REFR_CLKS_P_CNT * divisor * 1000000000UL);
 
@@ -230,6 +229,25 @@ static unsigned long estar_to_divisor(unsigned long estar)
        return ret;
 }
 
+static unsigned int us2e_freq_get(unsigned int cpu)
+{
+       cpumask_t cpus_allowed;
+       unsigned long clock_tick, estar;
+
+       if (!cpu_online(cpu))
+               return 0;
+
+       cpus_allowed = current->cpus_allowed;
+       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+
+       clock_tick = sparc64_get_clock_tick(cpu) / 1000;
+       estar = read_hbreg(HBIRD_ESTAR_MODE_ADDR);
+
+       set_cpus_allowed(current, cpus_allowed);
+
+       return clock_tick / estar_to_divisor(estar);
+}
+
 static void us2e_set_cpu_divider_index(unsigned int cpu, unsigned int index)
 {
        unsigned long new_bits, new_freq;
@@ -243,7 +261,7 @@ static void us2e_set_cpu_divider_index(unsigned int cpu, unsigned int index)
        cpus_allowed = current->cpus_allowed;
        set_cpus_allowed(current, cpumask_of_cpu(cpu));
 
-       new_freq = clock_tick = sparc64_get_clock_tick(cpu);
+       new_freq = clock_tick = sparc64_get_clock_tick(cpu) / 1000;
        new_bits = index_to_estar_mode(index);
        divisor = index_to_divisor(index);
        new_freq /= divisor;
@@ -258,7 +276,8 @@ static void us2e_set_cpu_divider_index(unsigned int cpu, unsigned int index)
        cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
        if (old_divisor != divisor)
-               us2e_transition(estar, new_bits, clock_tick, old_divisor, divisor);
+               us2e_transition(estar, new_bits, clock_tick * 1000,
+                               old_divisor, divisor);
 
        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
@@ -272,10 +291,8 @@ static int us2e_freq_target(struct cpufreq_policy *policy,
        unsigned int new_index = 0;
 
        if (cpufreq_frequency_table_target(policy,
-                                             &us2e_freq_table[policy->cpu].table[0],
-                                             target_freq,
-                                             relation,
-                                             &new_index))
+                                          &us2e_freq_table[policy->cpu].table[0],
+                                          target_freq, relation, &new_index))
                return -EINVAL;
 
        us2e_set_cpu_divider_index(policy->cpu, new_index);
@@ -292,7 +309,7 @@ static int us2e_freq_verify(struct cpufreq_policy *policy)
 static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy)
 {
        unsigned int cpu = policy->cpu;
-       unsigned long clock_tick = sparc64_get_clock_tick(cpu);
+       unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000;
        struct cpufreq_frequency_table *table =
                &us2e_freq_table[cpu].table[0];
 
@@ -351,9 +368,10 @@ static int __init us2e_freq_init(void)
                memset(us2e_freq_table, 0,
                       (NR_CPUS * sizeof(struct us2e_freq_percpu_info)));
 
+               driver->init = us2e_freq_cpu_init;
                driver->verify = us2e_freq_verify;
                driver->target = us2e_freq_target;
-               driver->init = us2e_freq_cpu_init;
+               driver->get = us2e_freq_get;
                driver->exit = us2e_freq_cpu_exit;
                driver->owner = THIS_MODULE,
                strcpy(driver->name, "UltraSPARC-IIe");
index 18fe54b..9080e7c 100644 (file)
@@ -56,7 +56,7 @@ static void write_safari_cfg(unsigned long val)
 
 static unsigned long get_current_freq(unsigned int cpu, unsigned long safari_cfg)
 {
-       unsigned long clock_tick = sparc64_get_clock_tick(cpu);
+       unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000;
        unsigned long ret;
 
        switch (safari_cfg & SAFARI_CFG_DIV_MASK) {
@@ -76,6 +76,26 @@ static unsigned long get_current_freq(unsigned int cpu, unsigned long safari_cfg
        return ret;
 }
 
+static unsigned int us3_freq_get(unsigned int cpu)
+{
+       cpumask_t cpus_allowed;
+       unsigned long reg;
+       unsigned int ret;
+
+       if (!cpu_online(cpu))
+               return 0;
+
+       cpus_allowed = current->cpus_allowed;
+       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+
+       reg = read_safari_cfg();
+       ret = get_current_freq(cpu, reg);
+
+       set_cpus_allowed(current, cpus_allowed);
+
+       return ret;
+}
+
 static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index)
 {
        unsigned long new_bits, new_freq, reg;
@@ -88,7 +108,7 @@ static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index)
        cpus_allowed = current->cpus_allowed;
        set_cpus_allowed(current, cpumask_of_cpu(cpu));
 
-       new_freq = sparc64_get_clock_tick(cpu);
+       new_freq = sparc64_get_clock_tick(cpu) / 1000;
        switch (index) {
        case 0:
                new_bits = SAFARI_CFG_DIV_1;
@@ -150,7 +170,7 @@ static int us3_freq_verify(struct cpufreq_policy *policy)
 static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
 {
        unsigned int cpu = policy->cpu;
-       unsigned long clock_tick = sparc64_get_clock_tick(cpu);
+       unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000;
        struct cpufreq_frequency_table *table =
                &us3_freq_table[cpu].table[0];
 
@@ -206,9 +226,10 @@ static int __init us3_freq_init(void)
                memset(us3_freq_table, 0,
                       (NR_CPUS * sizeof(struct us3_freq_percpu_info)));
 
+               driver->init = us3_freq_cpu_init;
                driver->verify = us3_freq_verify;
                driver->target = us3_freq_target;
-               driver->init = us3_freq_cpu_init;
+               driver->get = us3_freq_get;
                driver->exit = us3_freq_cpu_exit;
                driver->owner = THIS_MODULE,
                strcpy(driver->name, "UltraSPARC-III");
index 0674058..d3a66ea 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/net.h>
 #include <linux/compat.h>
 #include <net/compat.h>
+#include <net/sock.h>
 
 #include <asm/uaccess.h>
 #include <asm/string.h>
@@ -297,121 +298,165 @@ asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr __user *user_msg, unsi
 {
        struct socket *sock;
        char address[MAX_SOCK_ADDR];
-       struct iovec iov[UIO_FASTIOV];
+       struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
        unsigned char ctl[sizeof(struct cmsghdr) + 20];
        unsigned char *ctl_buf = ctl;
-       struct msghdr kern_msg;
-       int err, total_len;
+       struct msghdr msg_sys;
+       int err, ctl_len, iov_size, total_len;
 
-       if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-               return -EFAULT;
-       if(kern_msg.msg_iovlen > UIO_MAXIOV)
-               return -EINVAL;
-       err = verify_compat_iovec(&kern_msg, iov, address, VERIFY_READ);
-       if (err < 0)
+       err = -EFAULT;
+       if (msghdr_from_user32_to_kern(&msg_sys, user_msg))
+               goto out;
+
+       sock = sockfd_lookup(fd, &err);
+       if (!sock)
                goto out;
+
+       /* do not move before msg_sys is valid */
+       err = -EMSGSIZE;
+       if (msg_sys.msg_iovlen > UIO_MAXIOV)
+               goto out_put;
+
+       /* Check whether to allocate the iovec area*/
+       err = -ENOMEM;
+       iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
+       if (msg_sys.msg_iovlen > UIO_FASTIOV) {
+               iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
+               if (!iov)
+                       goto out_put;
+       }
+
+       err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ);
+       if (err < 0)
+               goto out_freeiov;
        total_len = err;
 
-       if(kern_msg.msg_controllen) {
-               struct sol_cmsghdr __user *ucmsg = kern_msg.msg_control;
+       err = -ENOBUFS;
+       if (msg_sys.msg_controllen > INT_MAX)
+               goto out_freeiov;
+
+       ctl_len = msg_sys.msg_controllen;
+       if (ctl_len) {
+               struct sol_cmsghdr __user *ucmsg = msg_sys.msg_control;
                unsigned long *kcmsg;
                compat_size_t cmlen;
 
-               if (kern_msg.msg_controllen <= sizeof(compat_size_t))
-                       return -EINVAL;
+               err = -EINVAL;
+               if (ctl_len <= sizeof(compat_size_t))
+                       goto out_freeiov;
 
-               if(kern_msg.msg_controllen > sizeof(ctl)) {
+               if (ctl_len > sizeof(ctl)) {
                        err = -ENOBUFS;
-                       ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL);
-                       if(!ctl_buf)
+                       ctl_buf = kmalloc(ctl_len, GFP_KERNEL);
+                       if (!ctl_buf)
                                goto out_freeiov;
                }
                __get_user(cmlen, &ucmsg->cmsg_len);
                kcmsg = (unsigned long *) ctl_buf;
                *kcmsg++ = (unsigned long)cmlen;
                err = -EFAULT;
-               if(copy_from_user(kcmsg, &ucmsg->cmsg_level,
-                                 kern_msg.msg_controllen - sizeof(compat_size_t)))
+               if (copy_from_user(kcmsg, &ucmsg->cmsg_level,
+                                  ctl_len - sizeof(compat_size_t)))
                        goto out_freectl;
-               kern_msg.msg_control = ctl_buf;
+               msg_sys.msg_control = ctl_buf;
        }
-       kern_msg.msg_flags = solaris_to_linux_msgflags(user_flags);
+       msg_sys.msg_flags = solaris_to_linux_msgflags(user_flags);
 
-       lock_kernel();
-       sock = sockfd_lookup(fd, &err);
-       if (sock != NULL) {
-               if (sock->file->f_flags & O_NONBLOCK)
-                       kern_msg.msg_flags |= MSG_DONTWAIT;
-               err = sock_sendmsg(sock, &kern_msg, total_len);
-               sockfd_put(sock);
-       }
-       unlock_kernel();
+       if (sock->file->f_flags & O_NONBLOCK)
+               msg_sys.msg_flags |= MSG_DONTWAIT;
+       err = sock_sendmsg(sock, &msg_sys, total_len);
 
 out_freectl:
-       /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
-       if(ctl_buf != ctl)
-               kfree(ctl_buf);
+       if (ctl_buf != ctl)    
+               sock_kfree_s(sock->sk, ctl_buf, ctl_len);
 out_freeiov:
-       if(kern_msg.msg_iov != iov)
-               kfree(kern_msg.msg_iov);
-out:
+       if (iov != iovstack)
+               sock_kfree_s(sock->sk, iov, iov_size);
+out_put:
+       sockfd_put(sock);
+out:       
        return err;
 }
 
 asmlinkage int solaris_recvmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned int user_flags)
 {
-       struct iovec iovstack[UIO_FASTIOV];
-       struct msghdr kern_msg;
-       char addr[MAX_SOCK_ADDR];
        struct socket *sock;
+       struct iovec iovstack[UIO_FASTIOV];
        struct iovec *iov = iovstack;
+       struct msghdr msg_sys;
+       unsigned long cmsg_ptr;
+       int err, iov_size, total_len, len;
+
+       /* kernel mode address */
+       char addr[MAX_SOCK_ADDR];
+
+       /* user mode address pointers */
        struct sockaddr __user *uaddr;
        int __user *uaddr_len;
-       unsigned long cmsg_ptr;
-       int err, total_len, len = 0;
 
-       if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
+       if (msghdr_from_user32_to_kern(&msg_sys, user_msg))
                return -EFAULT;
-       if(kern_msg.msg_iovlen > UIO_MAXIOV)
-               return -EINVAL;
 
-       uaddr = kern_msg.msg_name;
+       sock = sockfd_lookup(fd, &err);
+       if (!sock)
+               goto out;
+
+       err = -EMSGSIZE;
+       if (msg_sys.msg_iovlen > UIO_MAXIOV)
+               goto out_put;
+
+       /* Check whether to allocate the iovec area*/
+       err = -ENOMEM;
+       iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
+       if (msg_sys.msg_iovlen > UIO_FASTIOV) {
+               iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
+               if (!iov)
+                       goto out_put;
+       }
+
+       /*
+        *      Save the user-mode address (verify_iovec will change the
+        *      kernel msghdr to use the kernel address space)
+        */
+        
+       uaddr = (void __user *) msg_sys.msg_name;
        uaddr_len = &user_msg->msg_namelen;
-       err = verify_compat_iovec(&kern_msg, iov, addr, VERIFY_WRITE);
+       err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
        if (err < 0)
-               goto out;
+               goto out_freeiov;
        total_len = err;
 
-       cmsg_ptr = (unsigned long) kern_msg.msg_control;
-       kern_msg.msg_flags = 0;
+       cmsg_ptr = (unsigned long) msg_sys.msg_control;
+       msg_sys.msg_flags = MSG_CMSG_COMPAT;
 
-       lock_kernel();
-       sock = sockfd_lookup(fd, &err);
-       if (sock != NULL) {
-               if (sock->file->f_flags & O_NONBLOCK)
-                       user_flags |= MSG_DONTWAIT;
-               err = sock_recvmsg(sock, &kern_msg, total_len, user_flags);
-               if(err >= 0)
-                       len = err;
-               sockfd_put(sock);
-       }
-       unlock_kernel();
-
-       if(uaddr != NULL && err >= 0)
-               err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
-       if(err >= 0) {
-               err = __put_user(linux_to_solaris_msgflags(kern_msg.msg_flags), &user_msg->msg_flags);
-               if(!err) {
-                       /* XXX Convert cmsg back into userspace 32-bit format... */
-                       err = __put_user((unsigned long)kern_msg.msg_control - cmsg_ptr,
-                                        &user_msg->msg_controllen);
-               }
+       if (sock->file->f_flags & O_NONBLOCK)
+               user_flags |= MSG_DONTWAIT;
+
+       err = sock_recvmsg(sock, &msg_sys, total_len, user_flags);
+       if(err < 0)
+               goto out_freeiov;
+
+       len = err;
+
+       if (uaddr != NULL) {
+               err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
+               if (err < 0)
+                       goto out_freeiov;
        }
+       err = __put_user(linux_to_solaris_msgflags(msg_sys.msg_flags), &user_msg->msg_flags);
+       if (err)
+               goto out_freeiov;
+       err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr,
+                        &user_msg->msg_controllen);
+       if (err)
+               goto out_freeiov;
+       err = len;
 
-       if(kern_msg.msg_iov != iov)
-               kfree(kern_msg.msg_iov);
+out_freeiov:
+       if (iov != iovstack)
+               sock_kfree_s(sock->sk, iov, iov_size);
+out_put:
+       sockfd_put(sock);
 out:
-       if(err < 0)
-               return err;
-       return len;
+       return err;
 }
index a37a5ac..022f67b 100644 (file)
@@ -9,19 +9,11 @@
  *
  */
 
-#include <linux/types.h>
-#include <linux/kdev_t.h>
-#include <linux/time.h>
-#include <linux/devfs_fs_kernel.h>
+#include <linux/init.h> 
 #include <linux/module.h>
 #include <linux/mm.h> 
-#include <linux/slab.h>
-#include <linux/init.h> 
-#include <linux/smp_lock.h>
 #include <linux/miscdevice.h>
 #include <asm/uaccess.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
 #include "mem_user.h"
 #include "user_util.h"
  
@@ -31,35 +23,22 @@ static unsigned long p_buf = 0;
 static char *v_buf = NULL;
 
 static ssize_t
-mmapper_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+mmapper_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
-       if(*ppos > mmapper_size)
-               return -EINVAL;
-
-       if(count + *ppos > mmapper_size)
-               count = count + *ppos - mmapper_size;
-
-       if(count < 0)
-               return -EINVAL;
-       copy_to_user(buf,&v_buf[*ppos],count);
-       
-       return count;
+       return simple_read_from_buffer(buf, count, ppos, v_buf, mmapper_size);
 }
 
 static ssize_t
-mmapper_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+mmapper_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
-       if(*ppos > mmapper_size)
+       if (*ppos > mmapper_size)
                return -EINVAL;
 
-       if(count + *ppos > mmapper_size)
-               count = count + *ppos - mmapper_size;
-
-       if(count < 0)
-               return -EINVAL;
+       if (count > mmapper_size - *ppos)
+               count = mmapper_size - *ppos;
 
-       copy_from_user(&v_buf[*ppos],buf,count);
+       if (copy_from_user(&v_buf[*ppos], buf, count))
+               return -EFAULT;
        
        return count;
 }
@@ -77,7 +56,6 @@ mmapper_mmap(struct file *file, struct vm_area_struct * vma)
        int ret = -EINVAL;
        int size;
 
-       lock_kernel();
        if (vma->vm_pgoff != 0)
                goto out;
        
@@ -92,7 +70,6 @@ mmapper_mmap(struct file *file, struct vm_area_struct * vma)
                goto out;
        ret = 0;
 out:
-       unlock_kernel();
        return ret;
 }
 
index 7807a3e..03618bd 100644 (file)
@@ -87,12 +87,12 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
                recalc_sigpending();
                spin_unlock_irq(&current->sighand->siglock);
                force_sigsegv(signr, current);
-       }
-       else if(!(ka->sa.sa_flags & SA_NODEFER)){
+       } else {
                spin_lock_irq(&current->sighand->siglock);
                sigorsets(&current->blocked, &current->blocked, 
                          &ka->sa.sa_mask);
-               sigaddset(&current->blocked, signr);
+                if(!(ka->sa.sa_flags & SA_NODEFER))
+                       sigaddset(&current->blocked, signr);
                recalc_sigpending();
                spin_unlock_irq(&current->sighand->siglock);
        }
index 6dd9e5b..f228f8b 100644 (file)
@@ -61,7 +61,11 @@ void wait_stub_done(int pid, int sig, char * fname)
 
                 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
         } while((n >= 0) && WIFSTOPPED(status) &&
-                (WSTOPSIG(status) == SIGVTALRM));
+                ((WSTOPSIG(status) == SIGVTALRM) ||
+                /* running UML inside a detached screen can cause
+                 * SIGWINCHes
+                 */
+                (WSTOPSIG(status) == SIGWINCH)));
 
         if((n < 0) || !WIFSTOPPED(status) ||
            (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){
index 9416e1c..4cca3e9 100644 (file)
@@ -9,7 +9,6 @@
  */
 #include <elf.h>
 #include <stddef.h>
-#include <asm/elf.h>
 #include "init.h"
 #include "elf_user.h"
 #include "mem_user.h"
index 37061e3..633e4e1 100644 (file)
@@ -462,13 +462,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
        else
                setup_frame(sig, ka, oldset, regs);
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
 }
 
 /*
index 2b5c401..acfdaa2 100644 (file)
@@ -322,3 +322,4 @@ module_exit(aes_fini);
 
 MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("aes");
index 776f3c8..b97a61e 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc3
-# Fri Jul 22 16:47:31 2005
+# Linux kernel version: 2.6.13-rc6-git3
+# Fri Aug 12 16:40:34 2005
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -284,10 +284,6 @@ CONFIG_IPV6=y
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
-CONFIG_NETPOLL=y
-# CONFIG_NETPOLL_RX is not set
-# CONFIG_NETPOLL_TRAP is not set
-CONFIG_NET_POLL_CONTROLLER=y
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -463,6 +459,7 @@ CONFIG_AIC79XX_DEBUG_MASK=0
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 CONFIG_SCSI_SATA=y
+# CONFIG_SCSI_SATA_AHCI is not set
 # CONFIG_SCSI_SATA_SVW is not set
 CONFIG_SCSI_ATA_PIIX=y
 # CONFIG_SCSI_SATA_NV is not set
@@ -492,6 +489,7 @@ CONFIG_SCSI_QLA2XXX=y
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -512,9 +510,11 @@ CONFIG_BLK_DEV_DM=y
 #
 # Fusion MPT device support
 #
-# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=y
 # CONFIG_FUSION_FC is not set
+CONFIG_FUSION_MAX_SGE=128
+# CONFIG_FUSION_CTL is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -585,6 +585,7 @@ CONFIG_8139TOO=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
@@ -624,6 +625,10 @@ CONFIG_S2IO=m
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 CONFIG_NETCONSOLE=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
 
 #
 # ISDN subsystem
index b98b6d2..2a925e2 100644 (file)
@@ -43,11 +43,11 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val)
        switch (regno) {
        case offsetof(struct user32, regs.fs):
                if (val && (val & 3) != 3) return -EIO; 
-               child->thread.fs = val & 0xffff; 
+               child->thread.fsindex = val & 0xffff;
                break;
        case offsetof(struct user32, regs.gs):
                if (val && (val & 3) != 3) return -EIO; 
-               child->thread.gs = val & 0xffff;
+               child->thread.gsindex = val & 0xffff;
                break;
        case offsetof(struct user32, regs.ds):
                if (val && (val & 3) != 3) return -EIO; 
@@ -138,10 +138,10 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val)
 
        switch (regno) {
        case offsetof(struct user32, regs.fs):
-               *val = child->thread.fs
+               *val = child->thread.fsindex;
                break;
        case offsetof(struct user32, regs.gs):
-               *val = child->thread.gs;
+               *val = child->thread.gsindex;
                break;
        case offsetof(struct user32, regs.ds):
                *val = child->thread.ds;
index 6ded3a5..b548dea 100644 (file)
@@ -185,6 +185,40 @@ unsigned long __init e820_end_of_ram(void)
 }
 
 /* 
+ * Compute how much memory is missing in a range.
+ * Unlike the other functions in this file the arguments are in page numbers.
+ */
+unsigned long __init
+e820_hole_size(unsigned long start_pfn, unsigned long end_pfn)
+{
+       unsigned long ram = 0;
+       unsigned long start = start_pfn << PAGE_SHIFT;
+       unsigned long end = end_pfn << PAGE_SHIFT;
+       int i;
+       for (i = 0; i < e820.nr_map; i++) {
+               struct e820entry *ei = &e820.map[i];
+               unsigned long last, addr;
+
+               if (ei->type != E820_RAM ||
+                   ei->addr+ei->size <= start ||
+                   ei->addr >= end)
+                       continue;
+
+               addr = round_up(ei->addr, PAGE_SIZE);
+               if (addr < start)
+                       addr = start;
+
+               last = round_down(ei->addr + ei->size, PAGE_SIZE);
+               if (last >= end)
+                       last = end;
+
+               if (last > addr)
+                       ram += last - addr;
+       }
+       return ((end - start) - ram) >> PAGE_SHIFT;
+}
+
+/*
  * Mark e820 reserved areas as busy for the resource manager.
  */
 void __init e820_reserve_resources(void)
index 3b267c9..8aa5673 100644 (file)
@@ -36,6 +36,7 @@ static unsigned long bank[NR_BANKS] = { [0 ... NR_BANKS-1] = ~0UL };
 static unsigned long console_logged;
 static int notify_user;
 static int rip_msr;
+static int mce_bootlog;
 
 /*
  * Lockless MCE logging infrastructure.
@@ -197,10 +198,11 @@ void do_machine_check(struct pt_regs * regs, long error_code)
                        rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr);
 
                mce_get_rip(&m, regs);
-               if (error_code != -1)
+               if (error_code >= 0)
                        rdtscll(m.tsc);
                wrmsrl(MSR_IA32_MC0_STATUS + i*4, 0);
-               mce_log(&m);
+               if (error_code != -2)
+                       mce_log(&m);
 
                /* Did this bank cause the exception? */
                /* Assume that the bank with uncorrectable errors did it,
@@ -315,7 +317,7 @@ static void mce_init(void *dummy)
 
        /* Log the machine checks left over from the previous reset.
           This also clears all registers */
-       do_machine_check(NULL, -1);
+       do_machine_check(NULL, mce_bootlog ? -1 : -2);
 
        set_in_cr4(X86_CR4_MCE);
 
@@ -476,11 +478,17 @@ static int __init mcheck_disable(char *str)
 }
 
 /* mce=off disables machine check. Note you can reenable it later
-   using sysfs */
+   using sysfs.
+   mce=bootlog Log MCEs from before booting. Disabled by default to work
+   around buggy BIOS that leave bogus MCEs.  */
 static int __init mcheck_enable(char *str)
 {
+       if (*str == '=')
+               str++;
        if (!strcmp(str, "off"))
                mce_dont_init = 1;
+       else if (!strcmp(str, "bootlog"))
+               mce_bootlog = 1;
        else
                printk("mce= argument %s ignored. Please use /sys", str); 
        return 0;
index 08abf9f..79c362d 100644 (file)
@@ -970,8 +970,21 @@ int mp_register_gsi(u32 gsi, int edge_level, int active_high_low)
                 * due to unused I/O APIC pins.
                 */
                int irq = gsi;
-               gsi = pci_irq++;
-               gsi_to_irq[irq] = gsi;
+               if (gsi < MAX_GSI_NUM) {
+                       if (gsi > 15)
+                               gsi = pci_irq++;
+#ifdef CONFIG_ACPI_BUS
+                       /*
+                        * Don't assign IRQ used by ACPI SCI
+                        */
+                       if (gsi == acpi_fadt.sci_int)
+                               gsi = pci_irq++;
+#endif
+                       gsi_to_irq[irq] = gsi;
+               } else {
+                       printk(KERN_ERR "GSI %u is too high\n", gsi);
+                       return gsi;
+               }
        }
 
        io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
index 0aa5262..116a491 100644 (file)
@@ -645,15 +645,15 @@ void __init setup_arch(char **cmdline_p)
                }
        }
 #endif
-
-       sparse_init();
-
 #ifdef CONFIG_KEXEC
        if (crashk_res.start != crashk_res.end) {
                reserve_bootmem(crashk_res.start,
                        crashk_res.end - crashk_res.start + 1);
        }
 #endif
+
+       sparse_init();
+
        paging_init();
 
        check_ioapic();
index 98590a9..d642fbf 100644 (file)
@@ -394,10 +394,11 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 #endif
        ret = setup_rt_frame(sig, ka, info, oldset, regs);
 
-       if (ret && !(ka->sa.sa_flags & SA_NODEFER)) {
+       if (ret) {
                spin_lock_irq(&current->sighand->siglock);
                sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-               sigaddset(&current->blocked,sig);
+               if (!(ka->sa.sa_flags & SA_NODEFER))
+                       sigaddset(&current->blocked,sig);
                recalc_sigpending();
                spin_unlock_irq(&current->sighand->siglock);
        }
index 6e4807d..fa25e39 100644 (file)
@@ -334,7 +334,7 @@ static void __cpuinit tsc_sync_wait(void)
 {
        if (notscsync || !cpu_has_tsc)
                return;
-       sync_tsc(boot_cpu_id);
+       sync_tsc(0);
 }
 
 static __init int notscsync_setup(char *s)
@@ -492,6 +492,14 @@ void __cpuinit start_secondary(void)
         */
        set_cpu_sibling_map(smp_processor_id());
 
+       /* 
+        * Wait for TSC sync to not schedule things before.
+        * We still process interrupts, which could see an inconsistent
+        * time in that window unfortunately. 
+        * Do this here because TSC sync has global unprotected state.
+        */
+       tsc_sync_wait();
+
        /*
         * We need to hold call_lock, so there is no inconsistency
         * between the time smp_call_function() determines number of
@@ -509,13 +517,6 @@ void __cpuinit start_secondary(void)
        per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
        unlock_ipi_call_lock();
 
-       mb();
-
-       /* Wait for TSC sync to not schedule things before.
-          We still process interrupts, which could see an inconsistent
-          time in that window unfortunately. */
-       tsc_sync_wait();
-
        cpu_idle();
 }
 
index 01808ec..72fd55e 100644 (file)
@@ -188,8 +188,8 @@ csum_partial_copy_generic:
        source
        movw (%rdi),%bx
        adcl %ebx,%eax
-       dest
        decl %ecx
+       dest
        movw %bx,(%rsi)
        leaq 2(%rdi),%rdi
        leaq 2(%rsi),%rsi
index 1379272..ca914c3 100644 (file)
@@ -211,9 +211,7 @@ int unhandled_signal(struct task_struct *tsk, int sig)
 {
        if (tsk->pid == 1)
                return 1;
-       /* Warn for strace, but not for gdb */
-       if (!test_ti_thread_flag(tsk->thread_info, TIF_SYSCALL_TRACE) &&
-           (tsk->ptrace & PT_PTRACED))
+       if (tsk->ptrace & PT_PTRACED)
                return 0;
        return (tsk->sighand->action[sig-1].sa.sa_handler == SIG_IGN) ||
                (tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL);
@@ -439,13 +437,13 @@ good_area:
         * the fault.
         */
        switch (handle_mm_fault(mm, vma, address, write)) {
-       case 1:
+       case VM_FAULT_MINOR:
                tsk->min_flt++;
                break;
-       case 2:
+       case VM_FAULT_MAJOR:
                tsk->maj_flt++;
                break;
-       case 0:
+       case VM_FAULT_SIGBUS:
                goto do_sigbus;
        default:
                goto out_of_memory;
index 72e4b36..aa4a518 100644 (file)
@@ -322,18 +322,26 @@ void zap_low_mappings(void)
 void __init paging_init(void)
 {
        {
-               unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+               unsigned long zones_size[MAX_NR_ZONES];
+               unsigned long holes[MAX_NR_ZONES];
                unsigned int max_dma;
 
+               memset(zones_size, 0, sizeof(zones_size));
+               memset(holes, 0, sizeof(holes));
+
                max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 
-               if (end_pfn < max_dma)
+               if (end_pfn < max_dma) {
                        zones_size[ZONE_DMA] = end_pfn;
-               else {
+                       holes[ZONE_DMA] = e820_hole_size(0, end_pfn);
+               } else {
                        zones_size[ZONE_DMA] = max_dma;
+                       holes[ZONE_DMA] = e820_hole_size(0, max_dma);
                        zones_size[ZONE_NORMAL] = end_pfn - max_dma;
+                       holes[ZONE_NORMAL] = e820_hole_size(max_dma, end_pfn);
                }
-               free_area_init(zones_size);
+               free_area_init_node(0, NODE_DATA(0), zones_size,
+                        __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes);
        }
        return;
 }
index 70cb290..6a156f5 100644 (file)
@@ -126,9 +126,11 @@ void __init setup_node_zones(int nodeid)
 { 
        unsigned long start_pfn, end_pfn; 
        unsigned long zones[MAX_NR_ZONES];
+       unsigned long holes[MAX_NR_ZONES];
        unsigned long dma_end_pfn;
 
        memset(zones, 0, sizeof(unsigned long) * MAX_NR_ZONES); 
+       memset(holes, 0, sizeof(unsigned long) * MAX_NR_ZONES);
 
        start_pfn = node_start_pfn(nodeid);
        end_pfn = node_end_pfn(nodeid);
@@ -139,13 +141,17 @@ void __init setup_node_zones(int nodeid)
        dma_end_pfn = __pa(MAX_DMA_ADDRESS) >> PAGE_SHIFT; 
        if (start_pfn < dma_end_pfn) { 
                zones[ZONE_DMA] = dma_end_pfn - start_pfn;
+               holes[ZONE_DMA] = e820_hole_size(start_pfn, dma_end_pfn);
                zones[ZONE_NORMAL] = end_pfn - dma_end_pfn; 
+               holes[ZONE_NORMAL] = e820_hole_size(dma_end_pfn, end_pfn);
+
        } else { 
                zones[ZONE_NORMAL] = end_pfn - start_pfn; 
+               holes[ZONE_NORMAL] = e820_hole_size(start_pfn, end_pfn);
        } 
     
        free_area_init_node(nodeid, NODE_DATA(nodeid), zones,
-                           start_pfn, NULL); 
+                           start_pfn, holes);
 } 
 
 void __init numa_init_array(void)
index c2c38b5..d80c323 100644 (file)
@@ -47,13 +47,22 @@ fill_mp_bus_to_cpumask(void)
                         * if there are no busses hanging off of the current
                         * ldt link then both the secondary and subordinate
                         * bus number fields are set to 0.
+                        * 
+                        * RED-PEN
+                        * This is slightly broken because it assumes
+                        * HT node IDs == Linux node ids, which is not always
+                        * true. However it is probably mostly true.
                         */
                        if (!(SECONDARY_LDT_BUS_NUMBER(ldtbus) == 0
                                && SUBORDINATE_LDT_BUS_NUMBER(ldtbus) == 0)) {
                                for (j = SECONDARY_LDT_BUS_NUMBER(ldtbus);
                                     j <= SUBORDINATE_LDT_BUS_NUMBER(ldtbus);
-                                    j++)
-                                       pci_bus_to_node[j] = NODE_ID(nid);
+                                    j++) { 
+                                       int node = NODE_ID(nid);
+                                       if (!node_online(node))
+                                               node = 0;
+                                       pci_bus_to_node[j] = node;
+                               }               
                        }
                }
        }
index df6e1e1..dc42ced 100644 (file)
@@ -702,12 +702,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
        if (ka.sa.sa_flags & SA_ONESHOT)
                ka.sa.sa_handler = SIG_DFL;
 
-       if (!(ka.sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask);
+       if (!(ka.sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked, signr);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
        return 1;
 }
index cecab0a..46d655f 100644 (file)
@@ -48,6 +48,8 @@ source "drivers/hwmon/Kconfig"
 
 source "drivers/misc/Kconfig"
 
+source "drivers/mfd/Kconfig"
+
 source "drivers/media/Kconfig"
 
 source "drivers/video/Kconfig"
index 126a851..9663132 100644 (file)
@@ -26,7 +26,7 @@ obj-$(CONFIG_FB_INTEL)          += video/intelfb/
 obj-$(CONFIG_SERIO)            += input/serio/
 obj-y                          += serial/
 obj-$(CONFIG_PARPORT)          += parport/
-obj-y                          += base/ block/ misc/ net/ media/
+obj-y                          += base/ block/ misc/ mfd/ net/ media/
 obj-$(CONFIG_NUBUS)            += nubus/
 obj-$(CONFIG_ATM)              += atm/
 obj-$(CONFIG_PPC_PMAC)         += macintosh/
index 3cd2e96..c0a37d9 100644 (file)
@@ -1283,8 +1283,7 @@ static void do_fd_request(request_queue_t* q)
        if (fdc_busy) return;
        save_flags(flags);
        cli();
-       while (fdc_busy)
-               sleep_on(&fdc_wait);
+       wait_event(fdc_wait, !fdc_busy);
        fdc_busy = 1;
        ENABLE_IRQ();
        restore_flags(flags);
index 986410e..ba13896 100644 (file)
@@ -133,9 +133,10 @@ config ACPI_HOTKEY
        depends on ACPI_INTERPRETER
        depends on EXPERIMENTAL
        depends on !IA64_SGI_SN
-       default m
+       default n
        help
-       ACPI generic hotkey
+         Experimental consolidated hotkey driver.
+         If you are unsure, say N.
 
 config ACPI_FAN
        tristate "Fan"
index 0f45d45..8162fd0 100644 (file)
@@ -26,6 +26,9 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
@@ -33,6 +36,9 @@
 #define ACPI_BUTTON_COMPONENT          0x00080000
 #define ACPI_BUTTON_DRIVER_NAME                "ACPI Button Driver"
 #define ACPI_BUTTON_CLASS              "button"
+#define ACPI_BUTTON_FILE_INFO          "info"
+#define ACPI_BUTTON_FILE_STATE         "state"
+#define ACPI_BUTTON_TYPE_UNKNOWN       0x00
 #define ACPI_BUTTON_NOTIFY_STATUS      0x80
 
 #define ACPI_BUTTON_SUBCLASS_POWER     "power"
@@ -64,6 +70,8 @@ MODULE_LICENSE("GPL");
 
 static int acpi_button_add (struct acpi_device *device);
 static int acpi_button_remove (struct acpi_device *device, int type);
+static int acpi_button_info_open_fs(struct inode *inode, struct file *file);
+static int acpi_button_state_open_fs(struct inode *inode, struct file *file);
 
 static struct acpi_driver acpi_button_driver = {
        .name =         ACPI_BUTTON_DRIVER_NAME,
@@ -82,6 +90,179 @@ struct acpi_button {
        unsigned long           pushed;
 };
 
+static struct file_operations acpi_button_info_fops = {
+       .open           = acpi_button_info_open_fs,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct file_operations acpi_button_state_fops = {
+       .open           = acpi_button_state_open_fs,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+/* --------------------------------------------------------------------------
+                              FS Interface (/proc)
+   -------------------------------------------------------------------------- */
+
+static struct proc_dir_entry   *acpi_button_dir;
+
+static int acpi_button_info_seq_show(struct seq_file *seq, void *offset)
+{
+       struct acpi_button      *button = (struct acpi_button *) seq->private;
+
+       ACPI_FUNCTION_TRACE("acpi_button_info_seq_show");
+
+       if (!button || !button->device)
+               return_VALUE(0);
+
+       seq_printf(seq, "type:                    %s\n", 
+               acpi_device_name(button->device));
+
+       return_VALUE(0);
+}
+
+static int acpi_button_info_open_fs(struct inode *inode, struct file *file)
+{
+       return single_open(file, acpi_button_info_seq_show, PDE(inode)->data);
+}
+       
+static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
+{
+       struct acpi_button      *button = (struct acpi_button *) seq->private;
+       acpi_status             status;
+       unsigned long           state;
+
+       ACPI_FUNCTION_TRACE("acpi_button_state_seq_show");
+
+       if (!button || !button->device)
+               return_VALUE(0);
+
+       status = acpi_evaluate_integer(button->handle,"_LID",NULL,&state);
+       if (ACPI_FAILURE(status)) {
+               seq_printf(seq, "state:      unsupported\n");
+       }
+       else{
+               seq_printf(seq, "state:      %s\n", (state ? "open" : "closed")); 
+       }
+
+       return_VALUE(0);
+}
+
+static int acpi_button_state_open_fs(struct inode *inode, struct file *file)
+{
+       return single_open(file, acpi_button_state_seq_show, PDE(inode)->data);
+}
+
+static struct proc_dir_entry *acpi_power_dir;
+static struct proc_dir_entry *acpi_sleep_dir;
+static struct proc_dir_entry *acpi_lid_dir;
+
+static int
+acpi_button_add_fs (
+       struct acpi_device      *device)
+{
+       struct proc_dir_entry   *entry = NULL;
+       struct acpi_button      *button = NULL;
+
+       ACPI_FUNCTION_TRACE("acpi_button_add_fs");
+
+       if (!device || !acpi_driver_data(device))
+               return_VALUE(-EINVAL);
+
+       button = acpi_driver_data(device);
+
+       switch (button->type) {
+       case ACPI_BUTTON_TYPE_POWER:
+       case ACPI_BUTTON_TYPE_POWERF:
+               if (!acpi_power_dir)
+                       acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER, 
+                               acpi_button_dir);
+               entry = acpi_power_dir;
+               break;
+       case ACPI_BUTTON_TYPE_SLEEP:
+       case ACPI_BUTTON_TYPE_SLEEPF:
+               if (!acpi_sleep_dir)
+                       acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP, 
+                               acpi_button_dir);
+               entry = acpi_sleep_dir;
+               break;
+       case ACPI_BUTTON_TYPE_LID:
+               if (!acpi_lid_dir)
+                       acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, 
+                               acpi_button_dir);
+               entry = acpi_lid_dir;
+               break;
+       }
+
+       if (!entry)
+               return_VALUE(-ENODEV);
+       entry->owner = THIS_MODULE;
+
+       acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry);
+       if (!acpi_device_dir(device))
+               return_VALUE(-ENODEV);
+       acpi_device_dir(device)->owner = THIS_MODULE;
+
+       /* 'info' [R] */
+       entry = create_proc_entry(ACPI_BUTTON_FILE_INFO,
+               S_IRUGO, acpi_device_dir(device));
+       if (!entry)
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                       "Unable to create '%s' fs entry\n",
+                       ACPI_BUTTON_FILE_INFO));
+       else {
+               entry->proc_fops = &acpi_button_info_fops;
+               entry->data = acpi_driver_data(device);
+               entry->owner = THIS_MODULE;
+       }
+
+       /* show lid state [R] */
+       if (button->type == ACPI_BUTTON_TYPE_LID) {
+               entry = create_proc_entry(ACPI_BUTTON_FILE_STATE,
+                       S_IRUGO, acpi_device_dir(device));
+               if (!entry)
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                               "Unable to create '%s' fs entry\n",
+                               ACPI_BUTTON_FILE_INFO));
+               else {
+                       entry->proc_fops = &acpi_button_state_fops;
+                       entry->data = acpi_driver_data(device);
+                       entry->owner = THIS_MODULE;
+               }
+       }
+
+       return_VALUE(0);
+}
+
+
+static int
+acpi_button_remove_fs (
+       struct acpi_device      *device)
+{
+       struct acpi_button      *button = NULL;
+
+       ACPI_FUNCTION_TRACE("acpi_button_remove_fs");
+
+       button = acpi_driver_data(device);
+       if (acpi_device_dir(device)) {
+               if (button->type == ACPI_BUTTON_TYPE_LID)
+                       remove_proc_entry(ACPI_BUTTON_FILE_STATE,
+                                            acpi_device_dir(device));
+               remove_proc_entry(ACPI_BUTTON_FILE_INFO,
+                                    acpi_device_dir(device));
+
+               remove_proc_entry(acpi_device_bid(device),
+                                    acpi_device_dir(device)->parent);
+               acpi_device_dir(device) = NULL;
+       }
+
+       return_VALUE(0);
+}
+
+
 /* --------------------------------------------------------------------------
                                 Driver Interface
    -------------------------------------------------------------------------- */
@@ -121,7 +302,8 @@ acpi_button_notify_fixed (
        
        ACPI_FUNCTION_TRACE("acpi_button_notify_fixed");
 
-       BUG_ON(!button);
+       if (!button)
+               return_ACPI_STATUS(AE_BAD_PARAMETER);
 
        acpi_button_notify(button->handle, ACPI_BUTTON_NOTIFY_STATUS, button);
 
@@ -197,6 +379,10 @@ acpi_button_add (
                goto end;
        }
 
+       result = acpi_button_add_fs(device);
+       if (result)
+               goto end;
+
        switch (button->type) {
        case ACPI_BUTTON_TYPE_POWERF:
                status = acpi_install_fixed_event_handler (
@@ -240,6 +426,7 @@ acpi_button_add (
 
 end:
        if (result) {
+               acpi_button_remove_fs(device);
                kfree(button);
        }
 
@@ -280,6 +467,8 @@ acpi_button_remove (struct acpi_device *device, int type)
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                        "Error removing notify handler\n"));
 
+       acpi_button_remove_fs(device);  
+
        kfree(button);
 
        return_VALUE(0);
@@ -293,14 +482,20 @@ acpi_button_init (void)
 
        ACPI_FUNCTION_TRACE("acpi_button_init");
 
+       acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
+       if (!acpi_button_dir)
+               return_VALUE(-ENODEV);
+       acpi_button_dir->owner = THIS_MODULE;
        result = acpi_bus_register_driver(&acpi_button_driver);
        if (result < 0) {
+               remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
                return_VALUE(-ENODEV);
        }
 
        return_VALUE(0);
 }
 
+
 static void __exit
 acpi_button_exit (void)
 {
@@ -308,8 +503,17 @@ acpi_button_exit (void)
 
        acpi_bus_unregister_driver(&acpi_button_driver);
 
+       if (acpi_power_dir) 
+               remove_proc_entry(ACPI_BUTTON_SUBCLASS_POWER, acpi_button_dir);
+       if (acpi_sleep_dir)
+               remove_proc_entry(ACPI_BUTTON_SUBCLASS_SLEEP, acpi_button_dir);
+       if (acpi_lid_dir)
+               remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
+       remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
+
        return_VOID;
 }
 
+
 module_init(acpi_button_init);
 module_exit(acpi_button_exit);
index 1ac197c..d116200 100644 (file)
@@ -491,12 +491,6 @@ acpi_ds_load2_begin_op (
                if ((!(walk_state->op_info->flags & AML_NSOPCODE) &&
                          (walk_state->opcode != AML_INT_NAMEPATH_OP)) ||
                        (!(walk_state->op_info->flags & AML_NAMED))) {
-                       if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
-                               (walk_state->op_info->class == AML_CLASS_CONTROL)) {
-                               ACPI_REPORT_WARNING ((
-                                       "Encountered executable code at module level, [%s]\n",
-                                       acpi_ps_get_opcode_name (walk_state->opcode)));
-                       }
                        return_ACPI_STATUS (AE_OK);
                }
 
index fca4140..1ac5731 100644 (file)
@@ -59,76 +59,186 @@ ACPI_MODULE_NAME           ("acpi_ec")
 #define ACPI_EC_DELAY          50      /* Wait 50ms max. during EC ops */
 #define ACPI_EC_UDELAY_GLK     1000    /* Wait 1ms max. to get global lock */
 
+#define ACPI_EC_UDELAY         100     /* Poll @ 100us increments */
+#define ACPI_EC_UDELAY_COUNT   1000    /* Wait 10ms max. during EC ops */
+
 #define ACPI_EC_COMMAND_READ   0x80
 #define ACPI_EC_COMMAND_WRITE  0x81
 #define ACPI_EC_BURST_ENABLE   0x82
 #define ACPI_EC_BURST_DISABLE  0x83
 #define ACPI_EC_COMMAND_QUERY  0x84
 
-static int acpi_ec_add (struct acpi_device *device);
+#define EC_POLLING             0xFF
+#define EC_BURST               0x00
+
+
 static int acpi_ec_remove (struct acpi_device *device, int type);
 static int acpi_ec_start (struct acpi_device *device);
 static int acpi_ec_stop (struct acpi_device *device, int type);
+static int acpi_ec_burst_add ( struct acpi_device *device);
+static int acpi_ec_polling_add ( struct acpi_device    *device);
 
 static struct acpi_driver acpi_ec_driver = {
        .name =         ACPI_EC_DRIVER_NAME,
        .class =        ACPI_EC_CLASS,
        .ids =          ACPI_EC_HID,
        .ops =          {
-                               .add =          acpi_ec_add,
+                               .add =          acpi_ec_polling_add,
                                .remove =       acpi_ec_remove,
                                .start =        acpi_ec_start,
                                .stop =         acpi_ec_stop,
                        },
 };
-
-struct acpi_ec {
-       acpi_handle                     handle;
-       unsigned long                   uid;
-       unsigned long                   gpe_bit;
-       struct acpi_generic_address     status_addr;
-       struct acpi_generic_address     command_addr;
-       struct acpi_generic_address     data_addr;
-       unsigned long                   global_lock;
-       unsigned int                    expect_event;
-       atomic_t                        leaving_burst; /* 0 : No, 1 : Yes, 2: abort*/
-       atomic_t                        pending_gpe;
-       struct semaphore                sem;
-       wait_queue_head_t               wait;
+union acpi_ec {
+       struct {
+               u32                             mode;
+               acpi_handle                     handle;
+               unsigned long                   uid;
+               unsigned long                   gpe_bit;
+               struct acpi_generic_address     status_addr;
+               struct acpi_generic_address     command_addr;
+               struct acpi_generic_address     data_addr;
+               unsigned long                   global_lock;
+       } common;
+
+       struct {
+               u32                             mode;
+               acpi_handle                     handle;
+               unsigned long                   uid;
+               unsigned long                   gpe_bit;
+               struct acpi_generic_address     status_addr;
+               struct acpi_generic_address     command_addr;
+               struct acpi_generic_address     data_addr;
+               unsigned long                   global_lock;
+               unsigned int                    expect_event;
+               atomic_t                        leaving_burst; /* 0 : No, 1 : Yes, 2: abort*/
+               atomic_t                        pending_gpe;
+               struct semaphore                sem;
+               wait_queue_head_t               wait;
+       }burst;
+
+       struct {
+               u32                             mode;
+               acpi_handle                     handle;
+               unsigned long                   uid;
+               unsigned long                   gpe_bit;
+               struct acpi_generic_address     status_addr;
+               struct acpi_generic_address     command_addr;
+               struct acpi_generic_address     data_addr;
+               unsigned long                   global_lock;
+                       spinlock_t                      lock;
+       }polling;
 };
 
+static int acpi_ec_polling_wait ( union acpi_ec *ec, u8 event); 
+static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event);
+static int acpi_ec_polling_read ( union acpi_ec *ec, u8 address, u32 *data);
+static int acpi_ec_burst_read( union acpi_ec *ec, u8 address, u32 *data);
+static int acpi_ec_polling_write ( union acpi_ec *ec, u8 address, u8 data);
+static int acpi_ec_burst_write ( union acpi_ec *ec, u8 address, u8 data);
+static int acpi_ec_polling_query ( union acpi_ec *ec, u32 *data);
+static int acpi_ec_burst_query ( union acpi_ec *ec, u32 *data);
+static void acpi_ec_gpe_polling_query ( void *ec_cxt);
+static void acpi_ec_gpe_burst_query ( void *ec_cxt);
+static u32 acpi_ec_gpe_polling_handler ( void *data);
+static u32 acpi_ec_gpe_burst_handler ( void *data);
+static acpi_status __init
+acpi_fake_ecdt_polling_callback (
+       acpi_handle     handle,
+       u32             Level,
+       void            *context,
+       void            **retval);
+
+static acpi_status __init
+acpi_fake_ecdt_burst_callback (
+       acpi_handle     handle,
+       u32             Level,
+       void            *context,
+       void            **retval);
+
+static int __init
+acpi_ec_polling_get_real_ecdt(void);
+static int __init
+acpi_ec_burst_get_real_ecdt(void);
 /* If we find an EC via the ECDT, we need to keep a ptr to its context */
-static struct acpi_ec  *ec_ecdt;
+static union acpi_ec   *ec_ecdt;
 
 /* External interfaces use first EC only, so remember */
 static struct acpi_device *first_ec;
+static int acpi_ec_polling_mode = EC_POLLING;
 
 /* --------------------------------------------------------------------------
                              Transaction Management
    -------------------------------------------------------------------------- */
 
-static inline u32 acpi_ec_read_status(struct acpi_ec *ec)
+static inline u32 acpi_ec_read_status(union acpi_ec *ec)
 {
        u32     status = 0;
 
-       acpi_hw_low_level_read(8, &status, &ec->status_addr);
+       acpi_hw_low_level_read(8, &status, &ec->common.status_addr);
        return status;
 }
 
-static int acpi_ec_wait(struct acpi_ec *ec, unsigned int event)
+static int
+acpi_ec_wait (
+       union acpi_ec           *ec,
+       u8                      event)
+{
+       if (acpi_ec_polling_mode) 
+               return acpi_ec_polling_wait (ec, event);
+       else
+               return acpi_ec_burst_wait (ec, event);
+}
+
+static int
+acpi_ec_polling_wait (
+       union acpi_ec           *ec,
+       u8                      event)
+{
+       u32                     acpi_ec_status = 0;
+       u32                     i = ACPI_EC_UDELAY_COUNT;
+
+       if (!ec)
+               return -EINVAL;
+
+       /* Poll the EC status register waiting for the event to occur. */
+       switch (event) {
+       case ACPI_EC_EVENT_OBF:
+               do {
+                       acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr);
+                       if (acpi_ec_status & ACPI_EC_FLAG_OBF)
+                               return 0;
+                       udelay(ACPI_EC_UDELAY);
+               } while (--i>0);
+               break;
+       case ACPI_EC_EVENT_IBE:
+               do {
+                       acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr);
+                       if (!(acpi_ec_status & ACPI_EC_FLAG_IBF))
+                               return 0;
+                       udelay(ACPI_EC_UDELAY);
+               } while (--i>0);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return -ETIME;
+}
+static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event)
 {
        int     result = 0;
 
        ACPI_FUNCTION_TRACE("acpi_ec_wait");
 
-       ec->expect_event = event;
+       ec->burst.expect_event = event;
        smp_mb();
 
-       result = wait_event_interruptible_timeout(ec->wait,
-                                       !ec->expect_event,
+       result = wait_event_interruptible_timeout(ec->burst.wait,
+                                       !ec->burst.expect_event,
                                        msecs_to_jiffies(ACPI_EC_DELAY));
        
-       ec->expect_event = 0;
+       ec->burst.expect_event = 0;
        smp_mb();
 
        if (result < 0){
@@ -160,7 +270,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, unsigned int event)
 
 static int
 acpi_ec_enter_burst_mode (
-       struct acpi_ec          *ec)
+       union acpi_ec           *ec)
 {
        u32                     tmp = 0;
        int                     status = 0;
@@ -170,43 +280,43 @@ acpi_ec_enter_burst_mode (
        status = acpi_ec_read_status(ec);
        if (status != -EINVAL &&
                !(status & ACPI_EC_FLAG_BURST)){
-               acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->command_addr);
+               acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr);
                status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
                if (status){
-                       acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+                       acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
                        return_VALUE(-EINVAL);
                }
-               acpi_hw_low_level_read(8, &tmp, &ec->data_addr);
-               acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+               acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr);
+               acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
                if(tmp != 0x90 ) {/* Burst ACK byte*/
                        return_VALUE(-EINVAL);
                }
        }
 
-       atomic_set(&ec->leaving_burst , 0);
+       atomic_set(&ec->burst.leaving_burst , 0);
        return_VALUE(0);
 }
 
 static int
 acpi_ec_leave_burst_mode (
-       struct acpi_ec          *ec)
+       union acpi_ec           *ec)
 {
        int                     status =0;
 
        ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode");
 
-       atomic_set(&ec->leaving_burst , 1);
+       atomic_set(&ec->burst.leaving_burst , 1);
        status = acpi_ec_read_status(ec);
        if (status != -EINVAL &&
                (status & ACPI_EC_FLAG_BURST)){
-               acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->command_addr);
+               acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr);
                status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF);
                if (status){
-                       acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+                       acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
                        ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"------->wait fail\n"));
                        return_VALUE(-EINVAL);
                }
-               acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+               acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
                status = acpi_ec_read_status(ec);
        }
 
@@ -215,7 +325,131 @@ acpi_ec_leave_burst_mode (
 
 static int
 acpi_ec_read (
-       struct acpi_ec          *ec,
+       union acpi_ec           *ec,
+       u8                      address,
+       u32                     *data)
+{
+       if (acpi_ec_polling_mode) 
+               return acpi_ec_polling_read(ec, address, data);
+       else
+               return acpi_ec_burst_read(ec, address, data);
+}
+static int
+acpi_ec_write (
+       union acpi_ec           *ec,
+       u8                      address,
+       u8                      data)
+{
+       if (acpi_ec_polling_mode) 
+               return acpi_ec_polling_write(ec, address, data);
+       else
+               return acpi_ec_burst_write(ec, address, data);
+}
+static int
+acpi_ec_polling_read (
+       union acpi_ec           *ec,
+       u8                      address,
+       u32                     *data)
+{
+       acpi_status             status = AE_OK;
+       int                     result = 0;
+       unsigned long           flags = 0;
+       u32                     glk = 0;
+
+       ACPI_FUNCTION_TRACE("acpi_ec_read");
+
+       if (!ec || !data)
+               return_VALUE(-EINVAL);
+
+       *data = 0;
+
+       if (ec->common.global_lock) {
+               status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
+               if (ACPI_FAILURE(status))
+                       return_VALUE(-ENODEV);
+       }
+
+       spin_lock_irqsave(&ec->polling.lock, flags);
+
+       acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr);
+       result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+       if (result)
+               goto end;
+
+       acpi_hw_low_level_write(8, address, &ec->common.data_addr);
+       result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
+       if (result)
+               goto end;
+
+       acpi_hw_low_level_read(8, data, &ec->common.data_addr);
+
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n",
+               *data, address));
+       
+end:
+       spin_unlock_irqrestore(&ec->polling.lock, flags);
+
+       if (ec->common.global_lock)
+               acpi_release_global_lock(glk);
+
+       return_VALUE(result);
+}
+
+
+static int
+acpi_ec_polling_write (
+       union acpi_ec           *ec,
+       u8                      address,
+       u8                      data)
+{
+       int                     result = 0;
+       acpi_status             status = AE_OK;
+       unsigned long           flags = 0;
+       u32                     glk = 0;
+
+       ACPI_FUNCTION_TRACE("acpi_ec_write");
+
+       if (!ec)
+               return_VALUE(-EINVAL);
+
+       if (ec->common.global_lock) {
+               status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
+               if (ACPI_FAILURE(status))
+                       return_VALUE(-ENODEV);
+       }
+
+       spin_lock_irqsave(&ec->polling.lock, flags);
+
+       acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr);
+       result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+       if (result)
+               goto end;
+
+       acpi_hw_low_level_write(8, address, &ec->common.data_addr);
+       result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+       if (result)
+               goto end;
+
+       acpi_hw_low_level_write(8, data, &ec->common.data_addr);
+       result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+       if (result)
+               goto end;
+
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n",
+               data, address));
+
+end:
+       spin_unlock_irqrestore(&ec->polling.lock, flags);
+
+       if (ec->common.global_lock)
+               acpi_release_global_lock(glk);
+
+       return_VALUE(result);
+}
+
+static int
+acpi_ec_burst_read (
+       union acpi_ec           *ec,
        u8                      address,
        u32                     *data)
 {
@@ -230,51 +464,51 @@ acpi_ec_read (
 retry:
        *data = 0;
 
-       if (ec->global_lock) {
+       if (ec->common.global_lock) {
                status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
                if (ACPI_FAILURE(status))
                        return_VALUE(-ENODEV);
        }
 
        WARN_ON(in_interrupt());
-       down(&ec->sem);
+       down(&ec->burst.sem);
 
        if(acpi_ec_enter_burst_mode(ec))
                goto end;
 
-       acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->command_addr);
+       acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr);
        status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
-       acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+       acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
        if (status) {
                goto end;
        }
 
-       acpi_hw_low_level_write(8, address, &ec->data_addr);
+       acpi_hw_low_level_write(8, address, &ec->common.data_addr);
        status= acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
        if (status){
-               acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+               acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
                goto end;
        }
 
-       acpi_hw_low_level_read(8, data, &ec->data_addr);
-       acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+       acpi_hw_low_level_read(8, data, &ec->common.data_addr);
+       acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n",
                *data, address));
        
 end:
        acpi_ec_leave_burst_mode(ec);
-       up(&ec->sem);
+       up(&ec->burst.sem);
 
-       if (ec->global_lock)
+       if (ec->common.global_lock)
                acpi_release_global_lock(glk);
 
-       if(atomic_read(&ec->leaving_burst) == 2){
+       if(atomic_read(&ec->burst.leaving_burst) == 2){
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n"));
-               while(atomic_read(&ec->pending_gpe)){
+               while(atomic_read(&ec->burst.pending_gpe)){
                        msleep(1);      
                }
-               acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+               acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
                goto retry;
        }
 
@@ -283,8 +517,8 @@ end:
 
 
 static int
-acpi_ec_write (
-       struct acpi_ec          *ec,
+acpi_ec_burst_write (
+       union acpi_ec           *ec,
        u8                      address,
        u8                      data)
 {
@@ -297,14 +531,14 @@ acpi_ec_write (
        if (!ec)
                return_VALUE(-EINVAL);
 retry:
-       if (ec->global_lock) {
+       if (ec->common.global_lock) {
                status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
                if (ACPI_FAILURE(status))
                        return_VALUE(-ENODEV);
        }
 
        WARN_ON(in_interrupt());
-       down(&ec->sem);
+       down(&ec->burst.sem);
 
        if(acpi_ec_enter_burst_mode(ec))
                goto end;
@@ -312,33 +546,33 @@ retry:
        status = acpi_ec_read_status(ec);
        if (status != -EINVAL &&
                !(status & ACPI_EC_FLAG_BURST)){
-               acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->command_addr);
+               acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr);
                status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
                if (status)
                        goto end;
-               acpi_hw_low_level_read(8, &tmp, &ec->data_addr);
+               acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr);
                if(tmp != 0x90 ) /* Burst ACK byte*/
                        goto end;
        }
        /*Now we are in burst mode*/
 
-       acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->command_addr);
+       acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr);
        status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
-       acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+       acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
        if (status){
                goto end;
        }
 
-       acpi_hw_low_level_write(8, address, &ec->data_addr);
+       acpi_hw_low_level_write(8, address, &ec->common.data_addr);
        status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
        if (status){
-               acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+               acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
                goto end;
        }
 
-       acpi_hw_low_level_write(8, data, &ec->data_addr);
+       acpi_hw_low_level_write(8, data, &ec->common.data_addr);
        status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
-       acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+       acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
        if (status)
                goto end;
 
@@ -347,17 +581,17 @@ retry:
 
 end:
        acpi_ec_leave_burst_mode(ec);
-       up(&ec->sem);
+       up(&ec->burst.sem);
 
-       if (ec->global_lock)
+       if (ec->common.global_lock)
                acpi_release_global_lock(glk);
 
-       if(atomic_read(&ec->leaving_burst) == 2){
+       if(atomic_read(&ec->burst.leaving_burst) == 2){
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n"));
-               while(atomic_read(&ec->pending_gpe)){
+               while(atomic_read(&ec->burst.pending_gpe)){
                        msleep(1);      
                }
-               acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+               acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
                goto retry;
        }
 
@@ -370,7 +604,7 @@ end:
 int
 ec_read(u8 addr, u8 *val)
 {
-       struct acpi_ec *ec;
+       union acpi_ec *ec;
        int err;
        u32 temp_data;
 
@@ -393,7 +627,7 @@ EXPORT_SYMBOL(ec_read);
 int
 ec_write(u8 addr, u8 val)
 {
-       struct acpi_ec *ec;
+       union acpi_ec *ec;
        int err;
 
        if (!first_ec)
@@ -407,10 +641,66 @@ ec_write(u8 addr, u8 val)
 }
 EXPORT_SYMBOL(ec_write);
 
-
 static int
 acpi_ec_query (
-       struct acpi_ec          *ec,
+       union acpi_ec           *ec,
+       u32                     *data)
+{
+       if (acpi_ec_polling_mode) 
+               return acpi_ec_polling_query(ec, data);
+       else
+               return acpi_ec_burst_query(ec, data);
+}
+static int
+acpi_ec_polling_query (
+       union acpi_ec           *ec,
+       u32                     *data)
+{
+       int                     result = 0;
+       acpi_status             status = AE_OK;
+       unsigned long           flags = 0;
+       u32                     glk = 0;
+
+       ACPI_FUNCTION_TRACE("acpi_ec_query");
+
+       if (!ec || !data)
+               return_VALUE(-EINVAL);
+
+       *data = 0;
+
+       if (ec->common.global_lock) {
+               status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
+               if (ACPI_FAILURE(status))
+                       return_VALUE(-ENODEV);
+       }
+
+       /*
+        * Query the EC to find out which _Qxx method we need to evaluate.
+        * Note that successful completion of the query causes the ACPI_EC_SCI
+        * bit to be cleared (and thus clearing the interrupt source).
+        */
+       spin_lock_irqsave(&ec->polling.lock, flags);
+
+       acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr);
+       result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
+       if (result)
+               goto end;
+
+       acpi_hw_low_level_read(8, data, &ec->common.data_addr);
+       if (!*data)
+               result = -ENODATA;
+
+end:
+       spin_unlock_irqrestore(&ec->polling.lock, flags);
+
+       if (ec->common.global_lock)
+               acpi_release_global_lock(glk);
+
+       return_VALUE(result);
+}
+static int
+acpi_ec_burst_query (
+       union acpi_ec           *ec,
        u32                     *data)
 {
        int                     status = 0;
@@ -422,13 +712,13 @@ acpi_ec_query (
                return_VALUE(-EINVAL);
        *data = 0;
 
-       if (ec->global_lock) {
+       if (ec->common.global_lock) {
                status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
                if (ACPI_FAILURE(status))
                        return_VALUE(-ENODEV);
        }
 
-       down(&ec->sem);
+       down(&ec->burst.sem);
        if(acpi_ec_enter_burst_mode(ec))
                goto end;
        /*
@@ -436,28 +726,28 @@ acpi_ec_query (
         * Note that successful completion of the query causes the ACPI_EC_SCI
         * bit to be cleared (and thus clearing the interrupt source).
         */
-       acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr);
+       acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr);
        status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
        if (status){
-               acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+               acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
                goto end;
        }
 
-       acpi_hw_low_level_read(8, data, &ec->data_addr);
-       acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+       acpi_hw_low_level_read(8, data, &ec->common.data_addr);
+       acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
        if (!*data)
                status = -ENODATA;
 
 end:
        acpi_ec_leave_burst_mode(ec);
-       up(&ec->sem);
+       up(&ec->burst.sem);
 
-       if (ec->global_lock)
+       if (ec->common.global_lock)
                acpi_release_global_lock(glk);
 
-       if(atomic_read(&ec->leaving_burst) == 2){
+       if(atomic_read(&ec->burst.leaving_burst) == 2){
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n"));
-               acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+               acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
                status = -ENODATA;
        }
        return_VALUE(status);
@@ -468,7 +758,7 @@ end:
                                 Event Management
    -------------------------------------------------------------------------- */
 
-struct acpi_ec_query_data {
+union acpi_ec_query_data {
        acpi_handle             handle;
        u8                      data;
 };
@@ -477,7 +767,59 @@ static void
 acpi_ec_gpe_query (
        void                    *ec_cxt)
 {
-       struct acpi_ec          *ec = (struct acpi_ec *) ec_cxt;
+       if (acpi_ec_polling_mode) 
+               acpi_ec_gpe_polling_query(ec_cxt);
+       else
+               acpi_ec_gpe_burst_query(ec_cxt);
+}
+
+static void
+acpi_ec_gpe_polling_query (
+       void                    *ec_cxt)
+{
+       union acpi_ec           *ec = (union acpi_ec *) ec_cxt;
+       u32                     value = 0;
+       unsigned long           flags = 0;
+       static char             object_name[5] = {'_','Q','0','0','\0'};
+       const char              hex[] = {'0','1','2','3','4','5','6','7',
+                                        '8','9','A','B','C','D','E','F'};
+
+       ACPI_FUNCTION_TRACE("acpi_ec_gpe_query");
+
+       if (!ec_cxt)
+               goto end;
+
+       spin_lock_irqsave(&ec->polling.lock, flags);
+       acpi_hw_low_level_read(8, &value, &ec->common.command_addr);
+       spin_unlock_irqrestore(&ec->polling.lock, flags);
+
+       /* TBD: Implement asynch events!
+        * NOTE: All we care about are EC-SCI's.  Other EC events are
+        * handled via polling (yuck!).  This is because some systems
+        * treat EC-SCIs as level (versus EDGE!) triggered, preventing
+        *  a purely interrupt-driven approach (grumble, grumble).
+        */
+       if (!(value & ACPI_EC_FLAG_SCI))
+               goto end;
+
+       if (acpi_ec_query(ec, &value))
+               goto end;
+
+       object_name[2] = hex[((value >> 4) & 0x0F)];
+       object_name[3] = hex[(value & 0x0F)];
+
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name));
+
+       acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL);
+
+end:   
+       acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
+}
+static void
+acpi_ec_gpe_burst_query (
+       void                    *ec_cxt)
+{
+       union acpi_ec           *ec = (union acpi_ec *) ec_cxt;
        u32                     value;
        int                     result = -ENODATA;
        static char             object_name[5] = {'_','Q','0','0','\0'};
@@ -497,58 +839,87 @@ acpi_ec_gpe_query (
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name));
 
-       acpi_evaluate_object(ec->handle, object_name, NULL, NULL);
+       acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL);
 end:   
-       atomic_dec(&ec->pending_gpe);
+       atomic_dec(&ec->burst.pending_gpe);
        return;
 }
 
 static u32
 acpi_ec_gpe_handler (
        void                    *data)
+{
+       if (acpi_ec_polling_mode) 
+               return acpi_ec_gpe_polling_handler(data);
+       else
+               return acpi_ec_gpe_burst_handler(data); 
+}
+static u32
+acpi_ec_gpe_polling_handler (
+       void                    *data)
+{
+       acpi_status             status = AE_OK;
+       union acpi_ec           *ec = (union acpi_ec *) data;
+
+       if (!ec)
+               return ACPI_INTERRUPT_NOT_HANDLED;
+
+       acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
+
+       status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
+               acpi_ec_gpe_query, ec);
+
+       if (status == AE_OK)
+               return ACPI_INTERRUPT_HANDLED;
+       else
+               return ACPI_INTERRUPT_NOT_HANDLED;
+}
+static u32
+acpi_ec_gpe_burst_handler (
+       void                    *data)
 {
        acpi_status             status = AE_OK;
        u32                     value;
-       struct acpi_ec          *ec = (struct acpi_ec *) data;
+       union acpi_ec           *ec = (union acpi_ec *) data;
 
        if (!ec)
                return ACPI_INTERRUPT_NOT_HANDLED;
 
-       acpi_disable_gpe(NULL, ec->gpe_bit, ACPI_ISR);
+       acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
 
        value = acpi_ec_read_status(ec);
 
        if((value & ACPI_EC_FLAG_IBF) &&
                !(value & ACPI_EC_FLAG_BURST) &&
-                       (atomic_read(&ec->leaving_burst) == 0)) { 
+                       (atomic_read(&ec->burst.leaving_burst) == 0)) { 
        /*
         * the embedded controller disables 
         * burst mode for any reason other 
         * than the burst disable command
         * to process critical event.
         */
-               atomic_set(&ec->leaving_burst , 2); /* block current pending transaction
+               atomic_set(&ec->burst.leaving_burst , 2); /* block current pending transaction
                                        and retry */
-               wake_up(&ec->wait);
+               wake_up(&ec->burst.wait);
        }else {
-               if ((ec->expect_event == ACPI_EC_EVENT_OBF &&
+               if ((ec->burst.expect_event == ACPI_EC_EVENT_OBF &&
                                (value & ACPI_EC_FLAG_OBF)) ||
-                               (ec->expect_event == ACPI_EC_EVENT_IBE &&
+                               (ec->burst.expect_event == ACPI_EC_EVENT_IBE &&
                                !(value & ACPI_EC_FLAG_IBF))) {
-                       ec->expect_event = 0;
-                       wake_up(&ec->wait);
+                       ec->burst.expect_event = 0;
+                       wake_up(&ec->burst.wait);
                        return ACPI_INTERRUPT_HANDLED;
                }
        }
 
        if (value & ACPI_EC_FLAG_SCI){
-               atomic_add(1, &ec->pending_gpe) ;
+               atomic_add(1, &ec->burst.pending_gpe) ;
                status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
                                                acpi_ec_gpe_query, ec);
                return status == AE_OK ?
                ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
        } 
-       acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_ISR);
+       acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
        return status == AE_OK ?
                ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
 }
@@ -585,7 +956,7 @@ acpi_ec_space_handler (
        void                    *region_context)
 {
        int                     result = 0;
-       struct acpi_ec          *ec = NULL;
+       union acpi_ec           *ec = NULL;
        u64                     temp = *value;
        acpi_integer            f_v = 0;
        int                     i = 0;
@@ -600,7 +971,7 @@ acpi_ec_space_handler (
                return_VALUE(AE_BAD_PARAMETER);
        }
 
-       ec = (struct acpi_ec *) handler_context;
+       ec = (union acpi_ec *) handler_context;
 
 next_byte:
        switch (function) {
@@ -661,7 +1032,7 @@ static struct proc_dir_entry       *acpi_ec_dir;
 static int
 acpi_ec_read_info (struct seq_file *seq, void *offset)
 {
-       struct acpi_ec          *ec = (struct acpi_ec *) seq->private;
+       union acpi_ec           *ec = (union acpi_ec *) seq->private;
 
        ACPI_FUNCTION_TRACE("acpi_ec_read_info");
 
@@ -669,12 +1040,12 @@ acpi_ec_read_info (struct seq_file *seq, void *offset)
                goto end;
 
        seq_printf(seq, "gpe bit:                 0x%02x\n",
-               (u32) ec->gpe_bit);
+               (u32) ec->common.gpe_bit);
        seq_printf(seq, "ports:                   0x%02x, 0x%02x\n",
-               (u32) ec->status_addr.address, (u32) ec->data_addr.address);
+               (u32) ec->common.status_addr.address, (u32) ec->common.data_addr.address);
        seq_printf(seq, "use global lock:         %s\n",
-               ec->global_lock?"yes":"no");
-       acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+               ec->common.global_lock?"yes":"no");
+       acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
 
 end:
        return_VALUE(0);
@@ -697,7 +1068,7 @@ static int
 acpi_ec_add_fs (
        struct acpi_device      *device)
 {
-       struct proc_dir_entry   *entry;
+       struct proc_dir_entry   *entry = NULL;
 
        ACPI_FUNCTION_TRACE("acpi_ec_add_fs");
 
@@ -744,13 +1115,14 @@ acpi_ec_remove_fs (
                                Driver Interface
    -------------------------------------------------------------------------- */
 
+
 static int
-acpi_ec_add (
+acpi_ec_polling_add (
        struct acpi_device      *device)
 {
-       int                     result;
-       acpi_status             status;
-       struct acpi_ec          *ec;
+       int                     result = 0;
+       acpi_status             status = AE_OK;
+       union acpi_ec           *ec = NULL;
        unsigned long           uid;
 
        ACPI_FUNCTION_TRACE("acpi_ec_add");
@@ -758,39 +1130,107 @@ acpi_ec_add (
        if (!device)
                return_VALUE(-EINVAL);
 
-       ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
+       ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
        if (!ec)
                return_VALUE(-ENOMEM);
-       memset(ec, 0, sizeof(struct acpi_ec));
-
-       ec->handle = device->handle;
-       ec->uid = -1;
-       atomic_set(&ec->pending_gpe, 0);
-       atomic_set(&ec->leaving_burst , 1);
-       init_MUTEX(&ec->sem);
-       init_waitqueue_head(&ec->wait);
+       memset(ec, 0, sizeof(union acpi_ec));
+
+       ec->common.handle = device->handle;
+       ec->common.uid = -1;
+       spin_lock_init(&ec->polling.lock);
        strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_EC_CLASS);
        acpi_driver_data(device) = ec;
 
        /* Use the global lock for all EC transactions? */
-       acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock);
+       acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock);
 
        /* If our UID matches the UID for the ECDT-enumerated EC,
           we now have the *real* EC info, so kill the makeshift one.*/
-       acpi_evaluate_integer(ec->handle, "_UID", NULL, &uid);
-       if (ec_ecdt && ec_ecdt->uid == uid) {
+       acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid);
+       if (ec_ecdt && ec_ecdt->common.uid == uid) {
                acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
                        ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
+       
+               acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler);
+
+               kfree(ec_ecdt);
+       }
+
+       /* Get GPE bit assignment (EC events). */
+       /* TODO: Add support for _GPE returning a package */
+       status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit);
+       if (ACPI_FAILURE(status)) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                       "Error obtaining GPE bit assignment\n"));
+               result = -ENODEV;
+               goto end;
+       }
 
-               acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, &acpi_ec_gpe_handler);
+       result = acpi_ec_add_fs(device);
+       if (result)
+               goto end;
+
+       printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n",
+               acpi_device_name(device), acpi_device_bid(device),
+               (u32) ec->common.gpe_bit);
+
+       if (!first_ec)
+               first_ec = device;
+
+end:
+       if (result)
+               kfree(ec);
+
+       return_VALUE(result);
+}
+static int
+acpi_ec_burst_add (
+       struct acpi_device      *device)
+{
+       int                     result = 0;
+       acpi_status             status = AE_OK;
+       union acpi_ec           *ec = NULL;
+       unsigned long           uid;
+
+       ACPI_FUNCTION_TRACE("acpi_ec_add");
+
+       if (!device)
+               return_VALUE(-EINVAL);
+
+       ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
+       if (!ec)
+               return_VALUE(-ENOMEM);
+       memset(ec, 0, sizeof(union acpi_ec));
+
+       ec->common.handle = device->handle;
+       ec->common.uid = -1;
+       atomic_set(&ec->burst.pending_gpe, 0);
+       atomic_set(&ec->burst.leaving_burst , 1);
+       init_MUTEX(&ec->burst.sem);
+       init_waitqueue_head(&ec->burst.wait);
+       strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
+       strcpy(acpi_device_class(device), ACPI_EC_CLASS);
+       acpi_driver_data(device) = ec;
+
+       /* Use the global lock for all EC transactions? */
+       acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock);
+
+       /* If our UID matches the UID for the ECDT-enumerated EC,
+          we now have the *real* EC info, so kill the makeshift one.*/
+       acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid);
+       if (ec_ecdt && ec_ecdt->common.uid == uid) {
+               acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
+                       ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
+
+               acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler);
 
                kfree(ec_ecdt);
        }
 
        /* Get GPE bit assignment (EC events). */
        /* TODO: Add support for _GPE returning a package */
-       status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe_bit);
+       status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit);
        if (ACPI_FAILURE(status)) {
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                        "Error obtaining GPE bit assignment\n"));
@@ -804,7 +1244,7 @@ acpi_ec_add (
 
        printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n",
                acpi_device_name(device), acpi_device_bid(device),
-               (u32) ec->gpe_bit);
+               (u32) ec->common.gpe_bit);
 
        if (!first_ec)
                first_ec = device;
@@ -822,7 +1262,7 @@ acpi_ec_remove (
        struct acpi_device      *device,
        int                     type)
 {
-       struct acpi_ec          *ec;
+       union acpi_ec           *ec = NULL;
 
        ACPI_FUNCTION_TRACE("acpi_ec_remove");
 
@@ -844,7 +1284,7 @@ acpi_ec_io_ports (
        struct acpi_resource    *resource,
        void                    *context)
 {
-       struct acpi_ec          *ec = (struct acpi_ec *) context;
+       union acpi_ec           *ec = (union acpi_ec *) context;
        struct acpi_generic_address *addr;
 
        if (resource->id != ACPI_RSTYPE_IO) {
@@ -856,10 +1296,10 @@ acpi_ec_io_ports (
         * the second address region returned is the status/command
         * port.
         */
-       if (ec->data_addr.register_bit_width == 0) {
-               addr = &ec->data_addr;
-       } else if (ec->command_addr.register_bit_width == 0) {
-               addr = &ec->command_addr;
+       if (ec->common.data_addr.register_bit_width == 0) {
+               addr = &ec->common.data_addr;
+       } else if (ec->common.command_addr.register_bit_width == 0) {
+               addr = &ec->common.command_addr;
        } else {
                return AE_CTRL_TERMINATE;
        }
@@ -877,8 +1317,8 @@ static int
 acpi_ec_start (
        struct acpi_device      *device)
 {
-       acpi_status             status;
-       struct acpi_ec          *ec;
+       acpi_status             status = AE_OK;
+       union acpi_ec           *ec = NULL;
 
        ACPI_FUNCTION_TRACE("acpi_ec_start");
 
@@ -893,35 +1333,36 @@ acpi_ec_start (
        /*
         * Get I/O port addresses. Convert to GAS format.
         */
-       status = acpi_walk_resources(ec->handle, METHOD_NAME__CRS,
+       status = acpi_walk_resources(ec->common.handle, METHOD_NAME__CRS,
                acpi_ec_io_ports, ec);
-       if (ACPI_FAILURE(status) || ec->command_addr.register_bit_width == 0) {
+       if (ACPI_FAILURE(status) || ec->common.command_addr.register_bit_width == 0) {
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error getting I/O port addresses"));
                return_VALUE(-ENODEV);
        }
 
-       ec->status_addr = ec->command_addr;
+       ec->common.status_addr = ec->common.command_addr;
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n",
-               (u32) ec->gpe_bit, (u32) ec->command_addr.address,
-               (u32) ec->data_addr.address));
+               (u32) ec->common.gpe_bit, (u32) ec->common.command_addr.address,
+               (u32) ec->common.data_addr.address));
+
 
        /*
         * Install GPE handler
         */
-       status = acpi_install_gpe_handler(NULL, ec->gpe_bit,
+       status = acpi_install_gpe_handler(NULL, ec->common.gpe_bit,
                ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec);
        if (ACPI_FAILURE(status)) {
                return_VALUE(-ENODEV);
        }
-       acpi_set_gpe_type (NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
-       acpi_enable_gpe (NULL, ec->gpe_bit, ACPI_NOT_ISR);
+       acpi_set_gpe_type (NULL, ec->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME);
+       acpi_enable_gpe (NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
 
-       status = acpi_install_address_space_handler (ec->handle,
+       status = acpi_install_address_space_handler (ec->common.handle,
                        ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
                        &acpi_ec_space_setup, ec);
        if (ACPI_FAILURE(status)) {
-               acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler);
+               acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler);
                return_VALUE(-ENODEV);
        }
 
@@ -934,8 +1375,8 @@ acpi_ec_stop (
        struct acpi_device      *device,
        int                     type)
 {
-       acpi_status             status;
-       struct acpi_ec          *ec;
+       acpi_status             status = AE_OK;
+       union acpi_ec           *ec = NULL;
 
        ACPI_FUNCTION_TRACE("acpi_ec_stop");
 
@@ -944,12 +1385,12 @@ acpi_ec_stop (
 
        ec = acpi_driver_data(device);
 
-       status = acpi_remove_address_space_handler(ec->handle,
+       status = acpi_remove_address_space_handler(ec->common.handle,
                ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
        if (ACPI_FAILURE(status))
                return_VALUE(-ENODEV);
 
-       status = acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler);
+       status = acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler);
        if (ACPI_FAILURE(status))
                return_VALUE(-ENODEV);
 
@@ -963,26 +1404,76 @@ acpi_fake_ecdt_callback (
        void            *context,
        void            **retval)
 {
+
+       if (acpi_ec_polling_mode)
+               return acpi_fake_ecdt_polling_callback(handle,
+                       Level, context, retval);
+       else
+               return acpi_fake_ecdt_burst_callback(handle,
+                       Level, context, retval);
+}
+
+static acpi_status __init
+acpi_fake_ecdt_polling_callback (
+       acpi_handle     handle,
+       u32             Level,
+       void            *context,
+       void            **retval)
+{
        acpi_status     status;
 
        status = acpi_walk_resources(handle, METHOD_NAME__CRS,
                acpi_ec_io_ports, ec_ecdt);
        if (ACPI_FAILURE(status))
                return status;
-       ec_ecdt->status_addr = ec_ecdt->command_addr;
+       ec_ecdt->common.status_addr = ec_ecdt->common.command_addr;
 
-       ec_ecdt->uid = -1;
-       acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid);
+       ec_ecdt->common.uid = -1;
+       acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid);
 
-       status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->gpe_bit);
+       status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit);
        if (ACPI_FAILURE(status))
                return status;
-       ec_ecdt->global_lock = TRUE;
-       ec_ecdt->handle = handle;
+       spin_lock_init(&ec_ecdt->polling.lock);
+       ec_ecdt->common.global_lock = TRUE;
+       ec_ecdt->common.handle = handle;
 
        printk(KERN_INFO PREFIX  "GPE=0x%02x, ports=0x%2x, 0x%2x\n",
-               (u32) ec_ecdt->gpe_bit, (u32) ec_ecdt->command_addr.address,
-               (u32) ec_ecdt->data_addr.address);
+               (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address,
+               (u32) ec_ecdt->common.data_addr.address);
+
+       return AE_CTRL_TERMINATE;
+}
+
+static acpi_status __init
+acpi_fake_ecdt_burst_callback (
+       acpi_handle     handle,
+       u32             Level,
+       void            *context,
+       void            **retval)
+{
+       acpi_status     status;
+
+       init_MUTEX(&ec_ecdt->burst.sem);
+       init_waitqueue_head(&ec_ecdt->burst.wait);
+       status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+               acpi_ec_io_ports, ec_ecdt);
+       if (ACPI_FAILURE(status))
+               return status;
+       ec_ecdt->common.status_addr = ec_ecdt->common.command_addr;
+
+       ec_ecdt->common.uid = -1;
+       acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid);
+
+       status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit);
+       if (ACPI_FAILURE(status))
+               return status;
+       ec_ecdt->common.global_lock = TRUE;
+       ec_ecdt->common.handle = handle;
+
+       printk(KERN_INFO PREFIX  "GPE=0x%02x, ports=0x%2x, 0x%2x\n",
+               (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address,
+               (u32) ec_ecdt->common.data_addr.address);
 
        return AE_CTRL_TERMINATE;
 }
@@ -1005,12 +1496,12 @@ acpi_ec_fake_ecdt(void)
 
        printk(KERN_INFO PREFIX "Try to make an fake ECDT\n");
 
-       ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
+       ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
        if (!ec_ecdt) {
                ret = -ENOMEM;
                goto error;
        }
-       memset(ec_ecdt, 0, sizeof(struct acpi_ec));
+       memset(ec_ecdt, 0, sizeof(union acpi_ec));
 
        status = acpi_get_devices (ACPI_EC_HID,
                                acpi_fake_ecdt_callback,
@@ -1030,6 +1521,60 @@ error:
 
 static int __init
 acpi_ec_get_real_ecdt(void)
+{
+       if (acpi_ec_polling_mode)
+               return acpi_ec_polling_get_real_ecdt();
+       else
+               return acpi_ec_burst_get_real_ecdt();
+}
+
+static int __init
+acpi_ec_polling_get_real_ecdt(void)
+{
+       acpi_status             status;
+       struct acpi_table_ecdt  *ecdt_ptr;
+
+       status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING, 
+               (struct acpi_table_header **) &ecdt_ptr);
+       if (ACPI_FAILURE(status))
+               return -ENODEV;
+
+       printk(KERN_INFO PREFIX "Found ECDT\n");
+
+       /*
+        * Generate a temporary ec context to use until the namespace is scanned
+        */
+       ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
+       if (!ec_ecdt)
+               return -ENOMEM;
+       memset(ec_ecdt, 0, sizeof(union acpi_ec));
+
+       ec_ecdt->common.command_addr = ecdt_ptr->ec_control;
+       ec_ecdt->common.status_addr = ecdt_ptr->ec_control;
+       ec_ecdt->common.data_addr = ecdt_ptr->ec_data;
+       ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit;
+       spin_lock_init(&ec_ecdt->polling.lock);
+       /* use the GL just to be safe */
+       ec_ecdt->common.global_lock = TRUE;
+       ec_ecdt->common.uid = ecdt_ptr->uid;
+
+       status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle);
+       if (ACPI_FAILURE(status)) {
+               goto error;
+       }
+
+       return 0;
+error:
+       printk(KERN_ERR PREFIX "Could not use ECDT\n");
+       kfree(ec_ecdt);
+       ec_ecdt = NULL;
+
+       return -ENODEV;
+}
+
+
+static int __init
+acpi_ec_burst_get_real_ecdt(void)
 {
        acpi_status             status;
        struct acpi_table_ecdt  *ecdt_ptr;
@@ -1044,22 +1589,22 @@ acpi_ec_get_real_ecdt(void)
        /*
         * Generate a temporary ec context to use until the namespace is scanned
         */
-       ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
+       ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
        if (!ec_ecdt)
                return -ENOMEM;
-       memset(ec_ecdt, 0, sizeof(struct acpi_ec));
-
-       init_MUTEX(&ec_ecdt->sem);
-       init_waitqueue_head(&ec_ecdt->wait);
-       ec_ecdt->command_addr = ecdt_ptr->ec_control;
-       ec_ecdt->status_addr = ecdt_ptr->ec_control;
-       ec_ecdt->data_addr = ecdt_ptr->ec_data;
-       ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit;
+       memset(ec_ecdt, 0, sizeof(union acpi_ec));
+
+       init_MUTEX(&ec_ecdt->burst.sem);
+       init_waitqueue_head(&ec_ecdt->burst.wait);
+       ec_ecdt->common.command_addr = ecdt_ptr->ec_control;
+       ec_ecdt->common.status_addr = ecdt_ptr->ec_control;
+       ec_ecdt->common.data_addr = ecdt_ptr->ec_data;
+       ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit;
        /* use the GL just to be safe */
-       ec_ecdt->global_lock = TRUE;
-       ec_ecdt->uid = ecdt_ptr->uid;
+       ec_ecdt->common.global_lock = TRUE;
+       ec_ecdt->common.uid = ecdt_ptr->uid;
 
-       status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle);
+       status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle);
        if (ACPI_FAILURE(status)) {
                goto error;
        }
@@ -1092,20 +1637,20 @@ acpi_ec_ecdt_probe (void)
        /*
         * Install GPE handler
         */
-       status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe_bit,
+       status = acpi_install_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
                ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler,
                ec_ecdt);
        if (ACPI_FAILURE(status)) {
                goto error;
        }
-       acpi_set_gpe_type (NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
-       acpi_enable_gpe (NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR);
+       acpi_set_gpe_type (NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME);
+       acpi_enable_gpe (NULL, ec_ecdt->common.gpe_bit, ACPI_NOT_ISR);
 
        status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT,
                        ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
                        &acpi_ec_space_setup, ec_ecdt);
        if (ACPI_FAILURE(status)) {
-               acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit,
+               acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
                        &acpi_ec_gpe_handler);
                goto error;
        }
@@ -1123,7 +1668,7 @@ error:
 
 static int __init acpi_ec_init (void)
 {
-       int                     result;
+       int                     result = 0;
 
        ACPI_FUNCTION_TRACE("acpi_ec_init");
 
@@ -1166,4 +1711,24 @@ static int __init acpi_fake_ecdt_setup(char *str)
        acpi_fake_ecdt_enabled = 1;
        return 0;
 }
+
 __setup("acpi_fake_ecdt", acpi_fake_ecdt_setup);
+static int __init acpi_ec_set_polling_mode(char *str)
+{
+       int burst;
+
+       if (!get_option(&str, &burst))
+               return 0;
+
+       if (burst) {
+               acpi_ec_polling_mode = EC_BURST;
+               acpi_ec_driver.ops.add = acpi_ec_burst_add;
+       } else {
+               acpi_ec_polling_mode = EC_POLLING;
+               acpi_ec_driver.ops.add = acpi_ec_polling_add;
+       }
+       printk(KERN_INFO PREFIX "EC %s mode.\n",
+               burst ? "burst": "polling");
+       return 0;
+}
+__setup("ec_burst=", acpi_ec_set_polling_mode);
index babdf76..1f76a40 100644 (file)
@@ -1,5 +1,5 @@
-/* 
- *  hotkey.c - ACPI Hotkey Driver ($Revision:$)
+/*
+ *  hotkey.c - ACPI Hotkey Driver ($Revision: 0.2 $)
  *
  *  Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
  *
 #define ACPI_HOTKEY_POLLING 0x2
 #define ACPI_UNDEFINED_EVENT    0xf
 
-#define MAX_CONFIG_RECORD_LEN   80
-#define MAX_NAME_PATH_LEN   80
-#define MAX_CALL_PARM       80
+#define RESULT_STR_LEN     80
 
-#define IS_EVENT(e)       0xff /* ((e) & 0x40000000)  */
-#define IS_POLL(e)      0xff   /* (~((e) & 0x40000000))  */
+#define ACTION_METHOD  0
+#define POLL_METHOD    1
 
+#define IS_EVENT(e)            ((e) <= 10000 && (e) >0)
+#define IS_POLL(e)             ((e) > 10000)
+#define IS_OTHERS(e)           ((e)<=0 || (e)>=20000)
 #define _COMPONENT              ACPI_HOTKEY_COMPONENT
 ACPI_MODULE_NAME("acpi_hotkey")
 
-    MODULE_AUTHOR("luming.yu@intel.com");
+MODULE_AUTHOR("luming.yu@intel.com");
 MODULE_DESCRIPTION(ACPI_HOTK_NAME);
 MODULE_LICENSE("GPL");
 
@@ -114,7 +115,7 @@ struct acpi_event_hotkey {
        char *action_method;    /* action method */
 };
 
-/* 
+/*
  * There are two ways to poll status
  * 1. directy call read_xxx method, without any arguments passed in
  * 2. call write_xxx method, with arguments passed in, you need
@@ -131,7 +132,7 @@ struct acpi_polling_hotkey {
        char *poll_method;      /* poll method */
        acpi_handle action_handle;      /* acpi handle attached action method */
        char *action_method;    /* action method */
-       void *poll_result;      /* polling_result */
+       union acpi_object *poll_result; /* polling_result */
        struct proc_dir_entry *proc;
 };
 
@@ -162,20 +163,25 @@ static struct acpi_driver hotkey_driver = {
                },
 };
 
+static void free_hotkey_device(union acpi_hotkey *key);
+static void free_hotkey_buffer(union acpi_hotkey *key);
+static void free_poll_hotkey_buffer(union acpi_hotkey *key);
 static int hotkey_open_config(struct inode *inode, struct file *file);
+static int hotkey_poll_open_config(struct inode *inode, struct file *file);
 static ssize_t hotkey_write_config(struct file *file,
                                   const char __user * buffer,
                                   size_t count, loff_t * data);
-static ssize_t hotkey_write_poll_config(struct file *file,
-                                       const char __user * buffer,
-                                       size_t count, loff_t * data);
 static int hotkey_info_open_fs(struct inode *inode, struct file *file);
 static int hotkey_action_open_fs(struct inode *inode, struct file *file);
 static ssize_t hotkey_execute_aml_method(struct file *file,
                                         const char __user * buffer,
                                         size_t count, loff_t * data);
 static int hotkey_config_seq_show(struct seq_file *seq, void *offset);
+static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset);
 static int hotkey_polling_open_fs(struct inode *inode, struct file *file);
+static union acpi_hotkey *get_hotkey_by_event(struct
+                             acpi_hotkey_list
+                             *hotkey_list, int event);
 
 /* event based config */
 static struct file_operations hotkey_config_fops = {
@@ -188,9 +194,9 @@ static struct file_operations hotkey_config_fops = {
 
 /* polling based config */
 static struct file_operations hotkey_poll_config_fops = {
-       .open = hotkey_open_config,
+       .open = hotkey_poll_open_config,
        .read = seq_read,
-       .write = hotkey_write_poll_config,
+       .write = hotkey_write_config,
        .llseek = seq_lseek,
        .release = single_release,
 };
@@ -227,7 +233,7 @@ static int hotkey_info_seq_show(struct seq_file *seq, void *offset)
 {
        ACPI_FUNCTION_TRACE("hotkey_info_seq_show");
 
-       seq_printf(seq, "Hotkey generic driver ver: %s", HOTKEY_ACPI_VERSION);
+       seq_printf(seq, "Hotkey generic driver ver: %s\n", HOTKEY_ACPI_VERSION);
 
        return_VALUE(0);
 }
@@ -239,27 +245,35 @@ static int hotkey_info_open_fs(struct inode *inode, struct file *file)
 
 static char *format_result(union acpi_object *object)
 {
-       char *buf = (char *)kmalloc(sizeof(union acpi_object), GFP_KERNEL);
-
-       memset(buf, 0, sizeof(union acpi_object));
+       char *buf = NULL;
+       
+       buf = (char *)kmalloc(RESULT_STR_LEN, GFP_KERNEL);
+       if (buf)
+               memset(buf, 0, RESULT_STR_LEN);
+       else
+               goto do_fail;
 
        /* Now, just support integer type */
        if (object->type == ACPI_TYPE_INTEGER)
-               sprintf(buf, "%d", (u32) object->integer.value);
-
-       return buf;
+               sprintf(buf, "%d\n", (u32) object->integer.value);
+do_fail:
+       return (buf);
 }
 
 static int hotkey_polling_seq_show(struct seq_file *seq, void *offset)
 {
        struct acpi_polling_hotkey *poll_hotkey =
            (struct acpi_polling_hotkey *)seq->private;
+       char *buf;
 
        ACPI_FUNCTION_TRACE("hotkey_polling_seq_show");
 
-       if (poll_hotkey->poll_result)
-               seq_printf(seq, "%s", format_result(poll_hotkey->poll_result));
-
+       if (poll_hotkey->poll_result){
+               buf = format_result(poll_hotkey->poll_result);
+               if(buf)
+                       seq_printf(seq, "%s", buf);
+               kfree(buf);
+       }
        return_VALUE(0);
 }
 
@@ -276,19 +290,19 @@ static int hotkey_action_open_fs(struct inode *inode, struct file *file)
 /* Mapping external hotkey number to standardized hotkey event num */
 static int hotkey_get_internal_event(int event, struct acpi_hotkey_list *list)
 {
-       struct list_head *entries, *next;
-       int val = 0;
+       struct list_head *entries;
+       int val = -1;
 
        ACPI_FUNCTION_TRACE("hotkey_get_internal_event");
 
-       list_for_each_safe(entries, next, list->entries) {
+       list_for_each(entries, list->entries) {
                union acpi_hotkey *key =
                    container_of(entries, union acpi_hotkey, entries);
                if (key->link.hotkey_type == ACPI_HOTKEY_EVENT
-                   && key->event_hotkey.external_hotkey_num == event)
+                   && key->event_hotkey.external_hotkey_num == event){
                        val = key->link.hotkey_standard_num;
-               else
-                       val = -1;
+                       break;
+               }
        }
 
        return_VALUE(val);
@@ -306,7 +320,7 @@ acpi_hotkey_notify_handler(acpi_handle handle, u32 event, void *data)
                return_VOID;
 
        internal_event = hotkey_get_internal_event(event, &global_hotkey_list);
-       acpi_bus_generate_event(device, event, 0);
+       acpi_bus_generate_event(device, internal_event, 0);
 
        return_VOID;
 }
@@ -329,13 +343,17 @@ static int auto_hotkey_remove(struct acpi_device *device, int type)
 static int create_polling_proc(union acpi_hotkey *device)
 {
        struct proc_dir_entry *proc;
+       char  proc_name[80];
        mode_t mode;
 
        ACPI_FUNCTION_TRACE("create_polling_proc");
        mode = S_IFREG | S_IRUGO | S_IWUGO;
 
-       proc = create_proc_entry(device->poll_hotkey.action_method,
-                                mode, hotkey_proc_dir);
+       sprintf(proc_name, "%d", device->link.hotkey_standard_num);
+       /*
+       strcat(proc_name, device->poll_hotkey.poll_method);
+       */
+       proc = create_proc_entry(proc_name, mode, hotkey_proc_dir);
 
        if (!proc) {
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
@@ -353,23 +371,6 @@ static int create_polling_proc(union acpi_hotkey *device)
        return_VALUE(0);
 }
 
-static int is_valid_acpi_path(const char *pathname)
-{
-       acpi_handle handle;
-       acpi_status status;
-       ACPI_FUNCTION_TRACE("is_valid_acpi_path");
-
-       status = acpi_get_handle(NULL, (char *)pathname, &handle);
-       return_VALUE(!ACPI_FAILURE(status));
-}
-
-static int is_valid_hotkey(union acpi_hotkey *device)
-{
-       ACPI_FUNCTION_TRACE("is_valid_hotkey");
-       /* Implement valid check */
-       return_VALUE(1);
-}
-
 static int hotkey_add(union acpi_hotkey *device)
 {
        int status = 0;
@@ -378,15 +379,11 @@ static int hotkey_add(union acpi_hotkey *device)
        ACPI_FUNCTION_TRACE("hotkey_add");
 
        if (device->link.hotkey_type == ACPI_HOTKEY_EVENT) {
-               status =
-                   acpi_bus_get_device(device->event_hotkey.bus_handle, &dev);
-               if (status)
-                       return_VALUE(status);
-
+               acpi_bus_get_device(device->event_hotkey.bus_handle, &dev);
                status = acpi_install_notify_handler(dev->handle,
-                                                    ACPI_SYSTEM_NOTIFY,
+                                                    ACPI_DEVICE_NOTIFY,
                                                     acpi_hotkey_notify_handler,
-                                                    device);
+                                                    dev);
        } else                  /* Add polling hotkey */
                create_polling_proc(device);
 
@@ -409,84 +406,143 @@ static int hotkey_remove(union acpi_hotkey *device)
                if (key->link.hotkey_standard_num ==
                    device->link.hotkey_standard_num) {
                        list_del(&key->link.entries);
-                       remove_proc_entry(key->poll_hotkey.action_method,
-                                         hotkey_proc_dir);
+                       free_hotkey_device(key);
                        global_hotkey_list.count--;
                        break;
                }
        }
+       kfree(device);
        return_VALUE(0);
 }
 
-static void hotkey_update(union acpi_hotkey *key)
+static int  hotkey_update(union acpi_hotkey *key)
 {
-       struct list_head *entries, *next;
+       struct list_head *entries;
 
        ACPI_FUNCTION_TRACE("hotkey_update");
 
-       list_for_each_safe(entries, next, global_hotkey_list.entries) {
-               union acpi_hotkey *key =
+       list_for_each(entries, global_hotkey_list.entries) {
+               union acpi_hotkey *tmp=
                    container_of(entries, union acpi_hotkey, entries);
-               if (key->link.hotkey_standard_num ==
+               if (tmp->link.hotkey_standard_num ==
                    key->link.hotkey_standard_num) {
-                       key->event_hotkey.bus_handle =
-                           key->event_hotkey.bus_handle;
-                       key->event_hotkey.external_hotkey_num =
-                           key->event_hotkey.external_hotkey_num;
-                       key->event_hotkey.action_handle =
-                           key->event_hotkey.action_handle;
-                       key->event_hotkey.action_method =
-                           key->event_hotkey.action_method;
+                       if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) {
+                               free_hotkey_buffer(tmp);
+                               tmp->event_hotkey.bus_handle =
+                                       key->event_hotkey.bus_handle;
+                               tmp->event_hotkey.external_hotkey_num =
+                                       key->event_hotkey.external_hotkey_num;
+                               tmp->event_hotkey.action_handle =
+                                       key->event_hotkey.action_handle;
+                               tmp->event_hotkey.action_method =
+                                       key->event_hotkey.action_method;
+                               kfree(key);
+                       } else {
+                               /*
+                               char  proc_name[80];
+
+                               sprintf(proc_name, "%d", tmp->link.hotkey_standard_num);
+                               strcat(proc_name, tmp->poll_hotkey.poll_method);
+                               remove_proc_entry(proc_name,hotkey_proc_dir);
+                               */
+                               free_poll_hotkey_buffer(tmp);
+                               tmp->poll_hotkey.poll_handle =
+                                       key->poll_hotkey.poll_handle;
+                               tmp->poll_hotkey.poll_method =
+                                       key->poll_hotkey.poll_method;
+                               tmp->poll_hotkey.action_handle =
+                                       key->poll_hotkey.action_handle;
+                               tmp->poll_hotkey.action_method =
+                                       key->poll_hotkey.action_method;
+                               tmp->poll_hotkey.poll_result =
+                                       key->poll_hotkey.poll_result;
+                               /*
+                               create_polling_proc(tmp);
+                               */
+                               kfree(key);
+                       }
+                       return_VALUE(0);
                        break;
                }
        }
 
-       return_VOID;
+       return_VALUE(-ENODEV);
 }
 
 static void free_hotkey_device(union acpi_hotkey *key)
 {
        struct acpi_device *dev;
-       int status;
 
        ACPI_FUNCTION_TRACE("free_hotkey_device");
 
        if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) {
-               status =
-                   acpi_bus_get_device(key->event_hotkey.bus_handle, &dev);
+               acpi_bus_get_device(key->event_hotkey.bus_handle, &dev);
                if (dev->handle)
                        acpi_remove_notify_handler(dev->handle,
-                                                  ACPI_SYSTEM_NOTIFY,
+                                                  ACPI_DEVICE_NOTIFY,
                                                   acpi_hotkey_notify_handler);
-       } else
-               remove_proc_entry(key->poll_hotkey.action_method,
-                                 hotkey_proc_dir);
+               free_hotkey_buffer(key);
+       } else {
+               char  proc_name[80];
+
+               sprintf(proc_name, "%d", key->link.hotkey_standard_num);
+               /*
+               strcat(proc_name, key->poll_hotkey.poll_method);
+               */
+               remove_proc_entry(proc_name,hotkey_proc_dir);
+               free_poll_hotkey_buffer(key);
+       }
        kfree(key);
        return_VOID;
 }
 
+static void
+free_hotkey_buffer(union acpi_hotkey *key)
+{
+       kfree(key->event_hotkey.action_method);
+}
+
+static void
+free_poll_hotkey_buffer(union acpi_hotkey *key)
+{
+       kfree(key->poll_hotkey.action_method);
+       kfree(key->poll_hotkey.poll_method);
+       kfree(key->poll_hotkey.poll_result);
+}
 static int
 init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str,
                   char *method, int std_num, int external_num)
 {
+       acpi_handle     tmp_handle;
+       acpi_status status = AE_OK;
+
        ACPI_FUNCTION_TRACE("init_hotkey_device");
 
+       if(std_num < 0 || IS_POLL(std_num) || !key )
+               goto do_fail;
+
+       if(!bus_str || !action_str || !method)
+               goto do_fail;
+
        key->link.hotkey_type = ACPI_HOTKEY_EVENT;
        key->link.hotkey_standard_num = std_num;
        key->event_hotkey.flag = 0;
-       if (is_valid_acpi_path(bus_str))
-               acpi_get_handle((acpi_handle) 0,
-                               bus_str, &(key->event_hotkey.bus_handle));
-       else
-               return_VALUE(-ENODEV);
-       key->event_hotkey.external_hotkey_num = external_num;
-       if (is_valid_acpi_path(action_str))
-               acpi_get_handle((acpi_handle) 0,
-                               action_str, &(key->event_hotkey.action_handle));
-       key->event_hotkey.action_method = kmalloc(sizeof(method), GFP_KERNEL);
-       strcpy(key->event_hotkey.action_method, method);
+       key->event_hotkey.action_method = method;
 
-       return_VALUE(!is_valid_hotkey(key));
+       status = acpi_get_handle(NULL,bus_str, &(key->event_hotkey.bus_handle));
+       if(ACPI_FAILURE(status))
+               goto do_fail;
+       key->event_hotkey.external_hotkey_num = external_num;
+       status = acpi_get_handle(NULL,action_str, &(key->event_hotkey.action_handle));
+       if(ACPI_FAILURE(status))
+               goto do_fail;
+       status = acpi_get_handle(key->event_hotkey.action_handle,
+                               method, &tmp_handle);
+       if (ACPI_FAILURE(status))
+               goto do_fail;
+       return_VALUE(AE_OK);
+do_fail:
+       return_VALUE(-ENODEV);
 }
 
 static int
@@ -495,34 +551,46 @@ init_poll_hotkey_device(union acpi_hotkey *key,
                        char *poll_method,
                        char *action_str, char *action_method, int std_num)
 {
+       acpi_status status = AE_OK;
+       acpi_handle     tmp_handle;
+
        ACPI_FUNCTION_TRACE("init_poll_hotkey_device");
 
+       if(std_num < 0 || IS_EVENT(std_num) || !key)
+               goto do_fail;
+
+       if(!poll_str || !poll_method || !action_str || !action_method)
+               goto do_fail;
+
        key->link.hotkey_type = ACPI_HOTKEY_POLLING;
        key->link.hotkey_standard_num = std_num;
        key->poll_hotkey.flag = 0;
-       if (is_valid_acpi_path(poll_str))
-               acpi_get_handle((acpi_handle) 0,
-                               poll_str, &(key->poll_hotkey.poll_handle));
-       else
-               return_VALUE(-ENODEV);
        key->poll_hotkey.poll_method = poll_method;
-       if (is_valid_acpi_path(action_str))
-               acpi_get_handle((acpi_handle) 0,
-                               action_str, &(key->poll_hotkey.action_handle));
-       key->poll_hotkey.action_method =
-           kmalloc(sizeof(action_method), GFP_KERNEL);
-       strcpy(key->poll_hotkey.action_method, action_method);
+       key->poll_hotkey.action_method = action_method;
+
+       status = acpi_get_handle(NULL,poll_str, &(key->poll_hotkey.poll_handle));
+       if(ACPI_FAILURE(status))
+               goto do_fail;
+       status = acpi_get_handle(key->poll_hotkey.poll_handle,
+                               poll_method, &tmp_handle);
+        if (ACPI_FAILURE(status))
+                       goto do_fail;
+       status = acpi_get_handle(NULL,action_str, &(key->poll_hotkey.action_handle));
+       if (ACPI_FAILURE(status))
+               goto do_fail;
+       status = acpi_get_handle(key->poll_hotkey.action_handle,
+                               action_method, &tmp_handle);
+       if (ACPI_FAILURE(status))
+               goto do_fail;
        key->poll_hotkey.poll_result =
            (union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL);
-       return_VALUE(is_valid_hotkey(key));
+       if(!key->poll_hotkey.poll_result)
+               goto do_fail;
+       return_VALUE(AE_OK);
+do_fail:
+       return_VALUE(-ENODEV);
 }
 
-static int check_hotkey_valid(union acpi_hotkey *key,
-                             struct acpi_hotkey_list *list)
-{
-       ACPI_FUNCTION_TRACE("check_hotkey_valid");
-       return_VALUE(0);
-}
 
 static int hotkey_open_config(struct inode *inode, struct file *file)
 {
@@ -531,10 +599,17 @@ static int hotkey_open_config(struct inode *inode, struct file *file)
                     (file, hotkey_config_seq_show, PDE(inode)->data));
 }
 
+static int hotkey_poll_open_config(struct inode *inode, struct file *file)
+{
+       ACPI_FUNCTION_TRACE("hotkey_poll_open_config");
+       return_VALUE(single_open
+                    (file, hotkey_poll_config_seq_show, PDE(inode)->data));
+}
+
 static int hotkey_config_seq_show(struct seq_file *seq, void *offset)
 {
        struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
-       struct list_head *entries, *next;
+       struct list_head *entries;
        char bus_name[ACPI_PATHNAME_MAX] = { 0 };
        char action_name[ACPI_PATHNAME_MAX] = { 0 };
        struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name };
@@ -542,10 +617,7 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset)
 
        ACPI_FUNCTION_TRACE(("hotkey_config_seq_show"));
 
-       if (!hotkey_list)
-               goto end;
-
-       list_for_each_safe(entries, next, hotkey_list->entries) {
+       list_for_each(entries, hotkey_list->entries) {
                union acpi_hotkey *key =
                    container_of(entries, union acpi_hotkey, entries);
                if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) {
@@ -553,18 +625,37 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset)
                                      ACPI_NAME_TYPE_MAX, &bus);
                        acpi_get_name(key->event_hotkey.action_handle,
                                      ACPI_NAME_TYPE_MAX, &act);
-                       seq_printf(seq, "%s:%s:%s:%d:%d", bus_name,
+                       seq_printf(seq, "%s:%s:%s:%d:%d\n", bus_name,
                                   action_name,
                                   key->event_hotkey.action_method,
                                   key->link.hotkey_standard_num,
                                   key->event_hotkey.external_hotkey_num);
-               } /* ACPI_HOTKEY_POLLING */
-               else {
+               }
+       }
+       seq_puts(seq, "\n");
+       return_VALUE(0);
+}
+
+static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset)
+{
+       struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
+       struct list_head *entries;
+       char bus_name[ACPI_PATHNAME_MAX] = { 0 };
+       char action_name[ACPI_PATHNAME_MAX] = { 0 };
+       struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name };
+       struct acpi_buffer act = { ACPI_PATHNAME_MAX, action_name };
+
+       ACPI_FUNCTION_TRACE(("hotkey_config_seq_show"));
+
+       list_for_each(entries, hotkey_list->entries) {
+               union acpi_hotkey *key =
+                   container_of(entries, union acpi_hotkey, entries);
+               if (key->link.hotkey_type == ACPI_HOTKEY_POLLING) {
                        acpi_get_name(key->poll_hotkey.poll_handle,
                                      ACPI_NAME_TYPE_MAX, &bus);
                        acpi_get_name(key->poll_hotkey.action_handle,
                                      ACPI_NAME_TYPE_MAX, &act);
-                       seq_printf(seq, "%s:%s:%s:%s:%d", bus_name,
+                       seq_printf(seq, "%s:%s:%s:%s:%d\n", bus_name,
                                   key->poll_hotkey.poll_method,
                                   action_name,
                                   key->poll_hotkey.action_method,
@@ -572,49 +663,83 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset)
                }
        }
        seq_puts(seq, "\n");
-      end:
        return_VALUE(0);
 }
 
 static int
 get_parms(char *config_record,
          int *cmd,
-         char *bus_handle,
-         char *bus_method,
-         char *action_handle,
-         char *method, int *internal_event_num, int *external_event_num)
+         char **bus_handle,
+         char **bus_method,
+         char **action_handle,
+         char **method, int *internal_event_num, int *external_event_num)
 {
-       char *tmp, *tmp1;
+       char *tmp, *tmp1, count;
        ACPI_FUNCTION_TRACE(("get_parms"));
 
        sscanf(config_record, "%d", cmd);
 
+       if(*cmd == 1){
+               if(sscanf(config_record, "%d:%d", cmd, internal_event_num)!=2)
+                       goto do_fail;
+               else
+                       return (6);
+       }
        tmp = strchr(config_record, ':');
+       if (!tmp)
+               goto do_fail;
        tmp++;
        tmp1 = strchr(tmp, ':');
-       strncpy(bus_handle, tmp, tmp1 - tmp);
-       bus_handle[tmp1 - tmp] = 0;
+       if (!tmp1)
+               goto do_fail;
+
+       count = tmp1 - tmp;
+       *bus_handle = (char *) kmalloc(count+1, GFP_KERNEL);
+       if(!*bus_handle)
+               goto do_fail;
+       strncpy(*bus_handle, tmp, count);
+       *(*bus_handle + count) = 0;
 
        tmp = tmp1;
        tmp++;
        tmp1 = strchr(tmp, ':');
-       strncpy(bus_method, tmp, tmp1 - tmp);
-       bus_method[tmp1 - tmp] = 0;
+       if (!tmp1)
+               goto do_fail;
+       count = tmp1 - tmp;
+       *bus_method = (char *) kmalloc(count+1, GFP_KERNEL);
+       if(!*bus_method)
+               goto do_fail;
+       strncpy(*bus_method, tmp, count);
+       *(*bus_method + count) = 0;
 
        tmp = tmp1;
        tmp++;
        tmp1 = strchr(tmp, ':');
-       strncpy(action_handle, tmp, tmp1 - tmp);
-       action_handle[tmp1 - tmp] = 0;
+       if (!tmp1)
+               goto do_fail;
+       count = tmp1 - tmp;
+       *action_handle = (char *) kmalloc(count+1, GFP_KERNEL);
+       strncpy(*action_handle, tmp, count);
+       *(*action_handle + count) = 0;
 
        tmp = tmp1;
        tmp++;
        tmp1 = strchr(tmp, ':');
-       strncpy(method, tmp, tmp1 - tmp);
-       method[tmp1 - tmp] = 0;
+       if (!tmp1)
+               goto do_fail;
+       count = tmp1 - tmp;
+       *method = (char *) kmalloc(count+1, GFP_KERNEL);
+       if(!*method)
+               goto do_fail;
+       strncpy(*method, tmp, count);
+       *(*method + count) = 0;
+
+       if(sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num)<=0)
+               goto do_fail;
 
-       sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num);
        return_VALUE(6);
+do_fail:
+       return_VALUE(-1);
 }
 
 /*  count is length for one input record */
@@ -622,135 +747,117 @@ static ssize_t hotkey_write_config(struct file *file,
                                   const char __user * buffer,
                                   size_t count, loff_t * data)
 {
-       struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
-       char config_record[MAX_CONFIG_RECORD_LEN];
-       char bus_handle[MAX_NAME_PATH_LEN];
-       char bus_method[MAX_NAME_PATH_LEN];
-       char action_handle[MAX_NAME_PATH_LEN];
-       char method[20];
+       char *config_record = NULL;
+       char *bus_handle = NULL;
+       char *bus_method = NULL;
+       char *action_handle = NULL;
+       char *method = NULL;
        int cmd, internal_event_num, external_event_num;
        int ret = 0;
        union acpi_hotkey *key = NULL;
 
        ACPI_FUNCTION_TRACE(("hotkey_write_config"));
 
-       if (!hotkey_list || count > MAX_CONFIG_RECORD_LEN) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid arguments\n"));
-               return_VALUE(-EINVAL);
-       }
+       config_record = (char *) kmalloc(count+1, GFP_KERNEL);
+       if(!config_record)
+               return_VALUE(-ENOMEM);
 
        if (copy_from_user(config_record, buffer, count)) {
+               kfree(config_record);
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data \n"));
                return_VALUE(-EINVAL);
        }
-       config_record[count] = '\0';
+       config_record[count] = 0;
 
        ret = get_parms(config_record,
                        &cmd,
-                       bus_handle,
-                       bus_method,
-                       action_handle,
-                       method, &internal_event_num, &external_event_num);
+                       &bus_handle,
+                       &bus_method,
+                       &action_handle,
+                       &method, &internal_event_num, &external_event_num);
+
+       kfree(config_record);
+       if(IS_OTHERS(internal_event_num))
+               goto do_fail;
        if (ret != 6) {
+do_fail:       
+               kfree(bus_handle);
+               kfree(bus_method);
+               kfree(action_handle);
+               kfree(method);
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                                  "Invalid data format ret=%d\n", ret));
                return_VALUE(-EINVAL);
        }
 
        key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL);
-       ret = init_hotkey_device(key, bus_handle, action_handle, method,
+       if(!key)
+               goto do_fail;
+       memset(key, 0, sizeof(union acpi_hotkey));
+       if(cmd == 1) {
+               union acpi_hotkey *tmp = NULL;
+               tmp = get_hotkey_by_event(&global_hotkey_list,
+                               internal_event_num);
+               if(!tmp)
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid key"));
+               else
+                       memcpy(key, tmp, sizeof(union acpi_hotkey));
+               goto cont_cmd;
+       }
+       if (IS_EVENT(internal_event_num)) {
+               kfree(bus_method);
+               ret = init_hotkey_device(key, bus_handle, action_handle, method,
                                 internal_event_num, external_event_num);
-
-       if (ret || check_hotkey_valid(key, hotkey_list)) {
+       } else
+               ret = init_poll_hotkey_device(key, bus_handle, bus_method,
+                                     action_handle, method,
+                                     internal_event_num);
+       if (ret) {
+               kfree(bus_handle);
+               kfree(action_handle);
+               if(IS_EVENT(internal_event_num))
+                       free_hotkey_buffer(key);
+               else
+                       free_poll_hotkey_buffer(key);
                kfree(key);
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid hotkey \n"));
                return_VALUE(-EINVAL);
        }
-       switch (cmd) {
-       case 0:
-               hotkey_add(key);
-               break;
-       case 1:
-               hotkey_remove(key);
-               free_hotkey_device(key);
-               break;
-       case 2:
-               hotkey_update(key);
-               break;
-       default:
-               break;
-       }
-       return_VALUE(count);
-}
-
-/*  count is length for one input record */
-static ssize_t hotkey_write_poll_config(struct file *file,
-                                       const char __user * buffer,
-                                       size_t count, loff_t * data)
-{
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_hotkey_list *hotkey_list =
-           (struct acpi_hotkey_list *)m->private;
-
-       char config_record[MAX_CONFIG_RECORD_LEN];
-       char polling_handle[MAX_NAME_PATH_LEN];
-       char action_handle[MAX_NAME_PATH_LEN];
-       char poll_method[20], action_method[20];
-       int ret, internal_event_num, cmd, external_event_num;
-       union acpi_hotkey *key = NULL;
-
-       ACPI_FUNCTION_TRACE("hotkey_write_poll_config");
-
-       if (!hotkey_list || count > MAX_CONFIG_RECORD_LEN) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid arguments\n"));
-               return_VALUE(-EINVAL);
-       }
-
-       if (copy_from_user(config_record, buffer, count)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data \n"));
-               return_VALUE(-EINVAL);
-       }
-       config_record[count] = '\0';
 
-       ret = get_parms(config_record,
-                       &cmd,
-                       polling_handle,
-                       poll_method,
-                       action_handle,
-                       action_method,
-                       &internal_event_num, &external_event_num);
-
-       if (ret != 6) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n"));
-               return_VALUE(-EINVAL);
-       }
+cont_cmd:
+       kfree(bus_handle);
+       kfree(action_handle);
 
-       key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL);
-       ret = init_poll_hotkey_device(key, polling_handle, poll_method,
-                                     action_handle, action_method,
-                                     internal_event_num);
-       if (ret || check_hotkey_valid(key, hotkey_list)) {
-               kfree(key);
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid hotkey \n"));
-               return_VALUE(-EINVAL);
-       }
        switch (cmd) {
        case 0:
-               hotkey_add(key);
+               if(get_hotkey_by_event(&global_hotkey_list,key->link.hotkey_standard_num))
+                       goto fail_out;
+               else
+                       hotkey_add(key);
                break;
        case 1:
                hotkey_remove(key);
                break;
        case 2:
-               hotkey_update(key);
+               if(hotkey_update(key))
+                       goto fail_out;
                break;
        default:
+               goto fail_out;
                break;
        }
        return_VALUE(count);
+fail_out:
+       if(IS_EVENT(internal_event_num))
+               free_hotkey_buffer(key);
+       else
+               free_poll_hotkey_buffer(key);
+       kfree(key);
+       ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "invalid key\n"));
+       return_VALUE(-EINVAL);
 }
 
-/*  
+/*
  * This function evaluates an ACPI method, given an int as parameter, the
  * method is searched within the scope of the handle, can be NULL. The output
  * of the method is written is output, which can also be NULL
@@ -775,7 +882,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
        return_VALUE(status == AE_OK);
 }
 
-static int read_acpi_int(acpi_handle handle, const char *method, int *val)
+static int read_acpi_int(acpi_handle handle, const char *method, union acpi_object *val)
 {
        struct acpi_buffer output;
        union acpi_object out_obj;
@@ -786,62 +893,32 @@ static int read_acpi_int(acpi_handle handle, const char *method, int *val)
        output.pointer = &out_obj;
 
        status = acpi_evaluate_object(handle, (char *)method, NULL, &output);
-       *val = out_obj.integer.value;
+       if(val){
+               val->integer.value = out_obj.integer.value;
+               val->type = out_obj.type;
+       } else
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "null val pointer"));
        return_VALUE((status == AE_OK)
                     && (out_obj.type == ACPI_TYPE_INTEGER));
 }
 
-static acpi_handle
-get_handle_from_hotkeylist(struct acpi_hotkey_list *hotkey_list, int event_num)
+static union acpi_hotkey *get_hotkey_by_event(struct
+                             acpi_hotkey_list
+                             *hotkey_list, int event)
 {
-       struct list_head *entries, *next;
-
-       list_for_each_safe(entries, next, hotkey_list->entries) {
-               union acpi_hotkey *key =
-                   container_of(entries, union acpi_hotkey, entries);
-               if (key->link.hotkey_type == ACPI_HOTKEY_EVENT
-                   && key->link.hotkey_standard_num == event_num) {
-                       return (key->event_hotkey.action_handle);
-               }
-       }
-       return (NULL);
-}
-
-static
-char *get_method_from_hotkeylist(struct acpi_hotkey_list *hotkey_list,
-                                int event_num)
-{
-       struct list_head *entries, *next;
-
-       list_for_each_safe(entries, next, hotkey_list->entries) {
-               union acpi_hotkey *key =
-                   container_of(entries, union acpi_hotkey, entries);
-
-               if (key->link.hotkey_type == ACPI_HOTKEY_EVENT &&
-                   key->link.hotkey_standard_num == event_num)
-                       return (key->event_hotkey.action_method);
-       }
-       return (NULL);
-}
-
-static struct acpi_polling_hotkey *get_hotkey_by_event(struct
-                                                      acpi_hotkey_list
-                                                      *hotkey_list, int event)
-{
-       struct list_head *entries, *next;
+       struct list_head *entries;
 
-       list_for_each_safe(entries, next, hotkey_list->entries) {
+       list_for_each(entries, hotkey_list->entries) {
                union acpi_hotkey *key =
                    container_of(entries, union acpi_hotkey, entries);
-               if (key->link.hotkey_type == ACPI_HOTKEY_POLLING
-                   && key->link.hotkey_standard_num == event) {
-                       return (&key->poll_hotkey);
+               if (key->link.hotkey_standard_num == event) {
+                       return(key);
                }
        }
-       return (NULL);
+       return(NULL);
 }
 
-/*  
+/*
  * user call AML method interface:
  * Call convention:
  * echo "event_num: arg type : value"
@@ -854,48 +931,56 @@ static ssize_t hotkey_execute_aml_method(struct file *file,
                                         size_t count, loff_t * data)
 {
        struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
-       char arg[MAX_CALL_PARM];
-       int event, type, value;
-
-       char *method;
-       acpi_handle handle;
+       char *arg;
+       int event,method_type,type, value;
+       union acpi_hotkey *key;
 
        ACPI_FUNCTION_TRACE("hotkey_execte_aml_method");
 
-       if (!hotkey_list || count > MAX_CALL_PARM) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 1"));
-               return_VALUE(-EINVAL);
-       }
+       arg = (char *) kmalloc(count+1, GFP_KERNEL);
+       if(!arg)
+               return_VALUE(-ENOMEM);
+       arg[count]=0;
 
        if (copy_from_user(arg, buffer, count)) {
+               kfree(arg);
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 2"));
                return_VALUE(-EINVAL);
        }
 
-       arg[count] = '\0';
-
-       if (sscanf(arg, "%d:%d:%d", &event, &type, &value) != 3) {
+       if (sscanf(arg, "%d:%d:%d:%d", &event, &method_type, &type, &value) != 4) {
+               kfree(arg);
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 3"));
                return_VALUE(-EINVAL);
        }
-
+       kfree(arg);
        if (type == ACPI_TYPE_INTEGER) {
-               handle = get_handle_from_hotkeylist(hotkey_list, event);
-               method = (char *)get_method_from_hotkeylist(hotkey_list, event);
+               key = get_hotkey_by_event(hotkey_list, event);
+               if(!key)
+                       goto do_fail;
                if (IS_EVENT(event))
-                       write_acpi_int(handle, method, value, NULL);
+                       write_acpi_int(key->event_hotkey.action_handle,
+                                       key->event_hotkey.action_method, value, NULL);
                else if (IS_POLL(event)) {
-                       struct acpi_polling_hotkey *key;
-                       key = (struct acpi_polling_hotkey *)
-                           get_hotkey_by_event(hotkey_list, event);
-                       read_acpi_int(handle, method, key->poll_result);
+                       if ( method_type == POLL_METHOD )
+                               read_acpi_int(key->poll_hotkey.poll_handle,
+                                       key->poll_hotkey.poll_method,
+                                       key->poll_hotkey.poll_result);
+                       else if ( method_type == ACTION_METHOD )
+                               write_acpi_int(key->poll_hotkey.action_handle,
+                                       key->poll_hotkey.action_method, value, NULL);
+                       else
+                               goto do_fail;
+
                }
        } else {
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Not supported"));
                return_VALUE(-EINVAL);
        }
-
        return_VALUE(count);
+do_fail:
+       return_VALUE(-EINVAL);
+
 }
 
 static int __init hotkey_init(void)
@@ -928,7 +1013,7 @@ static int __init hotkey_init(void)
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                                  "Hotkey: Unable to create %s entry\n",
                                  HOTKEY_EV_CONFIG));
-               return (-ENODEV);
+               goto do_fail1;
        } else {
                hotkey_config->proc_fops = &hotkey_config_fops;
                hotkey_config->data = &global_hotkey_list;
@@ -943,7 +1028,8 @@ static int __init hotkey_init(void)
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                                  "Hotkey: Unable to create %s entry\n",
                                  HOTKEY_EV_CONFIG));
-               return (-ENODEV);
+
+               goto do_fail2;
        } else {
                hotkey_poll_config->proc_fops = &hotkey_poll_config_fops;
                hotkey_poll_config->data = &global_hotkey_list;
@@ -957,7 +1043,7 @@ static int __init hotkey_init(void)
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                                  "Hotkey: Unable to create %s entry\n",
                                  HOTKEY_ACTION));
-               return (-ENODEV);
+               goto do_fail3;
        } else {
                hotkey_action->proc_fops = &hotkey_action_fops;
                hotkey_action->owner = THIS_MODULE;
@@ -970,7 +1056,7 @@ static int __init hotkey_init(void)
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                                  "Hotkey: Unable to create %s entry\n",
                                  HOTKEY_INFO));
-               return (-ENODEV);
+               goto do_fail4;
        } else {
                hotkey_info->proc_fops = &hotkey_info_fops;
                hotkey_info->owner = THIS_MODULE;
@@ -979,23 +1065,33 @@ static int __init hotkey_init(void)
        }
 
        result = acpi_bus_register_driver(&hotkey_driver);
-       if (result < 0) {
-               remove_proc_entry(HOTKEY_PROC, acpi_root_dir);
-               return (-ENODEV);
-       }
+       if (result < 0)
+               goto do_fail5;
        global_hotkey_list.count = 0;
        global_hotkey_list.entries = &hotkey_entries;
 
        INIT_LIST_HEAD(&hotkey_entries);
 
        return (0);
+
+do_fail5:
+       remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir);
+do_fail4:
+       remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir);
+do_fail3:
+       remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir);
+do_fail2:
+       remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir);
+do_fail1:
+       remove_proc_entry(HOTKEY_PROC, acpi_root_dir);
+       return (-ENODEV);
 }
 
 static void __exit hotkey_exit(void)
 {
        struct list_head *entries, *next;
 
-       ACPI_FUNCTION_TRACE("hotkey_remove");
+       ACPI_FUNCTION_TRACE("hotkey_exit");
 
        list_for_each_safe(entries, next, global_hotkey_list.entries) {
                union acpi_hotkey *key =
index bdd9f37..0d11d6e 100644 (file)
@@ -71,7 +71,7 @@ EXPORT_SYMBOL(acpi_in_debugger);
 extern char line_buf[80];
 #endif /*ENABLE_DEBUGGER*/
 
-int acpi_specific_hotkey_enabled;
+int acpi_specific_hotkey_enabled = TRUE;
 EXPORT_SYMBOL(acpi_specific_hotkey_enabled);
 
 static unsigned int acpi_irq_irq;
@@ -145,10 +145,14 @@ acpi_os_vprintf(const char *fmt, va_list args)
 #endif
 }
 
+extern int acpi_in_resume;
 void *
 acpi_os_allocate(acpi_size size)
 {
-       return kmalloc(size, GFP_KERNEL);
+       if (acpi_in_resume)
+               return kmalloc(size, GFP_ATOMIC);
+       else
+               return kmalloc(size, GFP_KERNEL);
 }
 
 void
@@ -1158,11 +1162,11 @@ __setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
 int __init
 acpi_hotkey_setup(char *str)
 {
-       acpi_specific_hotkey_enabled = TRUE;
+       acpi_specific_hotkey_enabled = FALSE;
        return 1;
 }
 
-__setup("acpi_specific_hotkey", acpi_hotkey_setup);
+__setup("acpi_generic_hotkey", acpi_hotkey_setup);
 
 /*
  * max_cstate is defined in the base kernel so modules can
index d1f42b9..bb973d2 100644 (file)
@@ -269,7 +269,51 @@ acpi_pci_irq_del_prt (int segment, int bus)
 /* --------------------------------------------------------------------------
                           PCI Interrupt Routing Support
    -------------------------------------------------------------------------- */
+typedef int (*irq_lookup_func)(struct acpi_prt_entry *, int *, int *, char **);
 
+static int
+acpi_pci_allocate_irq(struct acpi_prt_entry *entry,
+       int     *edge_level,
+       int     *active_high_low,
+       char    **link)
+{
+       int     irq;
+
+       ACPI_FUNCTION_TRACE("acpi_pci_allocate_irq");
+
+       if (entry->link.handle) {
+               irq = acpi_pci_link_allocate_irq(entry->link.handle,
+                       entry->link.index, edge_level, active_high_low, link);
+               if (irq < 0) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n"));
+                       return_VALUE(-1);
+               }
+       } else {
+               irq = entry->link.index;
+               *edge_level = ACPI_LEVEL_SENSITIVE;
+               *active_high_low = ACPI_ACTIVE_LOW;
+       }
+
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq));
+       return_VALUE(irq);
+}
+
+static int
+acpi_pci_free_irq(struct acpi_prt_entry *entry,
+       int     *edge_level,
+       int     *active_high_low,
+       char    **link)
+{
+       int     irq;
+
+       ACPI_FUNCTION_TRACE("acpi_pci_free_irq");
+       if (entry->link.handle) {
+               irq = acpi_pci_link_free_irq(entry->link.handle);
+       } else {
+               irq = entry->link.index;
+       }
+       return_VALUE(irq);
+}
 /*
  * acpi_pci_irq_lookup
  * success: return IRQ >= 0
@@ -282,12 +326,13 @@ acpi_pci_irq_lookup (
        int                     pin,
        int                     *edge_level,
        int                     *active_high_low,
-       char                    **link)
+       char                    **link,
+       irq_lookup_func         func)
 {
        struct acpi_prt_entry   *entry = NULL;
        int segment = pci_domain_nr(bus);
        int bus_nr = bus->number;
-       int irq;
+       int ret;
 
        ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup");
 
@@ -301,22 +346,8 @@ acpi_pci_irq_lookup (
                return_VALUE(-1);
        }
        
-       if (entry->link.handle) {
-               irq = acpi_pci_link_get_irq(entry->link.handle,
-                       entry->link.index, edge_level, active_high_low, link);
-               if (irq < 0) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n"));
-                       return_VALUE(-1);
-               }
-       } else {
-               irq = entry->link.index;
-               *edge_level = ACPI_LEVEL_SENSITIVE;
-               *active_high_low = ACPI_ACTIVE_LOW;
-       }
-
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq));
-
-       return_VALUE(irq);
+       ret = func(entry, edge_level, active_high_low, link);
+       return_VALUE(ret);
 }
 
 /*
@@ -330,7 +361,8 @@ acpi_pci_irq_derive (
        int                     pin,
        int                     *edge_level,
        int                     *active_high_low,
-       char                    **link)
+       char                    **link,
+       irq_lookup_func         func)
 {
        struct pci_dev          *bridge = dev;
        int                     irq = -1;
@@ -363,7 +395,7 @@ acpi_pci_irq_derive (
                }
 
                irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn),
-                       pin, edge_level, active_high_low, link);
+                       pin, edge_level, active_high_low, link, func);
        }
 
        if (irq < 0) {
@@ -415,7 +447,7 @@ acpi_pci_irq_enable (
         * values override any BIOS-assigned IRQs set during boot.
         */
        irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
-               &edge_level, &active_high_low, &link);
+               &edge_level, &active_high_low, &link, acpi_pci_allocate_irq);
 
        /*
         * If no PRT entry was found, we'll try to derive an IRQ from the
@@ -423,7 +455,7 @@ acpi_pci_irq_enable (
         */
        if (irq < 0)
                irq = acpi_pci_irq_derive(dev, pin, &edge_level,
-                       &active_high_low, &link);
+                       &active_high_low, &link, acpi_pci_allocate_irq);
  
        /*
         * No IRQ known to the ACPI subsystem - maybe the BIOS / 
@@ -462,7 +494,9 @@ acpi_pci_irq_enable (
 EXPORT_SYMBOL(acpi_pci_irq_enable);
 
 
-#ifdef CONFIG_ACPI_DEALLOCATE_IRQ
+/* FIXME: implement x86/x86_64 version */
+void __attribute__((weak)) acpi_unregister_gsi(u32 i) {}
+
 void
 acpi_pci_irq_disable (
        struct pci_dev          *dev)
@@ -489,14 +523,14 @@ acpi_pci_irq_disable (
         * First we check the PCI IRQ routing table (PRT) for an IRQ.
         */
        gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
-                                 &edge_level, &active_high_low, NULL);
+                       &edge_level, &active_high_low, NULL, acpi_pci_free_irq);
        /*
         * If no PRT entry was found, we'll try to derive an IRQ from the
         * device's parent bridge.
         */
        if (gsi < 0)
                gsi = acpi_pci_irq_derive(dev, pin,
-                                         &edge_level, &active_high_low, NULL);
+                       &edge_level, &active_high_low, NULL, acpi_pci_free_irq);
        if (gsi < 0)
                return_VOID;
 
@@ -512,4 +546,3 @@ acpi_pci_irq_disable (
 
        return_VOID;
 }
-#endif /* CONFIG_ACPI_DEALLOCATE_IRQ */
index 6ad0e77..834c2ce 100644 (file)
@@ -68,6 +68,10 @@ static struct acpi_driver acpi_pci_link_driver = {
                        },
 };
 
+/*
+ * If a link is initialized, we never change its active and initialized
+ * later even the link is disable. Instead, we just repick the active irq
+ */
 struct acpi_pci_link_irq {
        u8                      active;                 /* Current IRQ */
        u8                      edge_level;             /* All IRQs */
@@ -76,8 +80,7 @@ struct acpi_pci_link_irq {
        u8                      possible_count;
        u8                      possible[ACPI_PCI_LINK_MAX_POSSIBLE];
        u8                      initialized:1;
-       u8                      suspend_resume:1;
-       u8                      reserved:6;
+       u8                      reserved:7;
 };
 
 struct acpi_pci_link {
@@ -85,12 +88,14 @@ struct acpi_pci_link {
        struct acpi_device      *device;
        acpi_handle             handle;
        struct acpi_pci_link_irq irq;
+       int                     refcnt;
 };
 
 static struct {
        int                     count;
        struct list_head        entries;
 }                              acpi_link;
+DECLARE_MUTEX(acpi_link_lock);
 
 
 /* --------------------------------------------------------------------------
@@ -532,12 +537,12 @@ static int acpi_pci_link_allocate(
 
        ACPI_FUNCTION_TRACE("acpi_pci_link_allocate");
 
-       if (link->irq.suspend_resume) {
-               acpi_pci_link_set(link, link->irq.active);
-               link->irq.suspend_resume = 0;
-       }
-       if (link->irq.initialized)
+       if (link->irq.initialized) {
+               if (link->refcnt == 0)
+                       /* This means the link is disabled but initialized */
+                       acpi_pci_link_set(link, link->irq.active);
                return_VALUE(0);
+       }
 
        /*
         * search for active IRQ in list of possible IRQs.
@@ -596,13 +601,13 @@ static int acpi_pci_link_allocate(
 }
 
 /*
- * acpi_pci_link_get_irq
+ * acpi_pci_link_allocate_irq
  * success: return IRQ >= 0
  * failure: return -1
  */
 
 int
-acpi_pci_link_get_irq (
+acpi_pci_link_allocate_irq (
        acpi_handle             handle,
        int                     index,
        int                     *edge_level,
@@ -613,7 +618,7 @@ acpi_pci_link_get_irq (
        struct acpi_device      *device = NULL;
        struct acpi_pci_link    *link = NULL;
 
-       ACPI_FUNCTION_TRACE("acpi_pci_link_get_irq");
+       ACPI_FUNCTION_TRACE("acpi_pci_link_allocate_irq");
 
        result = acpi_bus_get_device(handle, &device);
        if (result) {
@@ -633,21 +638,81 @@ acpi_pci_link_get_irq (
                return_VALUE(-1);
        }
 
-       if (acpi_pci_link_allocate(link))
+       down(&acpi_link_lock);
+       if (acpi_pci_link_allocate(link)) {
+               up(&acpi_link_lock);
                return_VALUE(-1);
+       }
           
        if (!link->irq.active) {
+               up(&acpi_link_lock);
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n"));
                return_VALUE(-1);
        }
+       link->refcnt ++;
+       up(&acpi_link_lock);
 
        if (edge_level) *edge_level = link->irq.edge_level;
        if (active_high_low) *active_high_low = link->irq.active_high_low;
        if (name) *name = acpi_device_bid(link->device);
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+               "Link %s is referenced\n", acpi_device_bid(link->device)));
        return_VALUE(link->irq.active);
 }
 
+/*
+ * We don't change link's irq information here.  After it is reenabled, we
+ * continue use the info
+ */
+int
+acpi_pci_link_free_irq(acpi_handle handle)
+{
+       struct acpi_device      *device = NULL;
+       struct acpi_pci_link    *link = NULL;
+       acpi_status             result;
+
+       ACPI_FUNCTION_TRACE("acpi_pci_link_free_irq");
+
+       result = acpi_bus_get_device(handle, &device);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link device\n"));
+               return_VALUE(-1);
+       }
+
+       link = (struct acpi_pci_link *) acpi_driver_data(device);
+       if (!link) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
+               return_VALUE(-1);
+       }
+
+       down(&acpi_link_lock);
+       if (!link->irq.initialized) {
+               up(&acpi_link_lock);
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link isn't initialized\n"));
+               return_VALUE(-1);
+       }
 
+#ifdef FUTURE_USE
+       /*
+        * The Link reference count allows us to _DISable an unused link
+        * and suspend time, and set it again  on resume.
+        * However, 2.6.12 still has irq_router.resume
+        * which blindly restores the link state.
+        * So we disable the reference count method
+        * to prevent duplicate acpi_pci_link_set()
+        * which would harm some systems
+        */
+       link->refcnt --;
+#endif
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+               "Link %s is dereferenced\n", acpi_device_bid(link->device)));
+
+       if (link->refcnt == 0) {
+               acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
+       }
+       up(&acpi_link_lock);
+       return_VALUE(link->irq.active);
+}
 /* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
@@ -677,6 +742,7 @@ acpi_pci_link_add (
        strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS);
        acpi_driver_data(device) = link;
 
+       down(&acpi_link_lock);
        result = acpi_pci_link_get_possible(link);
        if (result)
                goto end;
@@ -712,6 +778,7 @@ acpi_pci_link_add (
 end:
        /* disable all links -- to be activated on use */
        acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
+       up(&acpi_link_lock);
 
        if (result)
                kfree(link);
@@ -720,24 +787,42 @@ end:
 }
 
 static int
-irqrouter_suspend(
-       struct sys_device *dev,
-       u32     state)
+acpi_pci_link_resume(
+       struct acpi_pci_link *link)
+{
+       ACPI_FUNCTION_TRACE("acpi_pci_link_resume");
+
+       if (link->refcnt && link->irq.active && link->irq.initialized)
+               return_VALUE(acpi_pci_link_set(link, link->irq.active));
+       else
+               return_VALUE(0);
+}
+
+/*
+ * FIXME: this is a workaround to avoid nasty warning.  It will be removed
+ * after every device calls pci_disable_device in .resume.
+ */
+int acpi_in_resume;
+static int
+irqrouter_resume(
+       struct sys_device *dev)
 {
        struct list_head        *node = NULL;
        struct acpi_pci_link    *link = NULL;
 
-       ACPI_FUNCTION_TRACE("irqrouter_suspend");
+       ACPI_FUNCTION_TRACE("irqrouter_resume");
 
+       acpi_in_resume = 1;
        list_for_each(node, &acpi_link.entries) {
                link = list_entry(node, struct acpi_pci_link, node);
                if (!link) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                               "Invalid link context\n"));
                        continue;
                }
-               if (link->irq.active && link->irq.initialized)
-                       link->irq.suspend_resume = 1;
+               acpi_pci_link_resume(link);
        }
+       acpi_in_resume = 0;
        return_VALUE(0);
 }
 
@@ -756,8 +841,9 @@ acpi_pci_link_remove (
 
        link = (struct acpi_pci_link *) acpi_driver_data(device);
 
-       /* TBD: Acquire/release lock */
+       down(&acpi_link_lock);
        list_del(&link->node);
+       up(&acpi_link_lock);
 
        kfree(link);
 
@@ -849,9 +935,10 @@ int __init acpi_irq_balance_set(char *str)
 __setup("acpi_irq_balance", acpi_irq_balance_set);
 
 
+/* FIXME: we will remove this interface after all drivers call pci_disable_device */
 static struct sysdev_class irqrouter_sysdev_class = {
         set_kset_name("irqrouter"),
-        .suspend = irqrouter_suspend,
+        .resume = irqrouter_resume,
 };
 
 
index 893b074..2c04740 100644 (file)
@@ -81,30 +81,32 @@ module_param(bm_history, uint, 0644);
  *
  * To skip this limit, boot/load with a large max_cstate limit.
  */
-static int no_c2c3(struct dmi_system_id *id)
+static int set_max_cstate(struct dmi_system_id *id)
 {
        if (max_cstate > ACPI_PROCESSOR_MAX_POWER)
                return 0;
 
-       printk(KERN_NOTICE PREFIX "%s detected - C2,C3 disabled."
+       printk(KERN_NOTICE PREFIX "%s detected - limiting to C%ld max_cstate."
                " Override with \"processor.max_cstate=%d\"\n", id->ident,
-              ACPI_PROCESSOR_MAX_POWER + 1);
+               (long)id->driver_data, ACPI_PROCESSOR_MAX_POWER + 1);
 
-       max_cstate = 1;
+       max_cstate = (long)id->driver_data;
 
        return 0;
 }
 
 
-
-
 static struct dmi_system_id __initdata processor_power_dmi_table[] = {
-       { no_c2c3, "IBM ThinkPad R40e", {
+       { set_max_cstate, "IBM ThinkPad R40e", {
          DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
-         DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }},
-       { no_c2c3, "Medion 41700", {
+         DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }, (void*)1},
+       { set_max_cstate, "Medion 41700", {
+         DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
+         DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }, (void*)1},
+       { set_max_cstate, "Clevo 5600D", {
          DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
-         DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }},
+         DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307") },
+         (void*)2},
        {},
 };
 
@@ -549,7 +551,8 @@ static int acpi_processor_get_power_info_default_c1 (struct acpi_processor *pr)
        ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1");
 
        for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++)
-               memset(pr->power.states, 0, sizeof(struct acpi_processor_cx));
+               memset(&(pr->power.states[i]), 0, 
+                      sizeof(struct acpi_processor_cx));
 
        /* if info is obtained from pblk/fadt, type equals state */
        pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
@@ -580,7 +583,8 @@ static int acpi_processor_get_power_info_cst (struct acpi_processor *pr)
 
        pr->power.count = 0;
        for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++)
-               memset(pr->power.states, 0, sizeof(struct acpi_processor_cx));
+               memset(&(pr->power.states[i]), 0, 
+                      sizeof(struct acpi_processor_cx));
 
        status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer);
        if (ACPI_FAILURE(status)) {
@@ -763,7 +767,6 @@ static void acpi_processor_power_verify_c3(
        }
 
        if (pr->flags.bm_check) {
-               printk("Disabling BM access before entering C3\n");
                /* bus mastering control is necessary */
                if (!pr->flags.bm_control) {
                        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -771,7 +774,6 @@ static void acpi_processor_power_verify_c3(
                        return_VOID;
                }
        } else {
-               printk("Invalidating cache before entering C3\n");
                /*
                 * WBINVD should be set in fadt, for C3 state to be
                 * supported on when bm_check is not required.
@@ -842,7 +844,7 @@ static int acpi_processor_get_power_info (
        result = acpi_processor_get_power_info_cst(pr);
        if ((result) || (acpi_processor_power_verify(pr) < 2)) {
                result = acpi_processor_get_power_info_fadt(pr);
-               if (result)
+               if ((result) || (acpi_processor_power_verify(pr) < 2))
                        result = acpi_processor_get_power_info_default_c1(pr);
        }
 
index 186b182..f93d2ee 100644 (file)
@@ -55,7 +55,11 @@ void acpi_power_off(void)
 
 static int acpi_shutdown(struct sys_device *x)
 {
-       return acpi_sleep_prepare(ACPI_STATE_S5);
+       if (system_state == SYSTEM_POWER_OFF) {
+               /* Prepare if we are going to power off the system */
+               return acpi_sleep_prepare(ACPI_STATE_S5);
+       }
+       return 0;
 }
 
 static struct sysdev_class acpi_sysclass = {
index 96fe2f9..ab53832 100644 (file)
@@ -180,7 +180,9 @@ static ssize_t driver_bind(struct device_driver *drv,
                up(&dev->sem);
                put_device(dev);
        }
-       return err;
+       if (err)
+               return err;
+       return count;
 }
 static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
 
index 479c125..0154a16 100644 (file)
@@ -299,6 +299,11 @@ static void class_dev_release(struct kobject * kobj)
 
        pr_debug("device class '%s': release.\n", cd->class_id);
 
+       if (cd->devt_attr) {
+               kfree(cd->devt_attr);
+               cd->devt_attr = NULL;
+       }
+
        if (cls->release)
                cls->release(cd);
        else {
@@ -591,11 +596,8 @@ void class_device_del(struct class_device *class_dev)
 
        if (class_dev->dev)
                sysfs_remove_link(&class_dev->kobj, "device");
-       if (class_dev->devt_attr) {
+       if (class_dev->devt_attr)
                class_device_remove_file(class_dev, class_dev->devt_attr);
-               kfree(class_dev->devt_attr);
-               class_dev->devt_attr = NULL;
-       }
        class_device_remove_attrs(class_dev);
 
        kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
index de5746e..cd056e7 100644 (file)
@@ -47,7 +47,7 @@ static int cfq_slice_idle = HZ / 100;
 /*
  * disable queueing at the driver/hardware level
  */
-static int cfq_max_depth = 1;
+static int cfq_max_depth = 2;
 
 /*
  * for the hash of cfqq inside the cfqd
@@ -385,9 +385,15 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2)
                return crq2;
        if (crq2 == NULL)
                return crq1;
-       if (cfq_crq_requeued(crq1))
+
+       if (cfq_crq_requeued(crq1) && !cfq_crq_requeued(crq2))
                return crq1;
-       if (cfq_crq_requeued(crq2))
+       else if (cfq_crq_requeued(crq2) && !cfq_crq_requeued(crq1))
+               return crq2;
+
+       if (cfq_crq_is_sync(crq1) && !cfq_crq_is_sync(crq2))
+               return crq1;
+       else if (cfq_crq_is_sync(crq2) && !cfq_crq_is_sync(crq1))
                return crq2;
 
        s1 = crq1->request->sector;
@@ -1281,6 +1287,7 @@ dispatch:
                         */
                        if (!cfq_crq_in_driver(crq) &&
                            !cfq_cfqq_idle_window(cfqq) &&
+                           !blk_barrier_rq(rq) &&
                            cfqd->rq_in_driver >= cfqd->cfq_max_depth)
                                return NULL;
 
@@ -1768,18 +1775,23 @@ static void
 cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                 struct cfq_rq *crq)
 {
-       const int sync = cfq_crq_is_sync(crq);
+       struct cfq_io_context *cic;
 
        cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq);
 
-       if (sync) {
-               struct cfq_io_context *cic = crq->io_context;
+       /*
+        * we never wait for an async request and we don't allow preemption
+        * of an async request. so just return early
+        */
+       if (!cfq_crq_is_sync(crq))
+               return;
 
-               cfq_update_io_thinktime(cfqd, cic);
-               cfq_update_idle_window(cfqd, cfqq, cic);
+       cic = crq->io_context;
 
-               cic->last_queue = jiffies;
-       }
+       cfq_update_io_thinktime(cfqd, cic);
+       cfq_update_idle_window(cfqd, cfqq, cic);
+
+       cic->last_queue = jiffies;
 
        if (cfqq == cfqd->active_queue) {
                /*
index 692a5fc..3c81854 100644 (file)
@@ -719,7 +719,7 @@ struct request *blk_queue_find_tag(request_queue_t *q, int tag)
 {
        struct blk_queue_tag *bqt = q->queue_tags;
 
-       if (unlikely(bqt == NULL || tag >= bqt->max_depth))
+       if (unlikely(bqt == NULL || tag >= bqt->real_max_depth))
                return NULL;
 
        return bqt->tag_index[tag];
@@ -798,6 +798,7 @@ init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth)
 
        memset(tag_index, 0, depth * sizeof(struct request *));
        memset(tag_map, 0, nr_ulongs * sizeof(unsigned long));
+       tags->real_max_depth = depth;
        tags->max_depth = depth;
        tags->tag_index = tag_index;
        tags->tag_map = tag_map;
@@ -871,12 +872,23 @@ int blk_queue_resize_tags(request_queue_t *q, int new_depth)
        if (!bqt)
                return -ENXIO;
 
+       /*
+        * if we already have large enough real_max_depth.  just
+        * adjust max_depth.  *NOTE* as requests with tag value
+        * between new_depth and real_max_depth can be in-flight, tag
+        * map can not be shrunk blindly here.
+        */
+       if (new_depth <= bqt->real_max_depth) {
+               bqt->max_depth = new_depth;
+               return 0;
+       }
+
        /*
         * save the old state info, so we can copy it back
         */
        tag_index = bqt->tag_index;
        tag_map = bqt->tag_map;
-       max_depth = bqt->max_depth;
+       max_depth = bqt->real_max_depth;
 
        if (init_tag_map(q, bqt, new_depth))
                return -ENOMEM;
@@ -913,7 +925,7 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq)
 
        BUG_ON(tag == -1);
 
-       if (unlikely(tag >= bqt->max_depth))
+       if (unlikely(tag >= bqt->real_max_depth))
                /*
                 * This can happen after tag depth has been reduced.
                 * FIXME: how about a warning or info message here?
index 2771c86..f696da6 100644 (file)
@@ -367,11 +367,8 @@ static inline void bpa10x_free_urb(struct urb *urb)
        if (!urb)
                return;
 
-       if (urb->setup_packet)
-               kfree(urb->setup_packet);
-
-       if (urb->transfer_buffer)
-               kfree(urb->transfer_buffer);
+       kfree(urb->setup_packet);
+       kfree(urb->transfer_buffer);
 
        usb_free_urb(urb);
 }
index c0ed213..858fddb 100644 (file)
@@ -58,8 +58,6 @@
 #ifndef CONFIG_BT_HCIUART_DEBUG
 #undef  BT_DBG
 #define BT_DBG( A... )
-#undef  BT_DMP
-#define BT_DMP( A... )
 #endif
 
 static int hciextn = 1;
index ade94a5..533323b 100644 (file)
@@ -57,8 +57,6 @@
 #ifndef CONFIG_BT_HCIUART_DEBUG
 #undef  BT_DBG
 #define BT_DBG( A... )
-#undef  BT_DMP
-#define BT_DMP( A... )
 #endif
 
 /* Initialize protocol */
@@ -125,7 +123,6 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
 
        BT_DBG("len %d room %d", len, room);
        if (!len) {
-               BT_DMP(h4->rx_skb->data, h4->rx_skb->len);
                hci_recv_frame(h4->rx_skb);
        } else if (len > room) {
                BT_ERR("Data length is too large");
@@ -169,8 +166,6 @@ static int h4_recv(struct hci_uart *hu, void *data, int count)
                        case H4_W4_DATA:
                                BT_DBG("Complete data");
 
-                               BT_DMP(h4->rx_skb->data, h4->rx_skb->len);
-
                                hci_recv_frame(h4->rx_skb);
 
                                h4->rx_state = H4_W4_PACKET_TYPE;
index f766bc2..90be2ea 100644 (file)
@@ -57,8 +57,6 @@
 #ifndef CONFIG_BT_HCIUART_DEBUG
 #undef  BT_DBG
 #define BT_DBG( A... )
-#undef  BT_DMP
-#define BT_DMP( A... )
 #endif
 
 static int reset = 0;
index b120ecf..657719b 100644 (file)
@@ -57,8 +57,6 @@
 #ifndef CONFIG_BT_HCIUSB_DEBUG
 #undef  BT_DBG
 #define BT_DBG(D...)
-#undef  BT_DMP
-#define BT_DMP(D...)
 #endif
 
 #ifndef CONFIG_BT_HCIUSB_ZERO_PACKET
@@ -110,6 +108,9 @@ static struct usb_device_id blacklist_ids[] = {
        /* Microsoft Wireless Transceiver for Bluetooth 2.0 */
        { USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET },
 
+       /* Kensington Bluetooth USB adapter */
+       { USB_DEVICE(0x047d, 0x105d), .driver_info = HCI_RESET },
+
        /* ISSC Bluetooth Adapter v3.1 */
        { USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET },
 
@@ -387,10 +388,8 @@ static void hci_usb_unlink_urbs(struct hci_usb *husb)
                        urb = &_urb->urb;
                        BT_DBG("%s freeing _urb %p type %d urb %p",
                                        husb->hdev->name, _urb, _urb->type, urb);
-                       if (urb->setup_packet)
-                               kfree(urb->setup_packet);
-                       if (urb->transfer_buffer)
-                               kfree(urb->transfer_buffer);
+                       kfree(urb->setup_packet);
+                       kfree(urb->transfer_buffer);
                        _urb_free(_urb);
                }
 
index 4f27e55..7333b41 100644 (file)
@@ -80,7 +80,7 @@ config SERIAL_NONSTANDARD
 
 config COMPUTONE
        tristate "Computone IntelliPort Plus serial support"
-       depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+       depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP && (BROKEN || !SPARC32)
        ---help---
          This driver supports the entire family of Intelliport II/Plus
          controllers with the exception of the MicroChannel controllers and
@@ -138,7 +138,7 @@ config CYZ_INTR
 
 config DIGIEPCA
        tristate "Digiboard Intelligent Async Support"
-       depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+       depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP && (!64BIT || BROKEN)
        ---help---
          This is a driver for Digi International's Xx, Xeve, and Xem series
          of cards which provide multiple serial ports. You would need
@@ -208,7 +208,7 @@ config SYNCLINK
 
 config SYNCLINKMP
        tristate "SyncLink Multiport support"
-       depends on SERIAL_NONSTANDARD
+       depends on SERIAL_NONSTANDARD && (BROKEN || !SPARC32)
        help
          Enable support for the SyncLink Multiport (2 or 4 ports)
          serial adapter, running asynchronous and HDLC communications up
@@ -735,7 +735,7 @@ config SGI_IP27_RTC
 
 config GEN_RTC
        tristate "Generic /dev/rtc emulation"
-       depends on RTC!=y && !IA64 && !ARM && !PPC64
+       depends on RTC!=y && !IA64 && !ARM && !PPC64 && !M32R && !SPARC32
        ---help---
          If you say Y here and create a character special file /dev/rtc with
          major number 10 and minor number 135 using mknod ("man mknod"), you
index 4218738..850a78c 100644 (file)
@@ -261,7 +261,11 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
 
 static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
 {
-        unsigned long long val;
+       unsigned long pfn;
+
+       /* Turn a kernel-virtual address into a physical page frame */
+       pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT;
+
        /*
         * RED-PEN: on some architectures there is more mapped memory
         * than available in mem_map which pfn_valid checks
@@ -269,10 +273,10 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
         *
         * RED-PEN: vmalloc is not supported right now.
         */
-       if (!pfn_valid(vma->vm_pgoff))
+       if (!pfn_valid(pfn))
                return -EIO;
-       val = (u64)vma->vm_pgoff << PAGE_SHIFT;
-       vma->vm_pgoff = __pa(val) >> PAGE_SHIFT;
+
+       vma->vm_pgoff = pfn;
        return mmap_mem(file, vma);
 }
 
index d8f9e94..cd4fe8b 100644 (file)
@@ -1209,6 +1209,7 @@ static int rtc_proc_open(struct inode *inode, struct file *file)
 
 void rtc_get_rtc_time(struct rtc_time *rtc_tm)
 {
+       unsigned long uip_watchdog = jiffies;
        unsigned char ctrl;
 #ifdef CONFIG_MACH_DECSTATION
        unsigned int real_year;
@@ -1224,8 +1225,10 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
         * Once the read clears, read the RTC time (again via ioctl). Easy.
         */
 
-       if (rtc_is_updating() != 0)
-               msleep(20);
+       while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100) {
+               barrier();
+               cpu_relax();
+       }
 
        /*
         * Only the values that we read from the RTC are set. We leave
index 94a3b3e..79e9832 100644 (file)
@@ -17,6 +17,8 @@ config TCG_TPM
          obtained at: <http://sourceforge.net/projects/trousers>.  To 
          compile this driver as a module, choose M here; the module 
          will be called tpm. If unsure, say N.
+         Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI_BUS
+         and CONFIG_PNPACPI.
 
 config TCG_NSC
        tristate "National Semiconductor TPM Interface"
@@ -36,12 +38,13 @@ config TCG_ATMEL
          as a module, choose M here; the module will be called tpm_atmel.
 
 config TCG_INFINEON
-       tristate "Infineon Technologies SLD 9630 TPM Interface"
-       depends on TCG_TPM
+       tristate "Infineon Technologies TPM Interface"
+       depends on TCG_TPM && PNPACPI
        ---help---
          If you have a TPM security chip from Infineon Technologies
-         say Yes and it will be accessible from within Linux.  To
-         compile this driver as a module, choose M here; the module
+         (either SLD 9630 TT 1.1 or SLB 9635 TT 1.2) say Yes and it
+         will be accessible from within Linux.
+         To compile this driver as a module, choose M here; the module
          will be called tpm_infineon.
          Further information on this driver and the supported hardware
          can be found at http://www.prosec.rub.de/tpm
index 0e32416..dc8c540 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Description:
  * Device Driver for the Infineon Technologies
- * SLD 9630 TT Trusted Platform Module
+ * SLD 9630 TT 1.1 and SLB 9635 TT 1.2 Trusted Platform Module
  * Specifications at www.trustedcomputinggroup.org
  *
  * Copyright (C) 2005, Marcel Selhorst <selhorst@crypto.rub.de>
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation, version 2 of the
  * License.
- *
  */
 
+#include <acpi/acpi_bus.h>
+#include <linux/pnp.h>
 #include "tpm.h"
 
 /* Infineon specific definitions */
 #define        TPM_MSLEEP_TIME         3
 /* gives number of max. msleep()-calls before throwing timeout */
 #define        TPM_MAX_TRIES           5000
-#define        TCPA_INFINEON_DEV_VEN_VALUE     0x15D1
-#define        TPM_DATA                        (TPM_ADDR + 1) & 0xff
+#define        TPM_INFINEON_DEV_VEN_VALUE      0x15D1
+
+/* These values will be filled after ACPI-call */
+static int TPM_INF_DATA = 0;
+static int TPM_INF_ADDR = 0;
 
 /* TPM header definitions */
 enum infineon_tpm_header {
@@ -305,9 +309,10 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
 
 static void tpm_inf_cancel(struct tpm_chip *chip)
 {
-       /* Nothing yet!
-          This has something to do with the internal functions
-          of the TPM. Abort isn't really necessary...
+       /*
+          Since we are using the legacy mode to communicate
+          with the TPM, we have no cancel functions, but have
+          a workaround for interrupting the TPM through WTX.
         */
 }
 
@@ -345,6 +350,32 @@ static struct tpm_vendor_specific tpm_inf = {
        .miscdev = {.fops = &inf_ops,},
 };
 
+static const struct pnp_device_id tpm_pnp_tbl[] = {
+       /* Infineon TPMs */
+       {"IFX0101", 0},
+       {"IFX0102", 0},
+       {"", 0}
+};
+
+static int __devinit tpm_inf_acpi_probe(struct pnp_dev *dev,
+                                       const struct pnp_device_id *dev_id)
+{
+       TPM_INF_ADDR = (pnp_port_start(dev, 0) & 0xff);
+       TPM_INF_DATA = ((TPM_INF_ADDR + 1) & 0xff);
+       tpm_inf.base = pnp_port_start(dev, 1);
+       dev_info(&dev->dev, "Found %s with ID %s\n",
+                dev->name, dev_id->id);
+       if (!((tpm_inf.base >> 8) & 0xff))
+               tpm_inf.base = 0;
+       return 0;
+}
+
+static struct pnp_driver tpm_inf_pnp = {
+       .name = "tpm_inf_pnp",
+       .id_table = tpm_pnp_tbl,
+       .probe = tpm_inf_acpi_probe,
+};
+
 static int __devinit tpm_inf_probe(struct pci_dev *pci_dev,
                                   const struct pci_device_id *pci_id)
 {
@@ -353,64 +384,99 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev,
        int vendorid[2];
        int version[2];
        int productid[2];
+       char chipname[20];
 
        if (pci_enable_device(pci_dev))
                return -EIO;
 
        dev_info(&pci_dev->dev, "LPC-bus found at 0x%x\n", pci_id->device);
 
+       /* read IO-ports from ACPI */
+       pnp_register_driver(&tpm_inf_pnp);
+       pnp_unregister_driver(&tpm_inf_pnp);
+
+       /* Make sure, we have received valid config ports */
+       if (!TPM_INF_ADDR) {
+               pci_disable_device(pci_dev);
+               return -EIO;
+       }
+
        /* query chip for its vendor, its version number a.s.o. */
-       outb(ENABLE_REGISTER_PAIR, TPM_ADDR);
-       outb(IDVENL, TPM_ADDR);
-       vendorid[1] = inb(TPM_DATA);
-       outb(IDVENH, TPM_ADDR);
-       vendorid[0] = inb(TPM_DATA);
-       outb(IDPDL, TPM_ADDR);
-       productid[1] = inb(TPM_DATA);
-       outb(IDPDH, TPM_ADDR);
-       productid[0] = inb(TPM_DATA);
-       outb(CHIP_ID1, TPM_ADDR);
-       version[1] = inb(TPM_DATA);
-       outb(CHIP_ID2, TPM_ADDR);
-       version[0] = inb(TPM_DATA);
-
-       if ((vendorid[0] << 8 | vendorid[1]) == (TCPA_INFINEON_DEV_VEN_VALUE)) {
-
-               /* read IO-ports from TPM */
-               outb(IOLIMH, TPM_ADDR);
-               ioh = inb(TPM_DATA);
-               outb(IOLIML, TPM_ADDR);
-               iol = inb(TPM_DATA);
-               tpm_inf.base = (ioh << 8) | iol;
+       outb(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
+       outb(IDVENL, TPM_INF_ADDR);
+       vendorid[1] = inb(TPM_INF_DATA);
+       outb(IDVENH, TPM_INF_ADDR);
+       vendorid[0] = inb(TPM_INF_DATA);
+       outb(IDPDL, TPM_INF_ADDR);
+       productid[1] = inb(TPM_INF_DATA);
+       outb(IDPDH, TPM_INF_ADDR);
+       productid[0] = inb(TPM_INF_DATA);
+       outb(CHIP_ID1, TPM_INF_ADDR);
+       version[1] = inb(TPM_INF_DATA);
+       outb(CHIP_ID2, TPM_INF_ADDR);
+       version[0] = inb(TPM_INF_DATA);
+
+       switch ((productid[0] << 8) | productid[1]) {
+       case 6:
+               sprintf(chipname, " (SLD 9630 TT 1.1)");
+               break;
+       case 11:
+               sprintf(chipname, " (SLB 9635 TT 1.2)");
+               break;
+       default:
+               sprintf(chipname, " (unknown chip)");
+               break;
+       }
+       chipname[19] = 0;
+
+       if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) {
 
                if (tpm_inf.base == 0) {
-                       dev_err(&pci_dev->dev, "No IO-ports set!\n");
+                       dev_err(&pci_dev->dev, "No IO-ports found!\n");
                        pci_disable_device(pci_dev);
-                       return -ENODEV;
+                       return -EIO;
+               }
+               /* configure TPM with IO-ports */
+               outb(IOLIMH, TPM_INF_ADDR);
+               outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA);
+               outb(IOLIML, TPM_INF_ADDR);
+               outb((tpm_inf.base & 0xff), TPM_INF_DATA);
+
+               /* control if IO-ports are set correctly */
+               outb(IOLIMH, TPM_INF_ADDR);
+               ioh = inb(TPM_INF_DATA);
+               outb(IOLIML, TPM_INF_ADDR);
+               iol = inb(TPM_INF_DATA);
+
+               if ((ioh << 8 | iol) != tpm_inf.base) {
+                       dev_err(&pci_dev->dev,
+                               "Could not set IO-ports to %04x\n",
+                               tpm_inf.base);
+                       pci_disable_device(pci_dev);
+                       return -EIO;
                }
 
                /* activate register */
-               outb(TPM_DAR, TPM_ADDR);
-               outb(0x01, TPM_DATA);
-               outb(DISABLE_REGISTER_PAIR, TPM_ADDR);
+               outb(TPM_DAR, TPM_INF_ADDR);
+               outb(0x01, TPM_INF_DATA);
+               outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
 
                /* disable RESET, LP and IRQC */
                outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD);
 
                /* Finally, we're done, print some infos */
                dev_info(&pci_dev->dev, "TPM found: "
+                        "config base 0x%x, "
                         "io base 0x%x, "
                         "chip version %02x%02x, "
                         "vendor id %x%x (Infineon), "
                         "product id %02x%02x"
                         "%s\n",
+                        TPM_INF_ADDR,
                         tpm_inf.base,
                         version[0], version[1],
                         vendorid[0], vendorid[1],
-                        productid[0], productid[1], ((productid[0] == 0)
-                                                     && (productid[1] ==
-                                                         6)) ?
-                        " (SLD 9630 TT 1.1)" : "");
+                        productid[0], productid[1], chipname);
 
                rc = tpm_register_hardware(pci_dev, &tpm_inf);
                if (rc < 0) {
@@ -462,6 +528,6 @@ module_init(init_inf);
 module_exit(cleanup_inf);
 
 MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
-MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT");
-MODULE_VERSION("1.4");
+MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
+MODULE_VERSION("1.5");
 MODULE_LICENSE("GPL");
index 30d9673..665103c 100644 (file)
@@ -2433,7 +2433,7 @@ static int con_open(struct tty_struct *tty, struct file *filp)
        int ret = 0;
 
        acquire_console_sem();
-       if (tty->count == 1) {
+       if (tty->driver_data == NULL) {
                ret = vc_allocate(currcons);
                if (ret == 0) {
                        struct vc_data *vc = vc_cons[currcons].d;
index f975dab..a13395e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *     i8xx_tco 0.07:  TCO timer driver for i8xx chipsets
+ *     i8xx_tco:       TCO timer driver for i8xx chipsets
  *
  *     (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
  *                             http://www.kernelconcepts.de
@@ -63,6 +63,9 @@
  *  20050128 Wim Van Sebroeck <wim@iguana.be>
  *     0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW
  *          chipsets. Also added support for the "undocumented" ICH7 chipset.
+ *  20050807 Wim Van Sebroeck <wim@iguana.be>
+ *     0.08 Make sure that the watchdog is only "armed" when started.
+ *          (Kernel Bug 4251)
  */
 
 /*
@@ -87,7 +90,7 @@
 #include "i8xx_tco.h"
 
 /* Module and version information */
-#define TCO_VERSION "0.07"
+#define TCO_VERSION "0.08"
 #define TCO_MODULE_NAME "i8xx TCO timer"
 #define TCO_DRIVER_NAME   TCO_MODULE_NAME ", v" TCO_VERSION
 #define PFX TCO_MODULE_NAME ": "
@@ -125,10 +128,18 @@ static int tco_timer_start (void)
        unsigned char val;
 
        spin_lock(&tco_lock);
+
+       /* disable chipset's NO_REBOOT bit */
+       pci_read_config_byte (i8xx_tco_pci, 0xd4, &val);
+       val &= 0xfd;
+       pci_write_config_byte (i8xx_tco_pci, 0xd4, val);
+
+       /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */
        val = inb (TCO1_CNT + 1);
        val &= 0xf7;
        outb (val, TCO1_CNT + 1);
        val = inb (TCO1_CNT + 1);
+
        spin_unlock(&tco_lock);
 
        if (val & 0x08)
@@ -138,13 +149,20 @@ static int tco_timer_start (void)
 
 static int tco_timer_stop (void)
 {
-       unsigned char val;
+       unsigned char val, val1;
 
        spin_lock(&tco_lock);
+       /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
        val = inb (TCO1_CNT + 1);
        val |= 0x08;
        outb (val, TCO1_CNT + 1);
        val = inb (TCO1_CNT + 1);
+
+       /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
+       pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
+       val1 |= 0x02;
+       pci_write_config_byte (i8xx_tco_pci, 0xd4, val1);
+
        spin_unlock(&tco_lock);
 
        if ((val & 0x08) == 0)
@@ -155,6 +173,7 @@ static int tco_timer_stop (void)
 static int tco_timer_keepalive (void)
 {
        spin_lock(&tco_lock);
+       /* Reload the timer by writing to the TCO Timer Reload register */
        outb (0x01, TCO1_RLD);
        spin_unlock(&tco_lock);
        return 0;
@@ -417,9 +436,8 @@ static unsigned char __init i8xx_tco_getdevice (void)
                        printk (KERN_ERR PFX "failed to get TCOBASE address\n");
                        return 0;
                }
-               /*
-                * Check chipset's NO_REBOOT bit
-                */
+
+               /* Check chipset's NO_REBOOT bit */
                pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
                if (val1 & 0x02) {
                        val1 &= 0xfd;
@@ -430,6 +448,10 @@ static unsigned char __init i8xx_tco_getdevice (void)
                                return 0;       /* Cannot reset NO_REBOOT bit */
                        }
                }
+               /* Disable reboots untill the watchdog starts */
+               val1 |= 0x02;
+               pci_write_config_byte (i8xx_tco_pci, 0xd4, val1);
+
                /* Set the TCO_EN bit in SMI_EN register */
                if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) {
                        printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
@@ -505,17 +527,10 @@ out:
 
 static void __exit watchdog_cleanup (void)
 {
-       u8 val;
-
        /* Stop the timer before we leave */
        if (!nowayout)
                tco_timer_stop ();
 
-       /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
-       pci_read_config_byte (i8xx_tco_pci, 0xd4, &val);
-       val |= 0x02;
-       pci_write_config_byte (i8xx_tco_pci, 0xd4, val);
-
        /* Deregister */
        misc_deregister (&i8xx_tco_miscdev);
        unregister_reboot_notifier(&i8xx_tco_notifier);
index 1b21326..fb88b40 100644 (file)
 #include <asm/uaccess.h>
 
 #define OSCR_FREQ              CLOCK_TICK_RATE
-#define SA1100_CLOSE_MAGIC     (0x5afc4453)
 
 static unsigned long sa1100wdt_users;
-static int expect_close;
 static int pre_margin;
 static int boot_status;
-static int nowayout = WATCHDOG_NOWAYOUT;
 
 /*
  *     Allow only one person to hold it open
@@ -62,55 +59,33 @@ static int sa1100dog_open(struct inode *inode, struct file *file)
 }
 
 /*
- *     Shut off the timer.
- *     Lock it in if it's a module and we defined ...NOWAYOUT
- *     Oddly, the watchdog can only be enabled, but we can turn off
- *     the interrupt, which appears to prevent the watchdog timing out.
+ * The watchdog cannot be disabled.
+ *
+ * Previous comments suggested that turning off the interrupt by
+ * clearing OIER[E3] would prevent the watchdog timing out but this
+ * does not appear to be true (at least on the PXA255).
  */
 static int sa1100dog_release(struct inode *inode, struct file *file)
 {
-       OSMR3 = OSCR + pre_margin;
-
-       if (expect_close == SA1100_CLOSE_MAGIC) {
-               OIER &= ~OIER_E3;
-       } else {
-               printk(KERN_CRIT "WATCHDOG: WDT device closed unexpectedly.  WDT will not stop!\n");
-       }
+       printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n");
 
        clear_bit(1, &sa1100wdt_users);
-       expect_close = 0;
 
        return 0;
 }
 
 static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
 {
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       expect_close = 0;
-
-                       for (i = 0; i != len; i++) {
-                               char c;
-
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = SA1100_CLOSE_MAGIC;
-                       }
-               }
+       if (len)
                /* Refresh OSMR3 timer. */
                OSMR3 = OSCR + pre_margin;
-       }
 
        return len;
 }
 
 static struct watchdog_info ident = {
-       .options        = WDIOF_CARDRESET | WDIOF_MAGICCLOSE |
-                         WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
-       .identity       = "SA1100 Watchdog",
+       .options        = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+       .identity       = "SA1100/PXA255 Watchdog",
 };
 
 static int sa1100dog_ioctl(struct inode *inode, struct file *file,
@@ -172,7 +147,7 @@ static struct file_operations sa1100dog_fops =
 static struct miscdevice sa1100dog_miscdev =
 {
        .minor          = WATCHDOG_MINOR,
-       .name           = "SA1100/PXA2xx watchdog",
+       .name           = "watchdog",
        .fops           = &sa1100dog_fops,
 };
 
@@ -194,7 +169,6 @@ static int __init sa1100dog_init(void)
        if (ret == 0)
                printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n",
                       margin);
-
        return ret;
 }
 
@@ -212,8 +186,5 @@ MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog");
 module_param(margin, int, 0);
 MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)");
 
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
-
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
index 5d961f5..e4710d1 100644 (file)
@@ -1004,8 +1004,8 @@ int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt)
                return FAILED;
        }
        fc->rst_pkt->eh_state = SCSI_STATE_UNUSED;
-       return SUCCESS;
 #endif
+       return SUCCESS;
 }
 
 static int __fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
index 4fa17c7..c8a7f47 100644 (file)
@@ -325,7 +325,7 @@ int adm1026_attach_adapter(struct i2c_adapter *adapter)
 int adm1026_detach_client(struct i2c_client *client)
 {
        i2c_detach_client(client);
-       kfree(client);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -1691,7 +1691,7 @@ int adm1026_detect(struct i2c_adapter *adapter, int address,
 
        /* Error out and cleanup code */
 exitfree:
-       kfree(new_client);
+       kfree(data);
 exit:
        return err;
 }
index 9168e98..9362509 100644 (file)
@@ -834,7 +834,7 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
        return 0;
 
 exit_free:
-       kfree(new_client);
+       kfree(data);
 exit:
        return err;
 }
@@ -845,7 +845,7 @@ static int adm1031_detach_client(struct i2c_client *client)
        if ((ret = i2c_detach_client(client)) != 0) {
                return ret;
        }
-       kfree(client);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
index 5c68e9c..ce2a6eb 100644 (file)
@@ -616,7 +616,7 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 exit_free:
-       kfree(new_client);
+       kfree(data);
 exit:
        return err;
 }
index 270015b..301ae98 100644 (file)
@@ -167,7 +167,7 @@ static ssize_t set_temp_reset(struct i2c_client *client, struct fscpos_data
                                "experience to the module author.\n");
 
        /* Supported value: 2 (clears the status) */
-       fscpos_write_value(client, FSCPOS_REG_TEMP_STATE[nr], 2);
+       fscpos_write_value(client, FSCPOS_REG_TEMP_STATE[nr - 1], 2);
        return count;
 }
 
index 251ac26..fdeeb3a 100644 (file)
@@ -298,7 +298,7 @@ static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
        return 0;
 
 error_free:
-       kfree(new_client);
+       kfree(data);
 error_release:
        release_region(addr, SMSC_EXTENT);
        return err;
index 897117a..7166ad0 100644 (file)
@@ -495,7 +495,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
        return 0;
 
 error_free:
-       kfree(new_client);
+       kfree(data);
 error_release:
        release_region(address, SMSC_EXTENT);
        return err;
index 04adde6..9ad3e92 100644 (file)
@@ -382,100 +382,6 @@ static void __exit fsl_i2c_exit(void)
 module_init(fsl_i2c_init);
 module_exit(fsl_i2c_exit);
 
-static int fsl_i2c_probe(struct device *device)
-{
-       int result = 0;
-       struct mpc_i2c *i2c;
-       struct platform_device *pdev = to_platform_device(device);
-       struct fsl_i2c_platform_data *pdata;
-       struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-       pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
-
-       if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) {
-               return -ENOMEM;
-       }
-       memset(i2c, 0, sizeof(*i2c));
-
-       i2c->irq = platform_get_irq(pdev, 0);
-       i2c->flags = pdata->device_flags;
-       init_waitqueue_head(&i2c->queue);
-
-       i2c->base = ioremap((phys_addr_t)r->start, MPC_I2C_REGION);
-
-       if (!i2c->base) {
-               printk(KERN_ERR "i2c-mpc - failed to map controller\n");
-               result = -ENOMEM;
-               goto fail_map;
-       }
-
-       if (i2c->irq != 0)
-               if ((result = request_irq(i2c->irq, mpc_i2c_isr,
-                                         SA_SHIRQ, "i2c-mpc", i2c)) < 0) {
-                       printk(KERN_ERR
-                              "i2c-mpc - failed to attach interrupt\n");
-                       goto fail_irq;
-               }
-
-       mpc_i2c_setclock(i2c);
-       dev_set_drvdata(device, i2c);
-
-       i2c->adap = mpc_ops;
-       i2c_set_adapdata(&i2c->adap, i2c);
-       i2c->adap.dev.parent = &pdev->dev;
-       if ((result = i2c_add_adapter(&i2c->adap)) < 0) {
-               printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
-               goto fail_add;
-       }
-
-       return result;
-
-      fail_add:
-       if (i2c->irq != 0)
-               free_irq(i2c->irq, NULL);
-      fail_irq:
-       iounmap(i2c->base);
-      fail_map:
-       kfree(i2c);
-       return result;
-};
-
-static int fsl_i2c_remove(struct device *device)
-{
-       struct mpc_i2c *i2c = dev_get_drvdata(device);
-
-       i2c_del_adapter(&i2c->adap);
-       dev_set_drvdata(device, NULL);
-
-       if (i2c->irq != 0)
-               free_irq(i2c->irq, i2c);
-
-       iounmap(i2c->base);
-       kfree(i2c);
-       return 0;
-};
-
-/* Structure for a device driver */
-static struct device_driver fsl_i2c_driver = {
-       .name = "fsl-i2c",
-       .bus = &platform_bus_type,
-       .probe = fsl_i2c_probe,
-       .remove = fsl_i2c_remove,
-};
-
-static int __init fsl_i2c_init(void)
-{
-       return driver_register(&fsl_i2c_driver);
-}
-
-static void __exit fsl_i2c_exit(void)
-{
-       driver_unregister(&fsl_i2c_driver);
-}
-
-module_init(fsl_i2c_init);
-module_exit(fsl_i2c_exit);
-
 MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>");
 MODULE_DESCRIPTION
     ("I2C-Bus adapter for MPC107 bridge and MPC824x/85xx/52xx processors");
index 1c99536..fa503ed 100644 (file)
@@ -23,8 +23,8 @@
 #include <asm/sibyte/sb1250_smbus.h>
 
 static struct i2c_algo_sibyte_data sibyte_board_data[2] = {
-       { NULL, 0, (void *) (KSEG1+A_SMB_BASE(0)) },
-       { NULL, 1, (void *) (KSEG1+A_SMB_BASE(1)) }
+       { NULL, 0, (void *) (CKSEG1+A_SMB_BASE(0)) },
+       { NULL, 1, (void *) (CKSEG1+A_SMB_BASE(1)) }
 };
 
 static struct i2c_adapter sibyte_board_adapter[2] = {
index 5f33df4..1cadd2c 100644 (file)
@@ -764,6 +764,7 @@ config BLK_DEV_IDE_PMAC_ATA100FIRST
 config BLK_DEV_IDEDMA_PMAC
        bool "PowerMac IDE DMA support"
        depends on BLK_DEV_IDE_PMAC
+       select BLK_DEV_IDEDMA_PCI
        help
          This option allows the driver for the built-in IDE controller on
          Power Macintoshes and PowerBooks to use DMA (direct memory access)
index f9c1acb..c9d3a00 100644 (file)
@@ -1220,7 +1220,7 @@ static int ide_disk_probe(struct device *dev)
                goto failed;
 
        g = alloc_disk_node(1 << PARTN_BITS,
-                       pcibus_to_node(drive->hwif->pci_dev->bus));
+                       hwif_to_node(drive->hwif));
        if (!g)
                goto out_free_idkp;
 
index 9eab642..29c22fc 100644 (file)
@@ -317,7 +317,7 @@ typedef struct ide_floppy_obj {
        unsigned long flags;
 } idefloppy_floppy_t;
 
-#define IDEFLOPPY_TICKS_DELAY  3       /* default delay for ZIP 100 */
+#define IDEFLOPPY_TICKS_DELAY  HZ/20   /* default delay for ZIP 100 (50ms) */
 
 /*
  *     Floppy flag bits values.
index 7df85af..c1128ae 100644 (file)
@@ -978,8 +978,7 @@ static int ide_init_queue(ide_drive_t *drive)
         *      do not.
         */
 
-       q = blk_init_queue_node(do_ide_request, &ide_lock,
-                               pcibus_to_node(drive->hwif->pci_dev->bus));
+       q = blk_init_queue_node(do_ide_request, &ide_lock, hwif_to_node(hwif));
        if (!q)
                return 1;
 
@@ -1048,6 +1047,8 @@ static int init_irq (ide_hwif_t *hwif)
 
        BUG_ON(in_interrupt());
        BUG_ON(irqs_disabled());        
+       BUG_ON(hwif == NULL);
+
        down(&ide_cfg_sem);
        hwif->hwgroup = NULL;
 #if MAX_HWIFS > 1
@@ -1097,7 +1098,7 @@ static int init_irq (ide_hwif_t *hwif)
                spin_unlock_irq(&ide_lock);
        } else {
                hwgroup = kmalloc_node(sizeof(ide_hwgroup_t), GFP_KERNEL,
-                       pcibus_to_node(hwif->drives[0].hwif->pci_dev->bus));
+                                       hwif_to_node(hwif->drives[0].hwif));
                if (!hwgroup)
                        goto out_up;
 
index 0374743..f1d1ec4 100644 (file)
@@ -508,5 +508,5 @@ static void __exit exit_ide_cs(void)
        BUG_ON(dev_list != NULL);
 }
 
-module_init(init_ide_cs);
+late_initcall(init_ide_cs);
 module_exit(exit_ide_cs);
index da46577..6e3ab0c 100644 (file)
@@ -173,6 +173,12 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = {
                .channels       = 2,
                .autodma        = NOAUTODMA,
                .bootable       = ON_BOARD,
+       },{     /* 14 */
+               .name           = "Revolution",
+               .init_hwif      = init_hwif_generic,
+               .channels       = 2,
+               .autodma        = AUTODMA,
+               .bootable       = OFF_BOARD,
        }
 };
 
@@ -231,6 +237,7 @@ static struct pci_device_id generic_pci_tbl[] = {
        { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11},
        { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12},
        { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13},
+       { PCI_VENDOR_ID_NETCELL,PCI_DEVICE_ID_REVOLUTION,          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14},
        /* Must come last. If you add entries adjust this table appropriately and the init_one code */
        { PCI_ANY_ID,           PCI_ANY_ID,                        PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0},
        { 0, },
index c6f5fa4..ff2e217 100644 (file)
@@ -21,6 +21,9 @@
  *
  *   CSB6: `Champion South Bridge' IDE Interface (optional: third channel)
  *
+ *   HT1000: AKA BCM5785 - Hypertransport Southbridge for Opteron systems. IDE
+ *   controller same as the CSB6. Single channel ATA100 only.
+ *
  * Documentation:
  *     Available under NDA only. Errata info very hard to get.
  *
@@ -71,6 +74,8 @@ static u8 svwks_ratemask (ide_drive_t *drive)
        if (!svwks_revision)
                pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision);
 
+       if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE)
+               return 2;
        if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
                u32 reg = 0;
                if (isa_dev)
@@ -109,6 +114,7 @@ static u8 svwks_csb_check (struct pci_dev *dev)
                case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
                case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
                case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
+               case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE:
                        return 1;
                default:
                        break;
@@ -438,6 +444,13 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
                        btr |= (svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
                pci_write_config_byte(dev, 0x5A, btr);
        }
+       /* Setup HT1000 SouthBridge Controller - Single Channel Only */
+       else if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) {
+               pci_read_config_byte(dev, 0x5A, &btr);
+               btr &= ~0x40;
+               btr |= 0x3;
+               pci_write_config_byte(dev, 0x5A, btr);
+       }
 
        return (dev->irq) ? dev->irq : 0;
 }
@@ -629,6 +642,15 @@ static ide_pci_device_t serverworks_chipsets[] __devinitdata = {
                .channels       = 1,    /* 2 */
                .autodma        = AUTODMA,
                .bootable       = ON_BOARD,
+       },{     /* 4 */
+               .name           = "SvrWks HT1000",
+               .init_setup     = init_setup_svwks,
+               .init_chipset   = init_chipset_svwks,
+               .init_hwif      = init_hwif_svwks,
+               .init_dma       = init_dma_svwks,
+               .channels       = 1,    /* 2 */
+               .autodma        = AUTODMA,
+               .bootable       = ON_BOARD,
        }
 };
 
@@ -653,6 +675,7 @@ static struct pci_device_id svwks_pci_tbl[] = {
        { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
        { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
        { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
+       { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
        { 0, },
 };
 MODULE_DEVICE_TABLE(pci, svwks_pci_tbl);
index be0fcc8..ea65b07 100644 (file)
@@ -1664,7 +1664,7 @@ static struct macio_driver pmac_ide_macio_driver =
 };
 
 static struct pci_device_id pmac_ide_pci_match[] = {
-       { PCI_VENDOR_ID_APPLE, PCI_DEVIEC_ID_APPLE_UNI_N_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_ATA,
index 77da827..18ed776 100644 (file)
@@ -229,6 +229,7 @@ second_chance_to_dma:
                        case PCI_DEVICE_ID_AMD_VIPER_7409:
                        case PCI_DEVICE_ID_CMD_643:
                        case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
+                       case PCI_DEVICE_ID_REVOLUTION:
                                simplex_stat = hwif->INB(dma_base + 2);
                                hwif->OUTB((simplex_stat&0x60),(dma_base + 2));
                                simplex_stat = hwif->INB(dma_base + 2);
index b12a970..27018c8 100644 (file)
@@ -478,7 +478,6 @@ static void ohci_initialize(struct ti_ohci *ohci)
        int num_ports, i;
 
        spin_lock_init(&ohci->phy_reg_lock);
-       spin_lock_init(&ohci->event_lock);
 
        /* Put some defaults to these undefined bus options */
        buf = reg_read(ohci, OHCI1394_BusOptions);
@@ -3402,7 +3401,14 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
        /* We hopefully don't have to pre-allocate IT DMA like we did
         * for IR DMA above. Allocate it on-demand and mark inactive. */
        ohci->it_legacy_context.ohci = NULL;
+       spin_lock_init(&ohci->event_lock);
 
+       /*
+        * interrupts are disabled, all right, but... due to SA_SHIRQ we
+        * might get called anyway.  We'll see no event, of course, but
+        * we need to get to that "no event", so enough should be initialized
+        * by that point.
+        */
        if (request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ,
                         OHCI1394_DRIVER_NAME, ohci))
                FAIL(-ENOMEM, "Failed to allocate shared interrupt %d", dev->irq);
index 79c8e2d..32cdfb3 100644 (file)
@@ -1,6 +1,7 @@
 menu "InfiniBand support"
 
 config INFINIBAND
+       depends on PCI || BROKEN
        tristate "InfiniBand support"
        ---help---
          Core support for InfiniBand (IB).  Make sure to also select
index 10be367..678a7e0 100644 (file)
@@ -1,5 +1,3 @@
-EXTRA_CFLAGS += -Idrivers/infiniband/include
-
 obj-$(CONFIG_INFINIBAND) +=            ib_core.o ib_mad.o ib_sa.o \
                                        ib_cm.o ib_umad.o ib_ucm.o
 obj-$(CONFIG_INFINIBAND_USER_VERBS) += ib_uverbs.o
index 729f0b0..5ac86f5 100644 (file)
@@ -1,9 +1,10 @@
 /*
- * Copyright (c) 2004 Mellanox Technologies Ltd.  All rights reserved.
- * Copyright (c) 2004 Infinicon Corporation.  All rights reserved.
- * Copyright (c) 2004 Intel Corporation.  All rights reserved.
- * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
- * Copyright (c) 2004 Voltaire Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2005 Mellanox Technologies Ltd.  All rights reserved.
+ * Copyright (c) 2004, 2005 Infinicon Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2005 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2005 Topspin Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2005 Voltaire Corporation.  All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -40,7 +41,7 @@
 
 #include <asm/bug.h>
 
-#include <ib_smi.h>
+#include <rdma/ib_smi.h>
 
 #include "smi.h"
 #include "agent_priv.h"
index 17435af..2ec6d7f 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 2004 Mellanox Technologies Ltd.  All rights reserved.
- * Copyright (c) 2004 Infinicon Corporation.  All rights reserved.
- * Copyright (c) 2004 Intel Corporation.  All rights reserved.
- * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
- * Copyright (c) 2004 Voltaire Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2005 Mellanox Technologies Ltd.  All rights reserved.
+ * Copyright (c) 2004, 2005 Infinicon Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2005 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2005 Topspin Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2005 Voltaire Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 3042360..f014e63 100644 (file)
@@ -1,5 +1,8 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Intel Corporation. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
  * $Id: cache.c 1349 2004-12-16 21:09:43Z roland $
  */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 
-#include <ib_cache.h>
+#include <rdma/ib_cache.h>
 
 #include "core_priv.h"
 
index 403ed12..4de93ba 100644 (file)
@@ -43,8 +43,8 @@
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 
-#include <ib_cache.h>
-#include <ib_cm.h>
+#include <rdma/ib_cache.h>
+#include <rdma/ib_cm.h>
 #include "cm_msgs.h"
 
 MODULE_AUTHOR("Sean Hefty");
@@ -83,7 +83,7 @@ struct cm_port {
 struct cm_device {
        struct list_head list;
        struct ib_device *device;
-       u64 ca_guid;
+       __be64 ca_guid;
        struct cm_port port[0];
 };
 
@@ -100,8 +100,8 @@ struct cm_work {
        struct list_head list;
        struct cm_port *port;
        struct ib_mad_recv_wc *mad_recv_wc;     /* Received MADs */
-       u32 local_id;                           /* Established / timewait */
-       u32 remote_id;
+       __be32 local_id;                        /* Established / timewait */
+       __be32 remote_id;
        struct ib_cm_event cm_event;
        struct ib_sa_path_rec path[0];
 };
@@ -110,8 +110,8 @@ struct cm_timewait_info {
        struct cm_work work;                    /* Must be first. */
        struct rb_node remote_qp_node;
        struct rb_node remote_id_node;
-       u64 remote_ca_guid;
-       u32 remote_qpn;
+       __be64 remote_ca_guid;
+       __be32 remote_qpn;
        u8 inserted_remote_qp;
        u8 inserted_remote_id;
 };
@@ -132,11 +132,11 @@ struct cm_id_private {
        struct cm_av alt_av;
 
        void *private_data;
-       u64 tid;
-       u32 local_qpn;
-       u32 remote_qpn;
-       u32 sq_psn;
-       u32 rq_psn;
+       __be64 tid;
+       __be32 local_qpn;
+       __be32 remote_qpn;
+       __be32 sq_psn;
+       __be32 rq_psn;
        int timeout_ms;
        enum ib_mtu path_mtu;
        u8 private_data_len;
@@ -253,7 +253,7 @@ static void cm_set_ah_attr(struct ib_ah_attr *ah_attr, u8 port_num,
                           u16 dlid, u8 sl, u16 src_path_bits)
 {
        memset(ah_attr, 0, sizeof ah_attr);
-       ah_attr->dlid = be16_to_cpu(dlid);
+       ah_attr->dlid = dlid;
        ah_attr->sl = sl;
        ah_attr->src_path_bits = src_path_bits;
        ah_attr->port_num = port_num;
@@ -264,7 +264,7 @@ static void cm_init_av_for_response(struct cm_port *port,
 {
        av->port = port;
        av->pkey_index = wc->pkey_index;
-       cm_set_ah_attr(&av->ah_attr, port->port_num, cpu_to_be16(wc->slid),
+       cm_set_ah_attr(&av->ah_attr, port->port_num, wc->slid,
                       wc->sl, wc->dlid_path_bits);
 }
 
@@ -295,8 +295,9 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
                return ret;
 
        av->port = port;
-       cm_set_ah_attr(&av->ah_attr, av->port->port_num, path->dlid,
-                      path->sl, path->slid & 0x7F);
+       cm_set_ah_attr(&av->ah_attr, av->port->port_num,
+                      be16_to_cpu(path->dlid), path->sl,
+                      be16_to_cpu(path->slid) & 0x7F);
        av->packet_life_time = path->packet_life_time;
        return 0;
 }
@@ -309,26 +310,26 @@ static int cm_alloc_id(struct cm_id_private *cm_id_priv)
        do {
                spin_lock_irqsave(&cm.lock, flags);
                ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, 1,
-                                       (int *) &cm_id_priv->id.local_id);
+                                       (__force int *) &cm_id_priv->id.local_id);
                spin_unlock_irqrestore(&cm.lock, flags);
        } while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) );
        return ret;
 }
 
-static void cm_free_id(u32 local_id)
+static void cm_free_id(__be32 local_id)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&cm.lock, flags);
-       idr_remove(&cm.local_id_table, (int) local_id);
+       idr_remove(&cm.local_id_table, (__force int) local_id);
        spin_unlock_irqrestore(&cm.lock, flags);
 }
 
-static struct cm_id_private * cm_get_id(u32 local_id, u32 remote_id)
+static struct cm_id_private * cm_get_id(__be32 local_id, __be32 remote_id)
 {
        struct cm_id_private *cm_id_priv;
 
-       cm_id_priv = idr_find(&cm.local_id_table, (int) local_id);
+       cm_id_priv = idr_find(&cm.local_id_table, (__force int) local_id);
        if (cm_id_priv) {
                if (cm_id_priv->id.remote_id == remote_id)
                        atomic_inc(&cm_id_priv->refcount);
@@ -339,7 +340,7 @@ static struct cm_id_private * cm_get_id(u32 local_id, u32 remote_id)
        return cm_id_priv;
 }
 
-static struct cm_id_private * cm_acquire_id(u32 local_id, u32 remote_id)
+static struct cm_id_private * cm_acquire_id(__be32 local_id, __be32 remote_id)
 {
        struct cm_id_private *cm_id_priv;
        unsigned long flags;
@@ -356,8 +357,8 @@ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
        struct rb_node **link = &cm.listen_service_table.rb_node;
        struct rb_node *parent = NULL;
        struct cm_id_private *cur_cm_id_priv;
-       u64 service_id = cm_id_priv->id.service_id;
-       u64 service_mask = cm_id_priv->id.service_mask;
+       __be64 service_id = cm_id_priv->id.service_id;
+       __be64 service_mask = cm_id_priv->id.service_mask;
 
        while (*link) {
                parent = *link;
@@ -376,7 +377,7 @@ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
        return NULL;
 }
 
-static struct cm_id_private * cm_find_listen(u64 service_id)
+static struct cm_id_private * cm_find_listen(__be64 service_id)
 {
        struct rb_node *node = cm.listen_service_table.rb_node;
        struct cm_id_private *cm_id_priv;
@@ -400,8 +401,8 @@ static struct cm_timewait_info * cm_insert_remote_id(struct cm_timewait_info
        struct rb_node **link = &cm.remote_id_table.rb_node;
        struct rb_node *parent = NULL;
        struct cm_timewait_info *cur_timewait_info;
-       u64 remote_ca_guid = timewait_info->remote_ca_guid;
-       u32 remote_id = timewait_info->work.remote_id;
+       __be64 remote_ca_guid = timewait_info->remote_ca_guid;
+       __be32 remote_id = timewait_info->work.remote_id;
 
        while (*link) {
                parent = *link;
@@ -424,8 +425,8 @@ static struct cm_timewait_info * cm_insert_remote_id(struct cm_timewait_info
        return NULL;
 }
 
-static struct cm_timewait_info * cm_find_remote_id(u64 remote_ca_guid,
-                                                  u32 remote_id)
+static struct cm_timewait_info * cm_find_remote_id(__be64 remote_ca_guid,
+                                                  __be32 remote_id)
 {
        struct rb_node *node = cm.remote_id_table.rb_node;
        struct cm_timewait_info *timewait_info;
@@ -453,8 +454,8 @@ static struct cm_timewait_info * cm_insert_remote_qpn(struct cm_timewait_info
        struct rb_node **link = &cm.remote_qp_table.rb_node;
        struct rb_node *parent = NULL;
        struct cm_timewait_info *cur_timewait_info;
-       u64 remote_ca_guid = timewait_info->remote_ca_guid;
-       u32 remote_qpn = timewait_info->remote_qpn;
+       __be64 remote_ca_guid = timewait_info->remote_ca_guid;
+       __be32 remote_qpn = timewait_info->remote_qpn;
 
        while (*link) {
                parent = *link;
@@ -484,7 +485,7 @@ static struct cm_id_private * cm_insert_remote_sidr(struct cm_id_private
        struct rb_node *parent = NULL;
        struct cm_id_private *cur_cm_id_priv;
        union ib_gid *port_gid = &cm_id_priv->av.dgid;
-       u32 remote_id = cm_id_priv->id.remote_id;
+       __be32 remote_id = cm_id_priv->id.remote_id;
 
        while (*link) {
                parent = *link;
@@ -598,7 +599,7 @@ static void cm_cleanup_timewait(struct cm_timewait_info *timewait_info)
        spin_unlock_irqrestore(&cm.lock, flags);
 }
 
-static struct cm_timewait_info * cm_create_timewait_info(u32 local_id)
+static struct cm_timewait_info * cm_create_timewait_info(__be32 local_id)
 {
        struct cm_timewait_info *timewait_info;
 
@@ -715,14 +716,15 @@ retest:
 EXPORT_SYMBOL(ib_destroy_cm_id);
 
 int ib_cm_listen(struct ib_cm_id *cm_id,
-                u64 service_id,
-                u64 service_mask)
+                __be64 service_id,
+                __be64 service_mask)
 {
        struct cm_id_private *cm_id_priv, *cur_cm_id_priv;
        unsigned long flags;
        int ret = 0;
 
-       service_mask = service_mask ? service_mask : ~0ULL;
+       service_mask = service_mask ? service_mask :
+                      __constant_cpu_to_be64(~0ULL);
        service_id &= service_mask;
        if ((service_id & IB_SERVICE_ID_AGN_MASK) == IB_CM_ASSIGN_SERVICE_ID &&
            (service_id != IB_CM_ASSIGN_SERVICE_ID))
@@ -735,8 +737,8 @@ int ib_cm_listen(struct ib_cm_id *cm_id,
 
        spin_lock_irqsave(&cm.lock, flags);
        if (service_id == IB_CM_ASSIGN_SERVICE_ID) {
-               cm_id->service_id = __cpu_to_be64(cm.listen_service_id++);
-               cm_id->service_mask = ~0ULL;
+               cm_id->service_id = cpu_to_be64(cm.listen_service_id++);
+               cm_id->service_mask = __constant_cpu_to_be64(~0ULL);
        } else {
                cm_id->service_id = service_id;
                cm_id->service_mask = service_mask;
@@ -752,18 +754,19 @@ int ib_cm_listen(struct ib_cm_id *cm_id,
 }
 EXPORT_SYMBOL(ib_cm_listen);
 
-static u64 cm_form_tid(struct cm_id_private *cm_id_priv,
-                      enum cm_msg_sequence msg_seq)
+static __be64 cm_form_tid(struct cm_id_private *cm_id_priv,
+                         enum cm_msg_sequence msg_seq)
 {
        u64 hi_tid, low_tid;
 
        hi_tid   = ((u64) cm_id_priv->av.port->mad_agent->hi_tid) << 32;
-       low_tid  = (u64) (cm_id_priv->id.local_id | (msg_seq << 30));
+       low_tid  = (u64) ((__force u32)cm_id_priv->id.local_id |
+                         (msg_seq << 30));
        return cpu_to_be64(hi_tid | low_tid);
 }
 
 static void cm_format_mad_hdr(struct ib_mad_hdr *hdr,
-                             enum cm_msg_attr_id attr_id, u64 tid)
+                             __be16 attr_id, __be64 tid)
 {
        hdr->base_version  = IB_MGMT_BASE_VERSION;
        hdr->mgmt_class    = IB_MGMT_CLASS_CM;
@@ -896,7 +899,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
                        goto error1;
        }
        cm_id->service_id = param->service_id;
-       cm_id->service_mask = ~0ULL;
+       cm_id->service_mask = __constant_cpu_to_be64(~0ULL);
        cm_id_priv->timeout_ms = cm_convert_to_ms(
                                    param->primary_path->packet_life_time) * 2 +
                                 cm_convert_to_ms(
@@ -963,7 +966,7 @@ static int cm_issue_rej(struct cm_port *port,
        rej_msg->remote_comm_id = rcv_msg->local_comm_id;
        rej_msg->local_comm_id = rcv_msg->remote_comm_id;
        cm_rej_set_msg_rejected(rej_msg, msg_rejected);
-       rej_msg->reason = reason;
+       rej_msg->reason = cpu_to_be16(reason);
 
        if (ari && ari_length) {
                cm_rej_set_reject_info_len(rej_msg, ari_length);
@@ -977,8 +980,8 @@ static int cm_issue_rej(struct cm_port *port,
        return ret;
 }
 
-static inline int cm_is_active_peer(u64 local_ca_guid, u64 remote_ca_guid,
-                                   u32 local_qpn, u32 remote_qpn)
+static inline int cm_is_active_peer(__be64 local_ca_guid, __be64 remote_ca_guid,
+                                   __be32 local_qpn, __be32 remote_qpn)
 {
        return (be64_to_cpu(local_ca_guid) > be64_to_cpu(remote_ca_guid) ||
                ((local_ca_guid == remote_ca_guid) &&
@@ -1137,7 +1140,7 @@ static void cm_format_rej(struct cm_rej_msg *rej_msg,
                break;
        }
 
-       rej_msg->reason = reason;
+       rej_msg->reason = cpu_to_be16(reason);
        if (ari && ari_length) {
                cm_rej_set_reject_info_len(rej_msg, ari_length);
                memcpy(rej_msg->ari, ari, ari_length);
@@ -1276,7 +1279,7 @@ static int cm_req_handler(struct cm_work *work)
        cm_id_priv->id.cm_handler = listen_cm_id_priv->id.cm_handler;
        cm_id_priv->id.context = listen_cm_id_priv->id.context;
        cm_id_priv->id.service_id = req_msg->service_id;
-       cm_id_priv->id.service_mask = ~0ULL;
+       cm_id_priv->id.service_mask = __constant_cpu_to_be64(~0ULL);
 
        cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]);
        ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av);
@@ -1969,7 +1972,7 @@ static void cm_format_rej_event(struct cm_work *work)
        param = &work->cm_event.param.rej_rcvd;
        param->ari = rej_msg->ari;
        param->ari_length = cm_rej_get_reject_info_len(rej_msg);
-       param->reason = rej_msg->reason;
+       param->reason = __be16_to_cpu(rej_msg->reason);
        work->cm_event.private_data = &rej_msg->private_data;
 }
 
@@ -1978,20 +1981,20 @@ static struct cm_id_private * cm_acquire_rejected_id(struct cm_rej_msg *rej_msg)
        struct cm_timewait_info *timewait_info;
        struct cm_id_private *cm_id_priv;
        unsigned long flags;
-       u32 remote_id;
+       __be32 remote_id;
 
        remote_id = rej_msg->local_comm_id;
 
-       if (rej_msg->reason == IB_CM_REJ_TIMEOUT) {
+       if (__be16_to_cpu(rej_msg->reason) == IB_CM_REJ_TIMEOUT) {
                spin_lock_irqsave(&cm.lock, flags);
-               timewait_info = cm_find_remote_id( *((u64 *) rej_msg->ari),
+               timewait_info = cm_find_remote_id( *((__be64 *) rej_msg->ari),
                                                  remote_id);
                if (!timewait_info) {
                        spin_unlock_irqrestore(&cm.lock, flags);
                        return NULL;
                }
                cm_id_priv = idr_find(&cm.local_id_table,
-                                     (int) timewait_info->work.local_id);
+                                     (__force int) timewait_info->work.local_id);
                if (cm_id_priv) {
                        if (cm_id_priv->id.remote_id == remote_id)
                                atomic_inc(&cm_id_priv->refcount);
@@ -2032,7 +2035,7 @@ static int cm_rej_handler(struct cm_work *work)
                /* fall through */
        case IB_CM_REQ_RCVD:
        case IB_CM_MRA_REQ_SENT:
-               if (rej_msg->reason == IB_CM_REJ_STALE_CONN)
+               if (__be16_to_cpu(rej_msg->reason) == IB_CM_REJ_STALE_CONN)
                        cm_enter_timewait(cm_id_priv);
                else
                        cm_reset_to_idle(cm_id_priv);
@@ -2553,7 +2556,7 @@ static void cm_format_sidr_req(struct cm_sidr_req_msg *sidr_req_msg,
        cm_format_mad_hdr(&sidr_req_msg->hdr, CM_SIDR_REQ_ATTR_ID,
                          cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_SIDR));
        sidr_req_msg->request_id = cm_id_priv->id.local_id;
-       sidr_req_msg->pkey = param->pkey;
+       sidr_req_msg->pkey = cpu_to_be16(param->pkey);
        sidr_req_msg->service_id = param->service_id;
 
        if (param->private_data && param->private_data_len)
@@ -2580,7 +2583,7 @@ int ib_send_cm_sidr_req(struct ib_cm_id *cm_id,
                goto out;
 
        cm_id->service_id = param->service_id;
-       cm_id->service_mask = ~0ULL;
+       cm_id->service_mask = __constant_cpu_to_be64(~0ULL);
        cm_id_priv->timeout_ms = param->timeout_ms;
        cm_id_priv->max_cm_retries = param->max_cm_retries;
        ret = cm_alloc_msg(cm_id_priv, &msg);
@@ -2621,7 +2624,7 @@ static void cm_format_sidr_req_event(struct cm_work *work,
        sidr_req_msg = (struct cm_sidr_req_msg *)
                                work->mad_recv_wc->recv_buf.mad;
        param = &work->cm_event.param.sidr_req_rcvd;
-       param->pkey = sidr_req_msg->pkey;
+       param->pkey = __be16_to_cpu(sidr_req_msg->pkey);
        param->listen_id = listen_id;
        param->device = work->port->mad_agent->device;
        param->port = work->port->port_num;
@@ -2645,7 +2648,7 @@ static int cm_sidr_req_handler(struct cm_work *work)
        sidr_req_msg = (struct cm_sidr_req_msg *)
                                work->mad_recv_wc->recv_buf.mad;
        wc = work->mad_recv_wc->wc;
-       cm_id_priv->av.dgid.global.subnet_prefix = wc->slid;
+       cm_id_priv->av.dgid.global.subnet_prefix = cpu_to_be64(wc->slid);
        cm_id_priv->av.dgid.global.interface_id = 0;
        cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
                                &cm_id_priv->av);
@@ -2673,7 +2676,7 @@ static int cm_sidr_req_handler(struct cm_work *work)
        cm_id_priv->id.cm_handler = cur_cm_id_priv->id.cm_handler;
        cm_id_priv->id.context = cur_cm_id_priv->id.context;
        cm_id_priv->id.service_id = sidr_req_msg->service_id;
-       cm_id_priv->id.service_mask = ~0ULL;
+       cm_id_priv->id.service_mask = __constant_cpu_to_be64(~0ULL);
 
        cm_format_sidr_req_event(work, &cur_cm_id_priv->id);
        cm_process_work(cm_id_priv, work);
@@ -3175,10 +3178,10 @@ int ib_cm_init_qp_attr(struct ib_cm_id *cm_id,
 }
 EXPORT_SYMBOL(ib_cm_init_qp_attr);
 
-static u64 cm_get_ca_guid(struct ib_device *device)
+static __be64 cm_get_ca_guid(struct ib_device *device)
 {
        struct ib_device_attr *device_attr;
-       u64 guid;
+       __be64 guid;
        int ret;
 
        device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL);
index 15a309a..813ab70 100644 (file)
@@ -34,7 +34,7 @@
 #if !defined(CM_MSGS_H)
 #define CM_MSGS_H
 
-#include <ib_mad.h>
+#include <rdma/ib_mad.h>
 
 /*
  * Parameters to routines below should be in network-byte order, and values
 
 #define IB_CM_CLASS_VERSION    2 /* IB specification 1.2 */
 
-enum cm_msg_attr_id {
-       CM_REQ_ATTR_ID      = __constant_htons(0x0010),
-       CM_MRA_ATTR_ID      = __constant_htons(0x0011),
-       CM_REJ_ATTR_ID      = __constant_htons(0x0012),
-       CM_REP_ATTR_ID      = __constant_htons(0x0013),
-       CM_RTU_ATTR_ID      = __constant_htons(0x0014),
-       CM_DREQ_ATTR_ID     = __constant_htons(0x0015),
-       CM_DREP_ATTR_ID     = __constant_htons(0x0016),
-       CM_SIDR_REQ_ATTR_ID = __constant_htons(0x0017),
-       CM_SIDR_REP_ATTR_ID = __constant_htons(0x0018),
-       CM_LAP_ATTR_ID      = __constant_htons(0x0019),
-       CM_APR_ATTR_ID      = __constant_htons(0x001A)
-};
+#define CM_REQ_ATTR_ID     __constant_htons(0x0010)
+#define CM_MRA_ATTR_ID     __constant_htons(0x0011)
+#define CM_REJ_ATTR_ID     __constant_htons(0x0012)
+#define CM_REP_ATTR_ID     __constant_htons(0x0013)
+#define CM_RTU_ATTR_ID     __constant_htons(0x0014)
+#define CM_DREQ_ATTR_ID            __constant_htons(0x0015)
+#define CM_DREP_ATTR_ID            __constant_htons(0x0016)
+#define CM_SIDR_REQ_ATTR_ID __constant_htons(0x0017)
+#define CM_SIDR_REP_ATTR_ID __constant_htons(0x0018)
+#define CM_LAP_ATTR_ID      __constant_htons(0x0019)
+#define CM_APR_ATTR_ID      __constant_htons(0x001A)
 
 enum cm_msg_sequence {
        CM_MSG_SEQUENCE_REQ,
@@ -67,35 +65,35 @@ enum cm_msg_sequence {
 struct cm_req_msg {
        struct ib_mad_hdr hdr;
 
-       u32 local_comm_id;
-       u32 rsvd4;
-       u64 service_id;
-       u64 local_ca_guid;
-       u32 rsvd24;
-       u32 local_qkey;
+       __be32 local_comm_id;
+       __be32 rsvd4;
+       __be64 service_id;
+       __be64 local_ca_guid;
+       __be32 rsvd24;
+       __be32 local_qkey;
        /* local QPN:24, responder resources:8 */
-       u32 offset32;
+       __be32 offset32;
        /* local EECN:24, initiator depth:8 */
-       u32 offset36;
+       __be32 offset36;
        /*
         * remote EECN:24, remote CM response timeout:5,
         * transport service type:2, end-to-end flow control:1
         */
-       u32 offset40;
+       __be32 offset40;
        /* starting PSN:24, local CM response timeout:5, retry count:3 */
-       u32 offset44;
-       u16 pkey;
+       __be32 offset44;
+       __be16 pkey;
        /* path MTU:4, RDC exists:1, RNR retry count:3. */
        u8 offset50;
        /* max CM Retries:4, SRQ:1, rsvd:3 */
        u8 offset51;
 
-       u16 primary_local_lid;
-       u16 primary_remote_lid;
+       __be16 primary_local_lid;
+       __be16 primary_remote_lid;
        union ib_gid primary_local_gid;
        union ib_gid primary_remote_gid;
        /* flow label:20, rsvd:6, packet rate:6 */
-       u32 primary_offset88;
+       __be32 primary_offset88;
        u8 primary_traffic_class;
        u8 primary_hop_limit;
        /* SL:4, subnet local:1, rsvd:3 */
@@ -103,12 +101,12 @@ struct cm_req_msg {
        /* local ACK timeout:5, rsvd:3 */
        u8 primary_offset95;
 
-       u16 alt_local_lid;
-       u16 alt_remote_lid;
+       __be16 alt_local_lid;
+       __be16 alt_remote_lid;
        union ib_gid alt_local_gid;
        union ib_gid alt_remote_gid;
        /* flow label:20, rsvd:6, packet rate:6 */
-       u32 alt_offset132;
+       __be32 alt_offset132;
        u8 alt_traffic_class;
        u8 alt_hop_limit;
        /* SL:4, subnet local:1, rsvd:3 */
@@ -120,12 +118,12 @@ struct cm_req_msg {
 
 } __attribute__ ((packed));
 
-static inline u32 cm_req_get_local_qpn(struct cm_req_msg *req_msg)
+static inline __be32 cm_req_get_local_qpn(struct cm_req_msg *req_msg)
 {
        return cpu_to_be32(be32_to_cpu(req_msg->offset32) >> 8);
 }
 
-static inline void cm_req_set_local_qpn(struct cm_req_msg *req_msg, u32 qpn)
+static inline void cm_req_set_local_qpn(struct cm_req_msg *req_msg, __be32 qpn)
 {
        req_msg->offset32 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
                                         (be32_to_cpu(req_msg->offset32) &
@@ -208,13 +206,13 @@ static inline void cm_req_set_flow_ctrl(struct cm_req_msg *req_msg,
                                          0xFFFFFFFE));
 }
 
-static inline u32 cm_req_get_starting_psn(struct cm_req_msg *req_msg)
+static inline __be32 cm_req_get_starting_psn(struct cm_req_msg *req_msg)
 {
        return cpu_to_be32(be32_to_cpu(req_msg->offset44) >> 8);
 }
 
 static inline void cm_req_set_starting_psn(struct cm_req_msg *req_msg,
-                                          u32 starting_psn)
+                                          __be32 starting_psn)
 {
        req_msg->offset44 = cpu_to_be32((be32_to_cpu(starting_psn) << 8) |
                            (be32_to_cpu(req_msg->offset44) & 0x000000FF));
@@ -288,13 +286,13 @@ static inline void cm_req_set_srq(struct cm_req_msg *req_msg, u8 srq)
                                  ((srq & 0x1) << 3));
 }
 
-static inline u32 cm_req_get_primary_flow_label(struct cm_req_msg *req_msg)
+static inline __be32 cm_req_get_primary_flow_label(struct cm_req_msg *req_msg)
 {
-       return cpu_to_be32((be32_to_cpu(req_msg->primary_offset88) >> 12));
+       return cpu_to_be32(be32_to_cpu(req_msg->primary_offset88) >> 12);
 }
 
 static inline void cm_req_set_primary_flow_label(struct cm_req_msg *req_msg,
-                                                u32 flow_label)
+                                                __be32 flow_label)
 {
        req_msg->primary_offset88 = cpu_to_be32(
                                    (be32_to_cpu(req_msg->primary_offset88) &
@@ -350,13 +348,13 @@ static inline void cm_req_set_primary_local_ack_timeout(struct cm_req_msg *req_m
                                          (local_ack_timeout << 3));
 }
 
-static inline u32 cm_req_get_alt_flow_label(struct cm_req_msg *req_msg)
+static inline __be32 cm_req_get_alt_flow_label(struct cm_req_msg *req_msg)
 {
-       return cpu_to_be32((be32_to_cpu(req_msg->alt_offset132) >> 12));
+       return cpu_to_be32(be32_to_cpu(req_msg->alt_offset132) >> 12);
 }
 
 static inline void cm_req_set_alt_flow_label(struct cm_req_msg *req_msg,
-                                            u32 flow_label)
+                                            __be32 flow_label)
 {
        req_msg->alt_offset132 = cpu_to_be32(
                                 (be32_to_cpu(req_msg->alt_offset132) &
@@ -422,8 +420,8 @@ enum cm_msg_response {
  struct cm_mra_msg {
        struct ib_mad_hdr hdr;
 
-       u32 local_comm_id;
-       u32 remote_comm_id;
+       __be32 local_comm_id;
+       __be32 remote_comm_id;
        /* message MRAed:2, rsvd:6 */
        u8 offset8;
        /* service timeout:5, rsvd:3 */
@@ -458,13 +456,13 @@ static inline void cm_mra_set_service_timeout(struct cm_mra_msg *mra_msg,
 struct cm_rej_msg {
        struct ib_mad_hdr hdr;
 
-       u32 local_comm_id;
-       u32 remote_comm_id;
+       __be32 local_comm_id;
+       __be32 remote_comm_id;
        /* message REJected:2, rsvd:6 */
        u8 offset8;
        /* reject info length:7, rsvd:1. */
        u8 offset9;
-       u16 reason;
+       __be16 reason;
        u8 ari[IB_CM_REJ_ARI_LENGTH];
 
        u8 private_data[IB_CM_REJ_PRIVATE_DATA_SIZE];
@@ -495,45 +493,45 @@ static inline void cm_rej_set_reject_info_len(struct cm_rej_msg *rej_msg,
 struct cm_rep_msg {
        struct ib_mad_hdr hdr;
 
-       u32 local_comm_id;
-       u32 remote_comm_id;
-       u32 local_qkey;
+       __be32 local_comm_id;
+       __be32 remote_comm_id;
+       __be32 local_qkey;
        /* local QPN:24, rsvd:8 */
-       u32 offset12;
+       __be32 offset12;
        /* local EECN:24, rsvd:8 */
-       u32 offset16;
+       __be32 offset16;
        /* starting PSN:24 rsvd:8 */
-       u32 offset20;
+       __be32 offset20;
        u8 resp_resources;
        u8 initiator_depth;
        /* target ACK delay:5, failover accepted:2, end-to-end flow control:1 */
        u8 offset26;
        /* RNR retry count:3, SRQ:1, rsvd:5 */
        u8 offset27;
-       u64 local_ca_guid;
+       __be64 local_ca_guid;
 
        u8 private_data[IB_CM_REP_PRIVATE_DATA_SIZE];
 
 } __attribute__ ((packed));
 
-static inline u32 cm_rep_get_local_qpn(struct cm_rep_msg *rep_msg)
+static inline __be32 cm_rep_get_local_qpn(struct cm_rep_msg *rep_msg)
 {
        return cpu_to_be32(be32_to_cpu(rep_msg->offset12) >> 8);
 }
 
-static inline void cm_rep_set_local_qpn(struct cm_rep_msg *rep_msg, u32 qpn)
+static inline void cm_rep_set_local_qpn(struct cm_rep_msg *rep_msg, __be32 qpn)
 {
        rep_msg->offset12 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
                            (be32_to_cpu(rep_msg->offset12) & 0x000000FF));
 }
 
-static inline u32 cm_rep_get_starting_psn(struct cm_rep_msg *rep_msg)
+static inline __be32 cm_rep_get_starting_psn(struct cm_rep_msg *rep_msg)
 {
        return cpu_to_be32(be32_to_cpu(rep_msg->offset20) >> 8);
 }
 
 static inline void cm_rep_set_starting_psn(struct cm_rep_msg *rep_msg,
-                                          u32 starting_psn)
+                                          __be32 starting_psn)
 {
        rep_msg->offset20 = cpu_to_be32((be32_to_cpu(starting_psn) << 8) |
                            (be32_to_cpu(rep_msg->offset20) & 0x000000FF));
@@ -600,8 +598,8 @@ static inline void cm_rep_set_srq(struct cm_rep_msg *rep_msg, u8 srq)
 struct cm_rtu_msg {
        struct ib_mad_hdr hdr;
 
-       u32 local_comm_id;
-       u32 remote_comm_id;
+       __be32 local_comm_id;
+       __be32 remote_comm_id;
 
        u8 private_data[IB_CM_RTU_PRIVATE_DATA_SIZE];
 
@@ -610,21 +608,21 @@ struct cm_rtu_msg {
 struct cm_dreq_msg {
        struct ib_mad_hdr hdr;
 
-       u32 local_comm_id;
-       u32 remote_comm_id;
+       __be32 local_comm_id;
+       __be32 remote_comm_id;
        /* remote QPN/EECN:24, rsvd:8 */
-       u32 offset8;
+       __be32 offset8;
 
        u8 private_data[IB_CM_DREQ_PRIVATE_DATA_SIZE];
 
 } __attribute__ ((packed));
 
-static inline u32 cm_dreq_get_remote_qpn(struct cm_dreq_msg *dreq_msg)
+static inline __be32 cm_dreq_get_remote_qpn(struct cm_dreq_msg *dreq_msg)
 {
        return cpu_to_be32(be32_to_cpu(dreq_msg->offset8) >> 8);
 }
 
-static inline void cm_dreq_set_remote_qpn(struct cm_dreq_msg *dreq_msg, u32 qpn)
+static inline void cm_dreq_set_remote_qpn(struct cm_dreq_msg *dreq_msg, __be32 qpn)
 {
        dreq_msg->offset8 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
                            (be32_to_cpu(dreq_msg->offset8) & 0x000000FF));
@@ -633,8 +631,8 @@ static inline void cm_dreq_set_remote_qpn(struct cm_dreq_msg *dreq_msg, u32 qpn)
 struct cm_drep_msg {
        struct ib_mad_hdr hdr;
 
-       u32 local_comm_id;
-       u32 remote_comm_id;
+       __be32 local_comm_id;
+       __be32 remote_comm_id;
 
        u8 private_data[IB_CM_DREP_PRIVATE_DATA_SIZE];
 
@@ -643,37 +641,37 @@ struct cm_drep_msg {
 struct cm_lap_msg {
        struct ib_mad_hdr hdr;
 
-       u32 local_comm_id;
-       u32 remote_comm_id;
+       __be32 local_comm_id;
+       __be32 remote_comm_id;
 
-       u32 rsvd8;
+       __be32 rsvd8;
        /* remote QPN/EECN:24, remote CM response timeout:5, rsvd:3 */
-       u32 offset12;
-       u32 rsvd16;
+       __be32 offset12;
+       __be32 rsvd16;
 
-       u16 alt_local_lid;
-       u16 alt_remote_lid;
+       __be16 alt_local_lid;
+       __be16 alt_remote_lid;
        union ib_gid alt_local_gid;
        union ib_gid alt_remote_gid;
        /* flow label:20, rsvd:4, traffic class:8 */
-       u32 offset56;
+       __be32 offset56;
        u8 alt_hop_limit;
        /* rsvd:2, packet rate:6 */
-       uint8_t offset61;
+       u8 offset61;
        /* SL:4, subnet local:1, rsvd:3 */
-       uint8_t offset62;
+       u8 offset62;
        /* local ACK timeout:5, rsvd:3 */
-       uint8_t offset63;
+       u8 offset63;
 
        u8 private_data[IB_CM_LAP_PRIVATE_DATA_SIZE];
 } __attribute__  ((packed));
 
-static inline u32 cm_lap_get_remote_qpn(struct cm_lap_msg *lap_msg)
+static inline __be32 cm_lap_get_remote_qpn(struct cm_lap_msg *lap_msg)
 {
        return cpu_to_be32(be32_to_cpu(lap_msg->offset12) >> 8);
 }
 
-static inline void cm_lap_set_remote_qpn(struct cm_lap_msg *lap_msg, u32 qpn)
+static inline void cm_lap_set_remote_qpn(struct cm_lap_msg *lap_msg, __be32 qpn)
 {
        lap_msg->offset12 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
                                         (be32_to_cpu(lap_msg->offset12) &
@@ -693,17 +691,17 @@ static inline void cm_lap_set_remote_resp_timeout(struct cm_lap_msg *lap_msg,
                                          0xFFFFFF07));
 }
 
-static inline u32 cm_lap_get_flow_label(struct cm_lap_msg *lap_msg)
+static inline __be32 cm_lap_get_flow_label(struct cm_lap_msg *lap_msg)
 {
-       return be32_to_cpu(lap_msg->offset56) >> 12;
+       return cpu_to_be32(be32_to_cpu(lap_msg->offset56) >> 12);
 }
 
 static inline void cm_lap_set_flow_label(struct cm_lap_msg *lap_msg,
-                                        u32 flow_label)
+                                        __be32 flow_label)
 {
-       lap_msg->offset56 = cpu_to_be32((flow_label << 12) |
-                                        (be32_to_cpu(lap_msg->offset56) &
-                                         0x00000FFF));
+       lap_msg->offset56 = cpu_to_be32(
+                                (be32_to_cpu(lap_msg->offset56) & 0x00000FFF) |
+                                (be32_to_cpu(flow_label) << 12));
 }
 
 static inline u8 cm_lap_get_traffic_class(struct cm_lap_msg *lap_msg)
@@ -766,8 +764,8 @@ static inline void cm_lap_set_local_ack_timeout(struct cm_lap_msg *lap_msg,
 struct cm_apr_msg {
        struct ib_mad_hdr hdr;
 
-       u32 local_comm_id;
-       u32 remote_comm_id;
+       __be32 local_comm_id;
+       __be32 remote_comm_id;
 
        u8 info_length;
        u8 ap_status;
@@ -779,10 +777,10 @@ struct cm_apr_msg {
 struct cm_sidr_req_msg {
        struct ib_mad_hdr hdr;
 
-       u32 request_id;
-       u16 pkey;
-       u16 rsvd;
-       u64 service_id;
+       __be32 request_id;
+       __be16 pkey;
+       __be16 rsvd;
+       __be64 service_id;
 
        u8 private_data[IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE];
 } __attribute__ ((packed));
@@ -790,26 +788,26 @@ struct cm_sidr_req_msg {
 struct cm_sidr_rep_msg {
        struct ib_mad_hdr hdr;
 
-       u32 request_id;
+       __be32 request_id;
        u8 status;
        u8 info_length;
-       u16 rsvd;
+       __be16 rsvd;
        /* QPN:24, rsvd:8 */
-       u32 offset8;
-       u64 service_id;
-       u32 qkey;
+       __be32 offset8;
+       __be64 service_id;
+       __be32 qkey;
        u8 info[IB_CM_SIDR_REP_INFO_LENGTH];
 
        u8 private_data[IB_CM_SIDR_REP_PRIVATE_DATA_SIZE];
 } __attribute__ ((packed));
 
-static inline u32 cm_sidr_rep_get_qpn(struct cm_sidr_rep_msg *sidr_rep_msg)
+static inline __be32 cm_sidr_rep_get_qpn(struct cm_sidr_rep_msg *sidr_rep_msg)
 {
        return cpu_to_be32(be32_to_cpu(sidr_rep_msg->offset8) >> 8);
 }
 
 static inline void cm_sidr_rep_set_qpn(struct cm_sidr_rep_msg *sidr_rep_msg,
-                                      u32 qpn)
+                                      __be32 qpn)
 {
        sidr_rep_msg->offset8 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
                                        (be32_to_cpu(sidr_rep_msg->offset8) &
index 7970496..7ad47a4 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 
-#include <ib_verbs.h>
+#include <rdma/ib_verbs.h>
 
 int  ib_device_register_sysfs(struct ib_device *device);
 void ib_device_unregister_sysfs(struct ib_device *device);
index 9197e92..d3cf84e 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 7763b31..d34a6f1 100644 (file)
@@ -39,7 +39,7 @@
 #include <linux/jhash.h>
 #include <linux/kthread.h>
 
-#include <ib_fmr_pool.h>
+#include <rdma/ib_fmr_pool.h>
 
 #include "core_priv.h"
 
@@ -334,6 +334,7 @@ void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
 {
        struct ib_pool_fmr *fmr;
        struct ib_pool_fmr *tmp;
+       LIST_HEAD(fmr_list);
        int                 i;
 
        kthread_stop(pool->thread);
@@ -341,6 +342,11 @@ void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
 
        i = 0;
        list_for_each_entry_safe(fmr, tmp, &pool->free_list, list) {
+               if (fmr->remap_count) {
+                       INIT_LIST_HEAD(&fmr_list);
+                       list_add_tail(&fmr->fmr->list, &fmr_list);
+                       ib_unmap_fmr(&fmr_list);
+               }
                ib_dealloc_fmr(fmr->fmr);
                list_del(&fmr->list);
                kfree(fmr);
index b97e210..a4a4d9c 100644 (file)
@@ -693,7 +693,8 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
                goto out;
        }
 
-       build_smp_wc(send_wr->wr_id, smp->dr_slid, send_wr->wr.ud.pkey_index,
+       build_smp_wc(send_wr->wr_id, be16_to_cpu(smp->dr_slid),
+                    send_wr->wr.ud.pkey_index,
                     send_wr->wr.ud.port_num, &mad_wc);
 
        /* No GRH for DR SMP */
@@ -1554,7 +1555,7 @@ static int is_data_mad(struct ib_mad_agent_private *mad_agent_priv,
 }
 
 struct ib_mad_send_wr_private*
-ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, u64 tid)
+ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid)
 {
        struct ib_mad_send_wr_private *mad_send_wr;
 
@@ -1597,7 +1598,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
        struct ib_mad_send_wr_private *mad_send_wr;
        struct ib_mad_send_wc mad_send_wc;
        unsigned long flags;
-       u64 tid;
+       __be64 tid;
 
        INIT_LIST_HEAD(&mad_recv_wc->rmpp_list);
        list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list);
@@ -2165,7 +2166,8 @@ static void local_completions(void *data)
                         * Defined behavior is to complete response
                         * before request
                         */
-                       build_smp_wc(local->wr_id, IB_LID_PERMISSIVE,
+                       build_smp_wc(local->wr_id,
+                                    be16_to_cpu(IB_LID_PERMISSIVE),
                                     0 /* pkey index */,
                                     recv_mad_agent->agent.port_num, &wc);
 
@@ -2294,7 +2296,7 @@ static void timeout_sends(void *data)
        spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
 }
 
-static void ib_mad_thread_completion_handler(struct ib_cq *cq)
+static void ib_mad_thread_completion_handler(struct ib_cq *cq, void *arg)
 {
        struct ib_mad_port_private *port_priv = cq->cq_context;
 
@@ -2574,8 +2576,7 @@ static int ib_mad_port_open(struct ib_device *device,
 
        cq_size = (IB_MAD_QP_SEND_SIZE + IB_MAD_QP_RECV_SIZE) * 2;
        port_priv->cq = ib_create_cq(port_priv->device,
-                                    (ib_comp_handler)
-                                       ib_mad_thread_completion_handler,
+                                    ib_mad_thread_completion_handler,
                                     NULL, port_priv, cq_size);
        if (IS_ERR(port_priv->cq)) {
                printk(KERN_ERR PFX "Couldn't create ib_mad CQ\n");
index 568da10..f1ba794 100644 (file)
@@ -40,8 +40,8 @@
 #include <linux/pci.h>
 #include <linux/kthread.h>
 #include <linux/workqueue.h>
-#include <ib_mad.h>
-#include <ib_smi.h>
+#include <rdma/ib_mad.h>
+#include <rdma/ib_smi.h>
 
 
 #define PFX "ib_mad: "
@@ -121,7 +121,7 @@ struct ib_mad_send_wr_private {
        struct ib_send_wr send_wr;
        struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
        u64 wr_id;                      /* client WR ID */
-       u64 tid;
+       __be64 tid;
        unsigned long timeout;
        int retries;
        int retry;
@@ -144,7 +144,7 @@ struct ib_mad_local_private {
        struct ib_send_wr send_wr;
        struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
        u64 wr_id;                      /* client WR ID */
-       u64 tid;
+       __be64 tid;
 };
 
 struct ib_mad_mgmt_method_table {
@@ -210,7 +210,7 @@ extern kmem_cache_t *ib_mad_cache;
 int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr);
 
 struct ib_mad_send_wr_private *
-ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, u64 tid);
+ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid);
 
 void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
                             struct ib_mad_send_wc *mad_send_wc);
index 8f1eb80..43fd805 100644 (file)
@@ -61,7 +61,7 @@ struct mad_rmpp_recv {
        int seg_num;
        int newwin;
 
-       u64 tid;
+       __be64 tid;
        u32 src_qp;
        u16 slid;
        u8 mgmt_class;
@@ -100,6 +100,121 @@ void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent)
        }
 }
 
+static int data_offset(u8 mgmt_class)
+{
+       if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
+               return offsetof(struct ib_sa_mad, data);
+       else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
+                (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
+               return offsetof(struct ib_vendor_mad, data);
+       else
+               return offsetof(struct ib_rmpp_mad, data);
+}
+
+static void format_ack(struct ib_rmpp_mad *ack,
+                      struct ib_rmpp_mad *data,
+                      struct mad_rmpp_recv *rmpp_recv)
+{
+       unsigned long flags;
+
+       memcpy(&ack->mad_hdr, &data->mad_hdr,
+              data_offset(data->mad_hdr.mgmt_class));
+
+       ack->mad_hdr.method ^= IB_MGMT_METHOD_RESP;
+       ack->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_ACK;
+       ib_set_rmpp_flags(&ack->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
+
+       spin_lock_irqsave(&rmpp_recv->lock, flags);
+       rmpp_recv->last_ack = rmpp_recv->seg_num;
+       ack->rmpp_hdr.seg_num = cpu_to_be32(rmpp_recv->seg_num);
+       ack->rmpp_hdr.paylen_newwin = cpu_to_be32(rmpp_recv->newwin);
+       spin_unlock_irqrestore(&rmpp_recv->lock, flags);
+}
+
+static void ack_recv(struct mad_rmpp_recv *rmpp_recv,
+                    struct ib_mad_recv_wc *recv_wc)
+{
+       struct ib_mad_send_buf *msg;
+       struct ib_send_wr *bad_send_wr;
+       int hdr_len, ret;
+
+       hdr_len = sizeof(struct ib_mad_hdr) + sizeof(struct ib_rmpp_hdr);
+       msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp,
+                                recv_wc->wc->pkey_index, rmpp_recv->ah, 1,
+                                hdr_len, sizeof(struct ib_rmpp_mad) - hdr_len,
+                                GFP_KERNEL);
+       if (!msg)
+               return;
+
+       format_ack((struct ib_rmpp_mad *) msg->mad,
+                  (struct ib_rmpp_mad *) recv_wc->recv_buf.mad, rmpp_recv);
+       ret = ib_post_send_mad(&rmpp_recv->agent->agent, &msg->send_wr,
+                              &bad_send_wr);
+       if (ret)
+               ib_free_send_mad(msg);
+}
+
+static int alloc_response_msg(struct ib_mad_agent *agent,
+                             struct ib_mad_recv_wc *recv_wc,
+                             struct ib_mad_send_buf **msg)
+{
+       struct ib_mad_send_buf *m;
+       struct ib_ah *ah;
+       int hdr_len;
+
+       ah = ib_create_ah_from_wc(agent->qp->pd, recv_wc->wc,
+                                 recv_wc->recv_buf.grh, agent->port_num);
+       if (IS_ERR(ah))
+               return PTR_ERR(ah);
+
+       hdr_len = sizeof(struct ib_mad_hdr) + sizeof(struct ib_rmpp_hdr);
+       m = ib_create_send_mad(agent, recv_wc->wc->src_qp,
+                              recv_wc->wc->pkey_index, ah, 1, hdr_len,
+                              sizeof(struct ib_rmpp_mad) - hdr_len,
+                              GFP_KERNEL);
+       if (IS_ERR(m)) {
+               ib_destroy_ah(ah);
+               return PTR_ERR(m);
+       }
+       *msg = m;
+       return 0;
+}
+
+static void free_msg(struct ib_mad_send_buf *msg)
+{
+       ib_destroy_ah(msg->send_wr.wr.ud.ah);
+       ib_free_send_mad(msg);
+}
+
+static void nack_recv(struct ib_mad_agent_private *agent,
+                     struct ib_mad_recv_wc *recv_wc, u8 rmpp_status)
+{
+       struct ib_mad_send_buf *msg;
+       struct ib_rmpp_mad *rmpp_mad;
+       struct ib_send_wr *bad_send_wr;
+       int ret;
+
+       ret = alloc_response_msg(&agent->agent, recv_wc, &msg);
+       if (ret)
+               return;
+
+       rmpp_mad = (struct ib_rmpp_mad *) msg->mad;
+       memcpy(rmpp_mad, recv_wc->recv_buf.mad,
+              data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class));
+
+       rmpp_mad->mad_hdr.method ^= IB_MGMT_METHOD_RESP;
+       rmpp_mad->rmpp_hdr.rmpp_version = IB_MGMT_RMPP_VERSION;
+       rmpp_mad->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_ABORT;
+       ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
+       rmpp_mad->rmpp_hdr.rmpp_status = rmpp_status;
+       rmpp_mad->rmpp_hdr.seg_num = 0;
+       rmpp_mad->rmpp_hdr.paylen_newwin = 0;
+
+       ret = ib_post_send_mad(&agent->agent, &msg->send_wr, &bad_send_wr);
+       if (ret)
+               free_msg(msg);
+}
+
 static void recv_timeout_handler(void *data)
 {
        struct mad_rmpp_recv *rmpp_recv = data;
@@ -115,8 +230,8 @@ static void recv_timeout_handler(void *data)
        list_del(&rmpp_recv->list);
        spin_unlock_irqrestore(&rmpp_recv->agent->lock, flags);
 
-       /* TODO: send abort. */
        rmpp_wc = rmpp_recv->rmpp_wc;
+       nack_recv(rmpp_recv->agent, rmpp_wc, IB_MGMT_RMPP_STATUS_T2L);
        destroy_rmpp_recv(rmpp_recv);
        ib_free_recv_mad(rmpp_wc);
 }
@@ -230,60 +345,6 @@ insert_rmpp_recv(struct ib_mad_agent_private *agent,
        return cur_rmpp_recv;
 }
 
-static int data_offset(u8 mgmt_class)
-{
-       if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
-               return offsetof(struct ib_sa_mad, data);
-       else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
-                (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
-               return offsetof(struct ib_vendor_mad, data);
-       else
-               return offsetof(struct ib_rmpp_mad, data);
-}
-
-static void format_ack(struct ib_rmpp_mad *ack,
-                      struct ib_rmpp_mad *data,
-                      struct mad_rmpp_recv *rmpp_recv)
-{
-       unsigned long flags;
-
-       memcpy(&ack->mad_hdr, &data->mad_hdr,
-              data_offset(data->mad_hdr.mgmt_class));
-
-       ack->mad_hdr.method ^= IB_MGMT_METHOD_RESP;
-       ack->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_ACK;
-       ib_set_rmpp_flags(&ack->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
-
-       spin_lock_irqsave(&rmpp_recv->lock, flags);
-       rmpp_recv->last_ack = rmpp_recv->seg_num;
-       ack->rmpp_hdr.seg_num = cpu_to_be32(rmpp_recv->seg_num);
-       ack->rmpp_hdr.paylen_newwin = cpu_to_be32(rmpp_recv->newwin);
-       spin_unlock_irqrestore(&rmpp_recv->lock, flags);
-}
-
-static void ack_recv(struct mad_rmpp_recv *rmpp_recv,
-                    struct ib_mad_recv_wc *recv_wc)
-{
-       struct ib_mad_send_buf *msg;
-       struct ib_send_wr *bad_send_wr;
-       int hdr_len, ret;
-
-       hdr_len = sizeof(struct ib_mad_hdr) + sizeof(struct ib_rmpp_hdr);
-       msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp,
-                                recv_wc->wc->pkey_index, rmpp_recv->ah, 1,
-                                hdr_len, sizeof(struct ib_rmpp_mad) - hdr_len,
-                                GFP_KERNEL);
-       if (!msg)
-               return;
-
-       format_ack((struct ib_rmpp_mad *) msg->mad,
-                  (struct ib_rmpp_mad *) recv_wc->recv_buf.mad, rmpp_recv);
-       ret = ib_post_send_mad(&rmpp_recv->agent->agent, &msg->send_wr,
-                              &bad_send_wr);
-       if (ret)
-               ib_free_send_mad(msg);
-}
-
 static inline int get_last_flag(struct ib_mad_recv_buf *seg)
 {
        struct ib_rmpp_mad *rmpp_mad;
@@ -559,6 +620,34 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
        return ib_send_mad(mad_send_wr);
 }
 
+static void abort_send(struct ib_mad_agent_private *agent, __be64 tid,
+                      u8 rmpp_status)
+{
+       struct ib_mad_send_wr_private *mad_send_wr;
+       struct ib_mad_send_wc wc;
+       unsigned long flags;
+
+       spin_lock_irqsave(&agent->lock, flags);
+       mad_send_wr = ib_find_send_mad(agent, tid);
+       if (!mad_send_wr)
+               goto out;       /* Unmatched send */
+
+       if ((mad_send_wr->last_ack == mad_send_wr->total_seg) ||
+           (!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS))
+               goto out;       /* Send is already done */
+
+       ib_mark_mad_done(mad_send_wr);
+       spin_unlock_irqrestore(&agent->lock, flags);
+
+       wc.status = IB_WC_REM_ABORT_ERR;
+       wc.vendor_err = rmpp_status;
+       wc.wr_id = mad_send_wr->wr_id;
+       ib_mad_complete_send_wr(mad_send_wr, &wc);
+       return;
+out:
+       spin_unlock_irqrestore(&agent->lock, flags);
+}
+
 static void process_rmpp_ack(struct ib_mad_agent_private *agent,
                             struct ib_mad_recv_wc *mad_recv_wc)
 {
@@ -568,11 +657,21 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
        int seg_num, newwin, ret;
 
        rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
-       if (rmpp_mad->rmpp_hdr.rmpp_status)
+       if (rmpp_mad->rmpp_hdr.rmpp_status) {
+               abort_send(agent, rmpp_mad->mad_hdr.tid,
+                          IB_MGMT_RMPP_STATUS_BAD_STATUS);
+               nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
                return;
+       }
 
        seg_num = be32_to_cpu(rmpp_mad->rmpp_hdr.seg_num);
        newwin = be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
+       if (newwin < seg_num) {
+               abort_send(agent, rmpp_mad->mad_hdr.tid,
+                          IB_MGMT_RMPP_STATUS_W2S);
+               nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S);
+               return;
+       }
 
        spin_lock_irqsave(&agent->lock, flags);
        mad_send_wr = ib_find_send_mad(agent, rmpp_mad->mad_hdr.tid);
@@ -583,8 +682,13 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
            (!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS))
                goto out;       /* Send is already done */
 
-       if (seg_num > mad_send_wr->total_seg)
-               goto out;       /* Bad ACK */
+       if (seg_num > mad_send_wr->total_seg || seg_num > mad_send_wr->newwin) {
+               spin_unlock_irqrestore(&agent->lock, flags);
+               abort_send(agent, rmpp_mad->mad_hdr.tid,
+                          IB_MGMT_RMPP_STATUS_S2B);
+               nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B);
+               return;
+       }
 
        if (newwin < mad_send_wr->newwin || seg_num < mad_send_wr->last_ack)
                goto out;       /* Old ACK */
@@ -628,6 +732,72 @@ out:
        spin_unlock_irqrestore(&agent->lock, flags);
 }
 
+static struct ib_mad_recv_wc *
+process_rmpp_data(struct ib_mad_agent_private *agent,
+                 struct ib_mad_recv_wc *mad_recv_wc)
+{
+       struct ib_rmpp_hdr *rmpp_hdr;
+       u8 rmpp_status;
+
+       rmpp_hdr = &((struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad)->rmpp_hdr;
+
+       if (rmpp_hdr->rmpp_status) {
+               rmpp_status = IB_MGMT_RMPP_STATUS_BAD_STATUS;
+               goto bad;
+       }
+
+       if (rmpp_hdr->seg_num == __constant_htonl(1)) {
+               if (!(ib_get_rmpp_flags(rmpp_hdr) & IB_MGMT_RMPP_FLAG_FIRST)) {
+                       rmpp_status = IB_MGMT_RMPP_STATUS_BAD_SEG;
+                       goto bad;
+               }
+               return start_rmpp(agent, mad_recv_wc);
+       } else {
+               if (ib_get_rmpp_flags(rmpp_hdr) & IB_MGMT_RMPP_FLAG_FIRST) {
+                       rmpp_status = IB_MGMT_RMPP_STATUS_BAD_SEG;
+                       goto bad;
+               }
+               return continue_rmpp(agent, mad_recv_wc);
+       }
+bad:
+       nack_recv(agent, mad_recv_wc, rmpp_status);
+       ib_free_recv_mad(mad_recv_wc);
+       return NULL;
+}
+
+static void process_rmpp_stop(struct ib_mad_agent_private *agent,
+                             struct ib_mad_recv_wc *mad_recv_wc)
+{
+       struct ib_rmpp_mad *rmpp_mad;
+
+       rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
+
+       if (rmpp_mad->rmpp_hdr.rmpp_status != IB_MGMT_RMPP_STATUS_RESX) {
+               abort_send(agent, rmpp_mad->mad_hdr.tid,
+                          IB_MGMT_RMPP_STATUS_BAD_STATUS);
+               nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
+       } else
+               abort_send(agent, rmpp_mad->mad_hdr.tid,
+                          rmpp_mad->rmpp_hdr.rmpp_status);
+}
+
+static void process_rmpp_abort(struct ib_mad_agent_private *agent,
+                              struct ib_mad_recv_wc *mad_recv_wc)
+{
+       struct ib_rmpp_mad *rmpp_mad;
+
+       rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
+
+       if (rmpp_mad->rmpp_hdr.rmpp_status < IB_MGMT_RMPP_STATUS_ABORT_MIN ||
+           rmpp_mad->rmpp_hdr.rmpp_status > IB_MGMT_RMPP_STATUS_ABORT_MAX) {
+               abort_send(agent, rmpp_mad->mad_hdr.tid,
+                          IB_MGMT_RMPP_STATUS_BAD_STATUS);
+               nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
+       } else
+               abort_send(agent, rmpp_mad->mad_hdr.tid,
+                          rmpp_mad->rmpp_hdr.rmpp_status);
+}
+
 struct ib_mad_recv_wc *
 ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent,
                        struct ib_mad_recv_wc *mad_recv_wc)
@@ -638,23 +808,29 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent,
        if (!(rmpp_mad->rmpp_hdr.rmpp_rtime_flags & IB_MGMT_RMPP_FLAG_ACTIVE))
                return mad_recv_wc;
 
-       if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION)
+       if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION) {
+               abort_send(agent, rmpp_mad->mad_hdr.tid,
+                          IB_MGMT_RMPP_STATUS_UNV);
+               nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV);
                goto out;
+       }
 
        switch (rmpp_mad->rmpp_hdr.rmpp_type) {
        case IB_MGMT_RMPP_TYPE_DATA:
-               if (rmpp_mad->rmpp_hdr.seg_num == __constant_htonl(1))
-                       return start_rmpp(agent, mad_recv_wc);
-               else
-                       return continue_rmpp(agent, mad_recv_wc);
+               return process_rmpp_data(agent, mad_recv_wc);
        case IB_MGMT_RMPP_TYPE_ACK:
                process_rmpp_ack(agent, mad_recv_wc);
                break;
        case IB_MGMT_RMPP_TYPE_STOP:
+               process_rmpp_stop(agent, mad_recv_wc);
+               break;
        case IB_MGMT_RMPP_TYPE_ABORT:
-               /* TODO: process_rmpp_nack(agent, mad_recv_wc); */
+               process_rmpp_abort(agent, mad_recv_wc);
                break;
        default:
+               abort_send(agent, rmpp_mad->mad_hdr.tid,
+                          IB_MGMT_RMPP_STATUS_BADT);
+               nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT);
                break;
        }
 out:
@@ -714,7 +890,10 @@ int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr,
        if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA) {
                msg = (struct ib_mad_send_buf *) (unsigned long)
                      mad_send_wc->wr_id;
-               ib_free_send_mad(msg);
+               if (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_ACK)
+                       ib_free_send_mad(msg);
+               else
+                       free_msg(msg);
                return IB_RMPP_RESULT_INTERNAL;  /* ACK, STOP, or ABORT */
        }
 
index eb5ff54..35df501 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -32,7 +33,7 @@
  * $Id: packer.c 1349 2004-12-16 21:09:43Z roland $
  */
 
-#include <ib_pack.h>
+#include <rdma/ib_pack.h>
 
 static u64 value_read(int offset, int size, void *structure)
 {
index 7951849..126ac80 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Voltaire, Inc.  All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -44,8 +44,8 @@
 #include <linux/kref.h>
 #include <linux/idr.h>
 
-#include <ib_pack.h>
-#include <ib_sa.h>
+#include <rdma/ib_pack.h>
+#include <rdma/ib_sa.h>
 
 MODULE_AUTHOR("Roland Dreier");
 MODULE_DESCRIPTION("InfiniBand subnet administration query support");
index b4b2843..35852e7 100644 (file)
@@ -1,9 +1,10 @@
 /*
- * Copyright (c) 2004 Mellanox Technologies Ltd.  All rights reserved.
- * Copyright (c) 2004 Infinicon Corporation.  All rights reserved.
- * Copyright (c) 2004 Intel Corporation.  All rights reserved.
- * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
- * Copyright (c) 2004 Voltaire Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2005 Mellanox Technologies Ltd.  All rights reserved.
+ * Copyright (c) 2004, 2005 Infinicon Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2005 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2005 Topspin Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2005 Voltaire Corporation.  All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -36,7 +37,7 @@
  * $Id: smi.c 1389 2004-12-27 22:56:47Z roland $
  */
 
-#include <ib_smi.h>
+#include <rdma/ib_smi.h>
 #include "smi.h"
 
 /*
index 90d51b1..fae1c2d 100644 (file)
@@ -1,5 +1,7 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies Ltd.  All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -34,7 +36,7 @@
 
 #include "core_priv.h"
 
-#include <ib_mad.h>
+#include <rdma/ib_mad.h>
 
 struct ib_port {
        struct kobject         kobj;
@@ -253,14 +255,14 @@ static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr,
                return ret;
 
        return sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
-                      be16_to_cpu(((u16 *) gid.raw)[0]),
-                      be16_to_cpu(((u16 *) gid.raw)[1]),
-                      be16_to_cpu(((u16 *) gid.raw)[2]),
-                      be16_to_cpu(((u16 *) gid.raw)[3]),
-                      be16_to_cpu(((u16 *) gid.raw)[4]),
-                      be16_to_cpu(((u16 *) gid.raw)[5]),
-                      be16_to_cpu(((u16 *) gid.raw)[6]),
-                      be16_to_cpu(((u16 *) gid.raw)[7]));
+                      be16_to_cpu(((__be16 *) gid.raw)[0]),
+                      be16_to_cpu(((__be16 *) gid.raw)[1]),
+                      be16_to_cpu(((__be16 *) gid.raw)[2]),
+                      be16_to_cpu(((__be16 *) gid.raw)[3]),
+                      be16_to_cpu(((__be16 *) gid.raw)[4]),
+                      be16_to_cpu(((__be16 *) gid.raw)[5]),
+                      be16_to_cpu(((__be16 *) gid.raw)[6]),
+                      be16_to_cpu(((__be16 *) gid.raw)[7]));
 }
 
 static ssize_t show_port_pkey(struct ib_port *p, struct port_attribute *attr,
@@ -332,11 +334,11 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
                break;
        case 16:
                ret = sprintf(buf, "%u\n",
-                             be16_to_cpup((u16 *)(out_mad->data + 40 + offset / 8)));
+                             be16_to_cpup((__be16 *)(out_mad->data + 40 + offset / 8)));
                break;
        case 32:
                ret = sprintf(buf, "%u\n",
-                             be32_to_cpup((u32 *)(out_mad->data + 40 + offset / 8)));
+                             be32_to_cpup((__be32 *)(out_mad->data + 40 + offset / 8)));
                break;
        default:
                ret = 0;
@@ -598,10 +600,10 @@ static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf)
                return ret;
 
        return sprintf(buf, "%04x:%04x:%04x:%04x\n",
-                      be16_to_cpu(((u16 *) &attr.sys_image_guid)[0]),
-                      be16_to_cpu(((u16 *) &attr.sys_image_guid)[1]),
-                      be16_to_cpu(((u16 *) &attr.sys_image_guid)[2]),
-                      be16_to_cpu(((u16 *) &attr.sys_image_guid)[3]));
+                      be16_to_cpu(((__be16 *) &attr.sys_image_guid)[0]),
+                      be16_to_cpu(((__be16 *) &attr.sys_image_guid)[1]),
+                      be16_to_cpu(((__be16 *) &attr.sys_image_guid)[2]),
+                      be16_to_cpu(((__be16 *) &attr.sys_image_guid)[3]));
 }
 
 static ssize_t show_node_guid(struct class_device *cdev, char *buf)
@@ -615,10 +617,10 @@ static ssize_t show_node_guid(struct class_device *cdev, char *buf)
                return ret;
 
        return sprintf(buf, "%04x:%04x:%04x:%04x\n",
-                      be16_to_cpu(((u16 *) &attr.node_guid)[0]),
-                      be16_to_cpu(((u16 *) &attr.node_guid)[1]),
-                      be16_to_cpu(((u16 *) &attr.node_guid)[2]),
-                      be16_to_cpu(((u16 *) &attr.node_guid)[3]));
+                      be16_to_cpu(((__be16 *) &attr.node_guid)[0]),
+                      be16_to_cpu(((__be16 *) &attr.node_guid)[1]),
+                      be16_to_cpu(((__be16 *) &attr.node_guid)[2]),
+                      be16_to_cpu(((__be16 *) &attr.node_guid)[3]));
 }
 
 static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL);
index 61d07c7..7959582 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -73,14 +74,18 @@ static struct semaphore ctx_id_mutex;
 static struct idr       ctx_id_table;
 static int              ctx_id_rover = 0;
 
-static struct ib_ucm_context *ib_ucm_ctx_get(int id)
+static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id)
 {
        struct ib_ucm_context *ctx;
 
        down(&ctx_id_mutex);
        ctx = idr_find(&ctx_id_table, id);
-       if (ctx)
-               ctx->ref++;
+       if (!ctx)
+               ctx = ERR_PTR(-ENOENT);
+       else if (ctx->file != file)
+               ctx = ERR_PTR(-EINVAL);
+       else
+               atomic_inc(&ctx->ref);
        up(&ctx_id_mutex);
 
        return ctx;
@@ -88,21 +93,37 @@ static struct ib_ucm_context *ib_ucm_ctx_get(int id)
 
 static void ib_ucm_ctx_put(struct ib_ucm_context *ctx)
 {
+       if (atomic_dec_and_test(&ctx->ref))
+               wake_up(&ctx->wait);
+}
+
+static ssize_t ib_ucm_destroy_ctx(struct ib_ucm_file *file, int id)
+{
+       struct ib_ucm_context *ctx;
        struct ib_ucm_event *uevent;
 
        down(&ctx_id_mutex);
-
-       ctx->ref--;
-       if (!ctx->ref)
+       ctx = idr_find(&ctx_id_table, id);
+       if (!ctx)
+               ctx = ERR_PTR(-ENOENT);
+       else if (ctx->file != file)
+               ctx = ERR_PTR(-EINVAL);
+       else
                idr_remove(&ctx_id_table, ctx->id);
-
        up(&ctx_id_mutex);
 
-       if (ctx->ref)
-               return;
+       if (IS_ERR(ctx))
+               return PTR_ERR(ctx);
 
-       down(&ctx->file->mutex);
+       atomic_dec(&ctx->ref);
+       wait_event(ctx->wait, !atomic_read(&ctx->ref));
+
+       /* No new events will be generated after destroying the cm_id. */
+       if (!IS_ERR(ctx->cm_id))
+               ib_destroy_cm_id(ctx->cm_id);
 
+       /* Cleanup events not yet reported to the user. */
+       down(&file->mutex);
        list_del(&ctx->file_list);
        while (!list_empty(&ctx->events)) {
 
@@ -117,13 +138,10 @@ static void ib_ucm_ctx_put(struct ib_ucm_context *ctx)
 
                kfree(uevent);
        }
+       up(&file->mutex);
 
-       up(&ctx->file->mutex);
-
-       ucm_dbg("Destroyed CM ID <%d>\n", ctx->id);
-
-       ib_destroy_cm_id(ctx->cm_id);
        kfree(ctx);
+       return 0;
 }
 
 static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
@@ -135,11 +153,11 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
        if (!ctx)
                return NULL;
 
-       ctx->ref  = 1; /* user reference */
+       atomic_set(&ctx->ref, 1);
+       init_waitqueue_head(&ctx->wait);
        ctx->file = file;
 
        INIT_LIST_HEAD(&ctx->events);
-       init_MUTEX(&ctx->mutex);
 
        list_add_tail(&ctx->file_list, &file->ctxs);
 
@@ -177,8 +195,8 @@ static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath,
        if (!kpath || !upath)
                return;
 
-       memcpy(upath->dgid, kpath->dgid.raw, sizeof(union ib_gid));
-       memcpy(upath->sgid, kpath->sgid.raw, sizeof(union ib_gid));
+       memcpy(upath->dgid, kpath->dgid.raw, sizeof *upath->dgid);
+       memcpy(upath->sgid, kpath->sgid.raw, sizeof *upath->sgid);
 
        upath->dlid             = kpath->dlid;
        upath->slid             = kpath->slid;
@@ -201,10 +219,11 @@ static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath,
                kpath->packet_life_time_selector;
 }
 
-static void ib_ucm_event_req_get(struct ib_ucm_req_event_resp *ureq,
+static void ib_ucm_event_req_get(struct ib_ucm_context *ctx,
+                                struct ib_ucm_req_event_resp *ureq,
                                 struct ib_cm_req_event_param *kreq)
 {
-       ureq->listen_id = (long)kreq->listen_id->context;
+       ureq->listen_id = ctx->id;
 
        ureq->remote_ca_guid             = kreq->remote_ca_guid;
        ureq->remote_qkey                = kreq->remote_qkey;
@@ -240,34 +259,11 @@ static void ib_ucm_event_rep_get(struct ib_ucm_rep_event_resp *urep,
        urep->srq                 = krep->srq;
 }
 
-static void ib_ucm_event_rej_get(struct ib_ucm_rej_event_resp *urej,
-                                struct ib_cm_rej_event_param *krej)
-{
-       urej->reason = krej->reason;
-}
-
-static void ib_ucm_event_mra_get(struct ib_ucm_mra_event_resp *umra,
-                                struct ib_cm_mra_event_param *kmra)
-{
-       umra->timeout = kmra->service_timeout;
-}
-
-static void ib_ucm_event_lap_get(struct ib_ucm_lap_event_resp *ulap,
-                                struct ib_cm_lap_event_param *klap)
-{
-       ib_ucm_event_path_get(&ulap->path, klap->alternate_path);
-}
-
-static void ib_ucm_event_apr_get(struct ib_ucm_apr_event_resp *uapr,
-                                struct ib_cm_apr_event_param *kapr)
-{
-       uapr->status = kapr->ap_status;
-}
-
-static void ib_ucm_event_sidr_req_get(struct ib_ucm_sidr_req_event_resp *ureq,
+static void ib_ucm_event_sidr_req_get(struct ib_ucm_context *ctx,
+                                     struct ib_ucm_sidr_req_event_resp *ureq,
                                      struct ib_cm_sidr_req_event_param *kreq)
 {
-       ureq->listen_id = (long)kreq->listen_id->context;
+       ureq->listen_id = ctx->id;
        ureq->pkey      = kreq->pkey;
 }
 
@@ -279,19 +275,18 @@ static void ib_ucm_event_sidr_rep_get(struct ib_ucm_sidr_rep_event_resp *urep,
        urep->qpn    = krep->qpn;
 };
 
-static int ib_ucm_event_process(struct ib_cm_event *evt,
+static int ib_ucm_event_process(struct ib_ucm_context *ctx,
+                               struct ib_cm_event *evt,
                                struct ib_ucm_event *uvt)
 {
        void *info = NULL;
-       int result;
 
        switch (evt->event) {
        case IB_CM_REQ_RECEIVED:
-               ib_ucm_event_req_get(&uvt->resp.u.req_resp,
+               ib_ucm_event_req_get(ctx, &uvt->resp.u.req_resp,
                                     &evt->param.req_rcvd);
                uvt->data_len      = IB_CM_REQ_PRIVATE_DATA_SIZE;
-               uvt->resp.present |= (evt->param.req_rcvd.primary_path ?
-                                     IB_UCM_PRES_PRIMARY : 0);
+               uvt->resp.present  = IB_UCM_PRES_PRIMARY;
                uvt->resp.present |= (evt->param.req_rcvd.alternate_path ?
                                      IB_UCM_PRES_ALTERNATE : 0);
                break;
@@ -299,57 +294,46 @@ static int ib_ucm_event_process(struct ib_cm_event *evt,
                ib_ucm_event_rep_get(&uvt->resp.u.rep_resp,
                                     &evt->param.rep_rcvd);
                uvt->data_len = IB_CM_REP_PRIVATE_DATA_SIZE;
-
                break;
        case IB_CM_RTU_RECEIVED:
                uvt->data_len = IB_CM_RTU_PRIVATE_DATA_SIZE;
                uvt->resp.u.send_status = evt->param.send_status;
-
                break;
        case IB_CM_DREQ_RECEIVED:
                uvt->data_len = IB_CM_DREQ_PRIVATE_DATA_SIZE;
                uvt->resp.u.send_status = evt->param.send_status;
-
                break;
        case IB_CM_DREP_RECEIVED:
                uvt->data_len = IB_CM_DREP_PRIVATE_DATA_SIZE;
                uvt->resp.u.send_status = evt->param.send_status;
-
                break;
        case IB_CM_MRA_RECEIVED:
-               ib_ucm_event_mra_get(&uvt->resp.u.mra_resp,
-                                    &evt->param.mra_rcvd);
+               uvt->resp.u.mra_resp.timeout =
+                                       evt->param.mra_rcvd.service_timeout;
                uvt->data_len = IB_CM_MRA_PRIVATE_DATA_SIZE;
-
                break;
        case IB_CM_REJ_RECEIVED:
-               ib_ucm_event_rej_get(&uvt->resp.u.rej_resp,
-                                    &evt->param.rej_rcvd);
+               uvt->resp.u.rej_resp.reason = evt->param.rej_rcvd.reason;
                uvt->data_len = IB_CM_REJ_PRIVATE_DATA_SIZE;
                uvt->info_len = evt->param.rej_rcvd.ari_length;
                info          = evt->param.rej_rcvd.ari;
-
                break;
        case IB_CM_LAP_RECEIVED:
-               ib_ucm_event_lap_get(&uvt->resp.u.lap_resp,
-                                    &evt->param.lap_rcvd);
+               ib_ucm_event_path_get(&uvt->resp.u.lap_resp.path,
+                                     evt->param.lap_rcvd.alternate_path);
                uvt->data_len = IB_CM_LAP_PRIVATE_DATA_SIZE;
-               uvt->resp.present |= (evt->param.lap_rcvd.alternate_path ?
-                                     IB_UCM_PRES_ALTERNATE : 0);
+               uvt->resp.present = IB_UCM_PRES_ALTERNATE;
                break;
        case IB_CM_APR_RECEIVED:
-               ib_ucm_event_apr_get(&uvt->resp.u.apr_resp,
-                                    &evt->param.apr_rcvd);
+               uvt->resp.u.apr_resp.status = evt->param.apr_rcvd.ap_status;
                uvt->data_len = IB_CM_APR_PRIVATE_DATA_SIZE;
                uvt->info_len = evt->param.apr_rcvd.info_len;
                info          = evt->param.apr_rcvd.apr_info;
-
                break;
        case IB_CM_SIDR_REQ_RECEIVED:
-               ib_ucm_event_sidr_req_get(&uvt->resp.u.sidr_req_resp,
+               ib_ucm_event_sidr_req_get(ctx, &uvt->resp.u.sidr_req_resp,
                                          &evt->param.sidr_req_rcvd);
                uvt->data_len = IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE;
-
                break;
        case IB_CM_SIDR_REP_RECEIVED:
                ib_ucm_event_sidr_rep_get(&uvt->resp.u.sidr_rep_resp,
@@ -357,43 +341,35 @@ static int ib_ucm_event_process(struct ib_cm_event *evt,
                uvt->data_len = IB_CM_SIDR_REP_PRIVATE_DATA_SIZE;
                uvt->info_len = evt->param.sidr_rep_rcvd.info_len;
                info          = evt->param.sidr_rep_rcvd.info;
-
                break;
        default:
                uvt->resp.u.send_status = evt->param.send_status;
-
                break;
        }
 
-       if (uvt->data_len && evt->private_data) {
-
+       if (uvt->data_len) {
                uvt->data = kmalloc(uvt->data_len, GFP_KERNEL);
-               if (!uvt->data) {
-                       result = -ENOMEM;
-                       goto error;
-               }
+               if (!uvt->data)
+                       goto err1;
 
                memcpy(uvt->data, evt->private_data, uvt->data_len);
                uvt->resp.present |= IB_UCM_PRES_DATA;
        }
 
-       if (uvt->info_len && info) {
-
+       if (uvt->info_len) {
                uvt->info = kmalloc(uvt->info_len, GFP_KERNEL);
-               if (!uvt->info) {
-                       result = -ENOMEM;
-                       goto error;
-               }
+               if (!uvt->info)
+                       goto err2;
 
                memcpy(uvt->info, info, uvt->info_len);
                uvt->resp.present |= IB_UCM_PRES_INFO;
        }
-
        return 0;
-error:
-       kfree(uvt->info);
+
+err2:
        kfree(uvt->data);
-       return result;
+err1:
+       return -ENOMEM;
 }
 
 static int ib_ucm_event_handler(struct ib_cm_id *cm_id,
@@ -403,63 +379,42 @@ static int ib_ucm_event_handler(struct ib_cm_id *cm_id,
        struct ib_ucm_context *ctx;
        int result = 0;
        int id;
-       /*
-        * lookup correct context based on event type.
-        */
-       switch (event->event) {
-       case IB_CM_REQ_RECEIVED:
-               id = (long)event->param.req_rcvd.listen_id->context;
-               break;
-       case IB_CM_SIDR_REQ_RECEIVED:
-               id = (long)event->param.sidr_req_rcvd.listen_id->context;
-               break;
-       default:
-               id = (long)cm_id->context;
-               break;
-       }
 
-       ucm_dbg("Event. CM ID <%d> event <%d>\n", id, event->event);
-
-       ctx = ib_ucm_ctx_get(id);
-       if (!ctx)
-               return -ENOENT;
+       ctx = cm_id->context;
 
        if (event->event == IB_CM_REQ_RECEIVED ||
            event->event == IB_CM_SIDR_REQ_RECEIVED)
                id = IB_UCM_CM_ID_INVALID;
+       else
+               id = ctx->id;
 
        uevent = kmalloc(sizeof(*uevent), GFP_KERNEL);
-       if (!uevent) {
-               result = -ENOMEM;
-               goto done;
-       }
+       if (!uevent)
+               goto err1;
 
        memset(uevent, 0, sizeof(*uevent));
-
        uevent->resp.id    = id;
        uevent->resp.event = event->event;
 
-       result = ib_ucm_event_process(event, uevent);
+       result = ib_ucm_event_process(ctx, event, uevent);
        if (result)
-               goto done;
+               goto err2;
 
        uevent->ctx   = ctx;
-       uevent->cm_id = ((event->event == IB_CM_REQ_RECEIVED ||
-                         event->event == IB_CM_SIDR_REQ_RECEIVED ) ?
-                        cm_id : NULL);
+       uevent->cm_id = (id == IB_UCM_CM_ID_INVALID) ? cm_id : NULL;
 
        down(&ctx->file->mutex);
-
        list_add_tail(&uevent->file_list, &ctx->file->events);
        list_add_tail(&uevent->ctx_list, &ctx->events);
-
        wake_up_interruptible(&ctx->file->poll_wait);
-
        up(&ctx->file->mutex);
-done:
-       ctx->error = result;
-       ib_ucm_ctx_put(ctx); /* func reference */
-       return result;
+       return 0;
+
+err2:
+       kfree(uevent);
+err1:
+       /* Destroy new cm_id's */
+       return (id == IB_UCM_CM_ID_INVALID);
 }
 
 static ssize_t ib_ucm_event(struct ib_ucm_file *file,
@@ -517,9 +472,8 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
                goto done;
        }
 
-       ctx->cm_id             = uevent->cm_id;
-       ctx->cm_id->cm_handler = ib_ucm_event_handler;
-       ctx->cm_id->context    = (void *)(unsigned long)ctx->id;
+       ctx->cm_id          = uevent->cm_id;
+       ctx->cm_id->context = ctx;
 
        uevent->resp.id = ctx->id;
 
@@ -585,30 +539,29 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file,
        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
                return -EFAULT;
 
+       down(&file->mutex);
        ctx = ib_ucm_ctx_alloc(file);
+       up(&file->mutex);
        if (!ctx)
                return -ENOMEM;
 
-       ctx->cm_id = ib_create_cm_id(ib_ucm_event_handler,
-                                    (void *)(unsigned long)ctx->id);
-       if (!ctx->cm_id) {
-               result = -ENOMEM;
-               goto err_cm;
+       ctx->cm_id = ib_create_cm_id(ib_ucm_event_handler, ctx);
+       if (IS_ERR(ctx->cm_id)) {
+               result = PTR_ERR(ctx->cm_id);
+               goto err;
        }
 
        resp.id = ctx->id;
        if (copy_to_user((void __user *)(unsigned long)cmd.response,
                         &resp, sizeof(resp))) {
                result = -EFAULT;
-               goto err_ret;
+               goto err;
        }
 
        return 0;
-err_ret:
-       ib_destroy_cm_id(ctx->cm_id);
-err_cm:
-       ib_ucm_ctx_put(ctx); /* user reference */
 
+err:
+       ib_ucm_destroy_ctx(file, ctx->id);
        return result;
 }
 
@@ -617,19 +570,11 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file,
                                 int in_len, int out_len)
 {
        struct ib_ucm_destroy_id cmd;
-       struct ib_ucm_context *ctx;
 
        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
                return -EFAULT;
 
-       ctx = ib_ucm_ctx_get(cmd.id);
-       if (!ctx)
-               return -ENOENT;
-
-       ib_ucm_ctx_put(ctx); /* user reference */
-       ib_ucm_ctx_put(ctx); /* func reference */
-
-       return 0;
+       return ib_ucm_destroy_ctx(file, cmd.id);
 }
 
 static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
@@ -647,15 +592,9 @@ static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
                return -EFAULT;
 
-       ctx = ib_ucm_ctx_get(cmd.id);
-       if (!ctx)
-               return -ENOENT;
-
-       down(&ctx->file->mutex);
-       if (ctx->file != file) {
-               result = -EINVAL;
-               goto done;
-       }
+       ctx = ib_ucm_ctx_get(file, cmd.id);
+       if (IS_ERR(ctx))
+               return PTR_ERR(ctx);
 
        resp.service_id   = ctx->cm_id->service_id;
        resp.service_mask = ctx->cm_id->service_mask;
@@ -666,9 +605,7 @@ static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
                         &resp, sizeof(resp)))
                result = -EFAULT;
 
-done:
-       up(&ctx->file->mutex);
-       ib_ucm_ctx_put(ctx); /* func reference */
+       ib_ucm_ctx_put(ctx);
        return result;
 }
 
@@ -683,19 +620,12 @@ static ssize_t ib_ucm_listen(struct ib_ucm_file *file,
        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
                return -EFAULT;
 
-       ctx = ib_ucm_ctx_get(cmd.id);
-       if (!ctx)
-               return -ENOENT;
+       ctx = ib_ucm_ctx_get(file, cmd.id);
+       if (IS_ERR(ctx))
+               return PTR_ERR(ctx);
 
-       down(&ctx->file->mutex);
-       if (ctx->file != file)
-               result = -EINVAL;
-       else
-               result = ib_cm_listen(ctx->cm_id, cmd.service_id,
-                                     cmd.service_mask);
-
-       up(&ctx->file->mutex);
-       ib_ucm_ctx_put(ctx); /* func reference */
+       result = ib_cm_listen(ctx->cm_id, cmd.service_id, cmd.service_mask);
+       ib_ucm_ctx_put(ctx);
        return result;
 }
 
@@ -710,18 +640,12 @@ static ssize_t ib_ucm_establish(struct ib_ucm_file *file,
        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
                return -EFAULT;
 
-       ctx = ib_ucm_ctx_get(cmd.id);
-       if (!ctx)
-               return -ENOENT;
-
-       down(&ctx->file->mutex);
-       if (ctx->file != file)
-               result = -EINVAL;
-       else
-               result = ib_cm_establish(ctx->cm_id);
+       ctx = ib_ucm_ctx_get(file, cmd.id);
+       if (IS_ERR(ctx))
+               return PTR_ERR(ctx);
 
-       up(&ctx->file->mutex);
-       ib_ucm_ctx_put(ctx); /* func reference */
+       result = ib_cm_establish(ctx->cm_id);
+       ib_ucm_ctx_put(ctx);
        return result;
 }
 
@@ -768,8 +692,8 @@ static int ib_ucm_path_get(struct ib_sa_path_rec **path, u64 src)
                return -EFAULT;
        }
 
-       memcpy(sa_path->dgid.raw, ucm_path.dgid, sizeof(union ib_gid));
-       memcpy(sa_path->sgid.raw, ucm_path.sgid, sizeof(union ib_gid));
+       memcpy(sa_path->dgid.raw, ucm_path.dgid, sizeof sa_path->dgid);
+       memcpy(sa_path->sgid.raw, ucm_path.sgid, sizeof sa_path->sgid);
 
        sa_path->dlid             = ucm_path.dlid;
        sa_path->slid             = ucm_path.slid;
@@ -839,25 +763,17 @@ static ssize_t ib_ucm_send_req(struct ib_ucm_file *file,
        param.max_cm_retries             = cmd.max_cm_retries;
        param.srq                        = cmd.srq;
 
-       ctx = ib_ucm_ctx_get(cmd.id);
-       if (!ctx) {
-               result = -ENOENT;
-               goto done;
-       }
-
-       down(&ctx->file->mutex);
-       if (ctx->file != file)
-               result = -EINVAL;
-       else
+       ctx = ib_ucm_ctx_get(file, cmd.id);
+       if (!IS_ERR(ctx)) {
                result = ib_send_cm_req(ctx->cm_id, &param);
+               ib_ucm_ctx_put(ctx);
+       } else
+               result = PTR_ERR(ctx);
 
-       up(&ctx->file->mutex);
-       ib_ucm_ctx_put(ctx); /* func reference */
 done:
        kfree(param.private_data);
        kfree(param.primary_path);
        kfree(param.alternate_path);
-
        return result;
 }
 
@@ -890,23 +806,14 @@ static ssize_t ib_ucm_send_rep(struct ib_ucm_file *file,
        param.rnr_retry_count     = cmd.rnr_retry_count;
        param.srq                 = cmd.srq;
 
-       ctx = ib_ucm_ctx_get(cmd.id);
-       if (!ctx) {
-               result = -ENOENT;
-               goto done;
-       }
-
-       down(&ctx->file->mutex);
-       if (ctx->file != file)
-               result = -EINVAL;
-       else
+       ctx = ib_ucm_ctx_get(file, cmd.id);
+       if (!IS_ERR(ctx)) {
                result = ib_send_cm_rep(ctx->cm_id, &param);
+               ib_ucm_ctx_put(ctx);
+       } else
+               result = PTR_ERR(ctx);
 
-       up(&ctx->file->mutex);
-       ib_ucm_ctx_put(ctx); /* func reference */
-done:
        kfree(param.private_data);
-
        return result;
 }
 
@@ -928,23 +835,14 @@ static ssize_t ib_ucm_send_private_data(struct ib_ucm_file *file,
        if (result)
                return result;
 
-       ctx = ib_ucm_ctx_get(cmd.id);
-       if (!ctx) {
-               result = -ENOENT;
-               goto done;
-       }
-
-       down(&ctx->file->mutex);
-       if (ctx->file != file)
-               result = -EINVAL;
-       else
+       ctx = ib_ucm_ctx_get(file, cmd.id);
+       if (!IS_ERR(ctx)) {
                result = func(ctx->cm_id, private_data, cmd.len);
+               ib_ucm_ctx_put(ctx);
+       } else
+               result = PTR_ERR(ctx);
 
-       up(&ctx->file->mutex);
-       ib_ucm_ctx_put(ctx); /* func reference */
-done:
        kfree(private_data);
-
        return result;
 }
 
@@ -995,26 +893,17 @@ static ssize_t ib_ucm_send_info(struct ib_ucm_file *file,
        if (result)
                goto done;
 
-       ctx = ib_ucm_ctx_get(cmd.id);
-       if (!ctx) {
-               result = -ENOENT;
-               goto done;
-       }
-
-       down(&ctx->file->mutex);
-       if (ctx->file != file)
-               result = -EINVAL;
-       else
-               result = func(ctx->cm_id, cmd.status,
-                             info, cmd.info_len,
+       ctx = ib_ucm_ctx_get(file, cmd.id);
+       if (!IS_ERR(ctx)) {
+               result = func(ctx->cm_id, cmd.status, info, cmd.info_len,
                              data, cmd.data_len);
+               ib_ucm_ctx_put(ctx);
+       } else
+               result = PTR_ERR(ctx);
 
-       up(&ctx->file->mutex);
-       ib_ucm_ctx_put(ctx); /* func reference */
 done:
        kfree(data);
        kfree(info);
-
        return result;
 }
 
@@ -1048,24 +937,14 @@ static ssize_t ib_ucm_send_mra(struct ib_ucm_file *file,
        if (result)
                return result;
 
-       ctx = ib_ucm_ctx_get(cmd.id);
-       if (!ctx) {
-               result = -ENOENT;
-               goto done;
-       }
+       ctx = ib_ucm_ctx_get(file, cmd.id);
+       if (!IS_ERR(ctx)) {
+               result = ib_send_cm_mra(ctx->cm_id, cmd.timeout, data, cmd.len);
+               ib_ucm_ctx_put(ctx);
+       } else
+               result = PTR_ERR(ctx);
 
-       down(&ctx->file->mutex);
-       if (ctx->file != file)
-               result = -EINVAL;
-       else
-               result = ib_send_cm_mra(ctx->cm_id, cmd.timeout,
-                                       data, cmd.len);
-
-       up(&ctx->file->mutex);
-       ib_ucm_ctx_put(ctx); /* func reference */
-done:
        kfree(data);
-
        return result;
 }
 
@@ -1090,24 +969,16 @@ static ssize_t ib_ucm_send_lap(struct ib_ucm_file *file,
        if (result)
                goto done;
 
-       ctx = ib_ucm_ctx_get(cmd.id);
-       if (!ctx) {
-               result = -ENOENT;
-               goto done;
-       }
-
-       down(&ctx->file->mutex);
-       if (ctx->file != file)
-               result = -EINVAL;
-       else
+       ctx = ib_ucm_ctx_get(file, cmd.id);
+       if (!IS_ERR(ctx)) {
                result = ib_send_cm_lap(ctx->cm_id, path, data, cmd.len);
+               ib_ucm_ctx_put(ctx);
+       } else
+               result = PTR_ERR(ctx);
 
-       up(&ctx->file->mutex);
-       ib_ucm_ctx_put(ctx); /* func reference */
 done:
        kfree(data);
        kfree(path);
-
        return result;
 }
 
@@ -1140,24 +1011,16 @@ static ssize_t ib_ucm_send_sidr_req(struct ib_ucm_file *file,
        param.max_cm_retries   = cmd.max_cm_retries;
        param.pkey             = cmd.pkey;
 
-       ctx = ib_ucm_ctx_get(cmd.id);
-       if (!ctx) {
-               result = -ENOENT;
-               goto done;
-       }
-
-       down(&ctx->file->mutex);
-       if (ctx->file != file)
-               result = -EINVAL;
-       else
+       ctx = ib_ucm_ctx_get(file, cmd.id);
+       if (!IS_ERR(ctx)) {
                result = ib_send_cm_sidr_req(ctx->cm_id, &param);
+               ib_ucm_ctx_put(ctx);
+       } else
+               result = PTR_ERR(ctx);
 
-       up(&ctx->file->mutex);
-       ib_ucm_ctx_put(ctx); /* func reference */
 done:
        kfree(param.private_data);
        kfree(param.path);
-
        return result;
 }
 
@@ -1184,30 +1047,22 @@ static ssize_t ib_ucm_send_sidr_rep(struct ib_ucm_file *file,
        if (result)
                goto done;
 
-       param.qp_num       = cmd.qpn;
-       param.qkey           = cmd.qkey;
-       param.status       = cmd.status;
-       param.info_length      = cmd.info_len;
-       param.private_data_len = cmd.data_len;
-
-       ctx = ib_ucm_ctx_get(cmd.id);
-       if (!ctx) {
-               result = -ENOENT;
-               goto done;
-       }
+       param.qp_num            = cmd.qpn;
+       param.qkey              = cmd.qkey;
+       param.status            = cmd.status;
+       param.info_length       = cmd.info_len;
+       param.private_data_len  = cmd.data_len;
 
-       down(&ctx->file->mutex);
-       if (ctx->file != file)
-               result = -EINVAL;
-       else
+       ctx = ib_ucm_ctx_get(file, cmd.id);
+       if (!IS_ERR(ctx)) {
                result = ib_send_cm_sidr_rep(ctx->cm_id, &param);
+               ib_ucm_ctx_put(ctx);
+       } else
+               result = PTR_ERR(ctx);
 
-       up(&ctx->file->mutex);
-       ib_ucm_ctx_put(ctx); /* func reference */
 done:
        kfree(param.private_data);
        kfree(param.info);
-
        return result;
 }
 
@@ -1305,22 +1160,17 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
        struct ib_ucm_context *ctx;
 
        down(&file->mutex);
-
        while (!list_empty(&file->ctxs)) {
 
                ctx = list_entry(file->ctxs.next,
                                 struct ib_ucm_context, file_list);
 
-               up(&ctx->file->mutex);
-               ib_ucm_ctx_put(ctx); /* user reference */
+               up(&file->mutex);
+               ib_ucm_destroy_ctx(file, ctx->id);
                down(&file->mutex);
        }
-
        up(&file->mutex);
-
        kfree(file);
-
-       ucm_dbg("Deleted struct\n");
        return 0;
 }
 
index 6d36606..c8819b9 100644 (file)
 #include <linux/cdev.h>
 #include <linux/idr.h>
 
-#include <ib_cm.h>
-#include <ib_user_cm.h>
+#include <rdma/ib_cm.h>
+#include <rdma/ib_user_cm.h>
 
 #define IB_UCM_CM_ID_INVALID 0xffffffff
 
 struct ib_ucm_file {
        struct semaphore mutex;
        struct file *filp;
-       /*
-        * list of pending events
-        */
+
        struct list_head  ctxs;   /* list of active connections */
        struct list_head  events; /* list of pending events */
        wait_queue_head_t poll_wait;
@@ -58,12 +56,11 @@ struct ib_ucm_file {
 
 struct ib_ucm_context {
        int                 id;
-       int                 ref;
-       int                 error;
+       wait_queue_head_t   wait;
+       atomic_t            ref;
 
        struct ib_ucm_file *file;
        struct ib_cm_id    *cm_id;
-       struct semaphore    mutex;
 
        struct list_head    events;    /* list of pending events. */
        struct list_head    file_list; /* member in file ctx list */
index dc4eb1d..527b234 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -34,7 +35,7 @@
 
 #include <linux/errno.h>
 
-#include <ib_pack.h>
+#include <rdma/ib_pack.h>
 
 #define STRUCT_FIELD(header, field) \
        .struct_offset_bytes = offsetof(struct ib_unpacked_ ## header, field),      \
@@ -194,6 +195,7 @@ void ib_ud_header_init(int                      payload_bytes,
                       struct ib_ud_header *header)
 {
        int header_len;
+       u16 packet_length;
 
        memset(header, 0, sizeof *header);
 
@@ -208,7 +210,7 @@ void ib_ud_header_init(int                      payload_bytes,
        header->lrh.link_version     = 0;
        header->lrh.link_next_header =
                grh_present ? IB_LNH_IBA_GLOBAL : IB_LNH_IBA_LOCAL;
-       header->lrh.packet_length    = (IB_LRH_BYTES     +
+       packet_length                = (IB_LRH_BYTES     +
                                        IB_BTH_BYTES     +
                                        IB_DETH_BYTES    +
                                        payload_bytes    +
@@ -217,8 +219,7 @@ void ib_ud_header_init(int                      payload_bytes,
 
        header->grh_present          = grh_present;
        if (grh_present) {
-               header->lrh.packet_length  += IB_GRH_BYTES / 4;
-
+               packet_length              += IB_GRH_BYTES / 4;
                header->grh.ip_version      = 6;
                header->grh.payload_length  =
                        cpu_to_be16((IB_BTH_BYTES     +
@@ -229,7 +230,7 @@ void ib_ud_header_init(int                      payload_bytes,
                header->grh.next_header     = 0x1b;
        }
 
-       cpu_to_be16s(&header->lrh.packet_length);
+       header->lrh.packet_length = cpu_to_be16(packet_length);
 
        if (header->immediate_present)
                header->bth.opcode           = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
index 2e38792..7c2f030 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc. All rights reserved. 
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -49,8 +49,8 @@
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 
-#include <ib_mad.h>
-#include <ib_user_mad.h>
+#include <rdma/ib_mad.h>
+#include <rdma/ib_user_mad.h>
 
 MODULE_AUTHOR("Roland Dreier");
 MODULE_DESCRIPTION("InfiniBand userspace MAD packet access");
@@ -271,7 +271,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
        struct ib_send_wr *bad_wr;
        struct ib_rmpp_mad *rmpp_mad;
        u8 method;
-       u64 *tid;
+       __be64 *tid;
        int ret, length, hdr_len, data_len, rmpp_hdr_size;
        int rmpp_active = 0;
 
@@ -316,7 +316,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
        if (packet->mad.hdr.grh_present) {
                ah_attr.ah_flags = IB_AH_GRH;
                memcpy(ah_attr.grh.dgid.raw, packet->mad.hdr.gid, 16);
-               ah_attr.grh.flow_label     = packet->mad.hdr.flow_label;
+               ah_attr.grh.flow_label     = be32_to_cpu(packet->mad.hdr.flow_label);
                ah_attr.grh.hop_limit      = packet->mad.hdr.hop_limit;
                ah_attr.grh.traffic_class  = packet->mad.hdr.traffic_class;
        }
index 7696022..180b3d4 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -43,8 +45,8 @@
 #include <linux/kref.h>
 #include <linux/idr.h>
 
-#include <ib_verbs.h>
-#include <ib_user_verbs.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_user_verbs.h>
 
 struct ib_uverbs_device {
        int                                     devnum;
@@ -97,10 +99,12 @@ extern struct idr ib_uverbs_mw_idr;
 extern struct idr ib_uverbs_ah_idr;
 extern struct idr ib_uverbs_cq_idr;
 extern struct idr ib_uverbs_qp_idr;
+extern struct idr ib_uverbs_srq_idr;
 
 void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context);
 void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr);
 void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
+void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
 
 int ib_umem_get(struct ib_device *dev, struct ib_umem *mem,
                void *addr, size_t size, int write);
@@ -129,5 +133,8 @@ IB_UVERBS_DECLARE_CMD(modify_qp);
 IB_UVERBS_DECLARE_CMD(destroy_qp);
 IB_UVERBS_DECLARE_CMD(attach_mcast);
 IB_UVERBS_DECLARE_CMD(detach_mcast);
+IB_UVERBS_DECLARE_CMD(create_srq);
+IB_UVERBS_DECLARE_CMD(modify_srq);
+IB_UVERBS_DECLARE_CMD(destroy_srq);
 
 #endif /* UVERBS_H */
index 5f2bbcd..ebccf9f 100644 (file)
@@ -724,6 +724,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
        struct ib_uobject              *uobj;
        struct ib_pd                   *pd;
        struct ib_cq                   *scq, *rcq;
+       struct ib_srq                  *srq;
        struct ib_qp                   *qp;
        struct ib_qp_init_attr          attr;
        int ret;
@@ -747,10 +748,12 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
        pd  = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
        scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle);
        rcq = idr_find(&ib_uverbs_cq_idr, cmd.recv_cq_handle);
+       srq = cmd.is_srq ? idr_find(&ib_uverbs_srq_idr, cmd.srq_handle) : NULL;
 
        if (!pd  || pd->uobject->context  != file->ucontext ||
            !scq || scq->uobject->context != file->ucontext ||
-           !rcq || rcq->uobject->context != file->ucontext) {
+           !rcq || rcq->uobject->context != file->ucontext ||
+           (cmd.is_srq && (!srq || srq->uobject->context != file->ucontext))) {
                ret = -EINVAL;
                goto err_up;
        }
@@ -759,7 +762,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
        attr.qp_context    = file;
        attr.send_cq       = scq;
        attr.recv_cq       = rcq;
-       attr.srq           = NULL;
+       attr.srq           = srq;
        attr.sq_sig_type   = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
        attr.qp_type       = cmd.qp_type;
 
@@ -1004,3 +1007,178 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
 
        return ret ? ret : in_len;
 }
+
+ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
+                            const char __user *buf, int in_len,
+                            int out_len)
+{
+       struct ib_uverbs_create_srq      cmd;
+       struct ib_uverbs_create_srq_resp resp;
+       struct ib_udata                  udata;
+       struct ib_uobject               *uobj;
+       struct ib_pd                    *pd;
+       struct ib_srq                   *srq;
+       struct ib_srq_init_attr          attr;
+       int ret;
+
+       if (out_len < sizeof resp)
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       INIT_UDATA(&udata, buf + sizeof cmd,
+                  (unsigned long) cmd.response + sizeof resp,
+                  in_len - sizeof cmd, out_len - sizeof resp);
+
+       uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
+       if (!uobj)
+               return -ENOMEM;
+
+       down(&ib_uverbs_idr_mutex);
+
+       pd  = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
+
+       if (!pd || pd->uobject->context != file->ucontext) {
+               ret = -EINVAL;
+               goto err_up;
+       }
+
+       attr.event_handler  = ib_uverbs_srq_event_handler;
+       attr.srq_context    = file;
+       attr.attr.max_wr    = cmd.max_wr;
+       attr.attr.max_sge   = cmd.max_sge;
+       attr.attr.srq_limit = cmd.srq_limit;
+
+       uobj->user_handle = cmd.user_handle;
+       uobj->context     = file->ucontext;
+
+       srq = pd->device->create_srq(pd, &attr, &udata);
+       if (IS_ERR(srq)) {
+               ret = PTR_ERR(srq);
+               goto err_up;
+       }
+
+       srq->device        = pd->device;
+       srq->pd            = pd;
+       srq->uobject       = uobj;
+       srq->event_handler = attr.event_handler;
+       srq->srq_context   = attr.srq_context;
+       atomic_inc(&pd->usecnt);
+       atomic_set(&srq->usecnt, 0);
+
+       memset(&resp, 0, sizeof resp);
+
+retry:
+       if (!idr_pre_get(&ib_uverbs_srq_idr, GFP_KERNEL)) {
+               ret = -ENOMEM;
+               goto err_destroy;
+       }
+
+       ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->id);
+
+       if (ret == -EAGAIN)
+               goto retry;
+       if (ret)
+               goto err_destroy;
+
+       resp.srq_handle = uobj->id;
+
+       spin_lock_irq(&file->ucontext->lock);
+       list_add_tail(&uobj->list, &file->ucontext->srq_list);
+       spin_unlock_irq(&file->ucontext->lock);
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp)) {
+               ret = -EFAULT;
+               goto err_list;
+       }
+
+       up(&ib_uverbs_idr_mutex);
+
+       return in_len;
+
+err_list:
+       spin_lock_irq(&file->ucontext->lock);
+       list_del(&uobj->list);
+       spin_unlock_irq(&file->ucontext->lock);
+
+err_destroy:
+       ib_destroy_srq(srq);
+
+err_up:
+       up(&ib_uverbs_idr_mutex);
+
+       kfree(uobj);
+       return ret;
+}
+
+ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
+                            const char __user *buf, int in_len,
+                            int out_len)
+{
+       struct ib_uverbs_modify_srq cmd;
+       struct ib_srq              *srq;
+       struct ib_srq_attr          attr;
+       int                         ret;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       down(&ib_uverbs_idr_mutex);
+
+       srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
+       if (!srq || srq->uobject->context != file->ucontext) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       attr.max_wr    = cmd.max_wr;
+       attr.max_sge   = cmd.max_sge;
+       attr.srq_limit = cmd.srq_limit;
+
+       ret = ib_modify_srq(srq, &attr, cmd.attr_mask);
+
+out:
+       up(&ib_uverbs_idr_mutex);
+
+       return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
+                             const char __user *buf, int in_len,
+                             int out_len)
+{
+       struct ib_uverbs_destroy_srq cmd;
+       struct ib_srq               *srq;
+       struct ib_uobject           *uobj;
+       int                          ret = -EINVAL;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       down(&ib_uverbs_idr_mutex);
+
+       srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
+       if (!srq || srq->uobject->context != file->ucontext)
+               goto out;
+
+       uobj = srq->uobject;
+
+       ret = ib_destroy_srq(srq);
+       if (ret)
+               goto out;
+
+       idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
+
+       spin_lock_irq(&file->ucontext->lock);
+       list_del(&uobj->list);
+       spin_unlock_irq(&file->ucontext->lock);
+
+       kfree(uobj);
+
+out:
+       up(&ib_uverbs_idr_mutex);
+
+       return ret ? ret : in_len;
+}
index eb99e69..09caf5b 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -67,6 +69,7 @@ DEFINE_IDR(ib_uverbs_mw_idr);
 DEFINE_IDR(ib_uverbs_ah_idr);
 DEFINE_IDR(ib_uverbs_cq_idr);
 DEFINE_IDR(ib_uverbs_qp_idr);
+DEFINE_IDR(ib_uverbs_srq_idr);
 
 static spinlock_t map_lock;
 static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -91,6 +94,9 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
        [IB_USER_VERBS_CMD_DESTROY_QP]    = ib_uverbs_destroy_qp,
        [IB_USER_VERBS_CMD_ATTACH_MCAST]  = ib_uverbs_attach_mcast,
        [IB_USER_VERBS_CMD_DETACH_MCAST]  = ib_uverbs_detach_mcast,
+       [IB_USER_VERBS_CMD_CREATE_SRQ]    = ib_uverbs_create_srq,
+       [IB_USER_VERBS_CMD_MODIFY_SRQ]    = ib_uverbs_modify_srq,
+       [IB_USER_VERBS_CMD_DESTROY_SRQ]   = ib_uverbs_destroy_srq,
 };
 
 static struct vfsmount *uverbs_event_mnt;
@@ -125,18 +131,26 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
                kfree(uobj);
        }
 
-       /* XXX Free SRQs */
+       list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
+               struct ib_srq *srq = idr_find(&ib_uverbs_srq_idr, uobj->id);
+               idr_remove(&ib_uverbs_srq_idr, uobj->id);
+               ib_destroy_srq(srq);
+               list_del(&uobj->list);
+               kfree(uobj);
+       }
+
        /* XXX Free MWs */
 
        list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) {
                struct ib_mr *mr = idr_find(&ib_uverbs_mr_idr, uobj->id);
+               struct ib_device *mrdev = mr->device;
                struct ib_umem_object *memobj;
 
                idr_remove(&ib_uverbs_mr_idr, uobj->id);
                ib_dereg_mr(mr);
 
                memobj = container_of(uobj, struct ib_umem_object, uobject);
-               ib_umem_release_on_close(mr->device, &memobj->umem);
+               ib_umem_release_on_close(mrdev, &memobj->umem);
 
                list_del(&uobj->list);
                kfree(memobj);
@@ -343,6 +357,13 @@ void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr)
                                event->event);
 }
 
+void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr)
+{
+       ib_uverbs_async_handler(context_ptr,
+                               event->element.srq->uobject->user_handle,
+                               event->event);
+}
+
 static void ib_uverbs_event_handler(struct ib_event_handler *handler,
                                    struct ib_event *event)
 {
index ed550f6..36a32c3 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 506fdf1..5081d90 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (c) 2004 Intel Corporation.  All rights reserved.
  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
  * Copyright (c) 2004 Voltaire Corporation.  All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -40,8 +41,8 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 
-#include <ib_verbs.h>
-#include <ib_cache.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_cache.h>
 
 /* Protection domains */
 
@@ -153,6 +154,66 @@ int ib_destroy_ah(struct ib_ah *ah)
 }
 EXPORT_SYMBOL(ib_destroy_ah);
 
+/* Shared receive queues */
+
+struct ib_srq *ib_create_srq(struct ib_pd *pd,
+                            struct ib_srq_init_attr *srq_init_attr)
+{
+       struct ib_srq *srq;
+
+       if (!pd->device->create_srq)
+               return ERR_PTR(-ENOSYS);
+
+       srq = pd->device->create_srq(pd, srq_init_attr, NULL);
+
+       if (!IS_ERR(srq)) {
+               srq->device        = pd->device;
+               srq->pd            = pd;
+               srq->uobject       = NULL;
+               srq->event_handler = srq_init_attr->event_handler;
+               srq->srq_context   = srq_init_attr->srq_context;
+               atomic_inc(&pd->usecnt);
+               atomic_set(&srq->usecnt, 0);
+       }
+
+       return srq;
+}
+EXPORT_SYMBOL(ib_create_srq);
+
+int ib_modify_srq(struct ib_srq *srq,
+                 struct ib_srq_attr *srq_attr,
+                 enum ib_srq_attr_mask srq_attr_mask)
+{
+       return srq->device->modify_srq(srq, srq_attr, srq_attr_mask);
+}
+EXPORT_SYMBOL(ib_modify_srq);
+
+int ib_query_srq(struct ib_srq *srq,
+                struct ib_srq_attr *srq_attr)
+{
+       return srq->device->query_srq ?
+               srq->device->query_srq(srq, srq_attr) : -ENOSYS;
+}
+EXPORT_SYMBOL(ib_query_srq);
+
+int ib_destroy_srq(struct ib_srq *srq)
+{
+       struct ib_pd *pd;
+       int ret;
+
+       if (atomic_read(&srq->usecnt))
+               return -EBUSY;
+
+       pd = srq->pd;
+
+       ret = srq->device->destroy_srq(srq);
+       if (!ret)
+               atomic_dec(&pd->usecnt);
+
+       return ret;
+}
+EXPORT_SYMBOL(ib_destroy_srq);
+
 /* Queue pairs */
 
 struct ib_qp *ib_create_qp(struct ib_pd *pd,
index 5dcbd43..c44f7ba 100644 (file)
@@ -1,5 +1,3 @@
-EXTRA_CFLAGS += -Idrivers/infiniband/include
-
 ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
 EXTRA_CFLAGS += -DDEBUG
 endif
@@ -9,4 +7,4 @@ obj-$(CONFIG_INFINIBAND_MTHCA) += ib_mthca.o
 ib_mthca-y :=  mthca_main.o mthca_cmd.o mthca_profile.o mthca_reset.o \
                mthca_allocator.o mthca_eq.o mthca_pd.o mthca_cq.o \
                mthca_mr.o mthca_qp.o mthca_av.o mthca_mcg.o mthca_mad.o \
-               mthca_provider.o mthca_memfree.o mthca_uar.o
+               mthca_provider.o mthca_memfree.o mthca_uar.o mthca_srq.o
index b1db48d..9ba3211 100644 (file)
@@ -177,3 +177,119 @@ void mthca_array_cleanup(struct mthca_array *array, int nent)
 
        kfree(array->page_list);
 }
+
+/*
+ * Handling for queue buffers -- we allocate a bunch of memory and
+ * register it in a memory region at HCA virtual address 0.  If the
+ * requested size is > max_direct, we split the allocation into
+ * multiple pages, so we don't require too much contiguous memory.
+ */
+
+int mthca_buf_alloc(struct mthca_dev *dev, int size, int max_direct,
+                   union mthca_buf *buf, int *is_direct, struct mthca_pd *pd,
+                   int hca_write, struct mthca_mr *mr)
+{
+       int err = -ENOMEM;
+       int npages, shift;
+       u64 *dma_list = NULL;
+       dma_addr_t t;
+       int i;
+
+       if (size <= max_direct) {
+               *is_direct = 1;
+               npages     = 1;
+               shift      = get_order(size) + PAGE_SHIFT;
+
+               buf->direct.buf = dma_alloc_coherent(&dev->pdev->dev,
+                                                    size, &t, GFP_KERNEL);
+               if (!buf->direct.buf)
+                       return -ENOMEM;
+
+               pci_unmap_addr_set(&buf->direct, mapping, t);
+
+               memset(buf->direct.buf, 0, size);
+
+               while (t & ((1 << shift) - 1)) {
+                       --shift;
+                       npages *= 2;
+               }
+
+               dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
+               if (!dma_list)
+                       goto err_free;
+
+               for (i = 0; i < npages; ++i)
+                       dma_list[i] = t + i * (1 << shift);
+       } else {
+               *is_direct = 0;
+               npages     = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+               shift      = PAGE_SHIFT;
+
+               dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
+               if (!dma_list)
+                       return -ENOMEM;
+
+               buf->page_list = kmalloc(npages * sizeof *buf->page_list,
+                                        GFP_KERNEL);
+               if (!buf->page_list)
+                       goto err_out;
+
+               for (i = 0; i < npages; ++i)
+                       buf->page_list[i].buf = NULL;
+
+               for (i = 0; i < npages; ++i) {
+                       buf->page_list[i].buf =
+                               dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE,
+                                                  &t, GFP_KERNEL);
+                       if (!buf->page_list[i].buf)
+                               goto err_free;
+
+                       dma_list[i] = t;
+                       pci_unmap_addr_set(&buf->page_list[i], mapping, t);
+
+                       memset(buf->page_list[i].buf, 0, PAGE_SIZE);
+               }
+       }
+
+       err = mthca_mr_alloc_phys(dev, pd->pd_num,
+                                 dma_list, shift, npages,
+                                 0, size,
+                                 MTHCA_MPT_FLAG_LOCAL_READ |
+                                 (hca_write ? MTHCA_MPT_FLAG_LOCAL_WRITE : 0),
+                                 mr);
+       if (err)
+               goto err_free;
+
+       kfree(dma_list);
+
+       return 0;
+
+err_free:
+       mthca_buf_free(dev, size, buf, *is_direct, NULL);
+
+err_out:
+       kfree(dma_list);
+
+       return err;
+}
+
+void mthca_buf_free(struct mthca_dev *dev, int size, union mthca_buf *buf,
+                   int is_direct, struct mthca_mr *mr)
+{
+       int i;
+
+       if (mr)
+               mthca_free_mr(dev, mr);
+
+       if (is_direct)
+               dma_free_coherent(&dev->pdev->dev, size, buf->direct.buf,
+                                 pci_unmap_addr(&buf->direct, mapping));
+       else {
+               for (i = 0; i < (size + PAGE_SIZE - 1) / PAGE_SIZE; ++i)
+                       dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
+                                         buf->page_list[i].buf,
+                                         pci_unmap_addr(&buf->page_list[i],
+                                                        mapping));
+               kfree(buf->page_list);
+       }
+}
index d58dcbe..889e850 100644 (file)
 
 #include <linux/init.h>
 
-#include <ib_verbs.h>
-#include <ib_cache.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_cache.h>
 
 #include "mthca_dev.h"
 
 struct mthca_av {
-       u32 port_pd;
-       u8  reserved1;
-       u8  g_slid;
-       u16 dlid;
-       u8  reserved2;
-       u8  gid_index;
-       u8  msg_sr;
-       u8  hop_limit;
-       u32 sl_tclass_flowlabel;
-       u32 dgid[4];
+       __be32 port_pd;
+       u8     reserved1;
+       u8     g_slid;
+       __be16 dlid;
+       u8     reserved2;
+       u8     gid_index;
+       u8     msg_sr;
+       u8     hop_limit;
+       __be32 sl_tclass_flowlabel;
+       __be32 dgid[4];
 };
 
 int mthca_create_ah(struct mthca_dev *dev,
@@ -128,7 +128,7 @@ on_hca_fail:
                          av, (unsigned long) ah->avdma);
                for (j = 0; j < 8; ++j)
                        printk(KERN_DEBUG "  [%2x] %08x\n",
-                              j * 4, be32_to_cpu(((u32 *) av)[j]));
+                              j * 4, be32_to_cpu(((__be32 *) av)[j]));
        }
 
        if (ah->type == MTHCA_AH_ON_HCA) {
@@ -169,7 +169,7 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
 
        header->lrh.service_level   = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28;
        header->lrh.destination_lid = ah->av->dlid;
-       header->lrh.source_lid      = ah->av->g_slid & 0x7f;
+       header->lrh.source_lid      = cpu_to_be16(ah->av->g_slid & 0x7f);
        if (ah->av->g_slid & 0x80) {
                header->grh_present = 1;
                header->grh.traffic_class =
index 1557a52..cc758a2 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -36,7 +37,7 @@
 #include <linux/pci.h>
 #include <linux/errno.h>
 #include <asm/io.h>
-#include <ib_mad.h>
+#include <rdma/ib_mad.h>
 
 #include "mthca_dev.h"
 #include "mthca_config_reg.h"
@@ -108,6 +109,7 @@ enum {
        CMD_SW2HW_SRQ       = 0x35,
        CMD_HW2SW_SRQ       = 0x36,
        CMD_QUERY_SRQ       = 0x37,
+       CMD_ARM_SRQ         = 0x40,
 
        /* QP/EE commands */
        CMD_RST2INIT_QPEE   = 0x19,
@@ -219,20 +221,20 @@ static int mthca_cmd_post(struct mthca_dev *dev,
         * (and some architectures such as ia64 implement memcpy_toio
         * in terms of writeb).
         */
-       __raw_writel(cpu_to_be32(in_param >> 32),           dev->hcr + 0 * 4);
-       __raw_writel(cpu_to_be32(in_param & 0xfffffffful),  dev->hcr + 1 * 4);
-       __raw_writel(cpu_to_be32(in_modifier),              dev->hcr + 2 * 4);
-       __raw_writel(cpu_to_be32(out_param >> 32),          dev->hcr + 3 * 4);
-       __raw_writel(cpu_to_be32(out_param & 0xfffffffful), dev->hcr + 4 * 4);
-       __raw_writel(cpu_to_be32(token << 16),              dev->hcr + 5 * 4);
+       __raw_writel((__force u32) cpu_to_be32(in_param >> 32),           dev->hcr + 0 * 4);
+       __raw_writel((__force u32) cpu_to_be32(in_param & 0xfffffffful),  dev->hcr + 1 * 4);
+       __raw_writel((__force u32) cpu_to_be32(in_modifier),              dev->hcr + 2 * 4);
+       __raw_writel((__force u32) cpu_to_be32(out_param >> 32),          dev->hcr + 3 * 4);
+       __raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful), dev->hcr + 4 * 4);
+       __raw_writel((__force u32) cpu_to_be32(token << 16),              dev->hcr + 5 * 4);
 
        /* __raw_writel may not order writes. */
        wmb();
 
-       __raw_writel(cpu_to_be32((1 << HCR_GO_BIT)                |
-                                (event ? (1 << HCA_E_BIT) : 0)   |
-                                (op_modifier << HCR_OPMOD_SHIFT) |
-                                op),                       dev->hcr + 6 * 4);
+       __raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT)                |
+                                              (event ? (1 << HCA_E_BIT) : 0)   |
+                                              (op_modifier << HCR_OPMOD_SHIFT) |
+                                              op),                       dev->hcr + 6 * 4);
 
 out:
        up(&dev->cmd.hcr_sem);
@@ -273,12 +275,14 @@ static int mthca_cmd_poll(struct mthca_dev *dev,
                goto out;
        }
 
-       if (out_is_imm) {
-               memcpy_fromio(out_param, dev->hcr + HCR_OUT_PARAM_OFFSET, sizeof (u64));
-               be64_to_cpus(out_param);
-       }
+       if (out_is_imm)
+               *out_param = 
+                       (u64) be32_to_cpu((__force __be32)
+                                         __raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET)) << 32 |
+                       (u64) be32_to_cpu((__force __be32)
+                                         __raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET + 4));
 
-       *status = be32_to_cpu(__raw_readl(dev->hcr + HCR_STATUS_OFFSET)) >> 24;
+       *status = be32_to_cpu((__force __be32) __raw_readl(dev->hcr + HCR_STATUS_OFFSET)) >> 24;
 
 out:
        up(&dev->cmd.poll_sem);
@@ -1029,6 +1033,8 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
 
        mthca_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n",
                  dev_lim->max_qps, dev_lim->reserved_qps, dev_lim->qpc_entry_sz);
+       mthca_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n",
+                 dev_lim->max_srqs, dev_lim->reserved_srqs, dev_lim->srq_entry_sz);
        mthca_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n",
                  dev_lim->max_cqs, dev_lim->reserved_cqs, dev_lim->cqc_entry_sz);
        mthca_dbg(dev, "Max EQs: %d, reserved EQs: %d, entry size: %d\n",
@@ -1082,6 +1088,34 @@ out:
        return err;
 }
 
+static void get_board_id(void *vsd, char *board_id)
+{
+       int i;
+
+#define VSD_OFFSET_SIG1                0x00
+#define VSD_OFFSET_SIG2                0xde
+#define VSD_OFFSET_MLX_BOARD_ID        0xd0
+#define VSD_OFFSET_TS_BOARD_ID 0x20
+
+#define VSD_SIGNATURE_TOPSPIN  0x5ad
+
+       memset(board_id, 0, MTHCA_BOARD_ID_LEN);
+
+       if (be16_to_cpup(vsd + VSD_OFFSET_SIG1) == VSD_SIGNATURE_TOPSPIN &&
+           be16_to_cpup(vsd + VSD_OFFSET_SIG2) == VSD_SIGNATURE_TOPSPIN) {
+               strlcpy(board_id, vsd + VSD_OFFSET_TS_BOARD_ID, MTHCA_BOARD_ID_LEN);
+       } else {
+               /*
+                * The board ID is a string but the firmware byte
+                * swaps each 4-byte word before passing it back to
+                * us.  Therefore we need to swab it before printing.
+                */
+               for (i = 0; i < 4; ++i)
+                       ((u32 *) board_id)[i] =
+                               swab32(*(u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4));
+       }
+}
+
 int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
                        struct mthca_adapter *adapter, u8 *status)
 {
@@ -1094,6 +1128,7 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
 #define QUERY_ADAPTER_DEVICE_ID_OFFSET     0x04
 #define QUERY_ADAPTER_REVISION_ID_OFFSET   0x08
 #define QUERY_ADAPTER_INTA_PIN_OFFSET      0x10
+#define QUERY_ADAPTER_VSD_OFFSET           0x20
 
        mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
        if (IS_ERR(mailbox))
@@ -1111,6 +1146,9 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
        MTHCA_GET(adapter->revision_id, outbox, QUERY_ADAPTER_REVISION_ID_OFFSET);
        MTHCA_GET(adapter->inta_pin, outbox,    QUERY_ADAPTER_INTA_PIN_OFFSET);
 
+       get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4,
+                    adapter->board_id);
+
 out:
        mthca_free_mailbox(dev, mailbox);
        return err;
@@ -1121,7 +1159,7 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
                   u8 *status)
 {
        struct mthca_mailbox *mailbox;
-       u32 *inbox;
+       __be32 *inbox;
        int err;
 
 #define INIT_HCA_IN_SIZE                0x200
@@ -1247,10 +1285,8 @@ int mthca_INIT_IB(struct mthca_dev *dev,
 #define INIT_IB_FLAG_SIG         (1 << 18)
 #define INIT_IB_FLAG_NG          (1 << 17)
 #define INIT_IB_FLAG_G0          (1 << 16)
-#define INIT_IB_FLAG_1X          (1 << 8)
-#define INIT_IB_FLAG_4X          (1 << 9)
-#define INIT_IB_FLAG_12X         (1 << 11)
 #define INIT_IB_VL_SHIFT         4
+#define INIT_IB_PORT_WIDTH_SHIFT 8
 #define INIT_IB_MTU_SHIFT        12
 #define INIT_IB_MAX_GID_OFFSET   0x06
 #define INIT_IB_MAX_PKEY_OFFSET  0x0a
@@ -1266,12 +1302,11 @@ int mthca_INIT_IB(struct mthca_dev *dev,
        memset(inbox, 0, INIT_IB_IN_SIZE);
 
        flags = 0;
-       flags |= param->enable_1x     ? INIT_IB_FLAG_1X  : 0;
-       flags |= param->enable_4x     ? INIT_IB_FLAG_4X  : 0;
        flags |= param->set_guid0     ? INIT_IB_FLAG_G0  : 0;
        flags |= param->set_node_guid ? INIT_IB_FLAG_NG  : 0;
        flags |= param->set_si_guid   ? INIT_IB_FLAG_SIG : 0;
        flags |= param->vl_cap << INIT_IB_VL_SHIFT;
+       flags |= param->port_width << INIT_IB_PORT_WIDTH_SHIFT;
        flags |= param->mtu_cap << INIT_IB_MTU_SHIFT;
        MTHCA_PUT(inbox, flags, INIT_IB_FLAGS_OFFSET);
 
@@ -1342,7 +1377,7 @@ int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt, u8 *st
 int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status)
 {
        struct mthca_mailbox *mailbox;
-       u64 *inbox;
+       __be64 *inbox;
        int err;
 
        mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
@@ -1468,6 +1503,27 @@ int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
                             CMD_TIME_CLASS_A, status);
 }
 
+int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+                   int srq_num, u8 *status)
+{
+       return mthca_cmd(dev, mailbox->dma, srq_num, 0, CMD_SW2HW_SRQ,
+                       CMD_TIME_CLASS_A, status);
+}
+
+int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+                   int srq_num, u8 *status)
+{
+       return mthca_cmd_box(dev, 0, mailbox->dma, srq_num, 0,
+                            CMD_HW2SW_SRQ,
+                            CMD_TIME_CLASS_A, status);
+}
+
+int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status)
+{
+       return mthca_cmd(dev, limit, srq_num, 0, CMD_ARM_SRQ,
+                        CMD_TIME_CLASS_B, status);
+}
+
 int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
                    int is_ee, struct mthca_mailbox *mailbox, u32 optmask,
                    u8 *status)
@@ -1513,7 +1569,7 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
                                if (i % 8 == 0)
                                        printk("  [%02x] ", i * 4);
                                printk(" %08x",
-                                      be32_to_cpu(((u32 *) mailbox->buf)[i + 2]));
+                                      be32_to_cpu(((__be32 *) mailbox->buf)[i + 2]));
                                if ((i + 1) % 8 == 0)
                                        printk("\n");
                        }
@@ -1533,7 +1589,7 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
                                if (i % 8 == 0)
                                        printk("[%02x] ", i * 4);
                                printk(" %08x",
-                                      be32_to_cpu(((u32 *) mailbox->buf)[i + 2]));
+                                      be32_to_cpu(((__be32 *) mailbox->buf)[i + 2]));
                                if ((i + 1) % 8 == 0)
                                        printk("\n");
                        }
index ed517f1..65f976a 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -35,7 +36,7 @@
 #ifndef MTHCA_CMD_H
 #define MTHCA_CMD_H
 
-#include <ib_verbs.h>
+#include <rdma/ib_verbs.h>
 
 #define MTHCA_MAILBOX_SIZE 4096
 
@@ -183,10 +184,11 @@ struct mthca_dev_lim {
 };
 
 struct mthca_adapter {
-       u32 vendor_id;
-       u32 device_id;
-       u32 revision_id;
-       u8  inta_pin;
+       u32  vendor_id;
+       u32  device_id;
+       u32  revision_id;
+       char board_id[MTHCA_BOARD_ID_LEN];
+       u8   inta_pin;
 };
 
 struct mthca_init_hca_param {
@@ -218,8 +220,7 @@ struct mthca_init_hca_param {
 };
 
 struct mthca_init_ib_param {
-       int enable_1x;
-       int enable_4x;
+       int port_width;
        int vl_cap;
        int mtu_cap;
        u16 gid_cap;
@@ -297,6 +298,11 @@ int mthca_SW2HW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
                   int cq_num, u8 *status);
 int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
                   int cq_num, u8 *status);
+int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+                   int srq_num, u8 *status);
+int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+                   int srq_num, u8 *status);
+int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status);
 int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
                    int is_ee, struct mthca_mailbox *mailbox, u32 optmask,
                    u8 *status);
index b4bfbbf..afa56bf 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 5687c30..8600b6c 100644 (file)
@@ -2,6 +2,8 @@
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  * Copyright (c) 2005 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004 Voltaire, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -37,7 +39,7 @@
 #include <linux/init.h>
 #include <linux/hardirq.h>
 
-#include <ib_pack.h>
+#include <rdma/ib_pack.h>
 
 #include "mthca_dev.h"
 #include "mthca_cmd.h"
@@ -55,21 +57,21 @@ enum {
  * Must be packed because start is 64 bits but only aligned to 32 bits.
  */
 struct mthca_cq_context {
-       u32 flags;
-       u64 start;
-       u32 logsize_usrpage;
-       u32 error_eqn;          /* Tavor only */
-       u32 comp_eqn;
-       u32 pd;
-       u32 lkey;
-       u32 last_notified_index;
-       u32 solicit_producer_index;
-       u32 consumer_index;
-       u32 producer_index;
-       u32 cqn;
-       u32 ci_db;              /* Arbel only */
-       u32 state_db;           /* Arbel only */
-       u32 reserved;
+       __be32 flags;
+       __be64 start;
+       __be32 logsize_usrpage;
+       __be32 error_eqn;       /* Tavor only */
+       __be32 comp_eqn;
+       __be32 pd;
+       __be32 lkey;
+       __be32 last_notified_index;
+       __be32 solicit_producer_index;
+       __be32 consumer_index;
+       __be32 producer_index;
+       __be32 cqn;
+       __be32 ci_db;           /* Arbel only */
+       __be32 state_db;        /* Arbel only */
+       u32    reserved;
 } __attribute__((packed));
 
 #define MTHCA_CQ_STATUS_OK          ( 0 << 28)
@@ -108,31 +110,31 @@ enum {
 };
 
 struct mthca_cqe {
-       u32 my_qpn;
-       u32 my_ee;
-       u32 rqpn;
-       u16 sl_g_mlpath;
-       u16 rlid;
-       u32 imm_etype_pkey_eec;
-       u32 byte_cnt;
-       u32 wqe;
-       u8  opcode;
-       u8  is_send;
-       u8  reserved;
-       u8  owner;
+       __be32 my_qpn;
+       __be32 my_ee;
+       __be32 rqpn;
+       __be16 sl_g_mlpath;
+       __be16 rlid;
+       __be32 imm_etype_pkey_eec;
+       __be32 byte_cnt;
+       __be32 wqe;
+       u8     opcode;
+       u8     is_send;
+       u8     reserved;
+       u8     owner;
 };
 
 struct mthca_err_cqe {
-       u32 my_qpn;
-       u32 reserved1[3];
-       u8  syndrome;
-       u8  reserved2;
-       u16 db_cnt;
-       u32 reserved3;
-       u32 wqe;
-       u8  opcode;
-       u8  reserved4[2];
-       u8  owner;
+       __be32 my_qpn;
+       u32    reserved1[3];
+       u8     syndrome;
+       u8     reserved2;
+       __be16 db_cnt;
+       u32    reserved3;
+       __be32 wqe;
+       u8     opcode;
+       u8     reserved4[2];
+       u8     owner;
 };
 
 #define MTHCA_CQ_ENTRY_OWNER_SW      (0 << 7)
@@ -191,7 +193,7 @@ static void dump_cqe(struct mthca_dev *dev, void *cqe_ptr)
 static inline void update_cons_index(struct mthca_dev *dev, struct mthca_cq *cq,
                                     int incr)
 {
-       u32 doorbell[2];
+       __be32 doorbell[2];
 
        if (mthca_is_memfree(dev)) {
                *cq->set_ci_db = cpu_to_be32(cq->cons_index);
@@ -222,7 +224,8 @@ void mthca_cq_event(struct mthca_dev *dev, u32 cqn)
        cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
 }
 
-void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn)
+void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
+                   struct mthca_srq *srq)
 {
        struct mthca_cq *cq;
        struct mthca_cqe *cqe;
@@ -263,8 +266,11 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn)
         */
        while (prod_index > cq->cons_index) {
                cqe = get_cqe(cq, (prod_index - 1) & cq->ibcq.cqe);
-               if (cqe->my_qpn == cpu_to_be32(qpn))
+               if (cqe->my_qpn == cpu_to_be32(qpn)) {
+                       if (srq)
+                               mthca_free_srq_wqe(srq, be32_to_cpu(cqe->wqe));
                        ++nfreed;
+               }
                else if (nfreed)
                        memcpy(get_cqe(cq, (prod_index - 1 + nfreed) &
                                       cq->ibcq.cqe),
@@ -291,7 +297,7 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
 {
        int err;
        int dbd;
-       u32 new_wqe;
+       __be32 new_wqe;
 
        if (cqe->syndrome == SYNDROME_LOCAL_QP_OP_ERR) {
                mthca_dbg(dev, "local QP operation err "
@@ -365,6 +371,13 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
                break;
        }
 
+       /*
+        * Mem-free HCAs always generate one CQE per WQE, even in the
+        * error case, so we don't have to check the doorbell count, etc.
+        */
+       if (mthca_is_memfree(dev))
+               return 0;
+
        err = mthca_free_err_wqe(dev, qp, is_send, wqe_index, &dbd, &new_wqe);
        if (err)
                return err;
@@ -373,12 +386,8 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
         * If we're at the end of the WQE chain, or we've used up our
         * doorbell count, free the CQE.  Otherwise just update it for
         * the next poll operation.
-        *
-        * This does not apply to mem-free HCAs: they don't use the
-        * doorbell count field, and so we should always free the CQE.
         */
-       if (mthca_is_memfree(dev) ||
-           !(new_wqe & cpu_to_be32(0x3f)) || (!cqe->db_cnt && dbd))
+       if (!(new_wqe & cpu_to_be32(0x3f)) || (!cqe->db_cnt && dbd))
                return 0;
 
        cqe->db_cnt   = cpu_to_be16(be16_to_cpu(cqe->db_cnt) - dbd);
@@ -450,23 +459,27 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
                             >> wq->wqe_shift);
                entry->wr_id = (*cur_qp)->wrid[wqe_index +
                                               (*cur_qp)->rq.max];
+       } else if ((*cur_qp)->ibqp.srq) {
+               struct mthca_srq *srq = to_msrq((*cur_qp)->ibqp.srq);
+               u32 wqe = be32_to_cpu(cqe->wqe);
+               wq = NULL;
+               wqe_index = wqe >> srq->wqe_shift;
+               entry->wr_id = srq->wrid[wqe_index];
+               mthca_free_srq_wqe(srq, wqe);
        } else {
                wq = &(*cur_qp)->rq;
                wqe_index = be32_to_cpu(cqe->wqe) >> wq->wqe_shift;
                entry->wr_id = (*cur_qp)->wrid[wqe_index];
        }
 
-       if (wq->last_comp < wqe_index)
-               wq->tail += wqe_index - wq->last_comp;
-       else
-               wq->tail += wqe_index + wq->max - wq->last_comp;
-
-       wq->last_comp = wqe_index;
+       if (wq) {
+               if (wq->last_comp < wqe_index)
+                       wq->tail += wqe_index - wq->last_comp;
+               else
+                       wq->tail += wqe_index + wq->max - wq->last_comp;
 
-       if (0)
-               mthca_dbg(dev, "%s completion for QP %06x, index %d (nr %d)\n",
-                         is_send ? "Send" : "Receive",
-                         (*cur_qp)->qpn, wqe_index, wq->max);
+               wq->last_comp = wqe_index;
+       }
 
        if (is_error) {
                err = handle_error_cqe(dev, cq, *cur_qp, wqe_index, is_send,
@@ -584,13 +597,13 @@ int mthca_poll_cq(struct ib_cq *ibcq, int num_entries,
 
 int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify)
 {
-       u32 doorbell[2];
+       __be32 doorbell[2];
 
        doorbell[0] = cpu_to_be32((notify == IB_CQ_SOLICITED ?
                                   MTHCA_TAVOR_CQ_DB_REQ_NOT_SOL :
                                   MTHCA_TAVOR_CQ_DB_REQ_NOT)      |
                                  to_mcq(cq)->cqn);
-       doorbell[1] = 0xffffffff;
+       doorbell[1] = (__force __be32) 0xffffffff;
 
        mthca_write64(doorbell,
                      to_mdev(cq->device)->kar + MTHCA_CQ_DOORBELL,
@@ -602,9 +615,9 @@ int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify)
 int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
 {
        struct mthca_cq *cq = to_mcq(ibcq);
-       u32 doorbell[2];
+       __be32 doorbell[2];
        u32 sn;
-       u32 ci;
+       __be32 ci;
 
        sn = cq->arm_sn & 3;
        ci = cpu_to_be32(cq->cons_index);
@@ -637,113 +650,8 @@ int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
 
 static void mthca_free_cq_buf(struct mthca_dev *dev, struct mthca_cq *cq)
 {
-       int i;
-       int size;
-
-       if (cq->is_direct)
-               dma_free_coherent(&dev->pdev->dev,
-                                 (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE,
-                                 cq->queue.direct.buf,
-                                 pci_unmap_addr(&cq->queue.direct,
-                                                mapping));
-       else {
-               size = (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE;
-               for (i = 0; i < (size + PAGE_SIZE - 1) / PAGE_SIZE; ++i)
-                       if (cq->queue.page_list[i].buf)
-                               dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
-                                                 cq->queue.page_list[i].buf,
-                                                 pci_unmap_addr(&cq->queue.page_list[i],
-                                                                mapping));
-
-               kfree(cq->queue.page_list);
-       }
-}
-
-static int mthca_alloc_cq_buf(struct mthca_dev *dev, int size,
-                             struct mthca_cq *cq)
-{
-       int err = -ENOMEM;
-       int npages, shift;
-       u64 *dma_list = NULL;
-       dma_addr_t t;
-       int i;
-
-       if (size <= MTHCA_MAX_DIRECT_CQ_SIZE) {
-               cq->is_direct = 1;
-               npages        = 1;
-               shift         = get_order(size) + PAGE_SHIFT;
-
-               cq->queue.direct.buf = dma_alloc_coherent(&dev->pdev->dev,
-                                                         size, &t, GFP_KERNEL);
-               if (!cq->queue.direct.buf)
-                       return -ENOMEM;
-
-               pci_unmap_addr_set(&cq->queue.direct, mapping, t);
-
-               memset(cq->queue.direct.buf, 0, size);
-
-               while (t & ((1 << shift) - 1)) {
-                       --shift;
-                       npages *= 2;
-               }
-
-               dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
-               if (!dma_list)
-                       goto err_free;
-
-               for (i = 0; i < npages; ++i)
-                       dma_list[i] = t + i * (1 << shift);
-       } else {
-               cq->is_direct = 0;
-               npages        = (size + PAGE_SIZE - 1) / PAGE_SIZE;
-               shift         = PAGE_SHIFT;
-
-               dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
-               if (!dma_list)
-                       return -ENOMEM;
-
-               cq->queue.page_list = kmalloc(npages * sizeof *cq->queue.page_list,
-                                             GFP_KERNEL);
-               if (!cq->queue.page_list)
-                       goto err_out;
-
-               for (i = 0; i < npages; ++i)
-                       cq->queue.page_list[i].buf = NULL;
-
-               for (i = 0; i < npages; ++i) {
-                       cq->queue.page_list[i].buf =
-                               dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE,
-                                                  &t, GFP_KERNEL);
-                       if (!cq->queue.page_list[i].buf)
-                               goto err_free;
-
-                       dma_list[i] = t;
-                       pci_unmap_addr_set(&cq->queue.page_list[i], mapping, t);
-
-                       memset(cq->queue.page_list[i].buf, 0, PAGE_SIZE);
-               }
-       }
-
-       err = mthca_mr_alloc_phys(dev, dev->driver_pd.pd_num,
-                                 dma_list, shift, npages,
-                                 0, size,
-                                 MTHCA_MPT_FLAG_LOCAL_WRITE |
-                                 MTHCA_MPT_FLAG_LOCAL_READ,
-                                 &cq->mr);
-       if (err)
-               goto err_free;
-
-       kfree(dma_list);
-
-       return 0;
-
-err_free:
-       mthca_free_cq_buf(dev, cq);
-
-err_out:
-       kfree(dma_list);
-
-       return err;
+       mthca_buf_free(dev, (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE,
+                      &cq->queue, cq->is_direct, &cq->mr);
 }
 
 int mthca_init_cq(struct mthca_dev *dev, int nent,
@@ -795,7 +703,9 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
        cq_context = mailbox->buf;
 
        if (cq->is_kernel) {
-               err = mthca_alloc_cq_buf(dev, size, cq);
+               err = mthca_buf_alloc(dev, size, MTHCA_MAX_DIRECT_CQ_SIZE,
+                                     &cq->queue, &cq->is_direct,
+                                     &dev->driver_pd, 1, &cq->mr);
                if (err)
                        goto err_out_mailbox;
 
@@ -811,7 +721,6 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
        cq_context->flags           = cpu_to_be32(MTHCA_CQ_STATUS_OK      |
                                                  MTHCA_CQ_STATE_DISARMED |
                                                  MTHCA_CQ_FLAG_TR);
-       cq_context->start           = cpu_to_be64(0);
        cq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24);
        if (ctx)
                cq_context->logsize_usrpage |= cpu_to_be32(ctx->uar.index);
@@ -857,10 +766,8 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
        return 0;
 
 err_out_free_mr:
-       if (cq->is_kernel) {
-               mthca_free_mr(dev, &cq->mr);
+       if (cq->is_kernel)
                mthca_free_cq_buf(dev, cq);
-       }
 
 err_out_mailbox:
        mthca_free_mailbox(dev, mailbox);
@@ -904,7 +811,7 @@ void mthca_free_cq(struct mthca_dev *dev,
                mthca_warn(dev, "HW2SW_CQ returned status 0x%02x\n", status);
 
        if (0) {
-               u32 *ctx = mailbox->buf;
+               __be32 *ctx = mailbox->buf;
                int j;
 
                printk(KERN_ERR "context for CQN %x (cons index %x, next sw %d)\n",
@@ -928,7 +835,6 @@ void mthca_free_cq(struct mthca_dev *dev,
        wait_event(cq->wait, !atomic_read(&cq->refcount));
 
        if (cq->is_kernel) {
-               mthca_free_mr(dev, &cq->mr);
                mthca_free_cq_buf(dev, cq);
                if (mthca_is_memfree(dev)) {
                        mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM,    cq->arm_db_index);
index 5ecdd2e..7bff5a8 100644 (file)
@@ -2,6 +2,8 @@
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004 Voltaire, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -66,6 +68,10 @@ enum {
        MTHCA_MAX_PORTS = 2
 };
 
+enum {
+       MTHCA_BOARD_ID_LEN = 64
+};
+
 enum {
        MTHCA_EQ_CONTEXT_SIZE =  0x40,
        MTHCA_CQ_CONTEXT_SIZE =  0x40,
@@ -142,6 +148,7 @@ struct mthca_limits {
        int      reserved_mcgs;
        int      num_pds;
        int      reserved_pds;
+       u8       port_width_cap;
 };
 
 struct mthca_alloc {
@@ -211,6 +218,13 @@ struct mthca_cq_table {
        struct mthca_icm_table *table;
 };
 
+struct mthca_srq_table {
+       struct mthca_alloc      alloc;
+       spinlock_t              lock;
+       struct mthca_array      srq;
+       struct mthca_icm_table *table;
+};
+
 struct mthca_qp_table {
        struct mthca_alloc      alloc;
        u32                     rdb_base;
@@ -246,6 +260,7 @@ struct mthca_dev {
        unsigned long    device_cap_flags;
 
        u32              rev_id;
+       char             board_id[MTHCA_BOARD_ID_LEN];
 
        /* firmware info */
        u64              fw_ver;
@@ -291,6 +306,7 @@ struct mthca_dev {
        struct mthca_mr_table  mr_table;
        struct mthca_eq_table  eq_table;
        struct mthca_cq_table  cq_table;
+       struct mthca_srq_table srq_table;
        struct mthca_qp_table  qp_table;
        struct mthca_av_table  av_table;
        struct mthca_mcg_table mcg_table;
@@ -331,14 +347,13 @@ extern void __buggy_use_of_MTHCA_PUT(void);
 
 #define MTHCA_PUT(dest, source, offset)                               \
        do {                                                          \
-               __typeof__(source) *__p =                             \
-                       (__typeof__(source) *) ((char *) (dest) + (offset)); \
+               void *__d = ((char *) (dest) + (offset));             \
                switch (sizeof(source)) {                             \
-                       case 1: *__p = (source);            break;    \
-                       case 2: *__p = cpu_to_be16(source); break;    \
-                       case 4: *__p = cpu_to_be32(source); break;    \
-                       case 8: *__p = cpu_to_be64(source); break;    \
-                       default: __buggy_use_of_MTHCA_PUT();          \
+               case 1: *(u8 *) __d = (source);                break; \
+               case 2: *(__be16 *) __d = cpu_to_be16(source); break; \
+               case 4: *(__be32 *) __d = cpu_to_be32(source); break; \
+               case 8: *(__be64 *) __d = cpu_to_be64(source); break; \
+               default: __buggy_use_of_MTHCA_PUT();                  \
                }                                                     \
        } while (0)
 
@@ -354,12 +369,18 @@ int mthca_array_set(struct mthca_array *array, int index, void *value);
 void mthca_array_clear(struct mthca_array *array, int index);
 int mthca_array_init(struct mthca_array *array, int nent);
 void mthca_array_cleanup(struct mthca_array *array, int nent);
+int mthca_buf_alloc(struct mthca_dev *dev, int size, int max_direct,
+                   union mthca_buf *buf, int *is_direct, struct mthca_pd *pd,
+                   int hca_write, struct mthca_mr *mr);
+void mthca_buf_free(struct mthca_dev *dev, int size, union mthca_buf *buf,
+                   int is_direct, struct mthca_mr *mr);
 
 int mthca_init_uar_table(struct mthca_dev *dev);
 int mthca_init_pd_table(struct mthca_dev *dev);
 int mthca_init_mr_table(struct mthca_dev *dev);
 int mthca_init_eq_table(struct mthca_dev *dev);
 int mthca_init_cq_table(struct mthca_dev *dev);
+int mthca_init_srq_table(struct mthca_dev *dev);
 int mthca_init_qp_table(struct mthca_dev *dev);
 int mthca_init_av_table(struct mthca_dev *dev);
 int mthca_init_mcg_table(struct mthca_dev *dev);
@@ -369,6 +390,7 @@ void mthca_cleanup_pd_table(struct mthca_dev *dev);
 void mthca_cleanup_mr_table(struct mthca_dev *dev);
 void mthca_cleanup_eq_table(struct mthca_dev *dev);
 void mthca_cleanup_cq_table(struct mthca_dev *dev);
+void mthca_cleanup_srq_table(struct mthca_dev *dev);
 void mthca_cleanup_qp_table(struct mthca_dev *dev);
 void mthca_cleanup_av_table(struct mthca_dev *dev);
 void mthca_cleanup_mcg_table(struct mthca_dev *dev);
@@ -419,7 +441,19 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
 void mthca_free_cq(struct mthca_dev *dev,
                   struct mthca_cq *cq);
 void mthca_cq_event(struct mthca_dev *dev, u32 cqn);
-void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn);
+void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
+                   struct mthca_srq *srq);
+
+int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
+                   struct ib_srq_attr *attr, struct mthca_srq *srq);
+void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq);
+void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
+                    enum ib_event_type event_type);
+void mthca_free_srq_wqe(struct mthca_srq *srq, u32 wqe_addr);
+int mthca_tavor_post_srq_recv(struct ib_srq *srq, struct ib_recv_wr *wr,
+                             struct ib_recv_wr **bad_wr);
+int mthca_arbel_post_srq_recv(struct ib_srq *srq, struct ib_recv_wr *wr,
+                             struct ib_recv_wr **bad_wr);
 
 void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
                    enum ib_event_type event_type);
@@ -433,7 +467,7 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 int mthca_arbel_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
                             struct ib_recv_wr **bad_wr);
 int mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,
-                      int index, int *dbd, u32 *new_wqe);
+                      int index, int *dbd, __be32 *new_wqe);
 int mthca_alloc_qp(struct mthca_dev *dev,
                   struct mthca_pd *pd,
                   struct mthca_cq *send_cq,
index 535fad7..dd9a44d 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -57,13 +58,13 @@ static inline void mthca_write64_raw(__be64 val, void __iomem *dest)
        __raw_writeq((__force u64) val, dest);
 }
 
-static inline void mthca_write64(u32 val[2], void __iomem *dest,
+static inline void mthca_write64(__be32 val[2], void __iomem *dest,
                                 spinlock_t *doorbell_lock)
 {
        __raw_writeq(*(u64 *) val, dest);
 }
 
-static inline void mthca_write_db_rec(u32 val[2], u32 *db)
+static inline void mthca_write_db_rec(__be32 val[2], __be32 *db)
 {
        *(u64 *) db = *(u64 *) val;
 }
@@ -86,18 +87,18 @@ static inline void mthca_write64_raw(__be64 val, void __iomem *dest)
        __raw_writel(((__force u32 *) &val)[1], dest + 4);
 }
 
-static inline void mthca_write64(u32 val[2], void __iomem *dest,
+static inline void mthca_write64(__be32 val[2], void __iomem *dest,
                                 spinlock_t *doorbell_lock)
 {
        unsigned long flags;
 
        spin_lock_irqsave(doorbell_lock, flags);
-       __raw_writel(val[0], dest);
-       __raw_writel(val[1], dest + 4);
+       __raw_writel((__force u32) val[0], dest);
+       __raw_writel((__force u32) val[1], dest + 4);
        spin_unlock_irqrestore(doorbell_lock, flags);
 }
 
-static inline void mthca_write_db_rec(u32 val[2], u32 *db)
+static inline void mthca_write_db_rec(__be32 val[2], __be32 *db)
 {
        db[0] = val[0];
        wmb();
index cbcf2b4..18f0981 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -51,18 +52,18 @@ enum {
  * Must be packed because start is 64 bits but only aligned to 32 bits.
  */
 struct mthca_eq_context {
-       u32 flags;
-       u64 start;
-       u32 logsize_usrpage;
-       u32 tavor_pd;           /* reserved for Arbel */
-       u8  reserved1[3];
-       u8  intr;
-       u32 arbel_pd;           /* lost_count for Tavor */
-       u32 lkey;
-       u32 reserved2[2];
-       u32 consumer_index;
-       u32 producer_index;
-       u32 reserved3[4];
+       __be32 flags;
+       __be64 start;
+       __be32 logsize_usrpage;
+       __be32 tavor_pd;        /* reserved for Arbel */
+       u8     reserved1[3];
+       u8     intr;
+       __be32 arbel_pd;        /* lost_count for Tavor */
+       __be32 lkey;
+       u32    reserved2[2];
+       __be32 consumer_index;
+       __be32 producer_index;
+       u32    reserved3[4];
 } __attribute__((packed));
 
 #define MTHCA_EQ_STATUS_OK          ( 0 << 28)
@@ -127,28 +128,28 @@ struct mthca_eqe {
        union {
                u32 raw[6];
                struct {
-                       u32 cqn;
+                       __be32 cqn;
                } __attribute__((packed)) comp;
                struct {
-                       u16 reserved1;
-                       u16 token;
-                       u32 reserved2;
-                       u8  reserved3[3];
-                       u8  status;
-                       u64 out_param;
+                       u16    reserved1;
+                       __be16 token;
+                       u32    reserved2;
+                       u8     reserved3[3];
+                       u8     status;
+                       __be64 out_param;
                } __attribute__((packed)) cmd;
                struct {
-                       u32 qpn;
+                       __be32 qpn;
                } __attribute__((packed)) qp;
                struct {
-                       u32 cqn;
-                       u32 reserved1;
-                       u8  reserved2[3];
-                       u8  syndrome;
+                       __be32 cqn;
+                       u32    reserved1;
+                       u8     reserved2[3];
+                       u8     syndrome;
                } __attribute__((packed)) cq_err;
                struct {
-                       u32 reserved1[2];
-                       u32 port;
+                       u32    reserved1[2];
+                       __be32 port;
                } __attribute__((packed)) port_change;
        } event;
        u8 reserved3[3];
@@ -167,7 +168,7 @@ static inline u64 async_mask(struct mthca_dev *dev)
 
 static inline void tavor_set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
 {
-       u32 doorbell[2];
+       __be32 doorbell[2];
 
        doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_SET_CI | eq->eqn);
        doorbell[1] = cpu_to_be32(ci & (eq->nent - 1));
@@ -190,8 +191,8 @@ static inline void arbel_set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u
 {
        /* See comment in tavor_set_eq_ci() above. */
        wmb();
-       __raw_writel(cpu_to_be32(ci), dev->eq_regs.arbel.eq_set_ci_base +
-                    eq->eqn * 8);
+       __raw_writel((__force u32) cpu_to_be32(ci),
+                    dev->eq_regs.arbel.eq_set_ci_base + eq->eqn * 8);
        /* We still want ordering, just not swabbing, so add a barrier */
        mb();
 }
@@ -206,7 +207,7 @@ static inline void set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
 
 static inline void tavor_eq_req_not(struct mthca_dev *dev, int eqn)
 {
-       u32 doorbell[2];
+       __be32 doorbell[2];
 
        doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_REQ_NOT | eqn);
        doorbell[1] = 0;
@@ -224,7 +225,7 @@ static inline void arbel_eq_req_not(struct mthca_dev *dev, u32 eqn_mask)
 static inline void disarm_cq(struct mthca_dev *dev, int eqn, int cqn)
 {
        if (!mthca_is_memfree(dev)) {
-               u32 doorbell[2];
+               __be32 doorbell[2];
 
                doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_DISARM_CQ | eqn);
                doorbell[1] = cpu_to_be32(cqn);
index 7df2236..9804174 100644 (file)
@@ -1,5 +1,7 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004 Voltaire, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -32,9 +34,9 @@
  * $Id: mthca_mad.c 1349 2004-12-16 21:09:43Z roland $
  */
 
-#include <ib_verbs.h>
-#include <ib_mad.h>
-#include <ib_smi.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_mad.h>
+#include <rdma/ib_smi.h>
 
 #include "mthca_dev.h"
 #include "mthca_cmd.h"
@@ -192,7 +194,7 @@ int mthca_process_mad(struct ib_device *ibdev,
 {
        int err;
        u8 status;
-       u16 slid = in_wc ? in_wc->slid : IB_LID_PERMISSIVE;
+       u16 slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE);
 
        /* Forward locally generated traps to the SM */
        if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP &&
index 2ef9168..3241d6c 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -34,7 +35,6 @@
  */
 
 #include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/errno.h>
@@ -171,6 +171,7 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim
        mdev->limits.reserved_mrws      = dev_lim->reserved_mrws;
        mdev->limits.reserved_uars      = dev_lim->reserved_uars;
        mdev->limits.reserved_pds       = dev_lim->reserved_pds;
+       mdev->limits.port_width_cap     = dev_lim->max_port_width;
 
        /* IB_DEVICE_RESIZE_MAX_WR not supported by driver.
           May be doable since hardware supports it for SRQ.
@@ -212,7 +213,6 @@ static int __devinit mthca_init_tavor(struct mthca_dev *mdev)
        struct mthca_dev_lim        dev_lim;
        struct mthca_profile        profile;
        struct mthca_init_hca_param init_hca;
-       struct mthca_adapter        adapter;
 
        err = mthca_SYS_EN(mdev, &status);
        if (err) {
@@ -253,6 +253,8 @@ static int __devinit mthca_init_tavor(struct mthca_dev *mdev)
        profile = default_profile;
        profile.num_uar   = dev_lim.uar_size / PAGE_SIZE;
        profile.uarc_size = 0;
+       if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
+               profile.num_srq = dev_lim.max_srqs;
 
        err = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);
        if (err < 0)
@@ -270,26 +272,8 @@ static int __devinit mthca_init_tavor(struct mthca_dev *mdev)
                goto err_disable;
        }
 
-       err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);
-       if (err) {
-               mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n");
-               goto err_close;
-       }
-       if (status) {
-               mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, "
-                         "aborting.\n", status);
-               err = -EINVAL;
-               goto err_close;
-       }
-
-       mdev->eq_table.inta_pin = adapter.inta_pin;
-       mdev->rev_id            = adapter.revision_id;
-
        return 0;
 
-err_close:
-       mthca_CLOSE_HCA(mdev, 0, &status);
-
 err_disable:
        mthca_SYS_DIS(mdev, &status);
 
@@ -442,15 +426,29 @@ static int __devinit mthca_init_icm(struct mthca_dev *mdev,
        }
 
        mdev->cq_table.table = mthca_alloc_icm_table(mdev, init_hca->cqc_base,
-                                                    dev_lim->cqc_entry_sz,
-                                                    mdev->limits.num_cqs,
-                                                    mdev->limits.reserved_cqs, 0);
+                                                   dev_lim->cqc_entry_sz,
+                                                   mdev->limits.num_cqs,
+                                                   mdev->limits.reserved_cqs, 0);
        if (!mdev->cq_table.table) {
                mthca_err(mdev, "Failed to map CQ context memory, aborting.\n");
                err = -ENOMEM;
                goto err_unmap_rdb;
        }
 
+       if (mdev->mthca_flags & MTHCA_FLAG_SRQ) {
+               mdev->srq_table.table =
+                       mthca_alloc_icm_table(mdev, init_hca->srqc_base,
+                                             dev_lim->srq_entry_sz,
+                                             mdev->limits.num_srqs,
+                                             mdev->limits.reserved_srqs, 0);
+               if (!mdev->srq_table.table) {
+                       mthca_err(mdev, "Failed to map SRQ context memory, "
+                                 "aborting.\n");
+                       err = -ENOMEM;
+                       goto err_unmap_cq;
+               }
+       }
+
        /*
         * It's not strictly required, but for simplicity just map the
         * whole multicast group table now.  The table isn't very big
@@ -466,11 +464,15 @@ static int __devinit mthca_init_icm(struct mthca_dev *mdev,
        if (!mdev->mcg_table.table) {
                mthca_err(mdev, "Failed to map MCG context memory, aborting.\n");
                err = -ENOMEM;
-               goto err_unmap_cq;
+               goto err_unmap_srq;
        }
 
        return 0;
 
+err_unmap_srq:
+       if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
+               mthca_free_icm_table(mdev, mdev->srq_table.table);
+
 err_unmap_cq:
        mthca_free_icm_table(mdev, mdev->cq_table.table);
 
@@ -506,7 +508,6 @@ static int __devinit mthca_init_arbel(struct mthca_dev *mdev)
        struct mthca_dev_lim        dev_lim;
        struct mthca_profile        profile;
        struct mthca_init_hca_param init_hca;
-       struct mthca_adapter        adapter;
        u64 icm_size;
        u8 status;
        int err;
@@ -551,6 +552,8 @@ static int __devinit mthca_init_arbel(struct mthca_dev *mdev)
        profile = default_profile;
        profile.num_uar  = dev_lim.uar_size / PAGE_SIZE;
        profile.num_udav = 0;
+       if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
+               profile.num_srq = dev_lim.max_srqs;
 
        icm_size = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);
        if ((int) icm_size < 0) {
@@ -574,24 +577,11 @@ static int __devinit mthca_init_arbel(struct mthca_dev *mdev)
                goto err_free_icm;
        }
 
-       err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);
-       if (err) {
-               mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n");
-               goto err_free_icm;
-       }
-       if (status) {
-               mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, "
-                         "aborting.\n", status);
-               err = -EINVAL;
-               goto err_free_icm;
-       }
-
-       mdev->eq_table.inta_pin = adapter.inta_pin;
-       mdev->rev_id            = adapter.revision_id;
-
        return 0;
 
 err_free_icm:
+       if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
+               mthca_free_icm_table(mdev, mdev->srq_table.table);
        mthca_free_icm_table(mdev, mdev->cq_table.table);
        mthca_free_icm_table(mdev, mdev->qp_table.rdb_table);
        mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);
@@ -614,12 +604,70 @@ err_disable:
        return err;
 }
 
+static void mthca_close_hca(struct mthca_dev *mdev)
+{
+       u8 status;
+
+       mthca_CLOSE_HCA(mdev, 0, &status);
+
+       if (mthca_is_memfree(mdev)) {
+               if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
+                       mthca_free_icm_table(mdev, mdev->srq_table.table);
+               mthca_free_icm_table(mdev, mdev->cq_table.table);
+               mthca_free_icm_table(mdev, mdev->qp_table.rdb_table);
+               mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);
+               mthca_free_icm_table(mdev, mdev->qp_table.qp_table);
+               mthca_free_icm_table(mdev, mdev->mr_table.mpt_table);
+               mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);
+               mthca_unmap_eq_icm(mdev);
+
+               mthca_UNMAP_ICM_AUX(mdev, &status);
+               mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);
+
+               mthca_UNMAP_FA(mdev, &status);
+               mthca_free_icm(mdev, mdev->fw.arbel.fw_icm);
+
+               if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
+                       mthca_DISABLE_LAM(mdev, &status);
+       } else
+               mthca_SYS_DIS(mdev, &status);
+}
+
 static int __devinit mthca_init_hca(struct mthca_dev *mdev)
 {
+       u8 status;
+       int err;
+       struct mthca_adapter adapter;
+
        if (mthca_is_memfree(mdev))
-               return mthca_init_arbel(mdev);
+               err = mthca_init_arbel(mdev);
        else
-               return mthca_init_tavor(mdev);
+               err = mthca_init_tavor(mdev);
+
+       if (err)
+               return err;
+
+       err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);
+       if (err) {
+               mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n");
+               goto err_close;
+       }
+       if (status) {
+               mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, "
+                         "aborting.\n", status);
+               err = -EINVAL;
+               goto err_close;
+       }
+
+       mdev->eq_table.inta_pin = adapter.inta_pin;
+       mdev->rev_id            = adapter.revision_id;
+       memcpy(mdev->board_id, adapter.board_id, sizeof mdev->board_id);
+
+       return 0;
+
+err_close:
+       mthca_close_hca(mdev);
+       return err;
 }
 
 static int __devinit mthca_setup_hca(struct mthca_dev *dev)
@@ -709,11 +757,18 @@ static int __devinit mthca_setup_hca(struct mthca_dev *dev)
                goto err_cmd_poll;
        }
 
+       err = mthca_init_srq_table(dev);
+       if (err) {
+               mthca_err(dev, "Failed to initialize "
+                         "shared receive queue table, aborting.\n");
+               goto err_cq_table_free;
+       }
+
        err = mthca_init_qp_table(dev);
        if (err) {
                mthca_err(dev, "Failed to initialize "
                          "queue pair table, aborting.\n");
-               goto err_cq_table_free;
+               goto err_srq_table_free;
        }
 
        err = mthca_init_av_table(dev);
@@ -738,6 +793,9 @@ err_av_table_free:
 err_qp_table_free:
        mthca_cleanup_qp_table(dev);
 
+err_srq_table_free:
+       mthca_cleanup_srq_table(dev);
+
 err_cq_table_free:
        mthca_cleanup_cq_table(dev);
 
@@ -844,33 +902,6 @@ static int __devinit mthca_enable_msi_x(struct mthca_dev *mdev)
        return 0;
 }
 
-static void mthca_close_hca(struct mthca_dev *mdev)
-{
-       u8 status;
-
-       mthca_CLOSE_HCA(mdev, 0, &status);
-
-       if (mthca_is_memfree(mdev)) {
-               mthca_free_icm_table(mdev, mdev->cq_table.table);
-               mthca_free_icm_table(mdev, mdev->qp_table.rdb_table);
-               mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);
-               mthca_free_icm_table(mdev, mdev->qp_table.qp_table);
-               mthca_free_icm_table(mdev, mdev->mr_table.mpt_table);
-               mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);
-               mthca_unmap_eq_icm(mdev);
-
-               mthca_UNMAP_ICM_AUX(mdev, &status);
-               mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);
-
-               mthca_UNMAP_FA(mdev, &status);
-               mthca_free_icm(mdev, mdev->fw.arbel.fw_icm);
-
-               if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
-                       mthca_DISABLE_LAM(mdev, &status);
-       } else
-               mthca_SYS_DIS(mdev, &status);
-}
-
 /* Types of supported HCA */
 enum {
        TAVOR,                  /* MT23108                        */
@@ -887,9 +918,9 @@ static struct {
        int is_memfree;
        int is_pcie;
 } mthca_hca_table[] = {
-       [TAVOR]        = { .latest_fw = MTHCA_FW_VER(3, 3, 2), .is_memfree = 0, .is_pcie = 0 },
-       [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 6, 2), .is_memfree = 0, .is_pcie = 1 },
-       [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 0, 1), .is_memfree = 1, .is_pcie = 1 },
+       [TAVOR]        = { .latest_fw = MTHCA_FW_VER(3, 3, 3), .is_memfree = 0, .is_pcie = 0 },
+       [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 0), .is_memfree = 0, .is_pcie = 1 },
+       [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 0), .is_memfree = 1, .is_pcie = 1 },
        [SINAI]        = { .latest_fw = MTHCA_FW_VER(1, 0, 1), .is_memfree = 1, .is_pcie = 1 }
 };
 
@@ -1051,6 +1082,7 @@ err_cleanup:
        mthca_cleanup_mcg_table(mdev);
        mthca_cleanup_av_table(mdev);
        mthca_cleanup_qp_table(mdev);
+       mthca_cleanup_srq_table(mdev);
        mthca_cleanup_cq_table(mdev);
        mthca_cmd_use_polling(mdev);
        mthca_cleanup_eq_table(mdev);
@@ -1100,6 +1132,7 @@ static void __devexit mthca_remove_one(struct pci_dev *pdev)
                mthca_cleanup_mcg_table(mdev);
                mthca_cleanup_av_table(mdev);
                mthca_cleanup_qp_table(mdev);
+               mthca_cleanup_srq_table(mdev);
                mthca_cleanup_cq_table(mdev);
                mthca_cmd_use_polling(mdev);
                mthca_cleanup_eq_table(mdev);
index 5be7d94..a270760 100644 (file)
@@ -42,10 +42,10 @@ enum {
 };
 
 struct mthca_mgm {
-       u32 next_gid_index;
-       u32 reserved[3];
-       u8  gid[16];
-       u32 qp[MTHCA_QP_PER_MGM];
+       __be32 next_gid_index;
+       u32    reserved[3];
+       u8     gid[16];
+       __be32 qp[MTHCA_QP_PER_MGM];
 };
 
 static const u8 zero_gid[16];  /* automatically initialized to 0 */
@@ -94,10 +94,14 @@ static int find_mgm(struct mthca_dev *dev,
        if (0)
                mthca_dbg(dev, "Hash for %04x:%04x:%04x:%04x:"
                          "%04x:%04x:%04x:%04x is %04x\n",
-                         be16_to_cpu(((u16 *) gid)[0]), be16_to_cpu(((u16 *) gid)[1]),
-                         be16_to_cpu(((u16 *) gid)[2]), be16_to_cpu(((u16 *) gid)[3]),
-                         be16_to_cpu(((u16 *) gid)[4]), be16_to_cpu(((u16 *) gid)[5]),
-                         be16_to_cpu(((u16 *) gid)[6]), be16_to_cpu(((u16 *) gid)[7]),
+                         be16_to_cpu(((__be16 *) gid)[0]),
+                         be16_to_cpu(((__be16 *) gid)[1]),
+                         be16_to_cpu(((__be16 *) gid)[2]),
+                         be16_to_cpu(((__be16 *) gid)[3]),
+                         be16_to_cpu(((__be16 *) gid)[4]),
+                         be16_to_cpu(((__be16 *) gid)[5]),
+                         be16_to_cpu(((__be16 *) gid)[6]),
+                         be16_to_cpu(((__be16 *) gid)[7]),
                          *hash);
 
        *index = *hash;
@@ -258,14 +262,14 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
        if (index == -1) {
                mthca_err(dev, "MGID %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
                          "not found\n",
-                         be16_to_cpu(((u16 *) gid->raw)[0]),
-                         be16_to_cpu(((u16 *) gid->raw)[1]),
-                         be16_to_cpu(((u16 *) gid->raw)[2]),
-                         be16_to_cpu(((u16 *) gid->raw)[3]),
-                         be16_to_cpu(((u16 *) gid->raw)[4]),
-                         be16_to_cpu(((u16 *) gid->raw)[5]),
-                         be16_to_cpu(((u16 *) gid->raw)[6]),
-                         be16_to_cpu(((u16 *) gid->raw)[7]));
+                         be16_to_cpu(((__be16 *) gid->raw)[0]),
+                         be16_to_cpu(((__be16 *) gid->raw)[1]),
+                         be16_to_cpu(((__be16 *) gid->raw)[2]),
+                         be16_to_cpu(((__be16 *) gid->raw)[3]),
+                         be16_to_cpu(((__be16 *) gid->raw)[4]),
+                         be16_to_cpu(((__be16 *) gid->raw)[5]),
+                         be16_to_cpu(((__be16 *) gid->raw)[6]),
+                         be16_to_cpu(((__be16 *) gid->raw)[7]));
                err = -EINVAL;
                goto out;
        }
index 2a86461..1827400 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -285,6 +286,7 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
 {
        struct mthca_icm_table *table;
        int num_icm;
+       unsigned chunk_size;
        int i;
        u8 status;
 
@@ -305,7 +307,11 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
                table->icm[i] = NULL;
 
        for (i = 0; i * MTHCA_TABLE_CHUNK_SIZE < reserved * obj_size; ++i) {
-               table->icm[i] = mthca_alloc_icm(dev, MTHCA_TABLE_CHUNK_SIZE >> PAGE_SHIFT,
+               chunk_size = MTHCA_TABLE_CHUNK_SIZE;
+               if ((i + 1) * MTHCA_TABLE_CHUNK_SIZE > nobj * obj_size)
+                       chunk_size = nobj * obj_size - i * MTHCA_TABLE_CHUNK_SIZE;
+
+               table->icm[i] = mthca_alloc_icm(dev, chunk_size >> PAGE_SHIFT,
                                                (use_lowmem ? GFP_KERNEL : GFP_HIGHUSER) |
                                                __GFP_NOWARN);
                if (!table->icm[i])
@@ -481,7 +487,7 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
        }
 }
 
-int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, u32 **db)
+int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db)
 {
        int group;
        int start, end, dir;
@@ -564,7 +570,7 @@ found:
 
        page->db_rec[j] = cpu_to_be64((qn << 8) | (type << 5));
 
-       *db = (u32 *) &page->db_rec[j];
+       *db = (__be32 *) &page->db_rec[j];
 
 out:
        up(&dev->db_tab->mutex);
index 4761d84..bafa515 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -137,7 +138,7 @@ enum {
 
 struct mthca_db_page {
        DECLARE_BITMAP(used, MTHCA_DB_REC_PER_PAGE);
-       u64       *db_rec;
+       __be64    *db_rec;
        dma_addr_t mapping;
 };
 
@@ -172,7 +173,7 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
 
 int mthca_init_db_tab(struct mthca_dev *dev);
 void mthca_cleanup_db_tab(struct mthca_dev *dev);
-int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, u32 **db);
+int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db);
 void mthca_free_db(struct mthca_dev *dev, int type, int db_index);
 
 #endif /* MTHCA_MEMFREE_H */
index cbe50fe..1f97a44 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -50,18 +51,18 @@ struct mthca_mtt {
  * Must be packed because mtt_seg is 64 bits but only aligned to 32 bits.
  */
 struct mthca_mpt_entry {
-       u32 flags;
-       u32 page_size;
-       u32 key;
-       u32 pd;
-       u64 start;
-       u64 length;
-       u32 lkey;
-       u32 window_count;
-       u32 window_count_limit;
-       u64 mtt_seg;
-       u32 mtt_sz;             /* Arbel only */
-       u32 reserved[2];
+       __be32 flags;
+       __be32 page_size;
+       __be32 key;
+       __be32 pd;
+       __be64 start;
+       __be64 length;
+       __be32 lkey;
+       __be32 window_count;
+       __be32 window_count_limit;
+       __be64 mtt_seg;
+       __be32 mtt_sz;          /* Arbel only */
+       u32    reserved[2];
 } __attribute__((packed));
 
 #define MTHCA_MPT_FLAG_SW_OWNS       (0xfUL << 28)
@@ -247,7 +248,7 @@ int mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
                    int start_index, u64 *buffer_list, int list_len)
 {
        struct mthca_mailbox *mailbox;
-       u64 *mtt_entry;
+       __be64 *mtt_entry;
        int err = 0;
        u8 status;
        int i;
@@ -389,7 +390,7 @@ int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift,
                for (i = 0; i < sizeof (struct mthca_mpt_entry) / 4; ++i) {
                        if (i % 4 == 0)
                                printk("[%02x] ", i * 4);
-                       printk(" %08x", be32_to_cpu(((u32 *) mpt_entry)[i]));
+                       printk(" %08x", be32_to_cpu(((__be32 *) mpt_entry)[i]));
                        if ((i + 1) % 4 == 0)
                                printk("\n");
                }
@@ -458,7 +459,7 @@ int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
 static void mthca_free_region(struct mthca_dev *dev, u32 lkey)
 {
        mthca_table_put(dev, dev->mr_table.mpt_table,
-                       arbel_key_to_hw_index(lkey));
+                       key_to_hw_index(dev, lkey));
 
        mthca_free(&dev->mr_table.mpt_alloc, key_to_hw_index(dev, lkey));
 }
@@ -562,7 +563,7 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
                for (i = 0; i < sizeof (struct mthca_mpt_entry) / 4; ++i) {
                        if (i % 4 == 0)
                                printk("[%02x] ", i * 4);
-                       printk(" %08x", be32_to_cpu(((u32 *) mpt_entry)[i]));
+                       printk(" %08x", be32_to_cpu(((__be32 *) mpt_entry)[i]));
                        if ((i + 1) % 4 == 0)
                                printk("\n");
                }
@@ -669,7 +670,7 @@ int mthca_tavor_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list,
        mpt_entry.length = cpu_to_be64(list_len * (1ull << fmr->attr.page_size));
        mpt_entry.start  = cpu_to_be64(iova);
 
-       writel(mpt_entry.lkey, &fmr->mem.tavor.mpt->key);
+       __raw_writel((__force u32) mpt_entry.lkey, &fmr->mem.tavor.mpt->key);
        memcpy_toio(&fmr->mem.tavor.mpt->start, &mpt_entry.start,
                    offsetof(struct mthca_mpt_entry, window_count) -
                    offsetof(struct mthca_mpt_entry, start));
index c2c8998..3dbf06a 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 4fedc32..0576056 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -101,6 +102,7 @@ u64 mthca_make_profile(struct mthca_dev *dev,
        profile[MTHCA_RES_UARC].size = request->uarc_size;
 
        profile[MTHCA_RES_QP].num    = request->num_qp;
+       profile[MTHCA_RES_SRQ].num   = request->num_srq;
        profile[MTHCA_RES_EQP].num   = request->num_qp;
        profile[MTHCA_RES_RDB].num   = request->num_qp * request->rdb_per_qp;
        profile[MTHCA_RES_CQ].num    = request->num_cq;
index 17aef33..9464180 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -41,6 +42,7 @@
 struct mthca_profile {
        int num_qp;
        int rdb_per_qp;
+       int num_srq;
        int num_cq;
        int num_mcg;
        int num_mpt;
index 81919a7..1c1c2e2 100644 (file)
@@ -2,6 +2,8 @@
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  * Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004 Voltaire, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -34,7 +36,7 @@
  * $Id: mthca_provider.c 1397 2004-12-28 05:09:00Z roland $
  */
 
-#include <ib_smi.h>
+#include <rdma/ib_smi.h>
 #include <linux/mm.h>
 
 #include "mthca_dev.h"
@@ -79,10 +81,10 @@ static int mthca_query_device(struct ib_device *ibdev,
        }
 
        props->device_cap_flags    = mdev->device_cap_flags;
-       props->vendor_id           = be32_to_cpup((u32 *) (out_mad->data + 36)) &
+       props->vendor_id           = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
                0xffffff;
-       props->vendor_part_id      = be16_to_cpup((u16 *) (out_mad->data + 30));
-       props->hw_ver              = be16_to_cpup((u16 *) (out_mad->data + 32));
+       props->vendor_part_id      = be16_to_cpup((__be16 *) (out_mad->data + 30));
+       props->hw_ver              = be16_to_cpup((__be16 *) (out_mad->data + 32));
        memcpy(&props->sys_image_guid, out_mad->data +  4, 8);
        memcpy(&props->node_guid,      out_mad->data + 12, 8);
 
@@ -118,6 +120,8 @@ static int mthca_query_port(struct ib_device *ibdev,
        if (!in_mad || !out_mad)
                goto out;
 
+       memset(props, 0, sizeof *props);
+
        memset(in_mad, 0, sizeof *in_mad);
        in_mad->base_version       = 1;
        in_mad->mgmt_class         = IB_MGMT_CLASS_SUBN_LID_ROUTED;
@@ -136,16 +140,17 @@ static int mthca_query_port(struct ib_device *ibdev,
                goto out;
        }
 
-       props->lid               = be16_to_cpup((u16 *) (out_mad->data + 16));
+       props->lid               = be16_to_cpup((__be16 *) (out_mad->data + 16));
        props->lmc               = out_mad->data[34] & 0x7;
-       props->sm_lid            = be16_to_cpup((u16 *) (out_mad->data + 18));
+       props->sm_lid            = be16_to_cpup((__be16 *) (out_mad->data + 18));
        props->sm_sl             = out_mad->data[36] & 0xf;
        props->state             = out_mad->data[32] & 0xf;
        props->phys_state        = out_mad->data[33] >> 4;
-       props->port_cap_flags    = be32_to_cpup((u32 *) (out_mad->data + 20));
+       props->port_cap_flags    = be32_to_cpup((__be32 *) (out_mad->data + 20));
        props->gid_tbl_len       = to_mdev(ibdev)->limits.gid_table_len;
+       props->max_msg_sz        = 0x80000000;
        props->pkey_tbl_len      = to_mdev(ibdev)->limits.pkey_table_len;
-       props->qkey_viol_cntr    = be16_to_cpup((u16 *) (out_mad->data + 48));
+       props->qkey_viol_cntr    = be16_to_cpup((__be16 *) (out_mad->data + 48));
        props->active_width      = out_mad->data[31] & 0xf;
        props->active_speed      = out_mad->data[35] >> 4;
 
@@ -221,7 +226,7 @@ static int mthca_query_pkey(struct ib_device *ibdev,
                goto out;
        }
 
-       *pkey = be16_to_cpu(((u16 *) out_mad->data)[index % 32]);
+       *pkey = be16_to_cpu(((__be16 *) out_mad->data)[index % 32]);
 
  out:
        kfree(in_mad);
@@ -420,6 +425,77 @@ static int mthca_ah_destroy(struct ib_ah *ah)
        return 0;
 }
 
+static struct ib_srq *mthca_create_srq(struct ib_pd *pd,
+                                      struct ib_srq_init_attr *init_attr,
+                                      struct ib_udata *udata)
+{
+       struct mthca_create_srq ucmd;
+       struct mthca_ucontext *context = NULL;
+       struct mthca_srq *srq;
+       int err;
+
+       srq = kmalloc(sizeof *srq, GFP_KERNEL);
+       if (!srq)
+               return ERR_PTR(-ENOMEM);
+
+       if (pd->uobject) {
+               context = to_mucontext(pd->uobject->context);
+
+               if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
+                       return ERR_PTR(-EFAULT);
+
+               err = mthca_map_user_db(to_mdev(pd->device), &context->uar,
+                                       context->db_tab, ucmd.db_index,
+                                       ucmd.db_page);
+
+               if (err)
+                       goto err_free;
+
+               srq->mr.ibmr.lkey = ucmd.lkey;
+               srq->db_index     = ucmd.db_index;
+       }
+
+       err = mthca_alloc_srq(to_mdev(pd->device), to_mpd(pd),
+                             &init_attr->attr, srq);
+
+       if (err && pd->uobject)
+               mthca_unmap_user_db(to_mdev(pd->device), &context->uar,
+                                   context->db_tab, ucmd.db_index);
+
+       if (err)
+               goto err_free;
+
+       if (context && ib_copy_to_udata(udata, &srq->srqn, sizeof (__u32))) {
+               mthca_free_srq(to_mdev(pd->device), srq);
+               err = -EFAULT;
+               goto err_free;
+       }
+
+       return &srq->ibsrq;
+
+err_free:
+       kfree(srq);
+
+       return ERR_PTR(err);
+}
+
+static int mthca_destroy_srq(struct ib_srq *srq)
+{
+       struct mthca_ucontext *context;
+
+       if (srq->uobject) {
+               context = to_mucontext(srq->uobject->context);
+
+               mthca_unmap_user_db(to_mdev(srq->device), &context->uar,
+                                   context->db_tab, to_msrq(srq)->db_index);
+       }
+
+       mthca_free_srq(to_mdev(srq->device), to_msrq(srq));
+       kfree(srq);
+
+       return 0;
+}
+
 static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
                                     struct ib_qp_init_attr *init_attr,
                                     struct ib_udata *udata)
@@ -956,14 +1032,22 @@ static ssize_t show_hca(struct class_device *cdev, char *buf)
        }
 }
 
+static ssize_t show_board(struct class_device *cdev, char *buf)
+{
+       struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev);
+       return sprintf(buf, "%.*s\n", MTHCA_BOARD_ID_LEN, dev->board_id);
+}
+
 static CLASS_DEVICE_ATTR(hw_rev,   S_IRUGO, show_rev,    NULL);
 static CLASS_DEVICE_ATTR(fw_ver,   S_IRUGO, show_fw_ver, NULL);
 static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca,    NULL);
+static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board,  NULL);
 
 static struct class_device_attribute *mthca_class_attributes[] = {
        &class_device_attr_hw_rev,
        &class_device_attr_fw_ver,
-       &class_device_attr_hca_type
+       &class_device_attr_hca_type,
+       &class_device_attr_board_id
 };
 
 int mthca_register_device(struct mthca_dev *dev)
@@ -990,6 +1074,17 @@ int mthca_register_device(struct mthca_dev *dev)
        dev->ib_dev.dealloc_pd           = mthca_dealloc_pd;
        dev->ib_dev.create_ah            = mthca_ah_create;
        dev->ib_dev.destroy_ah           = mthca_ah_destroy;
+
+       if (dev->mthca_flags & MTHCA_FLAG_SRQ) {
+               dev->ib_dev.create_srq           = mthca_create_srq;
+               dev->ib_dev.destroy_srq          = mthca_destroy_srq;
+
+               if (mthca_is_memfree(dev))
+                       dev->ib_dev.post_srq_recv = mthca_arbel_post_srq_recv;
+               else
+                       dev->ib_dev.post_srq_recv = mthca_tavor_post_srq_recv;
+       }
+
        dev->ib_dev.create_qp            = mthca_create_qp;
        dev->ib_dev.modify_qp            = mthca_modify_qp;
        dev->ib_dev.destroy_qp           = mthca_destroy_qp;
index 1d03279..bcd4b01 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -36,8 +37,8 @@
 #ifndef MTHCA_PROVIDER_H
 #define MTHCA_PROVIDER_H
 
-#include <ib_verbs.h>
-#include <ib_pack.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_pack.h>
 
 #define MTHCA_MPT_FLAG_ATOMIC        (1 << 14)
 #define MTHCA_MPT_FLAG_REMOTE_WRITE  (1 << 13)
@@ -50,6 +51,11 @@ struct mthca_buf_list {
        DECLARE_PCI_UNMAP_ADDR(mapping)
 };
 
+union mthca_buf {
+       struct mthca_buf_list direct;
+       struct mthca_buf_list *page_list;
+};
+
 struct mthca_uar {
        unsigned long pfn;
        int           index;
@@ -181,19 +187,39 @@ struct mthca_cq {
 
        /* Next fields are Arbel only */
        int                    set_ci_db_index;
-       u32                   *set_ci_db;
+       __be32                *set_ci_db;
        int                    arm_db_index;
-       u32                   *arm_db;
+       __be32                *arm_db;
        int                    arm_sn;
 
-       union {
-               struct mthca_buf_list direct;
-               struct mthca_buf_list *page_list;
-       }                      queue;
+       union mthca_buf        queue;
        struct mthca_mr        mr;
        wait_queue_head_t      wait;
 };
 
+struct mthca_srq {
+       struct ib_srq           ibsrq;
+       spinlock_t              lock;
+       atomic_t                refcount;
+       int                     srqn;
+       int                     max;
+       int                     max_gs;
+       int                     wqe_shift;
+       int                     first_free;
+       int                     last_free;
+       u16                     counter;  /* Arbel only */
+       int                     db_index; /* Arbel only */
+       __be32                 *db;       /* Arbel only */
+       void                   *last;
+
+       int                     is_direct;
+       u64                    *wrid;
+       union mthca_buf         queue;
+       struct mthca_mr         mr;
+
+       wait_queue_head_t       wait;
+};
+
 struct mthca_wq {
        spinlock_t lock;
        int        max;
@@ -206,7 +232,7 @@ struct mthca_wq {
        int        wqe_shift;
 
        int        db_index;    /* Arbel only */
-       u32       *db;
+       __be32    *db;
 };
 
 struct mthca_qp {
@@ -227,10 +253,7 @@ struct mthca_qp {
        int                    send_wqe_offset;
 
        u64                   *wrid;
-       union {
-               struct mthca_buf_list direct;
-               struct mthca_buf_list *page_list;
-       }                      queue;
+       union mthca_buf        queue;
 
        wait_queue_head_t      wait;
 };
@@ -277,6 +300,11 @@ static inline struct mthca_cq *to_mcq(struct ib_cq *ibcq)
        return container_of(ibcq, struct mthca_cq, ibcq);
 }
 
+static inline struct mthca_srq *to_msrq(struct ib_srq *ibsrq)
+{
+       return container_of(ibsrq, struct mthca_srq, ibsrq);
+}
+
 static inline struct mthca_qp *to_mqp(struct ib_qp *ibqp)
 {
        return container_of(ibqp, struct mthca_qp, ibqp);
index f7126b1..0164b84 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004 Voltaire, Inc. All rights reserved. 
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
 
 #include <linux/init.h>
 
-#include <ib_verbs.h>
-#include <ib_cache.h>
-#include <ib_pack.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_cache.h>
+#include <rdma/ib_pack.h>
 
 #include "mthca_dev.h"
 #include "mthca_cmd.h"
 #include "mthca_memfree.h"
+#include "mthca_wqe.h"
 
 enum {
        MTHCA_MAX_DIRECT_QP_SIZE = 4 * PAGE_SIZE,
@@ -95,62 +98,62 @@ enum {
 };
 
 struct mthca_qp_path {
-       u32 port_pkey;
-       u8  rnr_retry;
-       u8  g_mylmc;
-       u16 rlid;
-       u8  ackto;
-       u8  mgid_index;
-       u8  static_rate;
-       u8  hop_limit;
-       u32 sl_tclass_flowlabel;
-       u8  rgid[16];
+       __be32 port_pkey;
+       u8     rnr_retry;
+       u8     g_mylmc;
+       __be16 rlid;
+       u8     ackto;
+       u8     mgid_index;
+       u8     static_rate;
+       u8     hop_limit;
+       __be32 sl_tclass_flowlabel;
+       u8     rgid[16];
 } __attribute__((packed));
 
 struct mthca_qp_context {
-       u32 flags;
-       u32 tavor_sched_queue;  /* Reserved on Arbel */
-       u8  mtu_msgmax;
-       u8  rq_size_stride;     /* Reserved on Tavor */
-       u8  sq_size_stride;     /* Reserved on Tavor */
-       u8  rlkey_arbel_sched_queue;    /* Reserved on Tavor */
-       u32 usr_page;
-       u32 local_qpn;
-       u32 remote_qpn;
-       u32 reserved1[2];
+       __be32 flags;
+       __be32 tavor_sched_queue; /* Reserved on Arbel */
+       u8     mtu_msgmax;
+       u8     rq_size_stride;  /* Reserved on Tavor */
+       u8     sq_size_stride;  /* Reserved on Tavor */
+       u8     rlkey_arbel_sched_queue; /* Reserved on Tavor */
+       __be32 usr_page;
+       __be32 local_qpn;
+       __be32 remote_qpn;
+       u32    reserved1[2];
        struct mthca_qp_path pri_path;
        struct mthca_qp_path alt_path;
-       u32 rdd;
-       u32 pd;
-       u32 wqe_base;
-       u32 wqe_lkey;
-       u32 params1;
-       u32 reserved2;
-       u32 next_send_psn;
-       u32 cqn_snd;
-       u32 snd_wqe_base_l;     /* Next send WQE on Tavor */
-       u32 snd_db_index;       /* (debugging only entries) */
-       u32 last_acked_psn;
-       u32 ssn;
-       u32 params2;
-       u32 rnr_nextrecvpsn;
-       u32 ra_buff_indx;
-       u32 cqn_rcv;
-       u32 rcv_wqe_base_l;     /* Next recv WQE on Tavor */
-       u32 rcv_db_index;       /* (debugging only entries) */
-       u32 qkey;
-       u32 srqn;
-       u32 rmsn;
-       u16 rq_wqe_counter;     /* reserved on Tavor */
-       u16 sq_wqe_counter;     /* reserved on Tavor */
-       u32 reserved3[18];
+       __be32 rdd;
+       __be32 pd;
+       __be32 wqe_base;
+       __be32 wqe_lkey;
+       __be32 params1;
+       __be32 reserved2;
+       __be32 next_send_psn;
+       __be32 cqn_snd;
+       __be32 snd_wqe_base_l;  /* Next send WQE on Tavor */
+       __be32 snd_db_index;    /* (debugging only entries) */
+       __be32 last_acked_psn;
+       __be32 ssn;
+       __be32 params2;
+       __be32 rnr_nextrecvpsn;
+       __be32 ra_buff_indx;
+       __be32 cqn_rcv;
+       __be32 rcv_wqe_base_l;  /* Next recv WQE on Tavor */
+       __be32 rcv_db_index;    /* (debugging only entries) */
+       __be32 qkey;
+       __be32 srqn;
+       __be32 rmsn;
+       __be16 rq_wqe_counter;  /* reserved on Tavor */
+       __be16 sq_wqe_counter;  /* reserved on Tavor */
+       u32    reserved3[18];
 } __attribute__((packed));
 
 struct mthca_qp_param {
-       u32 opt_param_mask;
-       u32 reserved1;
+       __be32 opt_param_mask;
+       u32    reserved1;
        struct mthca_qp_context context;
-       u32 reserved2[62];
+       u32    reserved2[62];
 } __attribute__((packed));
 
 enum {
@@ -173,80 +176,6 @@ enum {
        MTHCA_QP_OPTPAR_SCHED_QUEUE       = 1 << 16
 };
 
-enum {
-       MTHCA_NEXT_DBD       = 1 << 7,
-       MTHCA_NEXT_FENCE     = 1 << 6,
-       MTHCA_NEXT_CQ_UPDATE = 1 << 3,
-       MTHCA_NEXT_EVENT_GEN = 1 << 2,
-       MTHCA_NEXT_SOLICIT   = 1 << 1,
-
-       MTHCA_MLX_VL15       = 1 << 17,
-       MTHCA_MLX_SLR        = 1 << 16
-};
-
-enum {
-       MTHCA_INVAL_LKEY = 0x100
-};
-
-struct mthca_next_seg {
-       u32 nda_op;             /* [31:6] next WQE [4:0] next opcode */
-       u32 ee_nds;             /* [31:8] next EE  [7] DBD [6] F [5:0] next WQE size */
-       u32 flags;              /* [3] CQ [2] Event [1] Solicit */
-       u32 imm;                /* immediate data */
-};
-
-struct mthca_tavor_ud_seg {
-       u32 reserved1;
-       u32 lkey;
-       u64 av_addr;
-       u32 reserved2[4];
-       u32 dqpn;
-       u32 qkey;
-       u32 reserved3[2];
-};
-
-struct mthca_arbel_ud_seg {
-       u32 av[8];
-       u32 dqpn;
-       u32 qkey;
-       u32 reserved[2];
-};
-
-struct mthca_bind_seg {
-       u32 flags;              /* [31] Atomic [30] rem write [29] rem read */
-       u32 reserved;
-       u32 new_rkey;
-       u32 lkey;
-       u64 addr;
-       u64 length;
-};
-
-struct mthca_raddr_seg {
-       u64 raddr;
-       u32 rkey;
-       u32 reserved;
-};
-
-struct mthca_atomic_seg {
-       u64 swap_add;
-       u64 compare;
-};
-
-struct mthca_data_seg {
-       u32 byte_count;
-       u32 lkey;
-       u64 addr;
-};
-
-struct mthca_mlx_seg {
-       u32 nda_op;
-       u32 nds;
-       u32 flags;              /* [17] VL15 [16] SLR [14:12] static rate
-                                  [11:8] SL [3] C [2] E */
-       u16 rlid;
-       u16 vcrc;
-};
-
 static const u8 mthca_opcode[] = {
        [IB_WR_SEND]                 = MTHCA_OPCODE_SEND,
        [IB_WR_SEND_WITH_IMM]        = MTHCA_OPCODE_SEND_IMM,
@@ -573,12 +502,11 @@ static void init_port(struct mthca_dev *dev, int port)
 
        memset(&param, 0, sizeof param);
 
-       param.enable_1x = 1;
-       param.enable_4x = 1;
-       param.vl_cap    = dev->limits.vl_cap;
-       param.mtu_cap   = dev->limits.mtu_cap;
-       param.gid_cap   = dev->limits.gid_table_len;
-       param.pkey_cap  = dev->limits.pkey_table_len;
+       param.port_width = dev->limits.port_width_cap;
+       param.vl_cap     = dev->limits.vl_cap;
+       param.mtu_cap    = dev->limits.mtu_cap;
+       param.gid_cap    = dev->limits.gid_table_len;
+       param.pkey_cap   = dev->limits.pkey_table_len;
 
        err = mthca_INIT_IB(dev, &param, port, &status);
        if (err)
@@ -684,10 +612,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
                qp_context->mtu_msgmax = (attr->path_mtu << 5) | 31;
 
        if (mthca_is_memfree(dev)) {
-               qp_context->rq_size_stride =
-                       ((ffs(qp->rq.max) - 1) << 3) | (qp->rq.wqe_shift - 4);
-               qp_context->sq_size_stride =
-                       ((ffs(qp->sq.max) - 1) << 3) | (qp->sq.wqe_shift - 4);
+               if (qp->rq.max)
+                       qp_context->rq_size_stride = long_log2(qp->rq.max) << 3;
+               qp_context->rq_size_stride |= qp->rq.wqe_shift - 4;
+
+               if (qp->sq.max)
+                       qp_context->sq_size_stride = long_log2(qp->sq.max) << 3;
+               qp_context->sq_size_stride |= qp->sq.wqe_shift - 4;
        }
 
        /* leave arbel_sched_queue as 0 */
@@ -856,6 +787,9 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
 
        qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RSC);
 
+       if (ibqp->srq)
+               qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RIC);
+
        if (attr_mask & IB_QP_MIN_RNR_TIMER) {
                qp_context->rnr_nextrecvpsn |= cpu_to_be32(attr->min_rnr_timer << 24);
                qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_TIMEOUT);
@@ -878,6 +812,10 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
                qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_Q_KEY);
        }
 
+       if (ibqp->srq)
+               qp_context->srqn = cpu_to_be32(1 << 24 |
+                                              to_msrq(ibqp->srq)->srqn);
+
        err = mthca_MODIFY_QP(dev, state_table[cur_state][new_state].trans,
                              qp->qpn, 0, mailbox, 0, &status);
        if (status) {
@@ -925,10 +863,6 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev,
                               struct mthca_qp *qp)
 {
        int size;
-       int i;
-       int npages, shift;
-       dma_addr_t t;
-       u64 *dma_list = NULL;
        int err = -ENOMEM;
 
        size = sizeof (struct mthca_next_seg) +
@@ -978,116 +912,24 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev,
        if (!qp->wrid)
                goto err_out;
 
-       if (size <= MTHCA_MAX_DIRECT_QP_SIZE) {
-               qp->is_direct = 1;
-               npages = 1;
-               shift = get_order(size) + PAGE_SHIFT;
-
-               if (0)
-                       mthca_dbg(dev, "Creating direct QP of size %d (shift %d)\n",
-                                 size, shift);
-
-               qp->queue.direct.buf = dma_alloc_coherent(&dev->pdev->dev, size,
-                                                         &t, GFP_KERNEL);
-               if (!qp->queue.direct.buf)
-                       goto err_out;
-
-               pci_unmap_addr_set(&qp->queue.direct, mapping, t);
-
-               memset(qp->queue.direct.buf, 0, size);
-
-               while (t & ((1 << shift) - 1)) {
-                       --shift;
-                       npages *= 2;
-               }
-
-               dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
-               if (!dma_list)
-                       goto err_out_free;
-
-               for (i = 0; i < npages; ++i)
-                       dma_list[i] = t + i * (1 << shift);
-       } else {
-               qp->is_direct = 0;
-               npages = size / PAGE_SIZE;
-               shift = PAGE_SHIFT;
-
-               if (0)
-                       mthca_dbg(dev, "Creating indirect QP with %d pages\n", npages);
-
-               dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
-               if (!dma_list)
-                       goto err_out;
-
-               qp->queue.page_list = kmalloc(npages *
-                                             sizeof *qp->queue.page_list,
-                                             GFP_KERNEL);
-               if (!qp->queue.page_list)
-                       goto err_out;
-
-               for (i = 0; i < npages; ++i) {
-                       qp->queue.page_list[i].buf =
-                               dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE,
-                                                  &t, GFP_KERNEL);
-                       if (!qp->queue.page_list[i].buf)
-                               goto err_out_free;
-
-                       memset(qp->queue.page_list[i].buf, 0, PAGE_SIZE);
-
-                       pci_unmap_addr_set(&qp->queue.page_list[i], mapping, t);
-                       dma_list[i] = t;
-               }
-       }
-
-       err = mthca_mr_alloc_phys(dev, pd->pd_num, dma_list, shift,
-                                 npages, 0, size,
-                                 MTHCA_MPT_FLAG_LOCAL_READ,
-                                 &qp->mr);
+       err = mthca_buf_alloc(dev, size, MTHCA_MAX_DIRECT_QP_SIZE,
+                             &qp->queue, &qp->is_direct, pd, 0, &qp->mr);
        if (err)
-               goto err_out_free;
+               goto err_out;
 
-       kfree(dma_list);
        return 0;
 
- err_out_free:
-       if (qp->is_direct) {
-               dma_free_coherent(&dev->pdev->dev, size, qp->queue.direct.buf,
-                                 pci_unmap_addr(&qp->queue.direct, mapping));
-       } else
-               for (i = 0; i < npages; ++i) {
-                       if (qp->queue.page_list[i].buf)
-                               dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
-                                                 qp->queue.page_list[i].buf,
-                                                 pci_unmap_addr(&qp->queue.page_list[i],
-                                                                mapping));
-
-               }
-
- err_out:
+err_out:
        kfree(qp->wrid);
-       kfree(dma_list);
        return err;
 }
 
 static void mthca_free_wqe_buf(struct mthca_dev *dev,
                               struct mthca_qp *qp)
 {
-       int i;
-       int size = PAGE_ALIGN(qp->send_wqe_offset +
-                             (qp->sq.max << qp->sq.wqe_shift));
-
-       if (qp->is_direct) {
-               dma_free_coherent(&dev->pdev->dev, size, qp->queue.direct.buf,
-                                 pci_unmap_addr(&qp->queue.direct, mapping));
-       } else {
-               for (i = 0; i < size / PAGE_SIZE; ++i) {
-                       dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
-                                         qp->queue.page_list[i].buf,
-                                         pci_unmap_addr(&qp->queue.page_list[i],
-                                                        mapping));
-               }
-       }
-
+       mthca_buf_free(dev, PAGE_ALIGN(qp->send_wqe_offset +
+                                      (qp->sq.max << qp->sq.wqe_shift)),
+                      &qp->queue, qp->is_direct, &qp->mr);
        kfree(qp->wrid);
 }
 
@@ -1428,11 +1270,12 @@ void mthca_free_qp(struct mthca_dev *dev,
         * unref the mem-free tables and free the QPN in our table.
         */
        if (!qp->ibqp.uobject) {
-               mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn);
+               mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn,
+                              qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
                if (qp->ibqp.send_cq != qp->ibqp.recv_cq)
-                       mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq)->cqn, qp->qpn);
+                       mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq)->cqn, qp->qpn,
+                                      qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
 
-               mthca_free_mr(dev, &qp->mr);
                mthca_free_memfree(dev, qp);
                mthca_free_wqe_buf(dev, qp);
        }
@@ -1457,6 +1300,7 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
 {
        int header_size;
        int err;
+       u16 pkey;
 
        ib_ud_header_init(256, /* assume a MAD */
                          sqp->ud_header.grh_present,
@@ -1467,8 +1311,8 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
                return err;
        mlx->flags &= ~cpu_to_be32(MTHCA_NEXT_SOLICIT | 1);
        mlx->flags |= cpu_to_be32((!sqp->qp.ibqp.qp_num ? MTHCA_MLX_VL15 : 0) |
-                                 (sqp->ud_header.lrh.destination_lid == 0xffff ?
-                                  MTHCA_MLX_SLR : 0) |
+                                 (sqp->ud_header.lrh.destination_lid ==
+                                  IB_LID_PERMISSIVE ? MTHCA_MLX_SLR : 0) |
                                  (sqp->ud_header.lrh.service_level << 8));
        mlx->rlid = sqp->ud_header.lrh.destination_lid;
        mlx->vcrc = 0;
@@ -1488,18 +1332,16 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
        }
 
        sqp->ud_header.lrh.virtual_lane    = !sqp->qp.ibqp.qp_num ? 15 : 0;
-       if (sqp->ud_header.lrh.destination_lid == 0xffff)
-               sqp->ud_header.lrh.source_lid = 0xffff;
+       if (sqp->ud_header.lrh.destination_lid == IB_LID_PERMISSIVE)
+               sqp->ud_header.lrh.source_lid = IB_LID_PERMISSIVE;
        sqp->ud_header.bth.solicited_event = !!(wr->send_flags & IB_SEND_SOLICITED);
        if (!sqp->qp.ibqp.qp_num)
                ib_get_cached_pkey(&dev->ib_dev, sqp->port,
-                                  sqp->pkey_index,
-                                  &sqp->ud_header.bth.pkey);
+                                  sqp->pkey_index, &pkey);
        else
                ib_get_cached_pkey(&dev->ib_dev, sqp->port,
-                                  wr->wr.ud.pkey_index,
-                                  &sqp->ud_header.bth.pkey);
-       cpu_to_be16s(&sqp->ud_header.bth.pkey);
+                                  wr->wr.ud.pkey_index, &pkey);
+       sqp->ud_header.bth.pkey = cpu_to_be16(pkey);
        sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->wr.ud.remote_qpn);
        sqp->ud_header.bth.psn = cpu_to_be32((sqp->send_psn++) & ((1 << 24) - 1));
        sqp->ud_header.deth.qkey = cpu_to_be32(wr->wr.ud.remote_qkey & 0x80000000 ?
@@ -1742,7 +1584,7 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 
 out:
        if (likely(nreq)) {
-               u32 doorbell[2];
+               __be32 doorbell[2];
 
                doorbell[0] = cpu_to_be32(((qp->sq.next_ind << qp->sq.wqe_shift) +
                                           qp->send_wqe_offset) | f0 | op0);
@@ -1843,7 +1685,7 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
 
 out:
        if (likely(nreq)) {
-               u32 doorbell[2];
+               __be32 doorbell[2];
 
                doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0);
                doorbell[1] = cpu_to_be32((qp->qpn << 8) | nreq);
@@ -2064,7 +1906,7 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 
 out:
        if (likely(nreq)) {
-               u32 doorbell[2];
+               __be32 doorbell[2];
 
                doorbell[0] = cpu_to_be32((nreq << 24)                  |
                                          ((qp->sq.head & 0xffff) << 8) |
@@ -2174,19 +2016,25 @@ out:
 }
 
 int mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,
-                      int index, int *dbd, u32 *new_wqe)
+                      int index, int *dbd, __be32 *new_wqe)
 {
        struct mthca_next_seg *next;
 
+       /*
+        * For SRQs, all WQEs generate a CQE, so we're always at the
+        * end of the doorbell chain.
+        */
+       if (qp->ibqp.srq) {
+               *new_wqe = 0;
+               return 0;
+       }
+
        if (is_send)
                next = get_send_wqe(qp, index);
        else
                next = get_recv_wqe(qp, index);
 
-       if (mthca_is_memfree(dev))
-               *dbd = 1;
-       else
-               *dbd = !!(next->ee_nds & cpu_to_be32(MTHCA_NEXT_DBD));
+       *dbd = !!(next->ee_nds & cpu_to_be32(MTHCA_NEXT_DBD));
        if (next->ee_nds & cpu_to_be32(0x3f))
                *new_wqe = (next->nda_op & cpu_to_be32(~0x3f)) |
                        (next->ee_nds & cpu_to_be32(0x3f));
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
new file mode 100644 (file)
index 0000000..75cd2d8
--- /dev/null
@@ -0,0 +1,591 @@
+/*
+ * Copyright (c) 2005 Cisco Systems. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: mthca_srq.c 3047 2005-08-10 03:59:35Z roland $
+ */
+
+#include "mthca_dev.h"
+#include "mthca_cmd.h"
+#include "mthca_memfree.h"
+#include "mthca_wqe.h"
+
+enum {
+       MTHCA_MAX_DIRECT_SRQ_SIZE = 4 * PAGE_SIZE
+};
+
+struct mthca_tavor_srq_context {
+       __be64 wqe_base_ds;     /* low 6 bits is descriptor size */
+       __be32 state_pd;
+       __be32 lkey;
+       __be32 uar;
+       __be32 wqe_cnt;
+       u32    reserved[2];
+};
+
+struct mthca_arbel_srq_context {
+       __be32 state_logsize_srqn;
+       __be32 lkey;
+       __be32 db_index;
+       __be32 logstride_usrpage;
+       __be64 wqe_base;
+       __be32 eq_pd;
+       __be16 limit_watermark;
+       __be16 wqe_cnt;
+       u16    reserved1;
+       __be16 wqe_counter;
+       u32    reserved2[3];
+};
+
+static void *get_wqe(struct mthca_srq *srq, int n)
+{
+       if (srq->is_direct)
+               return srq->queue.direct.buf + (n << srq->wqe_shift);
+       else
+               return srq->queue.page_list[(n << srq->wqe_shift) >> PAGE_SHIFT].buf +
+                       ((n << srq->wqe_shift) & (PAGE_SIZE - 1));
+}
+
+/*
+ * Return a pointer to the location within a WQE that we're using as a
+ * link when the WQE is in the free list.  We use an offset of 4
+ * because in the Tavor case, posting a WQE may overwrite the first
+ * four bytes of the previous WQE.  The offset avoids corrupting our
+ * free list if the WQE has already completed and been put on the free
+ * list when we post the next WQE.
+ */
+static inline int *wqe_to_link(void *wqe)
+{
+       return (int *) (wqe + 4);
+}
+
+static void mthca_tavor_init_srq_context(struct mthca_dev *dev,
+                                        struct mthca_pd *pd,
+                                        struct mthca_srq *srq,
+                                        struct mthca_tavor_srq_context *context)
+{
+       memset(context, 0, sizeof *context);
+
+       context->wqe_base_ds = cpu_to_be64(1 << (srq->wqe_shift - 4));
+       context->state_pd    = cpu_to_be32(pd->pd_num);
+       context->lkey        = cpu_to_be32(srq->mr.ibmr.lkey);
+
+       if (pd->ibpd.uobject)
+               context->uar =
+                       cpu_to_be32(to_mucontext(pd->ibpd.uobject->context)->uar.index);
+       else
+               context->uar = cpu_to_be32(dev->driver_uar.index);
+}
+
+static void mthca_arbel_init_srq_context(struct mthca_dev *dev,
+                                        struct mthca_pd *pd,
+                                        struct mthca_srq *srq,
+                                        struct mthca_arbel_srq_context *context)
+{
+       int logsize;
+
+       memset(context, 0, sizeof *context);
+
+       logsize = long_log2(srq->max) + srq->wqe_shift;
+       context->state_logsize_srqn = cpu_to_be32(logsize << 24 | srq->srqn);
+       context->lkey = cpu_to_be32(srq->mr.ibmr.lkey);
+       context->db_index = cpu_to_be32(srq->db_index);
+       context->logstride_usrpage = cpu_to_be32((srq->wqe_shift - 4) << 29);
+       if (pd->ibpd.uobject)
+               context->logstride_usrpage |=
+                       cpu_to_be32(to_mucontext(pd->ibpd.uobject->context)->uar.index);
+       else
+               context->logstride_usrpage |= cpu_to_be32(dev->driver_uar.index);
+       context->eq_pd = cpu_to_be32(MTHCA_EQ_ASYNC << 24 | pd->pd_num);
+}
+
+static void mthca_free_srq_buf(struct mthca_dev *dev, struct mthca_srq *srq)
+{
+       mthca_buf_free(dev, srq->max << srq->wqe_shift, &srq->queue,
+                      srq->is_direct, &srq->mr);
+       kfree(srq->wrid);
+}
+
+static int mthca_alloc_srq_buf(struct mthca_dev *dev, struct mthca_pd *pd,
+                              struct mthca_srq *srq)
+{
+       struct mthca_data_seg *scatter;
+       void *wqe;
+       int err;
+       int i;
+
+       if (pd->ibpd.uobject)
+               return 0;
+
+       srq->wrid = kmalloc(srq->max * sizeof (u64), GFP_KERNEL);
+       if (!srq->wrid)
+               return -ENOMEM;
+
+       err = mthca_buf_alloc(dev, srq->max << srq->wqe_shift,
+                             MTHCA_MAX_DIRECT_SRQ_SIZE,
+                             &srq->queue, &srq->is_direct, pd, 1, &srq->mr);
+       if (err) {
+               kfree(srq->wrid);
+               return err;
+       }
+
+       /*
+        * Now initialize the SRQ buffer so that all of the WQEs are
+        * linked into the list of free WQEs.  In addition, set the
+        * scatter list L_Keys to the sentry value of 0x100.
+        */
+       for (i = 0; i < srq->max; ++i) {
+               wqe = get_wqe(srq, i);
+
+               *wqe_to_link(wqe) = i < srq->max - 1 ? i + 1 : -1;
+
+               for (scatter = wqe + sizeof (struct mthca_next_seg);
+                    (void *) scatter < wqe + (1 << srq->wqe_shift);
+                    ++scatter)
+                       scatter->lkey = cpu_to_be32(MTHCA_INVAL_LKEY);
+       }
+
+       return 0;
+}
+
+int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
+                   struct ib_srq_attr *attr, struct mthca_srq *srq)
+{
+       struct mthca_mailbox *mailbox;
+       u8 status;
+       int ds;
+       int err;
+
+       /* Sanity check SRQ size before proceeding */
+       if (attr->max_wr > 16 << 20 || attr->max_sge > 64)
+               return -EINVAL;
+
+       srq->max      = attr->max_wr;
+       srq->max_gs   = attr->max_sge;
+       srq->last     = NULL;
+       srq->counter  = 0;
+
+       if (mthca_is_memfree(dev))
+               srq->max = roundup_pow_of_two(srq->max + 1);
+
+       ds = min(64UL,
+                roundup_pow_of_two(sizeof (struct mthca_next_seg) +
+                                   srq->max_gs * sizeof (struct mthca_data_seg)));
+       srq->wqe_shift = long_log2(ds);
+
+       srq->srqn = mthca_alloc(&dev->srq_table.alloc);
+       if (srq->srqn == -1)
+               return -ENOMEM;
+
+       if (mthca_is_memfree(dev)) {
+               err = mthca_table_get(dev, dev->srq_table.table, srq->srqn);
+               if (err)
+                       goto err_out;
+
+               if (!pd->ibpd.uobject) {
+                       srq->db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_SRQ,
+                                                      srq->srqn, &srq->db);
+                       if (srq->db_index < 0) {
+                               err = -ENOMEM;
+                               goto err_out_icm;
+                       }
+               }
+       }
+
+       mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
+       if (IS_ERR(mailbox)) {
+               err = PTR_ERR(mailbox);
+               goto err_out_db;
+       }
+
+       err = mthca_alloc_srq_buf(dev, pd, srq);
+       if (err)
+               goto err_out_mailbox;
+
+       spin_lock_init(&srq->lock);
+       atomic_set(&srq->refcount, 1);
+       init_waitqueue_head(&srq->wait);
+
+       if (mthca_is_memfree(dev))
+               mthca_arbel_init_srq_context(dev, pd, srq, mailbox->buf);
+       else
+               mthca_tavor_init_srq_context(dev, pd, srq, mailbox->buf);
+
+       err = mthca_SW2HW_SRQ(dev, mailbox, srq->srqn, &status);
+
+       if (err) {
+               mthca_warn(dev, "SW2HW_SRQ failed (%d)\n", err);
+               goto err_out_free_buf;
+       }
+       if (status) {
+               mthca_warn(dev, "SW2HW_SRQ returned status 0x%02x\n",
+                          status);
+               err = -EINVAL;
+               goto err_out_free_buf;
+       }
+
+       spin_lock_irq(&dev->srq_table.lock);
+       if (mthca_array_set(&dev->srq_table.srq,
+                           srq->srqn & (dev->limits.num_srqs - 1),
+                           srq)) {
+               spin_unlock_irq(&dev->srq_table.lock);
+               goto err_out_free_srq;
+       }
+       spin_unlock_irq(&dev->srq_table.lock);
+
+       mthca_free_mailbox(dev, mailbox);
+
+       srq->first_free = 0;
+       srq->last_free  = srq->max - 1;
+
+       return 0;
+
+err_out_free_srq:
+       err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn, &status);
+       if (err)
+               mthca_warn(dev, "HW2SW_SRQ failed (%d)\n", err);
+       else if (status)
+               mthca_warn(dev, "HW2SW_SRQ returned status 0x%02x\n", status);
+
+err_out_free_buf:
+       if (!pd->ibpd.uobject)
+               mthca_free_srq_buf(dev, srq);
+
+err_out_mailbox:
+       mthca_free_mailbox(dev, mailbox);
+
+err_out_db:
+       if (!pd->ibpd.uobject && mthca_is_memfree(dev))
+               mthca_free_db(dev, MTHCA_DB_TYPE_SRQ, srq->db_index);
+
+err_out_icm:
+       mthca_table_put(dev, dev->srq_table.table, srq->srqn);
+
+err_out:
+       mthca_free(&dev->srq_table.alloc, srq->srqn);
+
+       return err;
+}
+
+void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
+{
+       struct mthca_mailbox *mailbox;
+       int err;
+       u8 status;
+
+       mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
+       if (IS_ERR(mailbox)) {
+               mthca_warn(dev, "No memory for mailbox to free SRQ.\n");
+               return;
+       }
+
+       err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn, &status);
+       if (err)
+               mthca_warn(dev, "HW2SW_SRQ failed (%d)\n", err);
+       else if (status)
+               mthca_warn(dev, "HW2SW_SRQ returned status 0x%02x\n", status);
+
+       spin_lock_irq(&dev->srq_table.lock);
+       mthca_array_clear(&dev->srq_table.srq,
+                         srq->srqn & (dev->limits.num_srqs - 1));
+       spin_unlock_irq(&dev->srq_table.lock);
+
+       atomic_dec(&srq->refcount);
+       wait_event(srq->wait, !atomic_read(&srq->refcount));
+
+       if (!srq->ibsrq.uobject) {
+               mthca_free_srq_buf(dev, srq);
+               if (mthca_is_memfree(dev))
+                       mthca_free_db(dev, MTHCA_DB_TYPE_SRQ, srq->db_index);
+       }
+
+       mthca_table_put(dev, dev->srq_table.table, srq->srqn);
+       mthca_free(&dev->srq_table.alloc, srq->srqn);
+       mthca_free_mailbox(dev, mailbox);
+}
+
+void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
+                    enum ib_event_type event_type)
+{
+       struct mthca_srq *srq;
+       struct ib_event event;
+
+       spin_lock(&dev->srq_table.lock);
+       srq = mthca_array_get(&dev->srq_table.srq, srqn & (dev->limits.num_srqs - 1));
+       if (srq)
+               atomic_inc(&srq->refcount);
+       spin_unlock(&dev->srq_table.lock);
+
+       if (!srq) {
+               mthca_warn(dev, "Async event for bogus SRQ %08x\n", srqn);
+               return;
+       }
+
+       if (!srq->ibsrq.event_handler)
+               goto out;
+
+       event.device      = &dev->ib_dev;
+       event.event       = event_type;
+       event.element.srq  = &srq->ibsrq;
+       srq->ibsrq.event_handler(&event, srq->ibsrq.srq_context);
+
+out:
+       if (atomic_dec_and_test(&srq->refcount))
+               wake_up(&srq->wait);
+}
+
+/*
+ * This function must be called with IRQs disabled.
+ */
+void mthca_free_srq_wqe(struct mthca_srq *srq, u32 wqe_addr)
+{
+       int ind;
+
+       ind = wqe_addr >> srq->wqe_shift;
+
+       spin_lock(&srq->lock);
+
+       if (likely(srq->first_free >= 0))
+               *wqe_to_link(get_wqe(srq, srq->last_free)) = ind;
+       else
+               srq->first_free = ind;
+
+       *wqe_to_link(get_wqe(srq, ind)) = -1;
+       srq->last_free = ind;
+
+       spin_unlock(&srq->lock);
+}
+
+int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+                             struct ib_recv_wr **bad_wr)
+{
+       struct mthca_dev *dev = to_mdev(ibsrq->device);
+       struct mthca_srq *srq = to_msrq(ibsrq);
+       unsigned long flags;
+       int err = 0;
+       int first_ind;
+       int ind;
+       int next_ind;
+       int nreq;
+       int i;
+       void *wqe;
+       void *prev_wqe;
+
+       spin_lock_irqsave(&srq->lock, flags);
+
+       first_ind = srq->first_free;
+
+       for (nreq = 0; wr; ++nreq, wr = wr->next) {
+               ind = srq->first_free;
+
+               if (ind < 0) {
+                       mthca_err(dev, "SRQ %06x full\n", srq->srqn);
+                       err = -ENOMEM;
+                       *bad_wr = wr;
+                       return nreq;
+               }
+
+               wqe       = get_wqe(srq, ind);
+               next_ind  = *wqe_to_link(wqe);
+               prev_wqe  = srq->last;
+               srq->last = wqe;
+
+               ((struct mthca_next_seg *) wqe)->nda_op = 0;
+               ((struct mthca_next_seg *) wqe)->ee_nds = 0;
+               /* flags field will always remain 0 */
+
+               wqe += sizeof (struct mthca_next_seg);
+
+               if (unlikely(wr->num_sge > srq->max_gs)) {
+                       err = -EINVAL;
+                       *bad_wr = wr;
+                       srq->last = prev_wqe;
+                       return nreq;
+               }
+
+               for (i = 0; i < wr->num_sge; ++i) {
+                       ((struct mthca_data_seg *) wqe)->byte_count =
+                               cpu_to_be32(wr->sg_list[i].length);
+                       ((struct mthca_data_seg *) wqe)->lkey =
+                               cpu_to_be32(wr->sg_list[i].lkey);
+                       ((struct mthca_data_seg *) wqe)->addr =
+                               cpu_to_be64(wr->sg_list[i].addr);
+                       wqe += sizeof (struct mthca_data_seg);
+               }
+
+               if (i < srq->max_gs) {
+                       ((struct mthca_data_seg *) wqe)->byte_count = 0;
+                       ((struct mthca_data_seg *) wqe)->lkey = cpu_to_be32(MTHCA_INVAL_LKEY);
+                       ((struct mthca_data_seg *) wqe)->addr = 0;
+               }
+
+               if (likely(prev_wqe)) {
+                       ((struct mthca_next_seg *) prev_wqe)->nda_op =
+                               cpu_to_be32((ind << srq->wqe_shift) | 1);
+                       wmb();
+                       ((struct mthca_next_seg *) prev_wqe)->ee_nds =
+                               cpu_to_be32(MTHCA_NEXT_DBD);
+               }
+
+               srq->wrid[ind]  = wr->wr_id;
+               srq->first_free = next_ind;
+       }
+
+       return nreq;
+
+       if (likely(nreq)) {
+               __be32 doorbell[2];
+
+               doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift);
+               doorbell[1] = cpu_to_be32((srq->srqn << 8) | nreq);
+
+               /*
+                * Make sure that descriptors are written before
+                * doorbell is rung.
+                */
+               wmb();
+
+               mthca_write64(doorbell,
+                             dev->kar + MTHCA_RECEIVE_DOORBELL,
+                             MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+       }
+
+       spin_unlock_irqrestore(&srq->lock, flags);
+       return err;
+}
+
+int mthca_arbel_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+                             struct ib_recv_wr **bad_wr)
+{
+       struct mthca_dev *dev = to_mdev(ibsrq->device);
+       struct mthca_srq *srq = to_msrq(ibsrq);
+       unsigned long flags;
+       int err = 0;
+       int ind;
+       int next_ind;
+       int nreq;
+       int i;
+       void *wqe;
+
+       spin_lock_irqsave(&srq->lock, flags);
+
+       for (nreq = 0; wr; ++nreq, wr = wr->next) {
+               ind = srq->first_free;
+
+               if (ind < 0) {
+                       mthca_err(dev, "SRQ %06x full\n", srq->srqn);
+                       err = -ENOMEM;
+                       *bad_wr = wr;
+                       return nreq;
+               }
+
+               wqe       = get_wqe(srq, ind);
+               next_ind  = *wqe_to_link(wqe);
+
+               ((struct mthca_next_seg *) wqe)->nda_op =
+                       cpu_to_be32((next_ind << srq->wqe_shift) | 1);
+               ((struct mthca_next_seg *) wqe)->ee_nds = 0;
+               /* flags field will always remain 0 */
+
+               wqe += sizeof (struct mthca_next_seg);
+
+               if (unlikely(wr->num_sge > srq->max_gs)) {
+                       err = -EINVAL;
+                       *bad_wr = wr;
+                       return nreq;
+               }
+
+               for (i = 0; i < wr->num_sge; ++i) {
+                       ((struct mthca_data_seg *) wqe)->byte_count =
+                               cpu_to_be32(wr->sg_list[i].length);
+                       ((struct mthca_data_seg *) wqe)->lkey =
+                               cpu_to_be32(wr->sg_list[i].lkey);
+                       ((struct mthca_data_seg *) wqe)->addr =
+                               cpu_to_be64(wr->sg_list[i].addr);
+                       wqe += sizeof (struct mthca_data_seg);
+               }
+
+               if (i < srq->max_gs) {
+                       ((struct mthca_data_seg *) wqe)->byte_count = 0;
+                       ((struct mthca_data_seg *) wqe)->lkey = cpu_to_be32(MTHCA_INVAL_LKEY);
+                       ((struct mthca_data_seg *) wqe)->addr = 0;
+               }
+
+               srq->wrid[ind]  = wr->wr_id;
+               srq->first_free = next_ind;
+       }
+
+       if (likely(nreq)) {
+               srq->counter += nreq;
+
+               /*
+                * Make sure that descriptors are written before
+                * we write doorbell record.
+                */
+               wmb();
+               *srq->db = cpu_to_be32(srq->counter);
+       }
+
+       spin_unlock_irqrestore(&srq->lock, flags);
+       return err;
+}
+
+int __devinit mthca_init_srq_table(struct mthca_dev *dev)
+{
+       int err;
+
+       if (!(dev->mthca_flags & MTHCA_FLAG_SRQ))
+               return 0;
+
+       spin_lock_init(&dev->srq_table.lock);
+
+       err = mthca_alloc_init(&dev->srq_table.alloc,
+                              dev->limits.num_srqs,
+                              dev->limits.num_srqs - 1,
+                              dev->limits.reserved_srqs);
+       if (err)
+               return err;
+
+       err = mthca_array_init(&dev->srq_table.srq,
+                              dev->limits.num_srqs);
+       if (err)
+               mthca_alloc_cleanup(&dev->srq_table.alloc);
+
+       return err;
+}
+
+void __devexit mthca_cleanup_srq_table(struct mthca_dev *dev)
+{
+       if (!(dev->mthca_flags & MTHCA_FLAG_SRQ))
+               return;
+
+       mthca_array_cleanup(&dev->srq_table.srq, dev->limits.num_srqs);
+       mthca_alloc_cleanup(&dev->srq_table.alloc);
+}
index 3024c1b..41613ec 100644 (file)
@@ -69,6 +69,17 @@ struct mthca_create_cq_resp {
        __u32 reserved;
 };
 
+struct mthca_create_srq {
+       __u32 lkey;
+       __u32 db_index;
+       __u64 db_page;
+};
+
+struct mthca_create_srq_resp {
+       __u32 srqn;
+       __u32 reserved;
+};
+
 struct mthca_create_qp {
        __u32 lkey;
        __u32 reserved;
diff --git a/drivers/infiniband/hw/mthca/mthca_wqe.h b/drivers/infiniband/hw/mthca/mthca_wqe.h
new file mode 100644 (file)
index 0000000..1f4c0ff
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2005 Cisco Systems. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: mthca_wqe.h 3047 2005-08-10 03:59:35Z roland $
+ */
+
+#ifndef MTHCA_WQE_H
+#define MTHCA_WQE_H
+
+#include <linux/types.h>
+
+enum {
+       MTHCA_NEXT_DBD       = 1 << 7,
+       MTHCA_NEXT_FENCE     = 1 << 6,
+       MTHCA_NEXT_CQ_UPDATE = 1 << 3,
+       MTHCA_NEXT_EVENT_GEN = 1 << 2,
+       MTHCA_NEXT_SOLICIT   = 1 << 1,
+
+       MTHCA_MLX_VL15       = 1 << 17,
+       MTHCA_MLX_SLR        = 1 << 16
+};
+
+enum {
+       MTHCA_INVAL_LKEY = 0x100
+};
+
+struct mthca_next_seg {
+       __be32 nda_op;          /* [31:6] next WQE [4:0] next opcode */
+       __be32 ee_nds;          /* [31:8] next EE  [7] DBD [6] F [5:0] next WQE size */
+       __be32 flags;           /* [3] CQ [2] Event [1] Solicit */
+       __be32 imm;             /* immediate data */
+};
+
+struct mthca_tavor_ud_seg {
+       u32    reserved1;
+       __be32 lkey;
+       __be64 av_addr;
+       u32    reserved2[4];
+       __be32 dqpn;
+       __be32 qkey;
+       u32    reserved3[2];
+};
+
+struct mthca_arbel_ud_seg {
+       __be32 av[8];
+       __be32 dqpn;
+       __be32 qkey;
+       u32    reserved[2];
+};
+
+struct mthca_bind_seg {
+       __be32 flags;           /* [31] Atomic [30] rem write [29] rem read */
+       u32    reserved;
+       __be32 new_rkey;
+       __be32 lkey;
+       __be64 addr;
+       __be64 length;
+};
+
+struct mthca_raddr_seg {
+       __be64 raddr;
+       __be32 rkey;
+       u32    reserved;
+};
+
+struct mthca_atomic_seg {
+       __be64 swap_add;
+       __be64 compare;
+};
+
+struct mthca_data_seg {
+       __be32 byte_count;
+       __be32 lkey;
+       __be64 addr;
+};
+
+struct mthca_mlx_seg {
+       __be32 nda_op;
+       __be32 nds;
+       __be32 flags;           /* [17] VL15 [16] SLR [14:12] static rate
+                                  [11:8] SL [3] C [2] E */
+       __be16 rlid;
+       __be16 vcrc;
+};
+
+#endif /* MTHCA_WQE_H */
index 394bc08..8935e74 100644 (file)
@@ -1,5 +1,3 @@
-EXTRA_CFLAGS += -Idrivers/infiniband/include
-
 obj-$(CONFIG_INFINIBAND_IPOIB)                 += ib_ipoib.o
 
 ib_ipoib-y                                     := ipoib_main.o \
index 04c98f5..bea960b 100644 (file)
@@ -1,5 +1,7 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2004 Voltaire, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -49,9 +51,9 @@
 #include <asm/atomic.h>
 #include <asm/semaphore.h>
 
-#include <ib_verbs.h>
-#include <ib_pack.h>
-#include <ib_sa.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_pack.h>
+#include <rdma/ib_sa.h>
 
 /* constants */
 
@@ -88,8 +90,8 @@ enum {
 /* structs */
 
 struct ipoib_header {
-       u16 proto;
-       u16 reserved;
+       __be16  proto;
+       u16     reserved;
 };
 
 struct ipoib_pseudoheader {
index a84e5fe..38b150f 100644 (file)
@@ -97,7 +97,7 @@ static int ipoib_mcg_seq_show(struct seq_file *file, void *iter_ptr)
 
                for (n = 0, i = 0; i < sizeof mgid / 2; ++i) {
                        n += sprintf(gid_buf + n, "%x",
-                                    be16_to_cpu(((u16 *)mgid.raw)[i]));
+                                    be16_to_cpu(((__be16 *) mgid.raw)[i]));
                        if (i < sizeof mgid / 2 - 1)
                                gid_buf[n++] = ':';
                }
index eee8236..ef0e389 100644 (file)
@@ -1,5 +1,8 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -35,7 +38,7 @@
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 
-#include <ib_cache.h>
+#include <rdma/ib_cache.h>
 
 #include "ipoib.h"
 
index 6f60abb..0e8ac13 100644 (file)
@@ -1,5 +1,7 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2004 Voltaire, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -34,7 +36,6 @@
 
 #include "ipoib.h"
 
-#include <linux/version.h>
 #include <linux/module.h>
 
 #include <linux/init.h>
@@ -600,14 +601,15 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
                        ipoib_mcast_send(dev, (union ib_gid *) (phdr->hwaddr + 4), skb);
                } else {
-                       /* unicast GID -- should be ARP reply */
+                       /* unicast GID -- should be ARP or RARP reply */
 
-                       if (be16_to_cpup((u16 *) skb->data) != ETH_P_ARP) {
+                       if ((be16_to_cpup((__be16 *) skb->data) != ETH_P_ARP) &&
+                           (be16_to_cpup((__be16 *) skb->data) != ETH_P_RARP)) {
                                ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x "
                                           IPOIB_GID_FMT "\n",
                                           skb->dst ? "neigh" : "dst",
-                                          be16_to_cpup((u16 *) skb->data),
-                                          be32_to_cpup((u32 *) phdr->hwaddr),
+                                          be16_to_cpup((__be16 *) skb->data),
+                                          be32_to_cpup((__be32 *) phdr->hwaddr),
                                           IPOIB_GID_ARG(*(union ib_gid *) (phdr->hwaddr + 4)));
                                dev_kfree_skb_any(skb);
                                ++priv->stats.tx_dropped;
@@ -670,7 +672,7 @@ static void ipoib_set_mcast_list(struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
 
-       schedule_work(&priv->restart_task);
+       queue_work(ipoib_workqueue, &priv->restart_task);
 }
 
 static void ipoib_neigh_destructor(struct neighbour *n)
@@ -779,15 +781,11 @@ void ipoib_dev_cleanup(struct net_device *dev)
 
        ipoib_ib_dev_cleanup(dev);
 
-       if (priv->rx_ring) {
-               kfree(priv->rx_ring);
-               priv->rx_ring = NULL;
-       }
+       kfree(priv->rx_ring);
+       kfree(priv->tx_ring);
 
-       if (priv->tx_ring) {
-               kfree(priv->tx_ring);
-               priv->tx_ring = NULL;
-       }
+       priv->rx_ring = NULL;
+       priv->tx_ring = NULL;
 }
 
 static void ipoib_setup(struct net_device *dev)
@@ -885,6 +883,12 @@ static ssize_t create_child(struct class_device *cdev,
        if (pkey < 0 || pkey > 0xffff)
                return -EINVAL;
 
+       /*
+        * Set the full membership bit, so that we join the right
+        * broadcast group, etc.
+        */
+       pkey |= 0x8000;
+
        ret = ipoib_vlan_add(container_of(cdev, struct net_device, class_dev),
                             pkey);
 
@@ -937,6 +941,12 @@ static struct net_device *ipoib_add_port(const char *format,
                goto alloc_mem_failed;
        }
 
+       /*
+        * Set the full membership bit, so that we join the right
+        * broadcast group, etc.
+        */
+       priv->pkey |= 0x8000;
+
        priv->dev->broadcast[8] = priv->pkey >> 8;
        priv->dev->broadcast[9] = priv->pkey & 0xff;
 
index 70208c3..aca7aea 100644 (file)
@@ -1,5 +1,7 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2004 Voltaire, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -357,7 +359,7 @@ static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast)
 
        rec.mgid     = mcast->mcmember.mgid;
        rec.port_gid = priv->local_gid;
-       rec.pkey     = be16_to_cpu(priv->pkey);
+       rec.pkey     = cpu_to_be16(priv->pkey);
 
        ret = ib_sa_mcmember_rec_set(priv->ca, priv->port, &rec,
                                     IB_SA_MCMEMBER_REC_MGID            |
@@ -457,7 +459,7 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
 
        rec.mgid     = mcast->mcmember.mgid;
        rec.port_gid = priv->local_gid;
-       rec.pkey     = be16_to_cpu(priv->pkey);
+       rec.pkey     = cpu_to_be16(priv->pkey);
 
        comp_mask =
                IB_SA_MCMEMBER_REC_MGID         |
@@ -646,7 +648,7 @@ static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast)
 
        rec.mgid     = mcast->mcmember.mgid;
        rec.port_gid = priv->local_gid;
-       rec.pkey     = be16_to_cpu(priv->pkey);
+       rec.pkey     = cpu_to_be16(priv->pkey);
 
        /* Remove ourselves from the multicast group */
        ret = ipoib_mcast_detach(dev, be16_to_cpu(mcast->mcmember.mlid),
index 4933edf..79f59d0 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -32,7 +33,7 @@
  * $Id: ipoib_verbs.c 1349 2004-12-16 21:09:43Z roland $
  */
 
-#include <ib_cache.h>
+#include <rdma/ib_cache.h>
 
 #include "ipoib.h"
 
index 94b8ea8..332d730 100644 (file)
@@ -32,7 +32,6 @@
  * $Id: ipoib_vlan.c 1349 2004-12-16 21:09:43Z roland $
  */
 
-#include <linux/version.h>
 #include <linux/module.h>
 
 #include <linux/init.h>
index 1ab5f2d..70f0518 100644 (file)
@@ -275,9 +275,9 @@ static int __init ns558_init(void)
 
 static void __exit ns558_exit(void)
 {
-       struct ns558 *ns558;
+       struct ns558 *ns558, *safe;
 
-       list_for_each_entry(ns558, &ns558_list, node) {
+       list_for_each_entry_safe(ns558, safe, &ns558_list, node) {
                gameport_unregister_port(ns558->gameport);
                release_region(ns558->io & ~(ns558->size - 1), ns558->size);
                kfree(ns558);
index f8570fd..3abd7fc 100644 (file)
@@ -191,8 +191,10 @@ static int __init capifs_init(void)
        err = register_filesystem(&capifs_fs_type);
        if (!err) {
                capifs_mnt = kern_mount(&capifs_fs_type);
-               if (IS_ERR(capifs_mnt))
+               if (IS_ERR(capifs_mnt)) {
                        err = PTR_ERR(capifs_mnt);
+                       unregister_filesystem(&capifs_fs_type);
+               }
        }
        if (!err)
                printk(KERN_NOTICE "capifs: Rev %s\n", rev);
index 6c7b8bf..801c98f 100644 (file)
@@ -134,6 +134,7 @@ config HISAX_AVM_A1
 
 config HISAX_FRITZPCI
        bool "AVM PnP/PCI (Fritz!PnP/PCI)"
+       depends on BROKEN || !PPC64
        help
          This enables HiSax support for the AVM "Fritz!PnP" and "Fritz!PCI".
          See <file:Documentation/isdn/README.HiSax> on how to configure it.
index e0d1b01..386df71 100644 (file)
@@ -1650,7 +1650,7 @@ static void __exit icn_exit(void)
 {
        isdn_ctrl cmd;
        icn_card *card = cards;
-       icn_card *last;
+       icn_card *last, *tmpcard;
        int i;
        unsigned long flags;
 
@@ -1670,8 +1670,9 @@ static void __exit icn_exit(void)
                        for (i = 0; i < ICN_BCH; i++)
                                icn_free_queue(card, i);
                }
-               card = card->next;
+               tmpcard = card->next;
                spin_unlock_irqrestore(&card->lock, flags);
+               card = tmpcard;
        }
        card = cards;
        cards = NULL;
index 65ab64c..bc3e096 100644 (file)
@@ -103,7 +103,7 @@ config PMAC_MEDIABAY
 # on non-powerbook machines (but only on PMU based ones AFAIK)
 config PMAC_BACKLIGHT
        bool "Backlight control for LCD screens"
-       depends on ADB_PMU
+       depends on ADB_PMU && (BROKEN || !PPC64)
        help
          Say Y here to build in code to manage the LCD backlight on a
          Macintosh PowerBook.  With this code, the backlight will be turned
index 70bca95..41df4cd 100644 (file)
@@ -818,8 +818,7 @@ int bitmap_unplug(struct bitmap *bitmap)
        return 0;
 }
 
-static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
-       unsigned long sectors, int in_sync);
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset);
 /* * bitmap_init_from_disk -- called at bitmap_create time to initialize
  * the in-memory bitmap from the on-disk bitmap -- also, sets up the
  * memory mapping of the bitmap file
@@ -828,7 +827,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
  *   previously kicked from the array, we mark all the bits as
  *   1's in order to cause a full resync.
  */
-static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
+static int bitmap_init_from_disk(struct bitmap *bitmap)
 {
        unsigned long i, chunks, index, oldindex, bit;
        struct page *page = NULL, *oldpage = NULL;
@@ -929,8 +928,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
                }
                if (test_bit(bit, page_address(page))) {
                        /* if the disk bit is set, set the memory bit */
-                       bitmap_set_memory_bits(bitmap,
-                                       i << CHUNK_BLOCK_SHIFT(bitmap), 1, in_sync);
+                       bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap));
                        bit_cnt++;
                }
        }
@@ -1426,35 +1424,53 @@ void bitmap_close_sync(struct bitmap *bitmap)
        }
 }
 
-static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
-                                  unsigned long sectors, int in_sync)
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset)
 {
        /* For each chunk covered by any of these sectors, set the
-        * counter to 1 and set resync_needed unless in_sync.  They should all
+        * counter to 1 and set resync_needed.  They should all
         * be 0 at this point
         */
-       while (sectors) {
-               int secs;
-               bitmap_counter_t *bmc;
-               spin_lock_irq(&bitmap->lock);
-               bmc = bitmap_get_counter(bitmap, offset, &secs, 1);
-               if (!bmc) {
-                       spin_unlock_irq(&bitmap->lock);
-                       return;
-               }
-               if (! *bmc) {
-                       struct page *page;
-                       *bmc = 1 | (in_sync? 0 : NEEDED_MASK);
-                       bitmap_count_page(bitmap, offset, 1);
-                       page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
-                       set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
-               }
+
+       int secs;
+       bitmap_counter_t *bmc;
+       spin_lock_irq(&bitmap->lock);
+       bmc = bitmap_get_counter(bitmap, offset, &secs, 1);
+       if (!bmc) {
                spin_unlock_irq(&bitmap->lock);
-               if (sectors > secs)
-                       sectors -= secs;
-               else
-                       sectors = 0;
+               return;
+       }
+       if (! *bmc) {
+               struct page *page;
+               *bmc = 1 | NEEDED_MASK;
+               bitmap_count_page(bitmap, offset, 1);
+               page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
+               set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
        }
+       spin_unlock_irq(&bitmap->lock);
+
+}
+
+/*
+ * flush out any pending updates
+ */
+void bitmap_flush(mddev_t *mddev)
+{
+       struct bitmap *bitmap = mddev->bitmap;
+       int sleep;
+
+       if (!bitmap) /* there was no bitmap */
+               return;
+
+       /* run the daemon_work three time to ensure everything is flushed
+        * that can be
+        */
+       sleep = bitmap->daemon_sleep;
+       bitmap->daemon_sleep = 0;
+       bitmap_daemon_work(bitmap);
+       bitmap_daemon_work(bitmap);
+       bitmap_daemon_work(bitmap);
+       bitmap->daemon_sleep = sleep;
+       bitmap_update_sb(bitmap);
 }
 
 /*
@@ -1565,7 +1581,8 @@ int bitmap_create(mddev_t *mddev)
 
        /* now that we have some pages available, initialize the in-memory
         * bitmap from the on-disk bitmap */
-       err = bitmap_init_from_disk(bitmap, mddev->recovery_cp == MaxSector);
+       err = bitmap_init_from_disk(bitmap);
+
        if (err)
                return err;
 
index 12031c9..b08df8b 100644 (file)
@@ -1230,7 +1230,7 @@ static int __init dm_mirror_init(void)
        if (r)
                return r;
 
-       _kmirrord_wq = create_workqueue("kmirrord");
+       _kmirrord_wq = create_singlethread_workqueue("kmirrord");
        if (!_kmirrord_wq) {
                DMERR("couldn't start kmirrord");
                dm_dirty_log_exit();
index 6580e0f..20ca80b 100644 (file)
@@ -256,8 +256,7 @@ static inline void mddev_unlock(mddev_t * mddev)
 {
        up(&mddev->reconfig_sem);
 
-       if (mddev->thread)
-               md_wakeup_thread(mddev->thread);
+       md_wakeup_thread(mddev->thread);
 }
 
 mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr)
@@ -623,6 +622,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                mddev->raid_disks = sb->raid_disks;
                mddev->size = sb->size;
                mddev->events = md_event(sb);
+               mddev->bitmap_offset = 0;
 
                if (sb->state & (1<<MD_SB_CLEAN))
                        mddev->recovery_cp = MaxSector;
@@ -938,6 +938,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                mddev->raid_disks = le32_to_cpu(sb->raid_disks);
                mddev->size = le64_to_cpu(sb->size)/2;
                mddev->events = le64_to_cpu(sb->events);
+               mddev->bitmap_offset = 0;
                
                mddev->recovery_cp = le64_to_cpu(sb->resync_offset);
                memcpy(mddev->uuid, sb->set_uuid, 16);
@@ -1688,6 +1689,7 @@ static int do_md_run(mddev_t * mddev)
        mddev->pers = pers[pnum];
        spin_unlock(&pers_lock);
 
+       mddev->recovery = 0;
        mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
 
        /* before we start the array running, initialise the bitmap */
@@ -1712,6 +1714,7 @@ static int do_md_run(mddev_t * mddev)
        mddev->in_sync = 1;
        
        set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+       md_wakeup_thread(mddev->thread);
        
        if (mddev->sb_dirty)
                md_update_sb(mddev);
@@ -1798,6 +1801,8 @@ static int do_md_stop(mddev_t * mddev, int ro)
                                goto out;
                        mddev->ro = 1;
                } else {
+                       bitmap_flush(mddev);
+                       wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0);
                        if (mddev->ro)
                                set_disk_ro(disk, 0);
                        blk_queue_make_request(mddev->queue, md_fail_request);
@@ -1822,6 +1827,7 @@ static int do_md_stop(mddev_t * mddev, int ro)
                fput(mddev->bitmap_file);
                mddev->bitmap_file = NULL;
        }
+       mddev->bitmap_offset = 0;
 
        /*
         * Free resources if final stop
@@ -2231,8 +2237,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
                        export_rdev(rdev);
 
                set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
-               if (mddev->thread)
-                       md_wakeup_thread(mddev->thread);
+               md_wakeup_thread(mddev->thread);
                return err;
        }
 
@@ -3484,7 +3489,6 @@ static void md_do_sync(mddev_t *mddev)
                        goto skip;
                }
                ITERATE_MDDEV(mddev2,tmp) {
-                       printk(".");
                        if (mddev2 == mddev)
                                continue;
                        if (mddev2->curr_resync && 
@@ -4007,3 +4011,5 @@ EXPORT_SYMBOL(md_wakeup_thread);
 EXPORT_SYMBOL(md_print_devices);
 EXPORT_SYMBOL(md_check_recovery);
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("md");
+MODULE_ALIAS_BLOCKDEV_MAJOR(MD_MAJOR);
index d3a64a0..51d9645 100644 (file)
@@ -893,7 +893,6 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
        if (!uptodate) {
                md_error(r1_bio->mddev,
                         conf->mirrors[r1_bio->read_disk].rdev);
-               set_bit(R1BIO_Degraded, &r1_bio->state);
        } else
                set_bit(R1BIO_Uptodate, &r1_bio->state);
        rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev);
@@ -918,10 +917,9 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
                        mirror = i;
                        break;
                }
-       if (!uptodate) {
+       if (!uptodate)
                md_error(mddev, conf->mirrors[mirror].rdev);
-               set_bit(R1BIO_Degraded, &r1_bio->state);
-       }
+
        update_head_pos(mirror, r1_bio);
 
        if (atomic_dec_and_test(&r1_bio->remaining)) {
@@ -1109,6 +1107,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
        int i;
        int write_targets = 0;
        int sync_blocks;
+       int still_degraded = 0;
 
        if (!conf->r1buf_pool)
        {
@@ -1137,7 +1136,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
                return 0;
        }
 
-       if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, mddev->degraded) &&
+       /* before building a request, check if we can skip these blocks..
+        * This call the bitmap_start_sync doesn't actually record anything
+        */
+       if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
            !conf->fullsync) {
                /* We can skip this block, and probably several more */
                *skipped = 1;
@@ -1203,24 +1205,23 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
                if (i == disk) {
                        bio->bi_rw = READ;
                        bio->bi_end_io = end_sync_read;
-               } else if (conf->mirrors[i].rdev &&
-                          !conf->mirrors[i].rdev->faulty &&
-                          (!conf->mirrors[i].rdev->in_sync ||
-                           sector_nr + RESYNC_SECTORS > mddev->recovery_cp)) {
+               } else if (conf->mirrors[i].rdev == NULL ||
+                          conf->mirrors[i].rdev->faulty) {
+                       still_degraded = 1;
+                       continue;
+               } else if (!conf->mirrors[i].rdev->in_sync ||
+                          sector_nr + RESYNC_SECTORS > mddev->recovery_cp) {
                        bio->bi_rw = WRITE;
                        bio->bi_end_io = end_sync_write;
                        write_targets ++;
                } else
+                       /* no need to read or write here */
                        continue;
                bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset;
                bio->bi_bdev = conf->mirrors[i].rdev->bdev;
                bio->bi_private = r1_bio;
        }
 
-       if (write_targets + 1 < conf->raid_disks)
-               /* array degraded, can't clear bitmap */
-               set_bit(R1BIO_Degraded, &r1_bio->state);
-
        if (write_targets == 0) {
                /* There is nowhere to write, so all non-sync
                 * drives must be failed - so we are finished
@@ -1243,7 +1244,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
                        break;
                if (sync_blocks == 0) {
                        if (!bitmap_start_sync(mddev->bitmap, sector_nr,
-                                       &sync_blocks, mddev->degraded) &&
+                                       &sync_blocks, still_degraded) &&
                                        !conf->fullsync)
                                break;
                        if (sync_blocks < (PAGE_SIZE>>9))
index 4698d5f..43f231a 100644 (file)
@@ -1653,6 +1653,7 @@ static int run (mddev_t *mddev)
 
        /* device size must be a multiple of chunk size */
        mddev->size &= ~(mddev->chunk_size/1024 -1);
+       mddev->resync_max_sectors = mddev->size << 1;
 
        if (!conf->chunk_size || conf->chunk_size % 4) {
                printk(KERN_ERR "raid5: invalid chunk size %d for %s\n",
index f5ee168..495dee1 100644 (file)
@@ -1813,6 +1813,7 @@ static int run (mddev_t *mddev)
 
        /* device size must be a multiple of chunk size */
        mddev->size &= ~(mddev->chunk_size/1024 -1);
+       mddev->resync_max_sectors = mddev->size << 1;
 
        if (conf->raid_disks < 4) {
                printk(KERN_ERR "raid6: not enough configured devices for %s (%d, minimum 4)\n",
index 63b626f..9b9d6f8 100644 (file)
@@ -70,13 +70,22 @@ EXPORT_SYMBOL(dibusb_power_ctrl);
 
 int dibusb2_0_streaming_ctrl(struct dvb_usb_device *d, int onoff)
 {
-       u8 b[2];
-       b[0] = DIBUSB_REQ_SET_IOCTL;
-       b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
+       u8 b[3] = { 0 };
+       int ret;
+
+       if ((ret = dibusb_streaming_ctrl(d,onoff)) < 0)
+               return ret;
 
-       dvb_usb_generic_write(d,b,3);
+       if (onoff) {
+               b[0] = DIBUSB_REQ_SET_STREAMING_MODE;
+               b[1] = 0x00;
+               if ((ret = dvb_usb_generic_write(d,b,2)) < 0)
+                       return ret;
+       }
 
-       return dibusb_streaming_ctrl(d,onoff);
+       b[0] = DIBUSB_REQ_SET_IOCTL;
+       b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
+       return dvb_usb_generic_write(d,b,3);
 }
 EXPORT_SYMBOL(dibusb2_0_streaming_ctrl);
 
index 3491ff4..6fa9210 100644 (file)
@@ -23,12 +23,12 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
         */
        if (newfeedcount == 0) {
                deb_ts("stop feeding\n");
+               dvb_usb_urb_kill(d);
 
                if (d->props.streaming_ctrl != NULL)
                        if ((ret = d->props.streaming_ctrl(d,0)))
                                err("error while stopping stream.");
 
-               dvb_usb_urb_kill(d);
        }
 
        d->feedcount = newfeedcount;
@@ -44,6 +44,8 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
         * for reception.
         */
        if (d->feedcount == onoff && d->feedcount > 0) {
+               deb_ts("submitting all URBs\n");
+               dvb_usb_urb_submit(d);
 
                deb_ts("controlling pid parser\n");
                if (d->props.caps & DVB_USB_HAS_PID_FILTER &&
@@ -59,7 +61,6 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
                                return -ENODEV;
                        }
 
-               dvb_usb_urb_submit(d);
        }
        return 0;
 }
index e83256d..a50a41f 100644 (file)
@@ -188,7 +188,7 @@ config DVB_BCM3510
          support this frontend.
 
 config DVB_LGDT330X
-       tristate "LGDT3302 or LGDT3303 based (DViCO FusionHDTV Gold)"
+       tristate "LG Electronics LGDT3302/LGDT3303 based"
        depends on DVB_CORE
        help
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
index 5264310..536c35d 100644 (file)
@@ -225,6 +225,22 @@ struct dvb_pll_desc dvb_pll_tua6034 = {
 };
 EXPORT_SYMBOL(dvb_pll_tua6034);
 
+/* Infineon TUA6034
+ * used in LG Innotek TDVS-H062F
+ */
+struct dvb_pll_desc dvb_pll_tdvs_tua6034 = {
+       .name  = "LG/Infineon TUA6034",
+       .min   =  54000000,
+       .max   = 863000000,
+       .count = 3,
+       .entries = {
+               {  160000000, 44000000, 62500, 0xce, 0x01 },
+               {  455000000, 44000000, 62500, 0xce, 0x02 },
+               {  999999999, 44000000, 62500, 0xce, 0x04 },
+       },
+};
+EXPORT_SYMBOL(dvb_pll_tdvs_tua6034);
+
 /* Philips FMD1216ME
  * used in Medion Hybrid PCMCIA card and USB Box
  */
index cb79475..205b2d1 100644 (file)
@@ -31,6 +31,7 @@ extern struct dvb_pll_desc dvb_pll_unknown_1;
 extern struct dvb_pll_desc dvb_pll_tua6010xs;
 extern struct dvb_pll_desc dvb_pll_env57h1xd5;
 extern struct dvb_pll_desc dvb_pll_tua6034;
+extern struct dvb_pll_desc dvb_pll_tdvs_tua6034;
 extern struct dvb_pll_desc dvb_pll_tda665x;
 extern struct dvb_pll_desc dvb_pll_fmd1216me;
 extern struct dvb_pll_desc dvb_pll_tded4;
index e94dee5..1f1cd7a 100644 (file)
@@ -1,11 +1,8 @@
 /*
- *    Support for LGDT3302 & LGDT3303 (DViCO FusionHDTV Gold) - VSB/QAM
+ *    Support for LGDT3302 and LGDT3303 - VSB/QAM
  *
  *    Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
  *
- *    Based on code from  Kirk Lapray <kirk_lapray@bigfoot.com>
- *                           Copyright (C) 2005
- *
  *    This program is free software; you can redistribute it and/or modify
  *    it under the terms of the GNU General Public License as published by
  *    the Free Software Foundation; either version 2 of the License, or
 /*
  *                      NOTES ABOUT THIS DRIVER
  *
- * This driver supports DViCO FusionHDTV Gold under Linux.
+ * This Linux driver supports:
+ *   DViCO FusionHDTV 3 Gold-Q
+ *   DViCO FusionHDTV 3 Gold-T
+ *   DViCO FusionHDTV 5 Gold
  *
  * TODO:
- * BER and signal strength always return 0.
- * Include support for LGDT3303
+ * signal strength always returns 0.
  *
  */
 
@@ -41,7 +40,6 @@
 #include <asm/byteorder.h>
 
 #include "dvb_frontend.h"
-#include "dvb-pll.h"
 #include "lgdt330x_priv.h"
 #include "lgdt330x.h"
 
@@ -70,55 +68,37 @@ struct lgdt330x_state
        u32 current_frequency;
 };
 
-static int i2c_writebytes (struct lgdt330x_state* state,
-                          u8 addr, /* demod_address or pll_address */
+static int i2c_write_demod_bytes (struct lgdt330x_state* state,
                           u8 *buf, /* data bytes to send */
                           int len  /* number of bytes to send */ )
 {
-       u8 tmp[] = { buf[0], buf[1] };
        struct i2c_msg msg =
-               { .addr = addr, .flags = 0, .buf = tmp,  .len = 2 };
-       int err;
+               { .addr = state->config->demod_address,
+                 .flags = 0,
+                 .buf = buf,
+                 .len = 2 };
        int i;
+       int err;
 
-       for (i=1; i<len; i++) {
-               tmp[1] = buf[i];
+       for (i=0; i<len-1; i+=2){
                if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-                       printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err == %i)\n", __FUNCTION__, addr, buf[0], err);
+                       printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err);
                        if (err < 0)
                                return err;
                        else
                                return -EREMOTEIO;
                }
-               tmp[0]++;
+               msg.buf += 2;
        }
        return 0;
 }
 
-#if 0
-static int i2c_readbytes (struct lgdt330x_state* state,
-                         u8 addr, /* demod_address or pll_address */
-                         u8 *buf, /* holds data bytes read */
-                         int len  /* number of bytes to read */ )
-{
-       struct i2c_msg msg =
-               { .addr = addr, .flags = I2C_M_RD, .buf = buf,  .len = len };
-       int err;
-
-       if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-               printk(KERN_WARNING "lgdt330x: %s error (addr %02x, err == %i)\n", __FUNCTION__, addr, err);
-               return -EREMOTEIO;
-       }
-       return 0;
-}
-#endif
-
 /*
  * This routine writes the register (reg) to the demod bus
  * then reads the data returned for (len) bytes.
  */
 
-static u8 i2c_selectreadbytes (struct lgdt330x_state* state,
+static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
                               enum I2C_REG reg, u8* buf, int len)
 {
        u8 wr [] = { reg };
@@ -139,7 +119,7 @@ static u8 i2c_selectreadbytes (struct lgdt330x_state* state,
 }
 
 /* Software reset */
-int lgdt330x_SwReset(struct lgdt330x_state* state)
+static int lgdt3302_SwReset(struct lgdt330x_state* state)
 {
        u8 ret;
        u8 reset[] = {
@@ -148,23 +128,51 @@ int lgdt330x_SwReset(struct lgdt330x_state* state)
                      * bits 5-0 are 1 to mask interrupts */
        };
 
-       ret = i2c_writebytes(state,
-                            state->config->demod_address,
+       ret = i2c_write_demod_bytes(state,
+                            reset, sizeof(reset));
+       if (ret == 0) {
+
+               /* force reset high (inactive) and unmask interrupts */
+               reset[1] = 0x7f;
+               ret = i2c_write_demod_bytes(state,
+                                    reset, sizeof(reset));
+       }
+       return ret;
+}
+
+static int lgdt3303_SwReset(struct lgdt330x_state* state)
+{
+       u8 ret;
+       u8 reset[] = {
+               0x02,
+               0x00 /* bit 0 is active low software reset */
+       };
+
+       ret = i2c_write_demod_bytes(state,
                             reset, sizeof(reset));
        if (ret == 0) {
-               /* spec says reset takes 100 ns why wait */
-               /* mdelay(100);    */ /* keep low for 100mS */
-               reset[1] = 0x7f;      /* force reset high (inactive)
-                                      * and unmask interrupts */
-               ret = i2c_writebytes(state,
-                                    state->config->demod_address,
+
+               /* force reset high (inactive) */
+               reset[1] = 0x01;
+               ret = i2c_write_demod_bytes(state,
                                     reset, sizeof(reset));
        }
-       /* Spec does not indicate a need for this either */
-       /*mdelay(5); */               /* wait 5 msec before doing more */
        return ret;
 }
 
+static int lgdt330x_SwReset(struct lgdt330x_state* state)
+{
+       switch (state->config->demod_chip) {
+       case LGDT3302:
+               return lgdt3302_SwReset(state);
+       case LGDT3303:
+               return lgdt3303_SwReset(state);
+       default:
+               return -ENODEV;
+       }
+}
+
+
 static int lgdt330x_init(struct dvb_frontend* fe)
 {
        /* Hardware reset is done using gpio[0] of cx23880x chip.
@@ -173,22 +181,98 @@ static int lgdt330x_init(struct dvb_frontend* fe)
         * Maybe there needs to be a callable function in cx88-core or
         * the caller of this function needs to do it. */
 
-       dprintk("%s entered\n", __FUNCTION__);
-       return lgdt330x_SwReset((struct lgdt330x_state*) fe->demodulator_priv);
+       /*
+        * Array of byte pairs <address, value>
+        * to initialize each different chip
+        */
+       static u8 lgdt3302_init_data[] = {
+               /* Use 50MHz parameter values from spec sheet since xtal is 50 */
+               /* Change the value of NCOCTFV[25:0] of carrier
+                  recovery center frequency register */
+               VSB_CARRIER_FREQ0, 0x00,
+               VSB_CARRIER_FREQ1, 0x87,
+               VSB_CARRIER_FREQ2, 0x8e,
+               VSB_CARRIER_FREQ3, 0x01,
+               /* Change the TPCLK pin polarity
+                  data is valid on falling clock */
+               DEMUX_CONTROL, 0xfb,
+               /* Change the value of IFBW[11:0] of
+                  AGC IF/RF loop filter bandwidth register */
+               AGC_RF_BANDWIDTH0, 0x40,
+               AGC_RF_BANDWIDTH1, 0x93,
+               AGC_RF_BANDWIDTH2, 0x00,
+               /* Change the value of bit 6, 'nINAGCBY' and
+                  'NSSEL[1:0] of ACG function control register 2 */
+               AGC_FUNC_CTRL2, 0xc6,
+               /* Change the value of bit 6 'RFFIX'
+                  of AGC function control register 3 */
+               AGC_FUNC_CTRL3, 0x40,
+               /* Set the value of 'INLVTHD' register 0x2a/0x2c
+                  to 0x7fe */
+               AGC_DELAY0, 0x07,
+               AGC_DELAY2, 0xfe,
+               /* Change the value of IAGCBW[15:8]
+                  of inner AGC loop filter bandwith */
+               AGC_LOOP_BANDWIDTH0, 0x08,
+               AGC_LOOP_BANDWIDTH1, 0x9a
+       };
+
+       static u8 lgdt3303_init_data[] = {
+               0x4c, 0x14
+       };
+
+       struct lgdt330x_state* state = fe->demodulator_priv;
+       char  *chip_name;
+       int    err;
+
+       switch (state->config->demod_chip) {
+       case LGDT3302:
+               chip_name = "LGDT3302";
+               err = i2c_write_demod_bytes(state, lgdt3302_init_data,
+                                                                       sizeof(lgdt3302_init_data));
+               break;
+       case LGDT3303:
+               chip_name = "LGDT3303";
+               err = i2c_write_demod_bytes(state, lgdt3303_init_data,
+                                                                       sizeof(lgdt3303_init_data));
+               break;
+       default:
+               chip_name = "undefined";
+               printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
+               err = -ENODEV;
+       }
+       dprintk("%s entered as %s\n", __FUNCTION__, chip_name);
+       if (err < 0)
+               return err;
+       return lgdt330x_SwReset(state);
 }
 
 static int lgdt330x_read_ber(struct dvb_frontend* fe, u32* ber)
 {
-       *ber = 0; /* Dummy out for now */
+       *ber = 0; /* Not supplied by the demod chips */
        return 0;
 }
 
 static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 {
-       struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+       struct lgdt330x_state* state = fe->demodulator_priv;
+       int err;
        u8 buf[2];
 
-       i2c_selectreadbytes(state, PACKET_ERR_COUNTER1, buf, sizeof(buf));
+       switch (state->config->demod_chip) {
+       case LGDT3302:
+               err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
+                                                                 buf, sizeof(buf));
+               break;
+       case LGDT3303:
+               err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1,
+                                                                 buf, sizeof(buf));
+               break;
+       default:
+               printk(KERN_WARNING
+                          "Only LGDT3302 and LGDT3303 are supported chips.\n");
+               err = -ENODEV;
+       }
 
        *ucblocks = (buf[0] << 8) | buf[1];
        return 0;
@@ -197,123 +281,113 @@ static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 static int lgdt330x_set_parameters(struct dvb_frontend* fe,
                                   struct dvb_frontend_parameters *param)
 {
-       struct lgdt330x_state* state =
-               (struct lgdt330x_state*) fe->demodulator_priv;
+       /*
+        * Array of byte pairs <address, value>
+        * to initialize 8VSB for lgdt3303 chip 50 MHz IF
+        */
+       static u8 lgdt3303_8vsb_44_data[] = {
+               0x04, 0x00,
+               0x0d, 0x40,
+        0x0e, 0x87,
+        0x0f, 0x8e,
+        0x10, 0x01,
+        0x47, 0x8b };
+
+       /*
+        * Array of byte pairs <address, value>
+        * to initialize QAM for lgdt3303 chip
+        */
+       static u8 lgdt3303_qam_data[] = {
+               0x04, 0x00,
+               0x0d, 0x00,
+               0x0e, 0x00,
+               0x0f, 0x00,
+               0x10, 0x00,
+               0x51, 0x63,
+               0x47, 0x66,
+               0x48, 0x66,
+               0x4d, 0x1a,
+               0x49, 0x08,
+               0x4a, 0x9b };
+
+       struct lgdt330x_state* state = fe->demodulator_priv;
 
-       /* Use 50MHz parameter values from spec sheet since xtal is 50 */
        static u8 top_ctrl_cfg[]   = { TOP_CONTROL, 0x03 };
-       static u8 vsb_freq_cfg[]   = { VSB_CARRIER_FREQ0, 0x00, 0x87, 0x8e, 0x01 };
-       static u8 demux_ctrl_cfg[] = { DEMUX_CONTROL, 0xfb };
-       static u8 agc_rf_cfg[]     = { AGC_RF_BANDWIDTH0, 0x40, 0x93, 0x00 };
-       static u8 agc_ctrl_cfg[]   = { AGC_FUNC_CTRL2, 0xc6, 0x40 };
-       static u8 agc_delay_cfg[]  = { AGC_DELAY0, 0x07, 0x00, 0xfe };
-       static u8 agc_loop_cfg[]   = { AGC_LOOP_BANDWIDTH0, 0x08, 0x9a };
 
+       int err;
        /* Change only if we are actually changing the modulation */
        if (state->current_modulation != param->u.vsb.modulation) {
                switch(param->u.vsb.modulation) {
                case VSB_8:
                        dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
 
-                       /* Select VSB mode and serial MPEG interface */
-                       top_ctrl_cfg[1] = 0x07;
+                       /* Select VSB mode */
+                       top_ctrl_cfg[1] = 0x03;
 
                        /* Select ANT connector if supported by card */
                        if (state->config->pll_rf_set)
                                state->config->pll_rf_set(fe, 1);
+
+                       if (state->config->demod_chip == LGDT3303) {
+                               err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data,
+                                                                                       sizeof(lgdt3303_8vsb_44_data));
+                       }
                        break;
 
                case QAM_64:
                        dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
 
-                       /* Select QAM_64 mode and serial MPEG interface */
-                       top_ctrl_cfg[1] = 0x04;
+                       /* Select QAM_64 mode */
+                       top_ctrl_cfg[1] = 0x00;
 
                        /* Select CABLE connector if supported by card */
                        if (state->config->pll_rf_set)
                                state->config->pll_rf_set(fe, 0);
+
+                       if (state->config->demod_chip == LGDT3303) {
+                               err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
+                                                                                       sizeof(lgdt3303_qam_data));
+                       }
                        break;
 
                case QAM_256:
                        dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
 
-                       /* Select QAM_256 mode and serial MPEG interface */
-                       top_ctrl_cfg[1] = 0x05;
+                       /* Select QAM_256 mode */
+                       top_ctrl_cfg[1] = 0x01;
 
                        /* Select CABLE connector if supported by card */
                        if (state->config->pll_rf_set)
                                state->config->pll_rf_set(fe, 0);
+
+                       if (state->config->demod_chip == LGDT3303) {
+                               err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
+                                                                                       sizeof(lgdt3303_qam_data));
+                       }
                        break;
                default:
                        printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
                        return -1;
                }
-               /* Initializations common to all modes */
+               /*
+                * select serial or parallel MPEG harware interface
+                * Serial:   0x04 for LGDT3302 or 0x40 for LGDT3303
+                * Parallel: 0x00
+                */
+               top_ctrl_cfg[1] |= state->config->serial_mpeg;
 
                /* Select the requested mode */
-               i2c_writebytes(state, state->config->demod_address,
-                              top_ctrl_cfg, sizeof(top_ctrl_cfg));
-
-               /* Change the value of IFBW[11:0]
-                  of AGC IF/RF loop filter bandwidth register */
-               i2c_writebytes(state, state->config->demod_address,
-                              agc_rf_cfg, sizeof(agc_rf_cfg));
-
-               /* Change the value of bit 6, 'nINAGCBY' and
-                  'NSSEL[1:0] of ACG function control register 2 */
-               /* Change the value of bit 6 'RFFIX'
-                  of AGC function control register 3 */
-               i2c_writebytes(state, state->config->demod_address,
-                              agc_ctrl_cfg, sizeof(agc_ctrl_cfg));
-
-               /* Change the TPCLK pin polarity
-                  data is valid on falling clock */
-               i2c_writebytes(state, state->config->demod_address,
-                              demux_ctrl_cfg, sizeof(demux_ctrl_cfg));
-
-               /* Change the value of NCOCTFV[25:0] of carrier
-                  recovery center frequency register */
-               i2c_writebytes(state, state->config->demod_address,
-                                      vsb_freq_cfg, sizeof(vsb_freq_cfg));
-
-               /* Set the value of 'INLVTHD' register 0x2a/0x2c to 0x7fe */
-               i2c_writebytes(state, state->config->demod_address,
-                              agc_delay_cfg, sizeof(agc_delay_cfg));
-
-               /* Change the value of IAGCBW[15:8]
-                  of inner AGC loop filter bandwith */
-               i2c_writebytes(state, state->config->demod_address,
-                              agc_loop_cfg, sizeof(agc_loop_cfg));
-
+               i2c_write_demod_bytes(state, top_ctrl_cfg,
+                                                         sizeof(top_ctrl_cfg));
                state->config->set_ts_params(fe, 0);
                state->current_modulation = param->u.vsb.modulation;
        }
 
        /* Change only if we are actually changing the channel */
        if (state->current_frequency != param->frequency) {
-               u8 buf[5];
-               struct i2c_msg msg = { .flags = 0, .buf = &buf[1], .len = 4 };
-               int err;
-
-               state->config->pll_set(fe, param, buf);
-               msg.addr = buf[0];
-
-               dprintk("%s: tuner at 0x%02x bytes: 0x%02x 0x%02x "
-                       "0x%02x 0x%02x\n", __FUNCTION__,
-                       buf[0],buf[1],buf[2],buf[3],buf[4]);
-               if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-                       printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, buf[0], buf[1], err);
-                       if (err < 0)
-                               return err;
-                       else
-                               return -EREMOTEIO;
-               }
-#if 0
-               /* Check the status of the tuner pll */
-               i2c_readbytes(state, buf[0], &buf[1], 1);
-               dprintk("%s: tuner status byte = 0x%02x\n", __FUNCTION__, buf[1]);
-#endif
-               /* Update current frequency */
+               /* Tune to the new frequency */
+               state->config->pll_set(fe, param);
+               /* Keep track of the new frequency */
                state->current_frequency = param->frequency;
        }
        lgdt330x_SwReset(state);
@@ -328,21 +402,15 @@ static int lgdt330x_get_frontend(struct dvb_frontend* fe,
        return 0;
 }
 
-static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
-       struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+       struct lgdt330x_state* state = fe->demodulator_priv;
        u8 buf[3];
 
        *status = 0; /* Reset status result */
 
-       /*
-        * You must set the Mask bits to 1 in the IRQ_MASK in order
-        * to see that status bit in the IRQ_STATUS register.
-        * This is done in SwReset();
-        */
-
        /* AGC status register */
-       i2c_selectreadbytes(state, AGC_STATUS, buf, 1);
+       i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
        dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
        if ((buf[0] & 0x0c) == 0x8){
                /* Test signal does not exist flag */
@@ -353,16 +421,15 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status)
                return 0;
        }
 
+       /*
+        * You must set the Mask bits to 1 in the IRQ_MASK in order
+        * to see that status bit in the IRQ_STATUS register.
+        * This is done in SwReset();
+        */
        /* signal status */
-       i2c_selectreadbytes(state, TOP_CONTROL, buf, sizeof(buf));
+       i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
        dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]);
 
-#if 0
-       /* Alternative method to check for a signal */
-       /* using the SNR good/bad interrupts.   */
-       if ((buf[2] & 0x30) == 0x10)
-               *status |= FE_HAS_SIGNAL;
-#endif
 
        /* sync status */
        if ((buf[2] & 0x03) == 0x01) {
@@ -376,7 +443,7 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status)
        }
 
        /* Carrier Recovery Lock Status Register */
-       i2c_selectreadbytes(state, CARRIER_LOCK, buf, 1);
+       i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
        dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
        switch (state->current_modulation) {
        case QAM_256:
@@ -396,13 +463,75 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status)
        return 0;
 }
 
+static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+       struct lgdt330x_state* state = fe->demodulator_priv;
+       int err;
+       u8 buf[3];
+
+       *status = 0; /* Reset status result */
+
+       /* lgdt3303 AGC status register */
+       err = i2c_read_demod_bytes(state, 0x58, buf, 1);
+       if (err < 0)
+               return err;
+
+       dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
+       if ((buf[0] & 0x21) == 0x01){
+               /* Test input signal does not exist flag */
+               /* as well as the AGC lock flag.   */
+               *status |= FE_HAS_SIGNAL;
+       } else {
+               /* Without a signal all other status bits are meaningless */
+               return 0;
+       }
+
+       /* Carrier Recovery Lock Status Register */
+       i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
+       dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
+       switch (state->current_modulation) {
+       case QAM_256:
+       case QAM_64:
+               /* Need to undestand why there are 3 lock levels here */
+               if ((buf[0] & 0x07) == 0x07)
+                       *status |= FE_HAS_CARRIER;
+               else
+                       break;
+               i2c_read_demod_bytes(state, 0x8a, buf, 1);
+               if ((buf[0] & 0x04) == 0x04)
+                       *status |= FE_HAS_SYNC;
+               if ((buf[0] & 0x01) == 0x01)
+                       *status |= FE_HAS_LOCK;
+               if ((buf[0] & 0x08) == 0x08)
+                       *status |= FE_HAS_VITERBI;
+               break;
+       case VSB_8:
+               if ((buf[0] & 0x80) == 0x80)
+                       *status |= FE_HAS_CARRIER;
+               else
+                       break;
+               i2c_read_demod_bytes(state, 0x38, buf, 1);
+               if ((buf[0] & 0x02) == 0x00)
+                       *status |= FE_HAS_SYNC;
+               if ((buf[0] & 0x01) == 0x01) {
+                       *status |= FE_HAS_LOCK;
+                       *status |= FE_HAS_VITERBI;
+               }
+               break;
+       default:
+               printk("KERN_WARNING lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
+       }
+       return 0;
+}
+
 static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
 {
        /* not directly available. */
+       *strength = 0;
        return 0;
 }
 
-static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr)
+static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
 {
 #ifdef SNR_IN_DB
        /*
@@ -451,7 +580,7 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr)
                  91,    115,    144,    182,    229,    288, 362,   456,   574,   722,
                  909,   1144,   1440,   1813,   2282,   2873, 3617,  4553,  5732,  7216,
                  9084,  11436,  14396,  18124,  22817,  28724,  36161, 45524, 57312, 72151,
-                 90833, 114351, 143960, 181235, 228161, 0x040000
+                 90833, 114351, 143960, 181235, 228161, 0x080000
                };
 
        static u8 buf[5];/* read data buffer */
@@ -459,8 +588,8 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr)
        static u32 snr_db;  /* index into SNR_EQ[] */
        struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
 
-       /* read both equalizer and pase tracker noise data */
-       i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf));
+       /* read both equalizer and phase tracker noise data */
+       i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
 
        if (state->current_modulation == VSB_8) {
                /* Equalizer Mean-Square Error Register for VSB */
@@ -496,19 +625,20 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr)
        struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
 
        /* read both equalizer and pase tracker noise data */
-       i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf));
+       i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
 
        if (state->current_modulation == VSB_8) {
-               /* Equalizer Mean-Square Error Register for VSB */
-               noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
-       } else {
-               /* Phase Tracker Mean-Square Error Register for QAM */
+               /* Phase Tracker Mean-Square Error Register for VSB */
                noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
+       } else {
+
+               /* Carrier Recovery Mean-Square Error for QAM */
+               i2c_read_demod_bytes(state, 0x1a, buf, 2);
+               noise = ((buf[0] & 3) << 8) | buf[1];
        }
 
        /* Small values for noise mean signal is better so invert noise */
-       /* Noise is 19 bit value so discard 3 LSB*/
-       *snr = ~noise>>3;
+       *snr = ~noise;
 #endif
 
        dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
@@ -516,6 +646,32 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr)
        return 0;
 }
 
+static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+       /* Return the raw noise value */
+       static u8 buf[5];/* read data buffer */
+       static u32 noise;   /* noise value */
+       struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+
+       if (state->current_modulation == VSB_8) {
+
+               /* Phase Tracker Mean-Square Error Register for VSB */
+               noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
+       } else {
+
+               /* Carrier Recovery Mean-Square Error for QAM */
+               i2c_read_demod_bytes(state, 0x1a, buf, 2);
+               noise = (buf[0] << 8) | buf[1];
+       }
+
+       /* Small values for noise mean signal is better so invert noise */
+       *snr = ~noise;
+
+       dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
+
+       return 0;
+}
+
 static int lgdt330x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
 {
        /* I have no idea about this - it may not be needed */
@@ -531,7 +687,8 @@ static void lgdt330x_release(struct dvb_frontend* fe)
        kfree(state);
 }
 
-static struct dvb_frontend_ops lgdt330x_ops;
+static struct dvb_frontend_ops lgdt3302_ops;
+static struct dvb_frontend_ops lgdt3303_ops;
 
 struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
                                     struct i2c_adapter* i2c)
@@ -548,9 +705,19 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
        /* Setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &lgdt330x_ops, sizeof(struct dvb_frontend_ops));
+       switch (config->demod_chip) {
+       case LGDT3302:
+               memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
+               break;
+       case LGDT3303:
+               memcpy(&state->ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
+               break;
+       default:
+               goto error;
+       }
+
        /* Verify communication with demod chip */
-       if (i2c_selectreadbytes(state, 2, buf, 1))
+       if (i2c_read_demod_bytes(state, 2, buf, 1))
                goto error;
 
        state->current_frequency = -1;
@@ -568,9 +735,33 @@ error:
        return NULL;
 }
 
-static struct dvb_frontend_ops lgdt330x_ops = {
+static struct dvb_frontend_ops lgdt3302_ops = {
+       .info = {
+               .name= "LG Electronics LGDT3302 VSB/QAM Frontend",
+               .type = FE_ATSC,
+               .frequency_min= 54000000,
+               .frequency_max= 858000000,
+               .frequency_stepsize= 62500,
+               /* Symbol rate is for all VSB modes need to check QAM */
+               .symbol_rate_min    = 10762000,
+               .symbol_rate_max    = 10762000,
+               .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+       },
+       .init                 = lgdt330x_init,
+       .set_frontend         = lgdt330x_set_parameters,
+       .get_frontend         = lgdt330x_get_frontend,
+       .get_tune_settings    = lgdt330x_get_tune_settings,
+       .read_status          = lgdt3302_read_status,
+       .read_ber             = lgdt330x_read_ber,
+       .read_signal_strength = lgdt330x_read_signal_strength,
+       .read_snr             = lgdt3302_read_snr,
+       .read_ucblocks        = lgdt330x_read_ucblocks,
+       .release              = lgdt330x_release,
+};
+
+static struct dvb_frontend_ops lgdt3303_ops = {
        .info = {
-               .name= "LG Electronics lgdt330x VSB/QAM Frontend",
+               .name= "LG Electronics LGDT3303 VSB/QAM Frontend",
                .type = FE_ATSC,
                .frequency_min= 54000000,
                .frequency_max= 858000000,
@@ -584,15 +775,15 @@ static struct dvb_frontend_ops lgdt330x_ops = {
        .set_frontend         = lgdt330x_set_parameters,
        .get_frontend         = lgdt330x_get_frontend,
        .get_tune_settings    = lgdt330x_get_tune_settings,
-       .read_status          = lgdt330x_read_status,
+       .read_status          = lgdt3303_read_status,
        .read_ber             = lgdt330x_read_ber,
        .read_signal_strength = lgdt330x_read_signal_strength,
-       .read_snr             = lgdt330x_read_snr,
+       .read_snr             = lgdt3303_read_snr,
        .read_ucblocks        = lgdt330x_read_ucblocks,
        .release              = lgdt330x_release,
 };
 
-MODULE_DESCRIPTION("lgdt330x [DViCO FusionHDTV 3 Gold] (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
+MODULE_DESCRIPTION("LGDT330X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
 MODULE_AUTHOR("Wilson Michaels");
 MODULE_LICENSE("GPL");
 
@@ -601,6 +792,5 @@ EXPORT_SYMBOL(lgdt330x_attach);
 /*
  * Local variables:
  * c-basic-offset: 8
- * compile-command: "make DVB=1"
  * End:
  */
index 04986f8..e209ba1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Support for LGDT3302 & LGDT3303 (DViCO FustionHDTV Gold) - VSB/QAM
+ *    Support for LGDT3302 and LGDT3303 - VSB/QAM
  *
  *    Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
  *
 
 #include <linux/dvb/frontend.h>
 
+typedef enum lg_chip_t {
+               UNDEFINED,
+               LGDT3302,
+               LGDT3303
+}lg_chip_type;
+
 struct lgdt330x_config
 {
        /* The demodulator's i2c address */
        u8 demod_address;
 
+       /* LG demodulator chip LGDT3302 or LGDT3303 */
+       lg_chip_type demod_chip;
+
+       /* MPEG hardware interface - 0:parallel 1:serial */
+       int serial_mpeg;
+
        /* PLL interface */
        int (*pll_rf_set) (struct dvb_frontend* fe, int index);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pll_address);
+       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 
        /* Need to set device param for start_dma */
        int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
index 4143ce8..59b7c5b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Support for LGDT3302 & LGDT3303 (DViCO FustionHDTV Gold) - VSB/QAM
+ *    Support for LGDT3302 and LGDT3303 - VSB/QAM
  *
  *    Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
  *
@@ -57,8 +57,10 @@ enum I2C_REG {
        PH_ERR1= 0x4a,
        PH_ERR2= 0x4b,
        DEMUX_CONTROL= 0x66,
-       PACKET_ERR_COUNTER1= 0x6a,
-       PACKET_ERR_COUNTER2= 0x6b,
+       LGDT3302_PACKET_ERR_COUNTER1= 0x6a,
+       LGDT3302_PACKET_ERR_COUNTER2= 0x6b,
+       LGDT3303_PACKET_ERR_COUNTER1= 0x8b,
+       LGDT3303_PACKET_ERR_COUNTER2= 0x8c,
 };
 
 #endif /* _LGDT330X_PRIV_ */
index 88e1250..d1cabb6 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <asm/irq.h>
 #include <asm/div64.h>
 
 #include "dvb_frontend.h"
index ac81e5e..3f57423 100644 (file)
@@ -356,7 +356,7 @@ config VIDEO_M32R_AR
 
 config VIDEO_M32R_AR_M64278
        tristate "Use Colour AR module M64278(VGA)"
-       depends on VIDEO_M32R_AR
+       depends on VIDEO_M32R_AR && PLAT_M32700UT
        ---help---
          Say Y here to use the Renesas M64278E-800 camera module,
          which supports VGA(640x480 pixcels) size of images.
index 6c52fd0..a97b9b9 100644 (file)
@@ -95,7 +95,7 @@ static int __devinit pvr_boot(struct bttv *btv);
 static unsigned int triton1=0;
 static unsigned int vsfx=0;
 static unsigned int latency = UNSET;
-static unsigned int no_overlay=-1;
+int no_overlay=-1;
 
 static unsigned int card[BTTV_MAX]   = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
 static unsigned int pll[BTTV_MAX]    = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
@@ -4296,9 +4296,11 @@ void __devinit bttv_check_chipset(void)
                printk(KERN_INFO "bttv: Host bridge needs VSFX enabled.\n");
        if (pcipci_fail) {
                printk(KERN_WARNING "bttv: BT848 and your chipset may not work together.\n");
-               if (UNSET == no_overlay) {
-                       printk(KERN_WARNING "bttv: going to disable overlay.\n");
+               if (!no_overlay) {
+                       printk(KERN_WARNING "bttv: overlay will be disabled.\n");
                        no_overlay = 1;
+               } else {
+                       printk(KERN_WARNING "bttv: overlay forced. Use this option at your own risk.\n");
                }
        }
        if (UNSET != latency)
index 51a0f6d..eee9322 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    $Id: bttv-driver.c,v 1.42 2005/07/05 17:37:35 nsh Exp $
+    $Id: bttv-driver.c,v 1.52 2005/08/04 00:55:16 mchehab Exp $
 
     bttv - Bt848 frame grabber driver
 
@@ -80,6 +80,7 @@ static unsigned int irq_iswitch = 0;
 static unsigned int uv_ratio    = 50;
 static unsigned int full_luma_range = 0;
 static unsigned int coring      = 0;
+extern int no_overlay;
 
 /* API features (turn on/off stuff for testing) */
 static unsigned int v4l2        = 1;
@@ -2151,6 +2152,10 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv,
                return 0;
        }
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+               if (no_overlay > 0) {
+                       printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+                       return -EINVAL;
+               }
                return setup_window(fh, btv, &f->fmt.win, 1);
        case V4L2_BUF_TYPE_VBI_CAPTURE:
                retval = bttv_switch_type(fh,f->type);
@@ -2224,9 +2229,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                        /* others */
                        cap->type = VID_TYPE_CAPTURE|
                                VID_TYPE_TUNER|
-                               VID_TYPE_OVERLAY|
                                VID_TYPE_CLIPPING|
                                VID_TYPE_SCALES;
+                       if (no_overlay <= 0)
+                               cap->type |= VID_TYPE_OVERLAY;
+
                        cap->maxwidth  = bttv_tvnorms[btv->tvnorm].swidth;
                        cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight;
                        cap->minwidth  = 48;
@@ -2302,6 +2309,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                struct video_window *win = arg;
                struct v4l2_window w2;
 
+               if (no_overlay > 0) {
+                       printk ("VIDIOCSWIN: no_overlay\n");
+                       return -EINVAL;
+               }
+
                w2.field = V4L2_FIELD_ANY;
                w2.w.left    = win->x;
                w2.w.top     = win->y;
@@ -2577,10 +2589,12 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                cap->version = BTTV_VERSION_CODE;
                cap->capabilities =
                        V4L2_CAP_VIDEO_CAPTURE |
-                       V4L2_CAP_VIDEO_OVERLAY |
                        V4L2_CAP_VBI_CAPTURE |
                        V4L2_CAP_READWRITE |
                        V4L2_CAP_STREAMING;
+               if (no_overlay <= 0)
+                       cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
+
                if (bttv_tvcards[btv->c.type].tuner != UNSET &&
                    bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT)
                        cap->capabilities |= V4L2_CAP_TUNER;
@@ -3076,7 +3090,7 @@ static struct file_operations bttv_fops =
 static struct video_device bttv_video_template =
 {
        .name     = "UNSET",
-       .type     = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY|
+       .type     = VID_TYPE_CAPTURE|VID_TYPE_TUNER|
                    VID_TYPE_CLIPPING|VID_TYPE_SCALES,
        .hardware = VID_HARDWARE_BT848,
        .fops     = &bttv_fops,
@@ -3756,6 +3770,12 @@ static void bttv_unregister_video(struct bttv *btv)
 /* register video4linux devices */
 static int __devinit bttv_register_video(struct bttv *btv)
 {
+       if (no_overlay <= 0) {
+               bttv_video_template.type |= VID_TYPE_OVERLAY;
+       } else {
+               printk("bttv: Overlay support disabled.\n");
+       }
+
        /* video */
        btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
         if (NULL == btv->video_dev)
@@ -3869,11 +3889,6 @@ static int __devinit bttv_probe(struct pci_dev *dev,
         pci_set_master(dev);
        pci_set_command(dev);
        pci_set_drvdata(dev,btv);
-       if (!pci_dma_supported(dev,0xffffffff)) {
-               printk("bttv%d: Oops: no 32bit PCI DMA ???\n", btv->c.nr);
-               result = -EIO;
-               goto fail1;
-       }
 
         pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision);
         pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
index 191eaf1..f2af9e1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: bttv.h,v 1.18 2005/05/24 23:41:42 nsh Exp $
+ * $Id: bttv.h,v 1.22 2005/07/28 18:41:21 mchehab Exp $
  *
  *  bttv - Bt848 frame grabber driver
  *
 #define BTTV_DVICO_DVBT_LITE  0x80
 #define BTTV_TIBET_CS16  0x83
 #define BTTV_KODICOM_4400R  0x84
-#define BTTV_ADLINK_RTV24   0x85
+#define BTTV_ADLINK_RTV24   0x86
+#define BTTV_DVICO_FUSIONHDTV_5_LITE 0x87
+#define BTTV_ACORP_Y878F   0x88
 
 /* i2c address list */
 #define I2C_TSA5522        0xc2
index f3293e4..aab094b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    $Id: bttvp.h,v 1.19 2005/06/16 21:38:45 nsh Exp $
+    $Id: bttvp.h,v 1.21 2005/07/15 21:44:14 mchehab Exp $
 
     bttv - Bt848 frame grabber driver
 
@@ -27,7 +27,7 @@
 #define _BTTVP_H_
 
 #include <linux/version.h>
-#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,15)
+#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,16)
 
 #include <linux/types.h>
 #include <linux/wait.h>
index 3d0c784..ebf02a7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88-cards.c,v 1.86 2005/07/14 03:06:43 mchehab Exp $
+ * $Id: cx88-cards.c,v 1.90 2005/07/28 02:47:42 mkrufky Exp $
  *
  * device driver for Conexant 2388x based TV cards
  * card-specific stuff.
@@ -90,6 +90,9 @@ struct cx88_board cx88_boards[] = {
                .input          = {{
                        .type   = CX88_VMUX_TELEVISION,
                        .vmux   = 0,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
                }},
        },
        [CX88_BOARD_PIXELVIEW] = {
@@ -496,6 +499,9 @@ struct cx88_board cx88_boards[] = {
                .input          = {{
                         .type   = CX88_VMUX_DVB,
                         .vmux   = 0,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
                 }},
                .dvb            = 1,
        },
@@ -753,6 +759,27 @@ struct cx88_board cx88_boards[] = {
                }},
                .dvb            = 1,
        },
+       [CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD] = {
+               .name           = "DViCO FusionHDTV 5 Gold",
+               .tuner_type     = TUNER_LG_TDVS_H062F,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               /*  See DViCO FusionHDTV 3 Gold-Q for GPIO documentation.  */
+               .input          = {{
+                        .type   = CX88_VMUX_TELEVISION,
+                        .vmux   = 0,
+                        .gpio0  = 0x0f0d,
+                },{
+                        .type   = CX88_VMUX_COMPOSITE1,
+                        .vmux   = 1,
+                        .gpio0  = 0x0f00,
+                },{
+                        .type   = CX88_VMUX_SVIDEO,
+                        .vmux   = 2,
+                        .gpio0  = 0x0f00,
+                }},
+       },
 };
 const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
 
@@ -880,6 +907,10 @@ struct cx88_subid cx88_subids[] = {
                .subvendor = 0x153b,
                .subdevice = 0x1166,
                .card      = CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1,
+       },{
+               .subvendor = 0x18ac,
+               .subdevice = 0xd500,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD,
        },
 };
 const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
index ef0e9a8..78d2232 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88-dvb.c,v 1.54 2005/07/25 05:13:50 mkrufky Exp $
+ * $Id: cx88-dvb.c,v 1.58 2005/08/07 09:24:08 mkrufky Exp $
  *
  * device driver for Conexant 2388x based TV cards
  * MPEG Transport Stream (DVB) routines
@@ -208,14 +208,26 @@ static struct or51132_config pchdtv_hd3000 = {
 
 #ifdef HAVE_LGDT330X
 static int lgdt330x_pll_set(struct dvb_frontend* fe,
-                           struct dvb_frontend_parameters* params,
-                           u8* pllbuf)
+                           struct dvb_frontend_parameters* params)
 {
        struct cx8802_dev *dev= fe->dvb->priv;
+       u8 buf[4];
+       struct i2c_msg msg =
+               { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 };
+       int err;
 
-       pllbuf[0] = dev->core->pll_addr;
-       dvb_pll_configure(dev->core->pll_desc, &pllbuf[1],
-                         params->frequency, 0);
+       dvb_pll_configure(dev->core->pll_desc, buf, params->frequency, 0);
+       dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
+                       __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
+       if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
+               printk(KERN_WARNING "cx88-dvb: %s error "
+                          "(addr %02x <- %02x, err = %i)\n",
+                          __FUNCTION__, buf[0], buf[1], err);
+               if (err < 0)
+                       return err;
+               else
+                       return -EREMOTEIO;
+       }
        return 0;
 }
 
@@ -244,6 +256,8 @@ static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
 
 static struct lgdt330x_config fusionhdtv_3_gold = {
        .demod_address    = 0x0e,
+       .demod_chip       = LGDT3302,
+       .serial_mpeg      = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */
        .pll_set          = lgdt330x_pll_set,
        .set_ts_params    = lgdt330x_set_ts_param,
 };
index 5588a3a..5f58c10 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88-video.c,v 1.80 2005/07/13 08:49:08 mchehab Exp $
+ * $Id: cx88-video.c,v 1.82 2005/07/22 05:13:34 mkrufky Exp $
  *
  * device driver for Conexant 2388x based TV cards
  * video4linux video interface
@@ -758,10 +758,10 @@ static int video_open(struct inode *inode, struct file *file)
                struct cx88_core *core = dev->core;
                int board = core->board;
                dprintk(1,"video_open: setting radio device\n");
+               cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3);
                cx_write(MO_GP0_IO, cx88_boards[board].radio.gpio0);
                cx_write(MO_GP1_IO, cx88_boards[board].radio.gpio1);
                cx_write(MO_GP2_IO, cx88_boards[board].radio.gpio2);
-               cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3);
                dev->core->tvaudio = WW_FM;
                cx88_set_tvaudio(core);
                cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
index b008f7d..da65dc9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88.h,v 1.69 2005/07/13 17:25:25 mchehab Exp $
+ * $Id: cx88.h,v 1.70 2005/07/24 17:44:09 mkrufky Exp $
  *
  * v4l2 device driver for cx2388x based TV cards
  *
@@ -171,6 +171,7 @@ extern struct sram_channel cx88_sram_channels[];
 #define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T  28
 #define CX88_BOARD_ADSTECH_DVB_T_PCI          29
 #define CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1  30
+#define CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD 31
 
 enum cx88_itype {
        CX88_VMUX_COMPOSITE1 = 1,
index 6239254..62f1b8d 100644 (file)
@@ -741,11 +741,9 @@ static int msp34xx_sleep(struct msp3400c *msp, int timeout)
                        schedule_timeout(msecs_to_jiffies(timeout));
                }
        }
-       if (current->flags & PF_FREEZE) {
-               refrigerator ();
-       }
 
        remove_wait_queue(&msp->wq, &wait);
+       try_to_freeze();
        return msp->restart;
 }
 
index 93dd619..1203b93 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: saa7134-i2c.c,v 1.19 2005/07/07 01:49:30 mkrufky Exp $
+ * $Id: saa7134-i2c.c,v 1.22 2005/07/22 04:09:41 mkrufky Exp $
  *
  * device driver for philips saa7134 based TV cards
  * i2c interface support
@@ -300,6 +300,8 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
        status = i2c_get_status(dev);
        if (i2c_is_error(status))
                goto err;
+       /* ensure that the bus is idle for at least one bit slot */
+       msleep(1);
 
        d1printk("\n");
        return num;
index 6836c07..2af0cb2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: saa7134.h,v 1.48 2005/07/01 08:22:24 nsh Exp $
+ * $Id: saa7134.h,v 1.49 2005/07/13 17:25:25 mchehab Exp $
  *
  * v4l2 device driver for philips saa7134 based TV cards
  *
@@ -21,7 +21,7 @@
  */
 
 #include <linux/version.h>
-#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,13)
+#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,14)
 
 #include <linux/pci.h>
 #include <linux/i2c.h>
index 4d27ac1..cebcc1f 100644 (file)
@@ -2,7 +2,7 @@
  * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview
  * I2C address is allways 0xC0.
  *
- * $Id: tea5767.c,v 1.21 2005/07/14 03:06:43 mchehab Exp $
+ * $Id: tea5767.c,v 1.27 2005/07/31 12:10:56 mchehab Exp $
  *
  * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br)
  * This code is placed under the terms of the GNU General Public License
@@ -15,7 +15,6 @@
 #include <linux/videodev.h>
 #include <linux/delay.h>
 #include <media/tuner.h>
-#include <media/tuner.h>
 
 #define PREFIX "TEA5767 "
 
@@ -293,16 +292,16 @@ static int tea5767_stereo(struct i2c_client *c)
 
 int tea5767_autodetection(struct i2c_client *c)
 {
-       unsigned char buffer[5] = { 0xff, 0xff, 0xff, 0xff, 0xff };
+       unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
        int rc;
        struct tuner *t = i2c_get_clientdata(c);
 
-       if (5 != (rc = i2c_master_recv(c, buffer, 5))) {
+       if (7 != (rc = i2c_master_recv(c, buffer, 7))) {
                tuner_warn("It is not a TEA5767. Received %i bytes.\n", rc);
                return EINVAL;
        }
 
-       /* If all bytes are the same then it's a TV tuner and not a tea5767 chip. */
+       /* If all bytes are the same then it's a TV tuner and not a tea5767 */
        if (buffer[0] == buffer[1] && buffer[0] == buffer[2] &&
            buffer[0] == buffer[3] && buffer[0] == buffer[4]) {
                tuner_warn("All bytes are equal. It is not a TEA5767\n");
@@ -318,6 +317,17 @@ int tea5767_autodetection(struct i2c_client *c)
                tuner_warn("Chip ID is not zero. It is not a TEA5767\n");
                return EINVAL;
        }
+       /* It seems that tea5767 returns 0xff after the 5th byte */
+       if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
+               tuner_warn("Returned more than 5 bytes. It is not a TEA5767\n");
+               return EINVAL;
+       }
+
+       /* It seems that tea5767 returns 0xff after the 5th byte */
+       if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
+               tuner_warn("Returned more than 5 bytes. It is not a TEA5767\n");
+               return EINVAL;
+       }
 
        tuner_warn("TEA5767 detected.\n");
        return 0;
@@ -327,10 +337,8 @@ int tea5767_tuner_init(struct i2c_client *c)
 {
        struct tuner *t = i2c_get_clientdata(c);
 
-       if (tea5767_autodetection(c) == EINVAL)
-               return EINVAL;
-
-       tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5767HN FM Radio");
+       tuner_info("type set to %d (%s)\n", t->type,
+                       "Philips TEA5767HN FM Radio");
        strlcpy(c->name, "tea5767", sizeof(c->name));
 
        t->tv_freq = set_tv_freq;
index b25a9c0..f0a5798 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: tuner-core.c,v 1.58 2005/07/14 03:06:43 mchehab Exp $
+ * $Id: tuner-core.c,v 1.63 2005/07/28 18:19:55 mchehab Exp $
  *
  * i2c tv tuner chip device driver
  * core core, i.e. kernel interfaces, registering and so on
@@ -23,6 +23,8 @@
 #include <media/tuner.h>
 #include <media/audiochip.h>
 
+#include "msp3400.h"
+
 #define UNSET (-1U)
 
 /* standard i2c insmod options */
@@ -42,6 +44,9 @@ module_param(addr, int, 0444);
 static unsigned int no_autodetect = 0;
 module_param(no_autodetect, int, 0444);
 
+static unsigned int show_i2c = 0;
+module_param(show_i2c, int, 0444);
+
 /* insmod options used at runtime => read/write */
 unsigned int tuner_debug = 0;
 module_param(tuner_debug, int, 0644);
@@ -320,6 +325,17 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
 
        tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name);
 
+       if (show_i2c) {
+               unsigned char buffer[16];
+               int i,rc;
+
+               memset(buffer, 0, sizeof(buffer));
+               rc = i2c_master_recv(&t->i2c, buffer, sizeof(buffer));
+               printk("tuner-%04x I2C RECV = ",addr);
+               for (i=0;i<rc;i++)
+                       printk("%02x ",buffer[i]);
+               printk("\n");
+       }
        /* TEA5767 autodetection code - only for addr = 0xc0 */
        if (!no_autodetect) {
                if (addr == 0x60) {
@@ -451,6 +467,17 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                        break;
                }
                break;
+       case VIDIOCSAUDIO:
+               if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
+                       return 0;
+               if (check_v4l2(t) == EINVAL)
+                       return 0;
+
+               /* Should be implemented, since bttv calls it */
+               tuner_dbg("VIDIOCSAUDIO not implemented.\n");
+
+               break;
+       case MSP_SET_MATRIX:
        case TDA9887_SET_CONFIG:
                break;
        /* --- v4l ioctls --- */
index a3f8e83..de0c93a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: tuner-simple.c,v 1.39 2005/07/07 01:49:30 mkrufky Exp $
+ * $Id: tuner-simple.c,v 1.43 2005/07/28 18:41:21 mchehab Exp $
  *
  * i2c tv tuner chip device driver
  * controls all those simple 4-control-bytes style tuners.
@@ -245,6 +245,12 @@ static struct tunertype tuners[] = {
           /* see tea5767.c for details */},
        { "Philips FMD1216ME MK3 Hybrid Tuner", Philips, PAL,
          16*160.00,16*442.00,0x51,0x52,0x54,0x86,623 },
+
+       { "LG TDVS-H062F/TUA6034", LGINNOTEK, NTSC,
+         16*160.00,16*455.00,0x01,0x02,0x04,0x8e,732},
+
+       { "Ymec TVF66T5-B/DFF", Philips, PAL,
+          16*160.25,16*464.25,0x01,0x02,0x08,0x8e,623},
 };
 
 unsigned const int tuner_count = ARRAY_SIZE(tuners);
index 62b03ef..127ec38 100644 (file)
@@ -189,7 +189,7 @@ hauppauge_tuner[] =
        { TUNER_ABSENT,        "Philips FQ1236 MK3"},
        { TUNER_ABSENT,        "Samsung TCPN 2121P30A"},
        { TUNER_ABSENT,        "Samsung TCPE 4121P30A"},
-       { TUNER_ABSENT,        "TCL MFPE05 2"},
+       { TUNER_PHILIPS_FM1216ME_MK3, "TCL MFPE05 2"},
        /* 90-99 */
        { TUNER_ABSENT,        "LG TALN H202T"},
        { TUNER_PHILIPS_FQ1216AME_MK4, "Philips FQ1216AME MK4"},
index 06e8eb1..43a942a 100644 (file)
@@ -53,6 +53,9 @@ config I2O_CONFIG
          To compile this support as a module, choose M here: the
          module will be called i2o_config.
 
+         Note: If you want to use the new API you have to download the
+         i2o_config patch from http://i2o.shadowconnect.com/
+
 config I2O_CONFIG_OLD_IOCTL
        bool "Enable ioctls (OBSOLETE)"
        depends on I2O_CONFIG
index fe2e7af..af32ab4 100644 (file)
 
 static struct i2o_driver i2o_config_driver;
 
-/* Special file operations for sysfs */
-struct fops_attribute {
-       struct bin_attribute bin;
-       struct file_operations fops;
-};
-
-/**
- *     sysfs_read_dummy
- */
-static ssize_t sysfs_read_dummy(struct kobject *kobj, char *buf, loff_t offset,
-                               size_t count)
-{
-       return 0;
-};
-
-/**
- *     sysfs_write_dummy
- */
-static ssize_t sysfs_write_dummy(struct kobject *kobj, char *buf, loff_t offset,
-                                size_t count)
-{
-       return 0;
-};
-
-/**
- *     sysfs_create_fops_file - Creates attribute with special file operations
- *     @kobj: kobject which should contains the attribute
- *     @attr: attributes which should be used to create file
- *
- *     First creates attribute @attr in kobject @kobj. If it is the first time
- *     this function is called, merge old fops from sysfs with new one and
- *     write it back. Afterwords the new fops will be set for the created
- *     attribute.
- *
- *     Returns 0 on success or negative error code on failure.
- */
-static int sysfs_create_fops_file(struct kobject *kobj,
-                                 struct fops_attribute *attr)
-{
-       struct file_operations tmp, *fops;
-       struct dentry *d;
-       struct qstr qstr;
-       int rc;
-
-       fops = &attr->fops;
-
-       if (fops->read)
-               attr->bin.read = sysfs_read_dummy;
-
-       if (fops->write)
-               attr->bin.write = sysfs_write_dummy;
-
-       if ((rc = sysfs_create_bin_file(kobj, &attr->bin)))
-               return rc;
-
-       qstr.name = attr->bin.attr.name;
-       qstr.len = strlen(qstr.name);
-       qstr.hash = full_name_hash(qstr.name, qstr.len);
-
-       if ((d = lookup_hash(&qstr, kobj->dentry))) {
-               if (!fops->owner) {
-                       memcpy(&tmp, d->d_inode->i_fop, sizeof(tmp));
-                       if (fops->read)
-                               tmp.read = fops->read;
-                       if (fops->write)
-                               tmp.write = fops->write;
-                       memcpy(fops, &tmp, sizeof(tmp));
-               }
-
-               d->d_inode->i_fop = fops;
-       } else
-               sysfs_remove_bin_file(kobj, &attr->bin);
-
-       return -ENOENT;
-};
-
-/**
- *     sysfs_remove_fops_file - Remove attribute with special file operations
- *     @kobj: kobject which contains the attribute
- *     @attr: attributes which are used to create file
- *
- *     Only wrapper arround sysfs_remove_bin_file()
- *
- *     Returns 0 on success or negative error code on failure.
- */
-static inline int sysfs_remove_fops_file(struct kobject *kobj,
-                                        struct fops_attribute *attr)
-{
-       return sysfs_remove_bin_file(kobj, &attr->bin);
-};
-
-/**
- *     i2o_config_read_hrt - Returns the HRT of the controller
- *     @kob: kernel object handle
- *     @buf: buffer into which the HRT should be copied
- *     @off: file offset
- *     @count: number of bytes to read
- *
- *     Put @count bytes starting at @off into @buf from the HRT of the I2O
- *     controller corresponding to @kobj.
- *
- *     Returns number of bytes copied into buffer.
- */
-static ssize_t i2o_config_read_hrt(struct kobject *kobj, char *buf,
-                                  loff_t offset, size_t count)
-{
-       struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
-       i2o_hrt *hrt = c->hrt.virt;
-
-       u32 size = (hrt->num_entries * hrt->entry_len + 2) * 4;
-
-       if (offset > size)
-               return 0;
-
-       if (offset + count > size)
-               count = size - offset;
-
-       memcpy(buf, (u8 *) hrt + offset, count);
-
-       return count;
-};
-
-/**
- *     i2o_config_read_lct - Returns the LCT of the controller
- *     @kob: kernel object handle
- *     @buf: buffer into which the LCT should be copied
- *     @off: file offset
- *     @count: number of bytes to read
- *
- *     Put @count bytes starting at @off into @buf from the LCT of the I2O
- *     controller corresponding to @kobj.
- *
- *     Returns number of bytes copied into buffer.
- */
-static ssize_t i2o_config_read_lct(struct kobject *kobj, char *buf,
-                                  loff_t offset, size_t count)
-{
-       struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
-       u32 size = c->lct->table_size * 4;
-
-       if (offset > size)
-               return 0;
-
-       if (offset + count > size)
-               count = size - offset;
-
-       memcpy(buf, (u8 *) c->lct + offset, count);
-
-       return count;
-};
-
-#define I2O_CONFIG_SW_ATTR(_name,_mode,_type,_swid) \
-static ssize_t i2o_config_##_name##_read(struct file *file, char __user *buf, size_t count, loff_t * offset) { \
-       return i2o_config_sw_read(file, buf, count, offset, _type, _swid); \
-};\
-\
-static ssize_t i2o_config_##_name##_write(struct file *file, const char __user *buf, size_t count, loff_t * offset) { \
-       return i2o_config_sw_write(file, buf, count, offset, _type, _swid); \
-}; \
-\
-static struct fops_attribute i2o_config_attr_##_name = { \
-       .bin = { .attr = { .name = __stringify(_name), .mode = _mode, \
-                          .owner = THIS_MODULE }, \
-                .size = 0, }, \
-       .fops = { .write = i2o_config_##_name##_write, \
-                 .read = i2o_config_##_name##_read} \
-};
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-
-/**
- *     i2o_config_dpt_reagion - Converts type and id to flash region
- *     @swtype: type of software module reading
- *     @swid: id of software which should be read
- *
- *     Converts type and id from I2O spec to the matching region for DPT /
- *     Adaptec controllers.
- *
- *     Returns region which match type and id or -1 on error.
- */
-static u32 i2o_config_dpt_region(u8 swtype, u8 swid)
-{
-       switch (swtype) {
-       case I2O_SOFTWARE_MODULE_IRTOS:
-               /*
-                * content: operation firmware
-                * region size:
-                *      0xbc000 for 2554, 3754, 2564, 3757
-                *      0x170000 for 2865
-                *      0x17c000 for 3966
-                */
-               if (!swid)
-                       return 0;
-
-               break;
-
-       case I2O_SOFTWARE_MODULE_IOP_PRIVATE:
-               /*
-                * content: BIOS and SMOR
-                * BIOS size: first 0x8000 bytes
-                * region size:
-                *      0x40000 for 2554, 3754, 2564, 3757
-                *      0x80000 for 2865, 3966
-                */
-               if (!swid)
-                       return 1;
-
-               break;
-
-       case I2O_SOFTWARE_MODULE_IOP_CONFIG:
-               switch (swid) {
-               case 0:
-                       /*
-                        * content: NVRAM defaults
-                        * region size: 0x2000 bytes
-                        */
-                       return 2;
-               case 1:
-                       /*
-                        * content: serial number
-                        * region size: 0x2000 bytes
-                        */
-                       return 3;
-               }
-               break;
-       }
-
-       return -1;
-};
-
-#endif
-
-/**
- *     i2o_config_sw_read - Read a software module from controller
- *     @file: file pointer
- *     @buf: buffer into which the data should be copied
- *     @count: number of bytes to read
- *     @off: file offset
- *     @swtype: type of software module reading
- *     @swid: id of software which should be read
- *
- *     Transfers @count bytes at offset @offset from IOP into buffer using
- *     type @swtype and id @swid as described in I2O spec.
- *
- *     Returns number of bytes copied into buffer or error code on failure.
- */
-static ssize_t i2o_config_sw_read(struct file *file, char __user * buf,
-                                 size_t count, loff_t * offset, u8 swtype,
-                                 u32 swid)
-{
-       struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata;
-       struct kobject *kobj = sd->s_element;
-       struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
-       u32 m, function = I2O_CMD_SW_UPLOAD;
-       struct i2o_dma buffer;
-       struct i2o_message __iomem *msg;
-       u32 __iomem *mptr;
-       int rc, status;
-
-       m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-       if (m == I2O_QUEUE_EMPTY)
-               return -EBUSY;
-
-       mptr = &msg->body[3];
-
-       if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) {
-               i2o_msg_nop(c, m);
-               return rc;
-       }
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-       if (c->adaptec) {
-               mptr = &msg->body[4];
-               function = I2O_CMD_PRIVATE;
-
-               writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]);
-
-               writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_READ,
-                      &msg->body[0]);
-               writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]);
-               writel(*offset, &msg->body[2]);
-               writel(count, &msg->body[3]);
-       } else
-#endif
-               writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
-
-       writel(0xD0000000 | count, mptr++);
-       writel(buffer.phys, mptr);
-
-       writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]);
-       writel(i2o_config_driver.context, &msg->u.head[2]);
-       writel(0, &msg->u.head[3]);
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-       if (!c->adaptec)
-#endif
-       {
-               writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]);
-               writel(0, &msg->body[1]);
-               writel(swid, &msg->body[2]);
-       }
-
-       status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
-
-       if (status == I2O_POST_WAIT_OK) {
-               if (!(rc = copy_to_user(buf, buffer.virt, count))) {
-                       rc = count;
-                       *offset += count;
-               }
-       } else
-               rc = -EIO;
-
-       if (status != -ETIMEDOUT)
-               i2o_dma_free(&c->pdev->dev, &buffer);
-
-       return rc;
-};
-
-/**
- *     i2o_config_sw_write - Write a software module to controller
- *     @file: file pointer
- *     @buf: buffer into which the data should be copied
- *     @count: number of bytes to read
- *     @off: file offset
- *     @swtype: type of software module writing
- *     @swid: id of software which should be written
- *
- *     Transfers @count bytes at offset @offset from buffer to IOP using
- *     type @swtype and id @swid as described in I2O spec.
- *
- *     Returns number of bytes copied from buffer or error code on failure.
- */
-static ssize_t i2o_config_sw_write(struct file *file, const char __user * buf,
-                                  size_t count, loff_t * offset, u8 swtype,
-                                  u32 swid)
-{
-       struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata;
-       struct kobject *kobj = sd->s_element;
-       struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
-       u32 m, function = I2O_CMD_SW_DOWNLOAD;
-       struct i2o_dma buffer;
-       struct i2o_message __iomem *msg;
-       u32 __iomem *mptr;
-       int rc, status;
-
-       m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-       if (m == I2O_QUEUE_EMPTY)
-               return -EBUSY;
-
-       mptr = &msg->body[3];
-
-       if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL)))
-               goto nop_msg;
-
-       if ((rc = copy_from_user(buffer.virt, buf, count)))
-               goto free_buffer;
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-       if (c->adaptec) {
-               mptr = &msg->body[4];
-               function = I2O_CMD_PRIVATE;
-
-               writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]);
-
-               writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_WRITE,
-                      &msg->body[0]);
-               writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]);
-               writel(*offset, &msg->body[2]);
-               writel(count, &msg->body[3]);
-       } else
-#endif
-               writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
-
-       writel(0xD4000000 | count, mptr++);
-       writel(buffer.phys, mptr);
-
-       writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]);
-       writel(i2o_config_driver.context, &msg->u.head[2]);
-       writel(0, &msg->u.head[3]);
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-       if (!c->adaptec)
-#endif
-       {
-               writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]);
-               writel(0, &msg->body[1]);
-               writel(swid, &msg->body[2]);
-       }
-
-       status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
-
-       if (status != -ETIMEDOUT)
-               i2o_dma_free(&c->pdev->dev, &buffer);
-
-       if (status != I2O_POST_WAIT_OK)
-               return -EIO;
-
-       *offset += count;
-
-       return count;
-
-      free_buffer:
-       i2o_dma_free(&c->pdev->dev, &buffer);
-
-      nop_msg:
-       i2o_msg_nop(c, m);
-
-       return rc;
-};
-
-/* attribute for HRT in sysfs */
-static struct bin_attribute i2o_config_hrt_attr = {
-       .attr = {
-                .name = "hrt",
-                .mode = S_IRUGO,
-                .owner = THIS_MODULE},
-       .size = 0,
-       .read = i2o_config_read_hrt
-};
-
-/* attribute for LCT in sysfs */
-static struct bin_attribute i2o_config_lct_attr = {
-       .attr = {
-                .name = "lct",
-                .mode = S_IRUGO,
-                .owner = THIS_MODULE},
-       .size = 0,
-       .read = i2o_config_read_lct
-};
-
-/* IRTOS firmware access */
-I2O_CONFIG_SW_ATTR(irtos, S_IWRSR, I2O_SOFTWARE_MODULE_IRTOS, 0);
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-
-/*
- * attribute for BIOS / SMOR, nvram and serial number access on DPT / Adaptec
- * controllers
- */
-I2O_CONFIG_SW_ATTR(bios, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_PRIVATE, 0);
-I2O_CONFIG_SW_ATTR(nvram, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 0);
-I2O_CONFIG_SW_ATTR(serial, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 1);
-
-#endif
-
-/**
- *     i2o_config_notify_controller_add - Notify of added controller
- *     @c: the controller which was added
- *
- *     If a I2O controller is added, we catch the notification to add sysfs
- *     entries.
- */
-static void i2o_config_notify_controller_add(struct i2o_controller *c)
-{
-       struct kobject *kobj = &c->exec->device.kobj;
-
-       sysfs_create_bin_file(kobj, &i2o_config_hrt_attr);
-       sysfs_create_bin_file(kobj, &i2o_config_lct_attr);
-
-       sysfs_create_fops_file(kobj, &i2o_config_attr_irtos);
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-       if (c->adaptec) {
-               sysfs_create_fops_file(kobj, &i2o_config_attr_bios);
-               sysfs_create_fops_file(kobj, &i2o_config_attr_nvram);
-               sysfs_create_fops_file(kobj, &i2o_config_attr_serial);
-       }
-#endif
-};
-
-/**
- *     i2o_config_notify_controller_remove - Notify of removed controller
- *     @c: the controller which was removed
- *
- *     If a I2O controller is removed, we catch the notification to remove the
- *     sysfs entries.
- */
-static void i2o_config_notify_controller_remove(struct i2o_controller *c)
-{
-       struct kobject *kobj = &c->exec->device.kobj;
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-       if (c->adaptec) {
-               sysfs_remove_fops_file(kobj, &i2o_config_attr_serial);
-               sysfs_remove_fops_file(kobj, &i2o_config_attr_nvram);
-               sysfs_remove_fops_file(kobj, &i2o_config_attr_bios);
-       }
-#endif
-       sysfs_remove_fops_file(kobj, &i2o_config_attr_irtos);
-
-       sysfs_remove_bin_file(kobj, &i2o_config_lct_attr);
-       sysfs_remove_bin_file(kobj, &i2o_config_hrt_attr);
-};
-
 /* Config OSM driver struct */
 static struct i2o_driver i2o_config_driver = {
        .name = OSM_NAME,
-       .notify_controller_add = i2o_config_notify_controller_add,
-       .notify_controller_remove = i2o_config_notify_controller_remove
 };
 
 #ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
index 7a60fd7..66c03e8 100644 (file)
@@ -32,6 +32,8 @@
 #include <linux/i2o.h>
 #include "core.h"
 
+#define OSM_DESCRIPTION        "I2O-subsystem"
+
 /* PCI device id table for all I2O controllers */
 static struct pci_device_id __devinitdata i2o_pci_ids[] = {
        {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)},
@@ -66,6 +68,8 @@ static void i2o_pci_free(struct i2o_controller *c)
 
        if (c->base.virt)
                iounmap(c->base.virt);
+
+       pci_release_regions(c->pdev);
 }
 
 /**
@@ -84,6 +88,11 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
        struct device *dev = &pdev->dev;
        int i;
 
+       if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
+               printk(KERN_ERR "%s: device already claimed\n", c->name);
+               return -ENODEV;
+       }
+
        for (i = 0; i < 6; i++) {
                /* Skip I/O spaces */
                if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
@@ -138,6 +147,7 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
        c->base.virt = ioremap_nocache(c->base.phys, c->base.len);
        if (!c->base.virt) {
                printk(KERN_ERR "%s: Unable to map controller.\n", c->name);
+               i2o_pci_free(c);
                return -ENOMEM;
        }
 
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
new file mode 100644 (file)
index 0000000..1588a59
--- /dev/null
@@ -0,0 +1,16 @@
+#
+# Multifunction miscellaneous devices
+#
+
+menu "Multimedia Capabilities Port drivers"
+
+config MCP
+       tristate
+
+# Interface drivers
+config MCP_SA11X0
+       tristate "Support SA11x0 MCP interface"
+       depends on ARCH_SA1100
+       select MCP
+
+endmenu
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
new file mode 100644 (file)
index 0000000..98bdd6a
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for multifunction miscellaneous devices
+#
+
+obj-$(CONFIG_MCP)              += mcp-core.o
+obj-$(CONFIG_MCP_SA11X0)       += mcp-sa11x0.o
diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c
new file mode 100644 (file)
index 0000000..c75d713
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ *  linux/drivers/mfd/mcp-core.c
+ *
+ *  Copyright (C) 2001 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ *  Generic MCP (Multimedia Communications Port) layer.  All MCP locking
+ *  is solely held within this file.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/device.h>
+
+#include <asm/dma.h>
+#include <asm/system.h>
+
+#include "mcp.h"
+
+#define to_mcp(d)              container_of(d, struct mcp, attached_device)
+#define to_mcp_driver(d)       container_of(d, struct mcp_driver, drv)
+
+static int mcp_bus_match(struct device *dev, struct device_driver *drv)
+{
+       return 1;
+}
+
+static int mcp_bus_probe(struct device *dev)
+{
+       struct mcp *mcp = to_mcp(dev);
+       struct mcp_driver *drv = to_mcp_driver(dev->driver);
+
+       return drv->probe(mcp);
+}
+
+static int mcp_bus_remove(struct device *dev)
+{
+       struct mcp *mcp = to_mcp(dev);
+       struct mcp_driver *drv = to_mcp_driver(dev->driver);
+
+       drv->remove(mcp);
+       return 0;
+}
+
+static int mcp_bus_suspend(struct device *dev, pm_message_t state)
+{
+       struct mcp *mcp = to_mcp(dev);
+       int ret = 0;
+
+       if (dev->driver) {
+               struct mcp_driver *drv = to_mcp_driver(dev->driver);
+
+               ret = drv->suspend(mcp, state);
+       }
+       return ret;
+}
+
+static int mcp_bus_resume(struct device *dev)
+{
+       struct mcp *mcp = to_mcp(dev);
+       int ret = 0;
+
+       if (dev->driver) {
+               struct mcp_driver *drv = to_mcp_driver(dev->driver);
+
+               ret = drv->resume(mcp);
+       }
+       return ret;
+}
+
+static struct bus_type mcp_bus_type = {
+       .name           = "mcp",
+       .match          = mcp_bus_match,
+       .suspend        = mcp_bus_suspend,
+       .resume         = mcp_bus_resume,
+};
+
+/**
+ *     mcp_set_telecom_divisor - set the telecom divisor
+ *     @mcp: MCP interface structure
+ *     @div: SIB clock divisor
+ *
+ *     Set the telecom divisor on the MCP interface.  The resulting
+ *     sample rate is SIBCLOCK/div.
+ */
+void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div)
+{
+       spin_lock_irq(&mcp->lock);
+       mcp->ops->set_telecom_divisor(mcp, div);
+       spin_unlock_irq(&mcp->lock);
+}
+EXPORT_SYMBOL(mcp_set_telecom_divisor);
+
+/**
+ *     mcp_set_audio_divisor - set the audio divisor
+ *     @mcp: MCP interface structure
+ *     @div: SIB clock divisor
+ *
+ *     Set the audio divisor on the MCP interface.
+ */
+void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div)
+{
+       spin_lock_irq(&mcp->lock);
+       mcp->ops->set_audio_divisor(mcp, div);
+       spin_unlock_irq(&mcp->lock);
+}
+EXPORT_SYMBOL(mcp_set_audio_divisor);
+
+/**
+ *     mcp_reg_write - write a device register
+ *     @mcp: MCP interface structure
+ *     @reg: 4-bit register index
+ *     @val: 16-bit data value
+ *
+ *     Write a device register.  The MCP interface must be enabled
+ *     to prevent this function hanging.
+ */
+void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&mcp->lock, flags);
+       mcp->ops->reg_write(mcp, reg, val);
+       spin_unlock_irqrestore(&mcp->lock, flags);
+}
+EXPORT_SYMBOL(mcp_reg_write);
+
+/**
+ *     mcp_reg_read - read a device register
+ *     @mcp: MCP interface structure
+ *     @reg: 4-bit register index
+ *
+ *     Read a device register and return its value.  The MCP interface
+ *     must be enabled to prevent this function hanging.
+ */
+unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg)
+{
+       unsigned long flags;
+       unsigned int val;
+
+       spin_lock_irqsave(&mcp->lock, flags);
+       val = mcp->ops->reg_read(mcp, reg);
+       spin_unlock_irqrestore(&mcp->lock, flags);
+
+       return val;
+}
+EXPORT_SYMBOL(mcp_reg_read);
+
+/**
+ *     mcp_enable - enable the MCP interface
+ *     @mcp: MCP interface to enable
+ *
+ *     Enable the MCP interface.  Each call to mcp_enable will need
+ *     a corresponding call to mcp_disable to disable the interface.
+ */
+void mcp_enable(struct mcp *mcp)
+{
+       spin_lock_irq(&mcp->lock);
+       if (mcp->use_count++ == 0)
+               mcp->ops->enable(mcp);
+       spin_unlock_irq(&mcp->lock);
+}
+EXPORT_SYMBOL(mcp_enable);
+
+/**
+ *     mcp_disable - disable the MCP interface
+ *     @mcp: MCP interface to disable
+ *
+ *     Disable the MCP interface.  The MCP interface will only be
+ *     disabled once the number of calls to mcp_enable matches the
+ *     number of calls to mcp_disable.
+ */
+void mcp_disable(struct mcp *mcp)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&mcp->lock, flags);
+       if (--mcp->use_count == 0)
+               mcp->ops->disable(mcp);
+       spin_unlock_irqrestore(&mcp->lock, flags);
+}
+EXPORT_SYMBOL(mcp_disable);
+
+static void mcp_release(struct device *dev)
+{
+       struct mcp *mcp = container_of(dev, struct mcp, attached_device);
+
+       kfree(mcp);
+}
+
+struct mcp *mcp_host_alloc(struct device *parent, size_t size)
+{
+       struct mcp *mcp;
+
+       mcp = kmalloc(sizeof(struct mcp) + size, GFP_KERNEL);
+       if (mcp) {
+               memset(mcp, 0, sizeof(struct mcp) + size);
+               spin_lock_init(&mcp->lock);
+               mcp->attached_device.parent = parent;
+               mcp->attached_device.bus = &mcp_bus_type;
+               mcp->attached_device.dma_mask = parent->dma_mask;
+               mcp->attached_device.release = mcp_release;
+       }
+       return mcp;
+}
+EXPORT_SYMBOL(mcp_host_alloc);
+
+int mcp_host_register(struct mcp *mcp)
+{
+       strcpy(mcp->attached_device.bus_id, "mcp0");
+       return device_register(&mcp->attached_device);
+}
+EXPORT_SYMBOL(mcp_host_register);
+
+void mcp_host_unregister(struct mcp *mcp)
+{
+       device_unregister(&mcp->attached_device);
+}
+EXPORT_SYMBOL(mcp_host_unregister);
+
+int mcp_driver_register(struct mcp_driver *mcpdrv)
+{
+       mcpdrv->drv.bus = &mcp_bus_type;
+       mcpdrv->drv.probe = mcp_bus_probe;
+       mcpdrv->drv.remove = mcp_bus_remove;
+       return driver_register(&mcpdrv->drv);
+}
+EXPORT_SYMBOL(mcp_driver_register);
+
+void mcp_driver_unregister(struct mcp_driver *mcpdrv)
+{
+       driver_unregister(&mcpdrv->drv);
+}
+EXPORT_SYMBOL(mcp_driver_unregister);
+
+static int __init mcp_init(void)
+{
+       return bus_register(&mcp_bus_type);
+}
+
+static void __exit mcp_exit(void)
+{
+       bus_unregister(&mcp_bus_type);
+}
+
+module_init(mcp_init);
+module_exit(mcp_exit);
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_DESCRIPTION("Core multimedia communications port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
new file mode 100644 (file)
index 0000000..e9806fb
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ *  linux/drivers/mfd/mcp-sa11x0.c
+ *
+ *  Copyright (C) 2001-2005 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ *  SA11x0 MCP (Multimedia Communications Port) driver.
+ *
+ *  MCP read/write timeouts from Jordi Colomer, rehacked by rmk.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+
+#include <asm/dma.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/system.h>
+#include <asm/arch/mcp.h>
+
+#include <asm/arch/assabet.h>
+
+#include "mcp.h"
+
+struct mcp_sa11x0 {
+       u32     mccr0;
+       u32     mccr1;
+};
+
+#define priv(mcp)      ((struct mcp_sa11x0 *)mcp_priv(mcp))
+
+static void
+mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
+{
+       unsigned int mccr0;
+
+       divisor /= 32;
+
+       mccr0 = Ser4MCCR0 & ~0x00007f00;
+       mccr0 |= divisor << 8;
+       Ser4MCCR0 = mccr0;
+}
+
+static void
+mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
+{
+       unsigned int mccr0;
+
+       divisor /= 32;
+
+       mccr0 = Ser4MCCR0 & ~0x0000007f;
+       mccr0 |= divisor;
+       Ser4MCCR0 = mccr0;
+}
+
+/*
+ * Write data to the device.  The bit should be set after 3 subframe
+ * times (each frame is 64 clocks).  We wait a maximum of 6 subframes.
+ * We really should try doing something more productive while we
+ * wait.
+ */
+static void
+mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val)
+{
+       int ret = -ETIME;
+       int i;
+
+       Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff);
+
+       for (i = 0; i < 2; i++) {
+               udelay(mcp->rw_timeout);
+               if (Ser4MCSR & MCSR_CWC) {
+                       ret = 0;
+                       break;
+               }
+       }
+
+       if (ret < 0)
+               printk(KERN_WARNING "mcp: write timed out\n");
+}
+
+/*
+ * Read data from the device.  The bit should be set after 3 subframe
+ * times (each frame is 64 clocks).  We wait a maximum of 6 subframes.
+ * We really should try doing something more productive while we
+ * wait.
+ */
+static unsigned int
+mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
+{
+       int ret = -ETIME;
+       int i;
+
+       Ser4MCDR2 = reg << 17 | MCDR2_Rd;
+
+       for (i = 0; i < 2; i++) {
+               udelay(mcp->rw_timeout);
+               if (Ser4MCSR & MCSR_CRC) {
+                       ret = Ser4MCDR2 & 0xffff;
+                       break;
+               }
+       }
+
+       if (ret < 0)
+               printk(KERN_WARNING "mcp: read timed out\n");
+
+       return ret;
+}
+
+static void mcp_sa11x0_enable(struct mcp *mcp)
+{
+       Ser4MCSR = -1;
+       Ser4MCCR0 |= MCCR0_MCE;
+}
+
+static void mcp_sa11x0_disable(struct mcp *mcp)
+{
+       Ser4MCCR0 &= ~MCCR0_MCE;
+}
+
+/*
+ * Our methods.
+ */
+static struct mcp_ops mcp_sa11x0 = {
+       .set_telecom_divisor    = mcp_sa11x0_set_telecom_divisor,
+       .set_audio_divisor      = mcp_sa11x0_set_audio_divisor,
+       .reg_write              = mcp_sa11x0_write,
+       .reg_read               = mcp_sa11x0_read,
+       .enable                 = mcp_sa11x0_enable,
+       .disable                = mcp_sa11x0_disable,
+};
+
+static int mcp_sa11x0_probe(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct mcp_plat_data *data = pdev->dev.platform_data;
+       struct mcp *mcp;
+       int ret;
+
+       if (!data)
+               return -ENODEV;
+
+       if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp"))
+               return -EBUSY;
+
+       mcp = mcp_host_alloc(&pdev->dev, sizeof(struct mcp_sa11x0));
+       if (!mcp) {
+               ret = -ENOMEM;
+               goto release;
+       }
+
+       mcp->owner              = THIS_MODULE;
+       mcp->ops                = &mcp_sa11x0;
+       mcp->sclk_rate          = data->sclk_rate;
+       mcp->dma_audio_rd       = DMA_Ser4MCP0Rd;
+       mcp->dma_audio_wr       = DMA_Ser4MCP0Wr;
+       mcp->dma_telco_rd       = DMA_Ser4MCP1Rd;
+       mcp->dma_telco_wr       = DMA_Ser4MCP1Wr;
+
+       dev_set_drvdata(dev, mcp);
+
+       if (machine_is_assabet()) {
+               ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
+       }
+
+       /*
+        * Setup the PPC unit correctly.
+        */
+       PPDR &= ~PPC_RXD4;
+       PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
+       PSDR |= PPC_RXD4;
+       PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+       PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+
+       /*
+        * Initialise device.  Note that we initially
+        * set the sampling rate to minimum.
+        */
+       Ser4MCSR = -1;
+       Ser4MCCR1 = data->mccr1;
+       Ser4MCCR0 = data->mccr0 | 0x7f7f;
+
+       /*
+        * Calculate the read/write timeout (us) from the bit clock
+        * rate.  This is the period for 3 64-bit frames.  Always
+        * round this time up.
+        */
+       mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
+                         mcp->sclk_rate;
+
+       ret = mcp_host_register(mcp);
+       if (ret == 0)
+               goto out;
+
+ release:
+       release_mem_region(0x80060000, 0x60);
+       dev_set_drvdata(dev, NULL);
+
+ out:
+       return ret;
+}
+
+static int mcp_sa11x0_remove(struct device *dev)
+{
+       struct mcp *mcp = dev_get_drvdata(dev);
+
+       dev_set_drvdata(dev, NULL);
+       mcp_host_unregister(mcp);
+       release_mem_region(0x80060000, 0x60);
+
+       return 0;
+}
+
+static int mcp_sa11x0_suspend(struct device *dev, pm_message_t state, u32 level)
+{
+       struct mcp *mcp = dev_get_drvdata(dev);
+
+       if (level == SUSPEND_DISABLE) {
+               priv(mcp)->mccr0 = Ser4MCCR0;
+               priv(mcp)->mccr1 = Ser4MCCR1;
+               Ser4MCCR0 &= ~MCCR0_MCE;
+       }
+       return 0;
+}
+
+static int mcp_sa11x0_resume(struct device *dev, u32 level)
+{
+       struct mcp *mcp = dev_get_drvdata(dev);
+
+       if (level == RESUME_RESTORE_STATE) {
+               Ser4MCCR1 = priv(mcp)->mccr1;
+               Ser4MCCR0 = priv(mcp)->mccr0;
+       }
+       return 0;
+}
+
+/*
+ * The driver for the SA11x0 MCP port.
+ */
+static struct device_driver mcp_sa11x0_driver = {
+       .name           = "sa11x0-mcp",
+       .bus            = &platform_bus_type,
+       .probe          = mcp_sa11x0_probe,
+       .remove         = mcp_sa11x0_remove,
+       .suspend        = mcp_sa11x0_suspend,
+       .resume         = mcp_sa11x0_resume,
+};
+
+/*
+ * This needs re-working
+ */
+static int __init mcp_sa11x0_init(void)
+{
+       return driver_register(&mcp_sa11x0_driver);
+}
+
+static void __exit mcp_sa11x0_exit(void)
+{
+       driver_unregister(&mcp_sa11x0_driver);
+}
+
+module_init(mcp_sa11x0_init);
+module_exit(mcp_sa11x0_exit);
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_DESCRIPTION("SA11x0 multimedia communications port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/mcp.h b/drivers/mfd/mcp.h
new file mode 100644 (file)
index 0000000..c093a93
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *  linux/drivers/mfd/mcp.h
+ *
+ *  Copyright (C) 2001 Russell King, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ */
+#ifndef MCP_H
+#define MCP_H
+
+struct mcp_ops;
+
+struct mcp {
+       struct module   *owner;
+       struct mcp_ops  *ops;
+       spinlock_t      lock;
+       int             use_count;
+       unsigned int    sclk_rate;
+       unsigned int    rw_timeout;
+       dma_device_t    dma_audio_rd;
+       dma_device_t    dma_audio_wr;
+       dma_device_t    dma_telco_rd;
+       dma_device_t    dma_telco_wr;
+       struct device   attached_device;
+};
+
+struct mcp_ops {
+       void            (*set_telecom_divisor)(struct mcp *, unsigned int);
+       void            (*set_audio_divisor)(struct mcp *, unsigned int);
+       void            (*reg_write)(struct mcp *, unsigned int, unsigned int);
+       unsigned int    (*reg_read)(struct mcp *, unsigned int);
+       void            (*enable)(struct mcp *);
+       void            (*disable)(struct mcp *);
+};
+
+void mcp_set_telecom_divisor(struct mcp *, unsigned int);
+void mcp_set_audio_divisor(struct mcp *, unsigned int);
+void mcp_reg_write(struct mcp *, unsigned int, unsigned int);
+unsigned int mcp_reg_read(struct mcp *, unsigned int);
+void mcp_enable(struct mcp *);
+void mcp_disable(struct mcp *);
+#define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate)
+
+struct mcp *mcp_host_alloc(struct device *, size_t);
+int mcp_host_register(struct mcp *);
+void mcp_host_unregister(struct mcp *);
+
+struct mcp_driver {
+       struct device_driver drv;
+       int (*probe)(struct mcp *);
+       void (*remove)(struct mcp *);
+       int (*suspend)(struct mcp *, pm_message_t);
+       int (*resume)(struct mcp *);
+};
+
+int mcp_driver_register(struct mcp_driver *);
+void mcp_driver_unregister(struct mcp_driver *);
+
+#define mcp_get_drvdata(mcp)   dev_get_drvdata(&(mcp)->attached_device)
+#define mcp_set_drvdata(mcp,d) dev_set_drvdata(&(mcp)->attached_device, d)
+
+#define mcp_priv(mcp)          ((void *)((mcp)+1))
+
+#endif
index eeb9f66..3c59048 100644 (file)
@@ -361,7 +361,7 @@ static void mmc_decode_cid(struct mmc_card *card)
 
        default:
                printk("%s: card has unknown MMCA version %d\n",
-                       card->host->host_name, card->csd.mmca_vsn);
+                       mmc_hostname(card->host), card->csd.mmca_vsn);
                mmc_card_set_bad(card);
                break;
        }
@@ -383,7 +383,7 @@ static void mmc_decode_csd(struct mmc_card *card)
        csd_struct = UNSTUFF_BITS(resp, 126, 2);
        if (csd_struct != 1 && csd_struct != 2) {
                printk("%s: unrecognised CSD structure version %d\n",
-                       card->host->host_name, csd_struct);
+                       mmc_hostname(card->host), csd_struct);
                mmc_card_set_bad(card);
                return;
        }
@@ -551,7 +551,7 @@ static void mmc_discover_cards(struct mmc_host *host)
                }
                if (err != MMC_ERR_NONE) {
                        printk(KERN_ERR "%s: error requesting CID: %d\n",
-                               host->host_name, err);
+                               mmc_hostname(host), err);
                        break;
                }
 
@@ -796,17 +796,13 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
 {
        struct mmc_host *host;
 
-       host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+       host = mmc_alloc_host_sysfs(extra, dev);
        if (host) {
-               memset(host, 0, sizeof(struct mmc_host) + extra);
-
                spin_lock_init(&host->lock);
                init_waitqueue_head(&host->wq);
                INIT_LIST_HEAD(&host->cards);
                INIT_WORK(&host->detect, mmc_rescan, host);
 
-               host->dev = dev;
-
                /*
                 * By default, hosts do not support SGIO or large requests.
                 * They have to set these according to their abilities.
@@ -828,15 +824,15 @@ EXPORT_SYMBOL(mmc_alloc_host);
  */
 int mmc_add_host(struct mmc_host *host)
 {
-       static unsigned int host_num;
+       int ret;
 
-       snprintf(host->host_name, sizeof(host->host_name),
-                "mmc%d", host_num++);
-
-       mmc_power_off(host);
-       mmc_detect_change(host);
+       ret = mmc_add_host_sysfs(host);
+       if (ret == 0) {
+               mmc_power_off(host);
+               mmc_detect_change(host);
+       }
 
-       return 0;
+       return ret;
 }
 
 EXPORT_SYMBOL(mmc_add_host);
@@ -859,6 +855,7 @@ void mmc_remove_host(struct mmc_host *host)
        }
 
        mmc_power_off(host);
+       mmc_remove_host_sysfs(host);
 }
 
 EXPORT_SYMBOL(mmc_remove_host);
@@ -872,7 +869,7 @@ EXPORT_SYMBOL(mmc_remove_host);
 void mmc_free_host(struct mmc_host *host)
 {
        flush_scheduled_work();
-       kfree(host);
+       mmc_free_host_sysfs(host);
 }
 
 EXPORT_SYMBOL(mmc_free_host);
index b498dff..97bae00 100644 (file)
@@ -13,4 +13,9 @@
 void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
 int mmc_register_card(struct mmc_card *card);
 void mmc_remove_card(struct mmc_card *card);
+
+struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev);
+int mmc_add_host_sysfs(struct mmc_host *host);
+void mmc_remove_host_sysfs(struct mmc_host *host);
+void mmc_free_host_sysfs(struct mmc_host *host);
 #endif
index 5556cd3..ad89498 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/idr.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -20,6 +21,7 @@
 
 #define dev_to_mmc_card(d)     container_of(d, struct mmc_card, dev)
 #define to_mmc_driver(d)       container_of(d, struct mmc_driver, drv)
+#define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev)
 
 #define MMC_ATTR(name, fmt, args...)                                   \
 static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf)        \
@@ -206,7 +208,7 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
 int mmc_register_card(struct mmc_card *card)
 {
        snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
-                "%s:%04x", card->host->host_name, card->rca);
+                "%s:%04x", mmc_hostname(card->host), card->rca);
 
        return device_add(&card->dev);
 }
@@ -224,13 +226,97 @@ void mmc_remove_card(struct mmc_card *card)
 }
 
 
+static void mmc_host_classdev_release(struct class_device *dev)
+{
+       struct mmc_host *host = cls_dev_to_mmc_host(dev);
+       kfree(host);
+}
+
+static struct class mmc_host_class = {
+       .name           = "mmc_host",
+       .release        = mmc_host_classdev_release,
+};
+
+static DEFINE_IDR(mmc_host_idr);
+static DEFINE_SPINLOCK(mmc_host_lock);
+
+/*
+ * Internal function. Allocate a new MMC host.
+ */
+struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
+{
+       struct mmc_host *host;
+
+       host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+       if (host) {
+               memset(host, 0, sizeof(struct mmc_host) + extra);
+
+               host->dev = dev;
+               host->class_dev.dev = host->dev;
+               host->class_dev.class = &mmc_host_class;
+               class_device_initialize(&host->class_dev);
+       }
+
+       return host;
+}
+
+/*
+ * Internal function. Register a new MMC host with the MMC class.
+ */
+int mmc_add_host_sysfs(struct mmc_host *host)
+{
+       int err;
+
+       if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
+               return -ENOMEM;
+
+       spin_lock(&mmc_host_lock);
+       err = idr_get_new(&mmc_host_idr, host, &host->index);
+       spin_unlock(&mmc_host_lock);
+       if (err)
+               return err;
+
+       snprintf(host->class_dev.class_id, BUS_ID_SIZE,
+                "mmc%d", host->index);
+
+       return class_device_add(&host->class_dev);
+}
+
+/*
+ * Internal function. Unregister a MMC host with the MMC class.
+ */
+void mmc_remove_host_sysfs(struct mmc_host *host)
+{
+       class_device_del(&host->class_dev);
+
+       spin_lock(&mmc_host_lock);
+       idr_remove(&mmc_host_idr, host->index);
+       spin_unlock(&mmc_host_lock);
+}
+
+/*
+ * Internal function. Free a MMC host.
+ */
+void mmc_free_host_sysfs(struct mmc_host *host)
+{
+       class_device_put(&host->class_dev);
+}
+
+
 static int __init mmc_init(void)
 {
-       return bus_register(&mmc_bus_type);
+       int ret = bus_register(&mmc_bus_type);
+       if (ret == 0) {
+               ret = class_register(&mmc_host_class);
+               if (ret)
+                       bus_unregister(&mmc_bus_type);
+       }
+       return ret;
 }
 
 static void __exit mmc_exit(void)
 {
+       class_unregister(&mmc_host_class);
        bus_unregister(&mmc_bus_type);
 }
 
index 7a42966..716c4ef 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifdef CONFIG_MMC_DEBUG
 #define DBG(host,fmt,args...)  \
-       pr_debug("%s: %s: " fmt, host->mmc->host_name, __func__ , args)
+       pr_debug("%s: %s: " fmt, mmc_hostname(host->mmc), __func__ , args)
 #else
 #define DBG(host,fmt,args...)  do { } while (0)
 #endif
@@ -541,7 +541,7 @@ static int mmci_probe(struct amba_device *dev, void *id)
        mmc_add_host(mmc);
 
        printk(KERN_INFO "%s: MMCI rev %x cfg %02x at 0x%08lx irq %d,%d\n",
-               mmc->host_name, amba_rev(dev), amba_config(dev),
+               mmc_hostname(mmc), amba_rev(dev), amba_config(dev),
                dev->res.start, dev->irq[0], dev->irq[1]);
 
        init_timer(&host->timer);
index 8b487ed..402c2d6 100644 (file)
@@ -42,7 +42,7 @@
 #include "wbsd.h"
 
 #define DRIVER_NAME "wbsd"
-#define DRIVER_VERSION "1.2"
+#define DRIVER_VERSION "1.3"
 
 #ifdef CONFIG_MMC_DEBUG
 #define DBG(x...) \
@@ -1796,7 +1796,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
        
        mmc_add_host(mmc);
 
-       printk(KERN_INFO "%s: W83L51xD", mmc->host_name);
+       printk(KERN_INFO "%s: W83L51xD", mmc_hostname(mmc));
        if (host->chip_id != 0)
                printk(" id %x", (int)host->chip_id);
        printk(" at 0x%x irq %d", (int)host->base, (int)host->irq);
index 7b293f0..34b80de 100644 (file)
@@ -1897,6 +1897,7 @@ static int cp_resume (struct pci_dev *pdev)
 {
        struct net_device *dev;
        struct cp_private *cp;
+       unsigned long flags;
 
        dev = pci_get_drvdata (pdev);
        cp  = netdev_priv(dev);
@@ -1910,6 +1911,12 @@ static int cp_resume (struct pci_dev *pdev)
        
        cp_init_hw (cp);
        netif_start_queue (dev);
+
+       spin_lock_irqsave (&cp->lock, flags);
+
+       mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
+
+       spin_unlock_irqrestore (&cp->lock, flags);
        
        return 0;
 }
index 26e4aa9..43d14bf 100644 (file)
@@ -131,6 +131,8 @@ config NET_SB1000
 
        source "drivers/net/arcnet/Kconfig"
 
+source "drivers/net/phy/Kconfig"
+
 #
 #      Ethernet
 #
@@ -1145,7 +1147,7 @@ config IBMVETH
          be called ibmveth.
 
 config IBM_EMAC
-       tristate "IBM PPC4xx EMAC driver support"
+       bool "IBM PPC4xx EMAC driver support"
        depends on 4xx
        select CRC32
        ---help---
@@ -1154,7 +1156,7 @@ config IBM_EMAC
 
 config IBM_EMAC_ERRMSG
        bool "Verbose error messages"
-       depends on IBM_EMAC
+       depends on IBM_EMAC && BROKEN
 
 config IBM_EMAC_RXB
        int "Number of receive buffers"
index 67b280a..c5c71d7 100644 (file)
@@ -66,6 +66,7 @@ obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
 #
 
 obj-$(CONFIG_MII) += mii.o
+obj-$(CONFIG_PHYLIB) += phy/
 
 obj-$(CONFIG_SUNDANCE) += sundance.o
 obj-$(CONFIG_HAMACHI) += hamachi.o
index 3707df6..60304f7 100644 (file)
@@ -87,7 +87,6 @@ extern struct net_device *mvme147lance_probe(int unit);
 extern struct net_device *tc515_probe(int unit);
 extern struct net_device *lance_probe(int unit);
 extern struct net_device *mace_probe(int unit);
-extern struct net_device *macsonic_probe(int unit);
 extern struct net_device *mac8390_probe(int unit);
 extern struct net_device *mac89x0_probe(int unit);
 extern struct net_device *mc32_probe(int unit);
@@ -284,9 +283,6 @@ static struct devprobe2 m68k_probes[] __initdata = {
 #ifdef CONFIG_MACMACE          /* Mac 68k Quadra AV builtin Ethernet */
        {mace_probe, 0},
 #endif
-#ifdef CONFIG_MACSONIC         /* Mac SONIC-based Ethernet of all sorts */ 
-       {macsonic_probe, 0},
-#endif
 #ifdef CONFIG_MAC8390           /* NuBus NS8390-based cards */
        {mac8390_probe, 0},
 #endif
@@ -318,17 +314,9 @@ static void __init ethif_probe2(int unit)
 #ifdef CONFIG_TR
 /* Token-ring device probe */
 extern int ibmtr_probe_card(struct net_device *);
-extern struct net_device *sk_isa_probe(int unit);
-extern struct net_device *proteon_probe(int unit);
 extern struct net_device *smctr_probe(int unit);
 
 static struct devprobe2 tr_probes2[] __initdata = {
-#ifdef CONFIG_SKISA
-       {sk_isa_probe, 0},
-#endif
-#ifdef CONFIG_PROTEON
-       {proteon_probe, 0},
-#endif
 #ifdef CONFIG_SMCTR
        {smctr_probe, 0},
 #endif
index 5ce606d..19e829b 100644 (file)
@@ -1106,18 +1106,13 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
                        }
                }
 
-               if (found) {
-                       /* a slave was found that is using the mac address
-                        * of the new slave
-                        */
-                       printk(KERN_ERR DRV_NAME
-                              ": Error: the hw address of slave %s is not "
-                              "unique - cannot enslave it!",
-                              slave->dev->name);
-                       return -EINVAL;
-               }
+               if (!found)
+                       return 0;
 
-               return 0;
+               /* Try setting slave mac to bond address and fall-through
+                  to code handling that situation below... */
+               alb_set_slave_mac_addr(slave, bond->dev->dev_addr,
+                                      bond->alb_info.rlb_enabled);
        }
 
        /* The slave's address is equal to the address of the bond.
index 2c930da..94c9f68 100644 (file)
@@ -1604,6 +1604,44 @@ static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_
        return 0;
 }
 
+#define BOND_INTERSECT_FEATURES \
+       (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)
+
+/* 
+ * Compute the features available to the bonding device by 
+ * intersection of all of the slave devices' BOND_INTERSECT_FEATURES.
+ * Call this after attaching or detaching a slave to update the 
+ * bond's features.
+ */
+static int bond_compute_features(struct bonding *bond)
+{
+       int i;
+       struct slave *slave;
+       struct net_device *bond_dev = bond->dev;
+       int features = bond->bond_features;
+
+       bond_for_each_slave(bond, slave, i) {
+               struct net_device * slave_dev = slave->dev;
+               if (i == 0) {
+                       features |= BOND_INTERSECT_FEATURES;
+               }
+               features &=
+                       ~(~slave_dev->features & BOND_INTERSECT_FEATURES);
+       }
+
+       /* turn off NETIF_F_SG if we need a csum and h/w can't do it */
+       if ((features & NETIF_F_SG) && 
+               !(features & (NETIF_F_IP_CSUM |
+                             NETIF_F_NO_CSUM |
+                             NETIF_F_HW_CSUM))) {
+               features &= ~NETIF_F_SG;
+       }
+
+       bond_dev->features = features;
+
+       return 0;
+}
+
 /* enslave device <slave> to bond device <master> */
 static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 {
@@ -1811,6 +1849,8 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
        new_slave->delay = 0;
        new_slave->link_failure_count = 0;
 
+       bond_compute_features(bond);
+
        if (bond->params.miimon && !bond->params.use_carrier) {
                link_reporting = bond_check_dev_link(bond, slave_dev, 1);
 
@@ -2015,7 +2055,7 @@ err_free:
 
 err_undo_flags:
        bond_dev->features = old_features;
-
        return res;
 }
 
@@ -2100,6 +2140,8 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de
        /* release the slave from its bond */
        bond_detach_slave(bond, slave);
 
+       bond_compute_features(bond);
+
        if (bond->primary_slave == slave) {
                bond->primary_slave = NULL;
        }
@@ -2243,6 +2285,8 @@ static int bond_release_all(struct net_device *bond_dev)
                        bond_alb_deinit_slave(bond, slave);
                }
 
+               bond_compute_features(bond);
+
                /* now that the slave is detached, unlock and perform
                 * all the undo steps that should not be called from
                 * within a lock.
@@ -3588,6 +3632,7 @@ static int bond_master_netdev_event(unsigned long event, struct net_device *bond
 static int bond_slave_netdev_event(unsigned long event, struct net_device *slave_dev)
 {
        struct net_device *bond_dev = slave_dev->master;
+       struct bonding *bond = bond_dev->priv;
 
        switch (event) {
        case NETDEV_UNREGISTER:
@@ -3626,6 +3671,9 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave
                 * TODO: handle changing the primary's name
                 */
                break;
+       case NETDEV_FEAT_CHANGE:
+               bond_compute_features(bond);
+               break;
        default:
                break;
        }
@@ -4526,6 +4574,11 @@ static inline void bond_set_mode_ops(struct bonding *bond, int mode)
        }
 }
 
+static struct ethtool_ops bond_ethtool_ops = {
+       .get_tx_csum            = ethtool_op_get_tx_csum,
+       .get_sg                 = ethtool_op_get_sg,
+};
+
 /*
  * Does not allocate but creates a /proc entry.
  * Allowed to fail.
@@ -4555,6 +4608,7 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par
        bond_dev->stop = bond_close;
        bond_dev->get_stats = bond_get_stats;
        bond_dev->do_ioctl = bond_do_ioctl;
+       bond_dev->ethtool_ops = &bond_ethtool_ops;
        bond_dev->set_multicast_list = bond_set_multicast_list;
        bond_dev->change_mtu = bond_change_mtu;
        bond_dev->set_mac_address = bond_set_mac_address;
@@ -4591,6 +4645,8 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par
                               NETIF_F_HW_VLAN_RX |
                               NETIF_F_HW_VLAN_FILTER);
 
+       bond->bond_features = bond_dev->features;
+
 #ifdef CONFIG_PROC_FS
        bond_create_proc_entry(bond);
 #endif
index d27f377..3881969 100644 (file)
@@ -211,6 +211,9 @@ struct bonding {
        struct   bond_params params;
        struct   list_head vlan_list;
        struct   vlan_group *vlgrp;
+       /* the features the bonding device supports, independently 
+        * of any slaves */
+       int      bond_features; 
 };
 
 /**
index 2c6dc24..b780307 100644 (file)
@@ -417,6 +417,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
        struct net_local *lp = netdev_priv(dev);
        static unsigned version_printed;
        int i;
+       int tmp;
        unsigned rev_type = 0;
        int eeprom_buff[CHKSUM_LEN];
        int retval;
@@ -492,14 +493,17 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
                                goto out2;
                        }
        }
-printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
+       printk(KERN_DEBUG "PP_addr at %x: 0x%x\n",
+                       ioaddr + ADD_PORT, inw(ioaddr + ADD_PORT));
 
        ioaddr &= ~3;
        outw(PP_ChipID, ioaddr + ADD_PORT);
 
-       if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) {
-               printk(KERN_ERR "%s: incorrect signature 0x%x\n",
-                       dev->name, inw(ioaddr + DATA_PORT));
+       tmp = inw(ioaddr + DATA_PORT);
+       if (tmp != CHIP_EISA_ID_SIG) {
+               printk(KERN_DEBUG "%s: incorrect signature at %x: 0x%x!="
+                       CHIP_EISA_ID_SIG_STR "\n",
+                       dev->name, ioaddr + DATA_PORT, tmp);
                retval = -ENODEV;
                goto out2;
        }
index bd3ad8e..decea26 100644 (file)
@@ -93,6 +93,7 @@
 #endif
 
 #define CHIP_EISA_ID_SIG 0x630E   /*  Product ID Code for Crystal Chip (CS8900 spec 4.3) */
+#define CHIP_EISA_ID_SIG_STR "0x630E"
 
 #ifdef IBMEIPKT
 #define EISA_ID_SIG 0x4D24     /*  IBM */
index 5fddc0f..6440a89 100644 (file)
  *                        net_device_stats
  *                      * introduced tx_timeout function
  *                      * reworked locking
+ *
+ *       01-Jul-2005   Ben Dooks <ben@simtec.co.uk>
+ *                     * fixed spinlock call without pointer
+ *                     * ensure spinlock is initialised
  */
 
 #include <linux/module.h>
@@ -148,7 +152,6 @@ static int dm9000_probe(struct device *);
 static int dm9000_open(struct net_device *);
 static int dm9000_start_xmit(struct sk_buff *, struct net_device *);
 static int dm9000_stop(struct net_device *);
-static int dm9000_do_ioctl(struct net_device *, struct ifreq *, int);
 
 
 static void dm9000_timer(unsigned long);
@@ -322,7 +325,7 @@ static void dm9000_timeout(struct net_device *dev)
 
        /* Save previous register address */
        reg_save = readb(db->io_addr);
-       spin_lock_irqsave(db->lock,flags);
+       spin_lock_irqsave(&db->lock,flags);
 
        netif_stop_queue(dev);
        dm9000_reset(db);
@@ -333,7 +336,7 @@ static void dm9000_timeout(struct net_device *dev)
 
        /* Restore previous register address */
        writeb(reg_save, db->io_addr);
-       spin_unlock_irqrestore(db->lock,flags);
+       spin_unlock_irqrestore(&db->lock,flags);
 }
 
 
@@ -387,8 +390,6 @@ dm9000_probe(struct device *dev)
        int i;
        u32 id_val;
 
-       printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME);
-
        /* Init network device */
        ndev = alloc_etherdev(sizeof (struct board_info));
        if (!ndev) {
@@ -405,6 +406,8 @@ dm9000_probe(struct device *dev)
        db = (struct board_info *) ndev->priv;
        memset(db, 0, sizeof (*db));
 
+       spin_lock_init(&db->lock);
+
        if (pdev->num_resources < 2) {
                ret = -ENODEV;
                goto out;
@@ -541,7 +544,6 @@ dm9000_probe(struct device *dev)
        ndev->stop               = &dm9000_stop;
        ndev->get_stats          = &dm9000_get_stats;
        ndev->set_multicast_list = &dm9000_hash_table;
-       ndev->do_ioctl           = &dm9000_do_ioctl;
 
 #ifdef DM9000_PROGRAM_EEPROM
        program_eeprom(db);
@@ -612,7 +614,7 @@ dm9000_open(struct net_device *dev)
 
        /* set and active a timer process */
        init_timer(&db->timer);
-       db->timer.expires  = DM9000_TIMER_WUT * 2;
+       db->timer.expires  = DM9000_TIMER_WUT;
        db->timer.data     = (unsigned long) dev;
        db->timer.function = &dm9000_timer;
        add_timer(&db->timer);
@@ -845,15 +847,6 @@ dm9000_get_stats(struct net_device *dev)
        return &db->stats;
 }
 
-/*
- *  Process the upper socket ioctl command
- */
-static int
-dm9000_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-       PRINTK1("entering %s\n",__FUNCTION__);
-       return 0;
-}
 
 /*
  *  A periodic timer routine
@@ -864,21 +857,11 @@ dm9000_timer(unsigned long data)
 {
        struct net_device *dev = (struct net_device *) data;
        board_info_t *db = (board_info_t *) dev->priv;
-       u8 reg_save;
-       unsigned long flags;
 
        PRINTK3("dm9000_timer()\n");
 
-       spin_lock_irqsave(db->lock,flags);
-       /* Save previous register address */
-       reg_save = readb(db->io_addr);
-
        mii_check_media(&db->mii, netif_msg_link(db), 0);
 
-       /* Restore previous register address */
-       writeb(reg_save, db->io_addr);
-       spin_unlock_irqrestore(db->lock,flags);
-
        /* Set timer again */
        db->timer.expires = DM9000_TIMER_WUT;
        add_timer(&db->timer);
@@ -1098,9 +1081,14 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
 {
        board_info_t *db = (board_info_t *) dev->priv;
        unsigned long flags;
+       unsigned int reg_save;
        int ret;
 
        spin_lock_irqsave(&db->lock,flags);
+
+       /* Save previous register address */
+       reg_save = readb(db->io_addr);
+
        /* Fill the phyxcer register into REG_0C */
        iow(db, DM9000_EPAR, DM9000_PHY | reg);
 
@@ -1111,6 +1099,9 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
        /* The read data keeps on REG_0D & REG_0E */
        ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
 
+       /* restore the previous address */
+       writeb(reg_save, db->io_addr);
+
        spin_unlock_irqrestore(&db->lock,flags);
 
        return ret;
@@ -1124,9 +1115,13 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
 {
        board_info_t *db = (board_info_t *) dev->priv;
        unsigned long flags;
+       unsigned long reg_save;
 
        spin_lock_irqsave(&db->lock,flags);
 
+       /* Save previous register address */
+       reg_save = readb(db->io_addr);
+
        /* Fill the phyxcer register into REG_0C */
        iow(db, DM9000_EPAR, DM9000_PHY | reg);
 
@@ -1138,6 +1133,9 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
        udelay(500);            /* Wait write complete */
        iow(db, DM9000_EPCR, 0x0);      /* Clear phyxcer write command */
 
+       /* restore the previous address */
+       writeb(reg_save, db->io_addr);
+
        spin_unlock_irqrestore(&db->lock,flags);
 }
 
@@ -1202,6 +1200,8 @@ static struct device_driver dm9000_driver = {
 static int __init
 dm9000_init(void)
 {
+       printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME);
+
        return driver_register(&dm9000_driver); /* search board and register */
 }
 
index 5e5d2c3..9b596e0 100644 (file)
@@ -2767,7 +2767,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
                                        "  next_to_use          <%x>\n"
                                        "  next_to_clean        <%x>\n"
                                        "buffer_info[next_to_clean]\n"
-                                       "  dma                  <%zx>\n"
+                                       "  dma                  <%llx>\n"
                                        "  time_stamp           <%lx>\n"
                                        "  next_to_watch        <%x>\n"
                                        "  jiffies              <%lx>\n"
@@ -2776,7 +2776,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
                                E1000_READ_REG(&adapter->hw, TDT),
                                tx_ring->next_to_use,
                                i,
-                               tx_ring->buffer_info[i].dma,
+                               (unsigned long long)tx_ring->buffer_info[i].dma,
                                tx_ring->buffer_info[i].time_stamp,
                                eop,
                                jiffies,
@@ -3789,6 +3789,7 @@ e1000_netpoll(struct net_device *netdev)
        struct e1000_adapter *adapter = netdev_priv(netdev);
        disable_irq(adapter->pdev->irq);
        e1000_intr(adapter->pdev->irq, netdev, NULL);
+       e1000_clean_tx_irq(adapter);
        enable_irq(adapter->pdev->irq);
 }
 #endif
index 1795425..8c62ced 100644 (file)
@@ -1263,8 +1263,8 @@ speedo_init_rx_ring(struct net_device *dev)
        for (i = 0; i < RX_RING_SIZE; i++) {
                struct sk_buff *skb;
                skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
-               /* XXX: do we really want to call this before the NULL check? --hch */
-               rx_align(skb);                  /* Align IP on 16 byte boundary */
+               if (skb)
+                       rx_align(skb);        /* Align IP on 16 byte boundary */
                sp->rx_skbuff[i] = skb;
                if (skb == NULL)
                        break;                  /* OK.  Just initially short of Rx bufs. */
@@ -1654,8 +1654,8 @@ static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry)
        struct sk_buff *skb;
        /* Get a fresh skbuff to replace the consumed one. */
        skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
-       /* XXX: do we really want to call this before the NULL check? --hch */
-       rx_align(skb);                          /* Align IP on 16 byte boundary */
+       if (skb)
+               rx_align(skb);          /* Align IP on 16 byte boundary */
        sp->rx_skbuff[entry] = skb;
        if (skb == NULL) {
                sp->rx_ringp[entry] = NULL;
index 64f0f69..7d93948 100644 (file)
  *     0.33: 16 May 2005: Support for MCP51 added.
  *     0.34: 18 Jun 2005: Add DEV_NEED_LINKTIMER to all nForce nics.
  *     0.35: 26 Jun 2005: Support for MCP55 added.
+ *     0.36: 28 Jun 2005: Add jumbo frame support.
+ *     0.37: 10 Jul 2005: Additional ethtool support, cleanup of pci id list
+ *     0.38: 16 Jul 2005: tx irq rewrite: Use global flags instead of
+ *                        per-packet flags.
+ *      0.39: 18 Jul 2005: Add 64bit descriptor support.
+ *      0.40: 19 Jul 2005: Add support for mac address change.
+ *      0.41: 30 Jul 2005: Write back original MAC in nv_close instead
+ *                        of nv_remove
+ *      0.42: 06 Aug 2005: Fix lack of link speed initialization
+ *                        in the second (and later) nv_open call
  *
  * Known bugs:
  * We suspect that on some hardware no TX done interrupts are generated.
  * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
  * superfluous timer interrupts from the nic.
  */
-#define FORCEDETH_VERSION              "0.35"
+#define FORCEDETH_VERSION              "0.41"
 #define DRV_NAME                       "forcedeth"
 
 #include <linux/module.h>
  * Hardware access:
  */
 
-#define DEV_NEED_LASTPACKET1   0x0001  /* set LASTPACKET1 in tx flags */
-#define DEV_IRQMASK_1          0x0002  /* use NVREG_IRQMASK_WANTED_1 for irq mask */
-#define DEV_IRQMASK_2          0x0004  /* use NVREG_IRQMASK_WANTED_2 for irq mask */
-#define DEV_NEED_TIMERIRQ      0x0008  /* set the timer irq flag in the irq mask */
-#define DEV_NEED_LINKTIMER     0x0010  /* poll link settings. Relies on the timer irq */
+#define DEV_NEED_TIMERIRQ      0x0001  /* set the timer irq flag in the irq mask */
+#define DEV_NEED_LINKTIMER     0x0002  /* poll link settings. Relies on the timer irq */
+#define DEV_HAS_LARGEDESC      0x0004  /* device supports jumbo frames and needs packet format 2 */
+#define DEV_HAS_HIGH_DMA        0x0008  /* device supports 64bit dma */
 
 enum {
        NvRegIrqStatus = 0x000,
@@ -146,13 +155,16 @@ enum {
 #define NVREG_IRQ_RX                   0x0002
 #define NVREG_IRQ_RX_NOBUF             0x0004
 #define NVREG_IRQ_TX_ERR               0x0008
-#define NVREG_IRQ_TX2                  0x0010
+#define NVREG_IRQ_TX_OK                        0x0010
 #define NVREG_IRQ_TIMER                        0x0020
 #define NVREG_IRQ_LINK                 0x0040
+#define NVREG_IRQ_TX_ERROR             0x0080
 #define NVREG_IRQ_TX1                  0x0100
-#define NVREG_IRQMASK_WANTED_1         0x005f
-#define NVREG_IRQMASK_WANTED_2         0x0147
-#define NVREG_IRQ_UNKNOWN              (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR|NVREG_IRQ_TX2|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX1))
+#define NVREG_IRQMASK_WANTED           0x00df
+
+#define NVREG_IRQ_UNKNOWN      (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR| \
+                                       NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX_ERROR| \
+                                       NVREG_IRQ_TX1))
 
        NvRegUnknownSetupReg6 = 0x008,
 #define NVREG_UNKSETUP6_VAL            3
@@ -286,6 +298,18 @@ struct ring_desc {
        u32 FlagLen;
 };
 
+struct ring_desc_ex {
+       u32 PacketBufferHigh;
+       u32 PacketBufferLow;
+       u32 Reserved;
+       u32 FlagLen;
+};
+
+typedef union _ring_type {
+       struct ring_desc* orig;
+       struct ring_desc_ex* ex;
+} ring_type;
+
 #define FLAG_MASK_V1 0xffff0000
 #define FLAG_MASK_V2 0xffffc000
 #define LEN_MASK_V1 (0xffffffff ^ FLAG_MASK_V1)
@@ -293,7 +317,7 @@ struct ring_desc {
 
 #define NV_TX_LASTPACKET       (1<<16)
 #define NV_TX_RETRYERROR       (1<<19)
-#define NV_TX_LASTPACKET1      (1<<24)
+#define NV_TX_FORCED_INTERRUPT (1<<24)
 #define NV_TX_DEFERRED         (1<<26)
 #define NV_TX_CARRIERLOST      (1<<27)
 #define NV_TX_LATECOLLISION    (1<<28)
@@ -303,7 +327,7 @@ struct ring_desc {
 
 #define NV_TX2_LASTPACKET      (1<<29)
 #define NV_TX2_RETRYERROR      (1<<18)
-#define NV_TX2_LASTPACKET1     (1<<23)
+#define NV_TX2_FORCED_INTERRUPT        (1<<30)
 #define NV_TX2_DEFERRED                (1<<25)
 #define NV_TX2_CARRIERLOST     (1<<26)
 #define NV_TX2_LATECOLLISION   (1<<27)
@@ -379,9 +403,13 @@ struct ring_desc {
 #define TX_LIMIT_START 62
 
 /* rx/tx mac addr + type + vlan + align + slack*/
-#define RX_NIC_BUFSIZE         (ETH_DATA_LEN + 64)
-/* even more slack */
-#define RX_ALLOC_BUFSIZE       (ETH_DATA_LEN + 128)
+#define NV_RX_HEADERS          (64)
+/* even more slack. */
+#define NV_RX_ALLOC_PAD                (64)
+
+/* maximum mtu size */
+#define NV_PKTLIMIT_1  ETH_DATA_LEN    /* hard limit not known */
+#define NV_PKTLIMIT_2  9100    /* Actual limit according to NVidia: 9202 */
 
 #define OOM_REFILL     (1+HZ/20)
 #define POLL_WAIT      (1+HZ/100)
@@ -396,6 +424,7 @@ struct ring_desc {
  */
 #define DESC_VER_1     0x0
 #define DESC_VER_2     (0x02100|NVREG_TXRXCTL_RXCHECK)
+#define DESC_VER_3      (0x02200|NVREG_TXRXCTL_RXCHECK)
 
 /* PHY defines */
 #define PHY_OUI_MARVELL        0x5043
@@ -468,11 +497,12 @@ struct fe_priv {
        /* rx specific fields.
         * Locking: Within irq hander or disable_irq+spin_lock(&np->lock);
         */
-       struct ring_desc *rx_ring;
+       ring_type rx_ring;
        unsigned int cur_rx, refill_rx;
        struct sk_buff *rx_skbuff[RX_RING];
        dma_addr_t rx_dma[RX_RING];
        unsigned int rx_buf_sz;
+       unsigned int pkt_limit;
        struct timer_list oom_kick;
        struct timer_list nic_poll;
 
@@ -484,7 +514,7 @@ struct fe_priv {
        /*
         * tx specific fields.
         */
-       struct ring_desc *tx_ring;
+       ring_type tx_ring;
        unsigned int next_tx, nic_tx;
        struct sk_buff *tx_skbuff[TX_RING];
        dma_addr_t tx_dma[TX_RING];
@@ -519,6 +549,11 @@ static inline u32 nv_descr_getlength(struct ring_desc *prd, u32 v)
                & ((v == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2);
 }
 
+static inline u32 nv_descr_getlength_ex(struct ring_desc_ex *prd, u32 v)
+{
+       return le32_to_cpu(prd->FlagLen) & LEN_MASK_V2;
+}
+
 static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target,
                                int delay, int delaymax, const char *msg)
 {
@@ -792,7 +827,7 @@ static int nv_alloc_rx(struct net_device *dev)
                nr = refill_rx % RX_RING;
                if (np->rx_skbuff[nr] == NULL) {
 
-                       skb = dev_alloc_skb(RX_ALLOC_BUFSIZE);
+                       skb = dev_alloc_skb(np->rx_buf_sz + NV_RX_ALLOC_PAD);
                        if (!skb)
                                break;
 
@@ -803,9 +838,16 @@ static int nv_alloc_rx(struct net_device *dev)
                }
                np->rx_dma[nr] = pci_map_single(np->pci_dev, skb->data, skb->len,
                                                PCI_DMA_FROMDEVICE);
-               np->rx_ring[nr].PacketBuffer = cpu_to_le32(np->rx_dma[nr]);
-               wmb();
-               np->rx_ring[nr].FlagLen = cpu_to_le32(RX_NIC_BUFSIZE | NV_RX_AVAIL);
+               if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+                       np->rx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->rx_dma[nr]);
+                       wmb();
+                       np->rx_ring.orig[nr].FlagLen = cpu_to_le32(np->rx_buf_sz | NV_RX_AVAIL);
+               } else {
+                       np->rx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->rx_dma[nr]) >> 32;
+                       np->rx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->rx_dma[nr]) & 0x0FFFFFFFF;
+                       wmb();
+                       np->rx_ring.ex[nr].FlagLen = cpu_to_le32(np->rx_buf_sz | NV_RX2_AVAIL);
+               }
                dprintk(KERN_DEBUG "%s: nv_alloc_rx: Packet %d marked as Available\n",
                                        dev->name, refill_rx);
                refill_rx++;
@@ -831,19 +873,37 @@ static void nv_do_rx_refill(unsigned long data)
        enable_irq(dev->irq);
 }
 
-static int nv_init_ring(struct net_device *dev)
+static void nv_init_rx(struct net_device *dev) 
 {
        struct fe_priv *np = get_nvpriv(dev);
        int i;
 
-       np->next_tx = np->nic_tx = 0;
-       for (i = 0; i < TX_RING; i++)
-               np->tx_ring[i].FlagLen = 0;
-
        np->cur_rx = RX_RING;
        np->refill_rx = 0;
        for (i = 0; i < RX_RING; i++)
-               np->rx_ring[i].FlagLen = 0;
+               if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+                       np->rx_ring.orig[i].FlagLen = 0;
+               else
+                       np->rx_ring.ex[i].FlagLen = 0;
+}
+
+static void nv_init_tx(struct net_device *dev)
+{
+       struct fe_priv *np = get_nvpriv(dev);
+       int i;
+
+       np->next_tx = np->nic_tx = 0;
+       for (i = 0; i < TX_RING; i++)
+               if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+                       np->tx_ring.orig[i].FlagLen = 0;
+               else
+                       np->tx_ring.ex[i].FlagLen = 0;
+}
+
+static int nv_init_ring(struct net_device *dev)
+{
+       nv_init_tx(dev);
+       nv_init_rx(dev);
        return nv_alloc_rx(dev);
 }
 
@@ -852,7 +912,10 @@ static void nv_drain_tx(struct net_device *dev)
        struct fe_priv *np = get_nvpriv(dev);
        int i;
        for (i = 0; i < TX_RING; i++) {
-               np->tx_ring[i].FlagLen = 0;
+               if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+                       np->tx_ring.orig[i].FlagLen = 0;
+               else
+                       np->tx_ring.ex[i].FlagLen = 0;
                if (np->tx_skbuff[i]) {
                        pci_unmap_single(np->pci_dev, np->tx_dma[i],
                                                np->tx_skbuff[i]->len,
@@ -869,7 +932,10 @@ static void nv_drain_rx(struct net_device *dev)
        struct fe_priv *np = get_nvpriv(dev);
        int i;
        for (i = 0; i < RX_RING; i++) {
-               np->rx_ring[i].FlagLen = 0;
+               if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+                       np->rx_ring.orig[i].FlagLen = 0;
+               else
+                       np->rx_ring.ex[i].FlagLen = 0;
                wmb();
                if (np->rx_skbuff[i]) {
                        pci_unmap_single(np->pci_dev, np->rx_dma[i],
@@ -900,11 +966,19 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
        np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data,skb->len,
                                        PCI_DMA_TODEVICE);
 
-       np->tx_ring[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
+       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+               np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
+       else {
+               np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
+               np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
+       }
 
        spin_lock_irq(&np->lock);
        wmb();
-       np->tx_ring[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
+       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+               np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
+       else
+               np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
        dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission.\n",
                                dev->name, np->next_tx);
        {
@@ -942,7 +1016,10 @@ static void nv_tx_done(struct net_device *dev)
        while (np->nic_tx != np->next_tx) {
                i = np->nic_tx % TX_RING;
 
-               Flags = le32_to_cpu(np->tx_ring[i].FlagLen);
+               if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+                       Flags = le32_to_cpu(np->tx_ring.orig[i].FlagLen);
+               else
+                       Flags = le32_to_cpu(np->tx_ring.ex[i].FlagLen);
 
                dprintk(KERN_DEBUG "%s: nv_tx_done: looking at packet %d, Flags 0x%x.\n",
                                        dev->name, np->nic_tx, Flags);
@@ -993,9 +1070,56 @@ static void nv_tx_timeout(struct net_device *dev)
        struct fe_priv *np = get_nvpriv(dev);
        u8 __iomem *base = get_hwbase(dev);
 
-       dprintk(KERN_DEBUG "%s: Got tx_timeout. irq: %08x\n", dev->name,
+       printk(KERN_INFO "%s: Got tx_timeout. irq: %08x\n", dev->name,
                        readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK);
 
+       {
+               int i;
+
+               printk(KERN_INFO "%s: Ring at %lx: next %d nic %d\n",
+                               dev->name, (unsigned long)np->ring_addr,
+                               np->next_tx, np->nic_tx);
+               printk(KERN_INFO "%s: Dumping tx registers\n", dev->name);
+               for (i=0;i<0x400;i+= 32) {
+                       printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+                                       i,
+                                       readl(base + i + 0), readl(base + i + 4),
+                                       readl(base + i + 8), readl(base + i + 12),
+                                       readl(base + i + 16), readl(base + i + 20),
+                                       readl(base + i + 24), readl(base + i + 28));
+               }
+               printk(KERN_INFO "%s: Dumping tx ring\n", dev->name);
+               for (i=0;i<TX_RING;i+= 4) {
+                       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+                               printk(KERN_INFO "%03x: %08x %08x // %08x %08x // %08x %08x // %08x %08x\n",
+                                      i, 
+                                      le32_to_cpu(np->tx_ring.orig[i].PacketBuffer),
+                                      le32_to_cpu(np->tx_ring.orig[i].FlagLen),
+                                      le32_to_cpu(np->tx_ring.orig[i+1].PacketBuffer),
+                                      le32_to_cpu(np->tx_ring.orig[i+1].FlagLen),
+                                      le32_to_cpu(np->tx_ring.orig[i+2].PacketBuffer),
+                                      le32_to_cpu(np->tx_ring.orig[i+2].FlagLen),
+                                      le32_to_cpu(np->tx_ring.orig[i+3].PacketBuffer),
+                                      le32_to_cpu(np->tx_ring.orig[i+3].FlagLen));
+                       } else {
+                               printk(KERN_INFO "%03x: %08x %08x %08x // %08x %08x %08x // %08x %08x %08x // %08x %08x %08x\n",
+                                      i, 
+                                      le32_to_cpu(np->tx_ring.ex[i].PacketBufferHigh),
+                                      le32_to_cpu(np->tx_ring.ex[i].PacketBufferLow),
+                                      le32_to_cpu(np->tx_ring.ex[i].FlagLen),
+                                      le32_to_cpu(np->tx_ring.ex[i+1].PacketBufferHigh),
+                                      le32_to_cpu(np->tx_ring.ex[i+1].PacketBufferLow),
+                                      le32_to_cpu(np->tx_ring.ex[i+1].FlagLen),
+                                      le32_to_cpu(np->tx_ring.ex[i+2].PacketBufferHigh),
+                                      le32_to_cpu(np->tx_ring.ex[i+2].PacketBufferLow),
+                                      le32_to_cpu(np->tx_ring.ex[i+2].FlagLen),
+                                      le32_to_cpu(np->tx_ring.ex[i+3].PacketBufferHigh),
+                                      le32_to_cpu(np->tx_ring.ex[i+3].PacketBufferLow),
+                                      le32_to_cpu(np->tx_ring.ex[i+3].FlagLen));
+                       }
+               }
+       }
+
        spin_lock_irq(&np->lock);
 
        /* 1) stop tx engine */
@@ -1009,7 +1133,10 @@ static void nv_tx_timeout(struct net_device *dev)
                printk(KERN_DEBUG "%s: tx_timeout: dead entries!\n", dev->name);
                nv_drain_tx(dev);
                np->next_tx = np->nic_tx = 0;
-               writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+               if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+                       writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+               else
+                       writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
                netif_wake_queue(dev);
        }
 
@@ -1084,8 +1211,13 @@ static void nv_rx_process(struct net_device *dev)
                        break;  /* we scanned the whole ring - do not continue */
 
                i = np->cur_rx % RX_RING;
-               Flags = le32_to_cpu(np->rx_ring[i].FlagLen);
-               len = nv_descr_getlength(&np->rx_ring[i], np->desc_ver);
+               if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+                       Flags = le32_to_cpu(np->rx_ring.orig[i].FlagLen);
+                       len = nv_descr_getlength(&np->rx_ring.orig[i], np->desc_ver);
+               } else {
+                       Flags = le32_to_cpu(np->rx_ring.ex[i].FlagLen);
+                       len = nv_descr_getlength_ex(&np->rx_ring.ex[i], np->desc_ver);
+               }
 
                dprintk(KERN_DEBUG "%s: nv_rx_process: looking at packet %d, Flags 0x%x.\n",
                                        dev->name, np->cur_rx, Flags);
@@ -1207,15 +1339,133 @@ next_pkt:
        }
 }
 
+static void set_bufsize(struct net_device *dev)
+{
+       struct fe_priv *np = netdev_priv(dev);
+
+       if (dev->mtu <= ETH_DATA_LEN)
+               np->rx_buf_sz = ETH_DATA_LEN + NV_RX_HEADERS;
+       else
+               np->rx_buf_sz = dev->mtu + NV_RX_HEADERS;
+}
+
 /*
  * nv_change_mtu: dev->change_mtu function
  * Called with dev_base_lock held for read.
  */
 static int nv_change_mtu(struct net_device *dev, int new_mtu)
 {
-       if (new_mtu > ETH_DATA_LEN)
+       struct fe_priv *np = get_nvpriv(dev);
+       int old_mtu;
+
+       if (new_mtu < 64 || new_mtu > np->pkt_limit)
                return -EINVAL;
+
+       old_mtu = dev->mtu;
        dev->mtu = new_mtu;
+
+       /* return early if the buffer sizes will not change */
+       if (old_mtu <= ETH_DATA_LEN && new_mtu <= ETH_DATA_LEN)
+               return 0;
+       if (old_mtu == new_mtu)
+               return 0;
+
+       /* synchronized against open : rtnl_lock() held by caller */
+       if (netif_running(dev)) {
+               u8 *base = get_hwbase(dev);
+               /*
+                * It seems that the nic preloads valid ring entries into an
+                * internal buffer. The procedure for flushing everything is
+                * guessed, there is probably a simpler approach.
+                * Changing the MTU is a rare event, it shouldn't matter.
+                */
+               disable_irq(dev->irq);
+               spin_lock_bh(&dev->xmit_lock);
+               spin_lock(&np->lock);
+               /* stop engines */
+               nv_stop_rx(dev);
+               nv_stop_tx(dev);
+               nv_txrx_reset(dev);
+               /* drain rx queue */
+               nv_drain_rx(dev);
+               nv_drain_tx(dev);
+               /* reinit driver view of the rx queue */
+               nv_init_rx(dev);
+               nv_init_tx(dev);
+               /* alloc new rx buffers */
+               set_bufsize(dev);
+               if (nv_alloc_rx(dev)) {
+                       if (!np->in_shutdown)
+                               mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
+               }
+               /* reinit nic view of the rx queue */
+               writel(np->rx_buf_sz, base + NvRegOffloadConfig);
+               writel((u32) np->ring_addr, base + NvRegRxRingPhysAddr);
+               if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+                       writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+               else
+                       writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
+               writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
+                       base + NvRegRingSizes);
+               pci_push(base);
+               writel(NVREG_TXRXCTL_KICK|np->desc_ver, get_hwbase(dev) + NvRegTxRxControl);
+               pci_push(base);
+
+               /* restart rx engine */
+               nv_start_rx(dev);
+               nv_start_tx(dev);
+               spin_unlock(&np->lock);
+               spin_unlock_bh(&dev->xmit_lock);
+               enable_irq(dev->irq);
+       }
+       return 0;
+}
+
+static void nv_copy_mac_to_hw(struct net_device *dev)
+{
+       u8 *base = get_hwbase(dev);
+       u32 mac[2];
+
+       mac[0] = (dev->dev_addr[0] << 0) + (dev->dev_addr[1] << 8) +
+                       (dev->dev_addr[2] << 16) + (dev->dev_addr[3] << 24);
+       mac[1] = (dev->dev_addr[4] << 0) + (dev->dev_addr[5] << 8);
+
+       writel(mac[0], base + NvRegMacAddrA);
+       writel(mac[1], base + NvRegMacAddrB);
+}
+
+/*
+ * nv_set_mac_address: dev->set_mac_address function
+ * Called with rtnl_lock() held.
+ */
+static int nv_set_mac_address(struct net_device *dev, void *addr)
+{
+       struct fe_priv *np = get_nvpriv(dev);
+       struct sockaddr *macaddr = (struct sockaddr*)addr;
+
+       if(!is_valid_ether_addr(macaddr->sa_data))
+               return -EADDRNOTAVAIL;
+
+       /* synchronized against open : rtnl_lock() held by caller */
+       memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN);
+
+       if (netif_running(dev)) {
+               spin_lock_bh(&dev->xmit_lock);
+               spin_lock_irq(&np->lock);
+
+               /* stop rx engine */
+               nv_stop_rx(dev);
+
+               /* set mac address */
+               nv_copy_mac_to_hw(dev);
+
+               /* restart rx engine */
+               nv_start_rx(dev);
+               spin_unlock_irq(&np->lock);
+               spin_unlock_bh(&dev->xmit_lock);
+       } else {
+               nv_copy_mac_to_hw(dev);
+       }
        return 0;
 }
 
@@ -1470,7 +1720,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
                if (!(events & np->irqmask))
                        break;
 
-               if (events & (NVREG_IRQ_TX1|NVREG_IRQ_TX2|NVREG_IRQ_TX_ERR)) {
+               if (events & (NVREG_IRQ_TX1|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_ERROR|NVREG_IRQ_TX_ERR)) {
                        spin_lock(&np->lock);
                        nv_tx_done(dev);
                        spin_unlock(&np->lock);
@@ -1761,6 +2011,50 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
        return 0;
 }
 
+#define FORCEDETH_REGS_VER     1
+#define FORCEDETH_REGS_SIZE    0x400 /* 256 32-bit registers */
+
+static int nv_get_regs_len(struct net_device *dev)
+{
+       return FORCEDETH_REGS_SIZE;
+}
+
+static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
+{
+       struct fe_priv *np = get_nvpriv(dev);
+       u8 __iomem *base = get_hwbase(dev);
+       u32 *rbuf = buf;
+       int i;
+
+       regs->version = FORCEDETH_REGS_VER;
+       spin_lock_irq(&np->lock);
+       for (i=0;i<FORCEDETH_REGS_SIZE/sizeof(u32);i++)
+               rbuf[i] = readl(base + i*sizeof(u32));
+       spin_unlock_irq(&np->lock);
+}
+
+static int nv_nway_reset(struct net_device *dev)
+{
+       struct fe_priv *np = get_nvpriv(dev);
+       int ret;
+
+       spin_lock_irq(&np->lock);
+       if (np->autoneg) {
+               int bmcr;
+
+               bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
+               bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+               mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
+
+               ret = 0;
+       } else {
+               ret = -EINVAL;
+       }
+       spin_unlock_irq(&np->lock);
+
+       return ret;
+}
+
 static struct ethtool_ops ops = {
        .get_drvinfo = nv_get_drvinfo,
        .get_link = ethtool_op_get_link,
@@ -1768,6 +2062,9 @@ static struct ethtool_ops ops = {
        .set_wol = nv_set_wol,
        .get_settings = nv_get_settings,
        .set_settings = nv_set_settings,
+       .get_regs_len = nv_get_regs_len,
+       .get_regs = nv_get_regs,
+       .nway_reset = nv_nway_reset,
 };
 
 static int nv_open(struct net_device *dev)
@@ -1792,6 +2089,7 @@ static int nv_open(struct net_device *dev)
        writel(0, base + NvRegAdapterControl);
 
        /* 2) initialize descriptor rings */
+       set_bufsize(dev);
        oom = nv_init_ring(dev);
 
        writel(0, base + NvRegLinkSpeed);
@@ -1802,20 +2100,14 @@ static int nv_open(struct net_device *dev)
        np->in_shutdown = 0;
 
        /* 3) set mac address */
-       {
-               u32 mac[2];
-
-               mac[0] = (dev->dev_addr[0] << 0) + (dev->dev_addr[1] << 8) +
-                               (dev->dev_addr[2] << 16) + (dev->dev_addr[3] << 24);
-               mac[1] = (dev->dev_addr[4] << 0) + (dev->dev_addr[5] << 8);
-
-               writel(mac[0], base + NvRegMacAddrA);
-               writel(mac[1], base + NvRegMacAddrB);
-       }
+       nv_copy_mac_to_hw(dev);
 
        /* 4) give hw rings */
        writel((u32) np->ring_addr, base + NvRegRxRingPhysAddr);
-       writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+               writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+       else
+               writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
        writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
                base + NvRegRingSizes);
 
@@ -1837,7 +2129,7 @@ static int nv_open(struct net_device *dev)
        writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1);
        writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus);
        writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags);
-       writel(NVREG_OFFLOAD_NORMAL, base + NvRegOffloadConfig);
+       writel(np->rx_buf_sz, base + NvRegOffloadConfig);
 
        writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus);
        get_random_bytes(&i, sizeof(i));
@@ -1888,6 +2180,9 @@ static int nv_open(struct net_device *dev)
                writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
                dprintk(KERN_INFO "startup: got 0x%08x.\n", miistat);
        }
+       /* set linkspeed to invalid value, thus force nv_update_linkspeed
+        * to init hw */
+       np->linkspeed = 0;
        ret = nv_update_linkspeed(dev);
        nv_start_rx(dev);
        nv_start_tx(dev);
@@ -1942,6 +2237,12 @@ static int nv_close(struct net_device *dev)
        if (np->wolenabled)
                nv_start_rx(dev);
 
+       /* special op: write back the misordered MAC address - otherwise
+        * the next nv_probe would see a wrong address.
+        */
+       writel(np->orig_mac[0], base + NvRegMacAddrA);
+       writel(np->orig_mac[1], base + NvRegMacAddrB);
+
        /* FIXME: power down nic */
 
        return 0;
@@ -2006,32 +2307,55 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
        }
 
        /* handle different descriptor versions */
-       if (pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_1 ||
-               pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_2 ||
-               pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_3 ||    
-               pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 ||
-               pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_13)
-               np->desc_ver = DESC_VER_1;
-       else
+       if (id->driver_data & DEV_HAS_HIGH_DMA) {
+               /* packet format 3: supports 40-bit addressing */
+               np->desc_ver = DESC_VER_3;
+               if (pci_set_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
+                       printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
+                                       pci_name(pci_dev));
+               }
+       } else if (id->driver_data & DEV_HAS_LARGEDESC) {
+               /* packet format 2: supports jumbo frames */
                np->desc_ver = DESC_VER_2;
+       } else {
+               /* original packet format */
+               np->desc_ver = DESC_VER_1;
+       }
+
+       np->pkt_limit = NV_PKTLIMIT_1;
+       if (id->driver_data & DEV_HAS_LARGEDESC)
+               np->pkt_limit = NV_PKTLIMIT_2;
 
        err = -ENOMEM;
        np->base = ioremap(addr, NV_PCI_REGSZ);
        if (!np->base)
                goto out_relreg;
        dev->base_addr = (unsigned long)np->base;
+
        dev->irq = pci_dev->irq;
-       np->rx_ring = pci_alloc_consistent(pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING),
-                                               &np->ring_addr);
-       if (!np->rx_ring)
-               goto out_unmap;
-       np->tx_ring = &np->rx_ring[RX_RING];
+
+       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+               np->rx_ring.orig = pci_alloc_consistent(pci_dev,
+                                       sizeof(struct ring_desc) * (RX_RING + TX_RING),
+                                       &np->ring_addr);
+               if (!np->rx_ring.orig)
+                       goto out_unmap;
+               np->tx_ring.orig = &np->rx_ring.orig[RX_RING];
+       } else {
+               np->rx_ring.ex = pci_alloc_consistent(pci_dev,
+                                       sizeof(struct ring_desc_ex) * (RX_RING + TX_RING),
+                                       &np->ring_addr);
+               if (!np->rx_ring.ex)
+                       goto out_unmap;
+               np->tx_ring.ex = &np->rx_ring.ex[RX_RING];
+       }
 
        dev->open = nv_open;
        dev->stop = nv_close;
        dev->hard_start_xmit = nv_start_xmit;
        dev->get_stats = nv_get_stats;
        dev->change_mtu = nv_change_mtu;
+       dev->set_mac_address = nv_set_mac_address;
        dev->set_multicast_list = nv_set_multicast;
 #ifdef CONFIG_NET_POLL_CONTROLLER
        dev->poll_controller = nv_poll_controller;
@@ -2080,17 +2404,10 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
 
        if (np->desc_ver == DESC_VER_1) {
                np->tx_flags = NV_TX_LASTPACKET|NV_TX_VALID;
-               if (id->driver_data & DEV_NEED_LASTPACKET1)
-                       np->tx_flags |= NV_TX_LASTPACKET1;
        } else {
                np->tx_flags = NV_TX2_LASTPACKET|NV_TX2_VALID;
-               if (id->driver_data & DEV_NEED_LASTPACKET1)
-                       np->tx_flags |= NV_TX2_LASTPACKET1;
        }
-       if (id->driver_data & DEV_IRQMASK_1)
-               np->irqmask = NVREG_IRQMASK_WANTED_1;
-       if (id->driver_data & DEV_IRQMASK_2)
-               np->irqmask = NVREG_IRQMASK_WANTED_2;
+       np->irqmask = NVREG_IRQMASK_WANTED;
        if (id->driver_data & DEV_NEED_TIMERIRQ)
                np->irqmask |= NVREG_IRQ_TIMER;
        if (id->driver_data & DEV_NEED_LINKTIMER) {
@@ -2155,8 +2472,12 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
        return 0;
 
 out_freering:
-       pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING),
-                               np->rx_ring, np->ring_addr);
+       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+               pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING),
+                                   np->rx_ring.orig, np->ring_addr);
+       else
+               pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (RX_RING + TX_RING),
+                                   np->rx_ring.ex, np->ring_addr);
        pci_set_drvdata(pci_dev, NULL);
 out_unmap:
        iounmap(get_hwbase(dev));
@@ -2174,18 +2495,14 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
 {
        struct net_device *dev = pci_get_drvdata(pci_dev);
        struct fe_priv *np = get_nvpriv(dev);
-       u8 __iomem *base = get_hwbase(dev);
 
        unregister_netdev(dev);
 
-       /* special op: write back the misordered MAC address - otherwise
-        * the next nv_probe would see a wrong address.
-        */
-       writel(np->orig_mac[0], base + NvRegMacAddrA);
-       writel(np->orig_mac[1], base + NvRegMacAddrB);
-
        /* free all structures */
-       pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING), np->rx_ring, np->ring_addr);
+       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+               pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING), np->rx_ring.orig, np->ring_addr);
+       else
+               pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (RX_RING + TX_RING), np->rx_ring.ex, np->ring_addr);
        iounmap(get_hwbase(dev));
        pci_release_regions(pci_dev);
        pci_disable_device(pci_dev);
@@ -2195,109 +2512,64 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
 
 static struct pci_device_id pci_tbl[] = {
        {       /* nForce Ethernet Controller */
-               .vendor = PCI_VENDOR_ID_NVIDIA,
-               .device = PCI_DEVICE_ID_NVIDIA_NVENET_1,
-               .subvendor = PCI_ANY_ID,
-               .subdevice = PCI_ANY_ID,
-               .driver_data = DEV_IRQMASK_1|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_1),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
        },
        {       /* nForce2 Ethernet Controller */
-               .vendor = PCI_VENDOR_ID_NVIDIA,
-               .device = PCI_DEVICE_ID_NVIDIA_NVENET_2,
-               .subvendor = PCI_ANY_ID,
-               .subdevice = PCI_ANY_ID,
-               .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_2),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
        },
        {       /* nForce3 Ethernet Controller */
-               .vendor = PCI_VENDOR_ID_NVIDIA,
-               .device = PCI_DEVICE_ID_NVIDIA_NVENET_3,
-               .subvendor = PCI_ANY_ID,
-               .subdevice = PCI_ANY_ID,
-               .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_3),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
        },
        {       /* nForce3 Ethernet Controller */
-               .vendor = PCI_VENDOR_ID_NVIDIA,
-               .device = PCI_DEVICE_ID_NVIDIA_NVENET_4,
-               .subvendor = PCI_ANY_ID,
-               .subdevice = PCI_ANY_ID,
-               .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_4),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
        },
        {       /* nForce3 Ethernet Controller */
-               .vendor = PCI_VENDOR_ID_NVIDIA,
-               .device = PCI_DEVICE_ID_NVIDIA_NVENET_5,
-               .subvendor = PCI_ANY_ID,
-               .subdevice = PCI_ANY_ID,
-               .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_5),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
        },
        {       /* nForce3 Ethernet Controller */
-               .vendor = PCI_VENDOR_ID_NVIDIA,
-               .device = PCI_DEVICE_ID_NVIDIA_NVENET_6,
-               .subvendor = PCI_ANY_ID,
-               .subdevice = PCI_ANY_ID,
-               .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_6),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
        },
        {       /* nForce3 Ethernet Controller */
-               .vendor = PCI_VENDOR_ID_NVIDIA,
-               .device = PCI_DEVICE_ID_NVIDIA_NVENET_7,
-               .subvendor = PCI_ANY_ID,
-               .subdevice = PCI_ANY_ID,
-               .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_7),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
        },
        {       /* CK804 Ethernet Controller */
-               .vendor = PCI_VENDOR_ID_NVIDIA,
-               .device = PCI_DEVICE_ID_NVIDIA_NVENET_8,
-               .subvendor = PCI_ANY_ID,
-               .subdevice = PCI_ANY_ID,
-               .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_8),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
        },
        {       /* CK804 Ethernet Controller */
-               .vendor = PCI_VENDOR_ID_NVIDIA,
-               .device = PCI_DEVICE_ID_NVIDIA_NVENET_9,
-               .subvendor = PCI_ANY_ID,
-               .subdevice = PCI_ANY_ID,
-               .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_9),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
        },
        {       /* MCP04 Ethernet Controller */
-               .vendor = PCI_VENDOR_ID_NVIDIA,
-               .device = PCI_DEVICE_ID_NVIDIA_NVENET_10,
-               .subvendor = PCI_ANY_ID,
-               .subdevice = PCI_ANY_ID,
-               .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_10),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
        },
        {       /* MCP04 Ethernet Controller */
-               .vendor = PCI_VENDOR_ID_NVIDIA,
-               .device = PCI_DEVICE_ID_NVIDIA_NVENET_11,
-               .subvendor = PCI_ANY_ID,
-               .subdevice = PCI_ANY_ID,
-               .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_11),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
        },
        {       /* MCP51 Ethernet Controller */
-               .vendor = PCI_VENDOR_ID_NVIDIA,
-               .device = PCI_DEVICE_ID_NVIDIA_NVENET_12,
-               .subvendor = PCI_ANY_ID,
-               .subdevice = PCI_ANY_ID,
-               .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA,
        },
        {       /* MCP51 Ethernet Controller */
-               .vendor = PCI_VENDOR_ID_NVIDIA,
-               .device = PCI_DEVICE_ID_NVIDIA_NVENET_13,
-               .subvendor = PCI_ANY_ID,
-               .subdevice = PCI_ANY_ID,
-               .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA,
        },
        {       /* MCP55 Ethernet Controller */
-               .vendor = PCI_VENDOR_ID_NVIDIA,
-               .device = PCI_DEVICE_ID_NVIDIA_NVENET_14,
-               .subvendor = PCI_ANY_ID,
-               .subdevice = PCI_ANY_ID,
-               .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
        },
        {       /* MCP55 Ethernet Controller */
-               .vendor = PCI_VENDOR_ID_NVIDIA,
-               .device = PCI_DEVICE_ID_NVIDIA_NVENET_15,
-               .subvendor = PCI_ANY_ID,
-               .subdevice = PCI_ANY_ID,
-               .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
        },
        {0,},
 };
index e44f8e9..0b23022 100644 (file)
@@ -130,12 +130,11 @@ struct sixpack {
 
 #define AX25_6PACK_HEADER_LEN 0
 
-static void sp_start_tx_timer(struct sixpack *);
 static void sixpack_decode(struct sixpack *, unsigned char[], int);
 static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
 
 /*
- * perform the persistence/slottime algorithm for CSMA access. If the
+ * Perform the persistence/slottime algorithm for CSMA access. If the
  * persistence check was successful, write the data to the serial driver.
  * Note that in case of DAMA operation, the data is not sent here.
  */
@@ -143,7 +142,7 @@ static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
 static void sp_xmit_on_air(unsigned long channel)
 {
        struct sixpack *sp = (struct sixpack *) channel;
-       int actual;
+       int actual, when = sp->slottime;
        static unsigned char random;
 
        random = random * 17 + 41;
@@ -159,20 +158,10 @@ static void sp_xmit_on_air(unsigned long channel)
                sp->tty->driver->write(sp->tty, &sp->led_state, 1);
                sp->status2 = 0;
        } else
-               sp_start_tx_timer(sp);
+               mod_timer(&sp->tx_t, jiffies + ((when + 1) * HZ) / 100);
 }
 
 /* ----> 6pack timer interrupt handler and friends. <---- */
-static void sp_start_tx_timer(struct sixpack *sp)
-{
-       int when = sp->slottime;
-
-       del_timer(&sp->tx_t);
-       sp->tx_t.data = (unsigned long) sp;
-       sp->tx_t.function = sp_xmit_on_air;
-       sp->tx_t.expires = jiffies + ((when + 1) * HZ) / 100;
-       add_timer(&sp->tx_t);
-}
 
 /* Encapsulate one AX.25 frame and stuff into a TTY queue. */
 static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
@@ -243,8 +232,7 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
                sp->xleft = count;
                sp->xhead = sp->xbuff;
                sp->status2 = count;
-               if (sp->duplex == 0)
-                       sp_start_tx_timer(sp);
+               sp_xmit_on_air((unsigned long)sp);
        }
 
        return;
@@ -320,12 +308,6 @@ static int sp_set_mac_address(struct net_device *dev, void *addr)
 {
        struct sockaddr_ax25 *sa = addr;
 
-       if (sa->sax25_family != AF_AX25)
-               return -EINVAL;
-
-       if (!sa->sax25_ndigis)
-               return -EINVAL;
-
        spin_lock_irq(&dev->xmit_lock);
        memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
        spin_unlock_irq(&dev->xmit_lock);
@@ -680,6 +662,9 @@ static int sixpack_open(struct tty_struct *tty)
        netif_start_queue(dev);
 
        init_timer(&sp->tx_t);
+       sp->tx_t.function = sp_xmit_on_air;
+       sp->tx_t.data = (unsigned long) sp;
+
        init_timer(&sp->resync_t);
 
        spin_unlock_bh(&sp->lock);
index 7cdebe1..de087cd 100644 (file)
@@ -1,6 +1,6 @@
 config MKISS
        tristate "Serial port KISS driver"
-       depends on AX25 && BROKEN_ON_SMP
+       depends on AX25
        ---help---
          KISS is a protocol used for the exchange of data between a computer
          and a Terminal Node Controller (a small embedded system commonly
@@ -17,7 +17,7 @@ config MKISS
 
 config 6PACK
        tristate "Serial port 6PACK driver"
-       depends on AX25 && BROKEN_ON_SMP
+       depends on AX25
        ---help---
          6pack is a transmission protocol for the data exchange between your
          PC and your TNC (the Terminal Node Controller acts as a kind of
index a7f15d9..5298096 100644 (file)
@@ -54,6 +54,7 @@
 #include <linux/kmod.h>
 #include <linux/hdlcdrv.h>
 #include <linux/baycom.h>
+#include <linux/jiffies.h>
 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 /* prototypes for ax25_encapsulate and ax25_rebuild_header */
 #include <net/ax25.h> 
@@ -287,7 +288,7 @@ static inline void baycom_int_freq(struct baycom_state *bc)
         * measure the interrupt frequency
         */
        bc->debug_vals.cur_intcnt++;
-       if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) {
+       if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
                bc->debug_vals.last_jiffies = cur_jiffies;
                bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
                bc->debug_vals.cur_intcnt = 0;
index 612ad45..3b1bef1 100644 (file)
@@ -84,6 +84,7 @@
 #include <linux/baycom.h>
 #include <linux/parport.h>
 #include <linux/bitops.h>
+#include <linux/jiffies.h>
 
 #include <asm/bug.h>
 #include <asm/system.h>
@@ -165,7 +166,7 @@ static void __inline__ baycom_int_freq(struct baycom_state *bc)
         * measure the interrupt frequency
         */
        bc->debug_vals.cur_intcnt++;
-       if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) {
+       if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
                bc->debug_vals.last_jiffies = cur_jiffies;
                bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
                bc->debug_vals.cur_intcnt = 0;
index 25f270b..232793d 100644 (file)
@@ -79,6 +79,7 @@
 #include <asm/io.h>
 #include <linux/hdlcdrv.h>
 #include <linux/baycom.h>
+#include <linux/jiffies.h>
 
 /* --------------------------------------------------------------------- */
 
@@ -159,7 +160,7 @@ static inline void baycom_int_freq(struct baycom_state *bc)
         * measure the interrupt frequency
         */
        bc->debug_vals.cur_intcnt++;
-       if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) {
+       if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
                bc->debug_vals.last_jiffies = cur_jiffies;
                bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
                bc->debug_vals.cur_intcnt = 0;
index eead85d..be596a3 100644 (file)
@@ -69,6 +69,7 @@
 #include <asm/io.h>
 #include <linux/hdlcdrv.h>
 #include <linux/baycom.h>
+#include <linux/jiffies.h>
 
 /* --------------------------------------------------------------------- */
 
@@ -150,7 +151,7 @@ static inline void baycom_int_freq(struct baycom_state *bc)
         * measure the interrupt frequency
         */
        bc->debug_vals.cur_intcnt++;
-       if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) {
+       if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
                bc->debug_vals.last_jiffies = cur_jiffies;
                bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
                bc->debug_vals.cur_intcnt = 0;
index 3035422..63b1a2b 100644 (file)
@@ -1,30 +1,19 @@
 /*
- *     MKISS Driver
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
  *
- *     This module:
- *             This module is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
  *
- *             This module implements the AX.25 protocol for kernel-based
- *             devices like TTYs. It interfaces between a raw TTY, and the
- *             kernel's AX.25 protocol layers, just like slip.c.
- *             AX.25 needs to be separated from slip.c while slip.c is no
- *             longer a static kernel device since it is a module.
- *             This method clears the way to implement other kiss protocols
- *             like mkiss smack g8bpq ..... so far only mkiss is implemented.
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * Hans Alblas <hans@esrac.ele.tue.nl>
- *
- *     History
- *     Jonathan (G4KLX)        Fixed to match Linux networking changes - 2.1.15.
- *     Matthias (DG2FEF)       Added support for FlexNet CRC (on special request)
- *                              Fixed bug in ax25_close(): dev_lock_wait() was
- *                              called twice, causing a deadlock.
- *     Jeroen (PE1RXQ)         Removed old MKISS_MAGIC stuff and calls to
- *                             MOD_*_USE_COUNT
- *                             Remove cli() and fix rtnl lock usage.
+ * Copyright (C) Hans Alblas PE1AYX <hans@esrac.ele.tue.nl>
+ * Copyright (C) 2004, 05 Ralf Baechle DL5RB <ralf@linux-mips.org>
  */
 
 #include <linux/config.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
+#include <linux/jiffies.h>
 
 #include <net/ax25.h>
 
-#include "mkiss.h"
-
 #ifdef CONFIG_INET
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #endif
 
-static char banner[] __initdata = KERN_INFO "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n";
-
-typedef struct ax25_ctrl {
-       struct ax_disp ctrl;    /*                              */
-       struct net_device  dev; /* the device                   */
-} ax25_ctrl_t;
-
-static ax25_ctrl_t **ax25_ctrls;
-
-int ax25_maxdev = AX25_MAXDEV;         /* Can be overridden with insmod! */
-
-static struct tty_ldisc        ax_ldisc;
-
-static int ax25_init(struct net_device *);
-static int kiss_esc(unsigned char *, unsigned char *, int);
-static int kiss_esc_crc(unsigned char *, unsigned char *, unsigned short, int);
-static void kiss_unesc(struct ax_disp *, unsigned char);
+#define AX_MTU         236
+
+/* SLIP/KISS protocol characters. */
+#define END             0300           /* indicates end of frame       */
+#define ESC             0333           /* indicates byte stuffing      */
+#define ESC_END         0334           /* ESC ESC_END means END 'data' */
+#define ESC_ESC         0335           /* ESC ESC_ESC means ESC 'data' */
+
+struct mkiss {
+       struct tty_struct       *tty;   /* ptr to TTY structure         */
+       struct net_device       *dev;   /* easy for intr handling       */
+
+       /* These are pointers to the malloc()ed frame buffers. */
+       spinlock_t              buflock;/* lock for rbuf and xbuf */
+       unsigned char           *rbuff; /* receiver buffer              */
+       int                     rcount; /* received chars counter       */
+       unsigned char           *xbuff; /* transmitter buffer           */
+       unsigned char           *xhead; /* pointer to next byte to XMIT */
+       int                     xleft;  /* bytes left in XMIT queue     */
+
+       struct net_device_stats stats;
+
+       /* Detailed SLIP statistics. */
+       int             mtu;            /* Our mtu (to spot changes!)   */
+       int             buffsize;       /* Max buffers sizes            */
+
+       unsigned long   flags;          /* Flag values/ mode etc        */
+                                       /* long req'd: used by set_bit --RR */
+#define AXF_INUSE      0               /* Channel in use               */
+#define AXF_ESCAPE     1               /* ESC received                 */
+#define AXF_ERROR      2               /* Parity, etc. error           */
+#define AXF_KEEPTEST   3               /* Keepalive test flag          */
+#define AXF_OUTWAIT    4               /* is outpacket was flag        */
+
+       int             mode;
+        int            crcmode;        /* MW: for FlexNet, SMACK etc.  */
+#define CRC_MODE_NONE   0
+#define CRC_MODE_FLEX   1
+#define CRC_MODE_SMACK  2
+
+       atomic_t                refcnt;
+       struct semaphore        dead_sem;
+};
 
 /*---------------------------------------------------------------------------*/
 
-static const unsigned short Crc_flex_table[] = {
-  0x0f87, 0x1e0e, 0x2c95, 0x3d1c, 0x49a3, 0x582a, 0x6ab1, 0x7b38,
-  0x83cf, 0x9246, 0xa0dd, 0xb154, 0xc5eb, 0xd462, 0xe6f9, 0xf770,
-  0x1f06, 0x0e8f, 0x3c14, 0x2d9d, 0x5922, 0x48ab, 0x7a30, 0x6bb9,
-  0x934e, 0x82c7, 0xb05c, 0xa1d5, 0xd56a, 0xc4e3, 0xf678, 0xe7f1,
-  0x2e85, 0x3f0c, 0x0d97, 0x1c1e, 0x68a1, 0x7928, 0x4bb3, 0x5a3a,
-  0xa2cd, 0xb344, 0x81df, 0x9056, 0xe4e9, 0xf560, 0xc7fb, 0xd672,
-  0x3e04, 0x2f8d, 0x1d16, 0x0c9f, 0x7820, 0x69a9, 0x5b32, 0x4abb,
-  0xb24c, 0xa3c5, 0x915e, 0x80d7, 0xf468, 0xe5e1, 0xd77a, 0xc6f3,
-  0x4d83, 0x5c0a, 0x6e91, 0x7f18, 0x0ba7, 0x1a2e, 0x28b5, 0x393c,
-  0xc1cb, 0xd042, 0xe2d9, 0xf350, 0x87ef, 0x9666, 0xa4fd, 0xb574,
-  0x5d02, 0x4c8b, 0x7e10, 0x6f99, 0x1b26, 0x0aaf, 0x3834, 0x29bd,
-  0xd14a, 0xc0c3, 0xf258, 0xe3d1, 0x976e, 0x86e7, 0xb47c, 0xa5f5,
-  0x6c81, 0x7d08, 0x4f93, 0x5e1a, 0x2aa5, 0x3b2c, 0x09b7, 0x183e,
-  0xe0c9, 0xf140, 0xc3db, 0xd252, 0xa6ed, 0xb764, 0x85ff, 0x9476,
-  0x7c00, 0x6d89, 0x5f12, 0x4e9b, 0x3a24, 0x2bad, 0x1936, 0x08bf,
-  0xf048, 0xe1c1, 0xd35a, 0xc2d3, 0xb66c, 0xa7e5, 0x957e, 0x84f7,
-  0x8b8f, 0x9a06, 0xa89d, 0xb914, 0xcdab, 0xdc22, 0xeeb9, 0xff30,
-  0x07c7, 0x164e, 0x24d5, 0x355c, 0x41e3, 0x506a, 0x62f1, 0x7378,
-  0x9b0e, 0x8a87, 0xb81c, 0xa995, 0xdd2a, 0xcca3, 0xfe38, 0xefb1,
-  0x1746, 0x06cf, 0x3454, 0x25dd, 0x5162, 0x40eb, 0x7270, 0x63f9,
-  0xaa8d, 0xbb04, 0x899f, 0x9816, 0xeca9, 0xfd20, 0xcfbb, 0xde32,
-  0x26c5, 0x374c, 0x05d7, 0x145e, 0x60e1, 0x7168, 0x43f3, 0x527a,
-  0xba0c, 0xab85, 0x991e, 0x8897, 0xfc28, 0xeda1, 0xdf3a, 0xceb3,
-  0x3644, 0x27cd, 0x1556, 0x04df, 0x7060, 0x61e9, 0x5372, 0x42fb,
-  0xc98b, 0xd802, 0xea99, 0xfb10, 0x8faf, 0x9e26, 0xacbd, 0xbd34,
-  0x45c3, 0x544a, 0x66d1, 0x7758, 0x03e7, 0x126e, 0x20f5, 0x317c,
-  0xd90a, 0xc883, 0xfa18, 0xeb91, 0x9f2e, 0x8ea7, 0xbc3c, 0xadb5,
-  0x5542, 0x44cb, 0x7650, 0x67d9, 0x1366, 0x02ef, 0x3074, 0x21fd,
-  0xe889, 0xf900, 0xcb9b, 0xda12, 0xaead, 0xbf24, 0x8dbf, 0x9c36,
-  0x64c1, 0x7548, 0x47d3, 0x565a, 0x22e5, 0x336c, 0x01f7, 0x107e,
-  0xf808, 0xe981, 0xdb1a, 0xca93, 0xbe2c, 0xafa5, 0x9d3e, 0x8cb7,
-  0x7440, 0x65c9, 0x5752, 0x46db, 0x3264, 0x23ed, 0x1176, 0x00ff
+static const unsigned short crc_flex_table[] = {
+       0x0f87, 0x1e0e, 0x2c95, 0x3d1c, 0x49a3, 0x582a, 0x6ab1, 0x7b38,
+       0x83cf, 0x9246, 0xa0dd, 0xb154, 0xc5eb, 0xd462, 0xe6f9, 0xf770,
+       0x1f06, 0x0e8f, 0x3c14, 0x2d9d, 0x5922, 0x48ab, 0x7a30, 0x6bb9,
+       0x934e, 0x82c7, 0xb05c, 0xa1d5, 0xd56a, 0xc4e3, 0xf678, 0xe7f1,
+       0x2e85, 0x3f0c, 0x0d97, 0x1c1e, 0x68a1, 0x7928, 0x4bb3, 0x5a3a,
+       0xa2cd, 0xb344, 0x81df, 0x9056, 0xe4e9, 0xf560, 0xc7fb, 0xd672,
+       0x3e04, 0x2f8d, 0x1d16, 0x0c9f, 0x7820, 0x69a9, 0x5b32, 0x4abb,
+       0xb24c, 0xa3c5, 0x915e, 0x80d7, 0xf468, 0xe5e1, 0xd77a, 0xc6f3,
+       0x4d83, 0x5c0a, 0x6e91, 0x7f18, 0x0ba7, 0x1a2e, 0x28b5, 0x393c,
+       0xc1cb, 0xd042, 0xe2d9, 0xf350, 0x87ef, 0x9666, 0xa4fd, 0xb574,
+       0x5d02, 0x4c8b, 0x7e10, 0x6f99, 0x1b26, 0x0aaf, 0x3834, 0x29bd,
+       0xd14a, 0xc0c3, 0xf258, 0xe3d1, 0x976e, 0x86e7, 0xb47c, 0xa5f5,
+       0x6c81, 0x7d08, 0x4f93, 0x5e1a, 0x2aa5, 0x3b2c, 0x09b7, 0x183e,
+       0xe0c9, 0xf140, 0xc3db, 0xd252, 0xa6ed, 0xb764, 0x85ff, 0x9476,
+       0x7c00, 0x6d89, 0x5f12, 0x4e9b, 0x3a24, 0x2bad, 0x1936, 0x08bf,
+       0xf048, 0xe1c1, 0xd35a, 0xc2d3, 0xb66c, 0xa7e5, 0x957e, 0x84f7,
+       0x8b8f, 0x9a06, 0xa89d, 0xb914, 0xcdab, 0xdc22, 0xeeb9, 0xff30,
+       0x07c7, 0x164e, 0x24d5, 0x355c, 0x41e3, 0x506a, 0x62f1, 0x7378,
+       0x9b0e, 0x8a87, 0xb81c, 0xa995, 0xdd2a, 0xcca3, 0xfe38, 0xefb1,
+       0x1746, 0x06cf, 0x3454, 0x25dd, 0x5162, 0x40eb, 0x7270, 0x63f9,
+       0xaa8d, 0xbb04, 0x899f, 0x9816, 0xeca9, 0xfd20, 0xcfbb, 0xde32,
+       0x26c5, 0x374c, 0x05d7, 0x145e, 0x60e1, 0x7168, 0x43f3, 0x527a,
+       0xba0c, 0xab85, 0x991e, 0x8897, 0xfc28, 0xeda1, 0xdf3a, 0xceb3,
+       0x3644, 0x27cd, 0x1556, 0x04df, 0x7060, 0x61e9, 0x5372, 0x42fb,
+       0xc98b, 0xd802, 0xea99, 0xfb10, 0x8faf, 0x9e26, 0xacbd, 0xbd34,
+       0x45c3, 0x544a, 0x66d1, 0x7758, 0x03e7, 0x126e, 0x20f5, 0x317c,
+       0xd90a, 0xc883, 0xfa18, 0xeb91, 0x9f2e, 0x8ea7, 0xbc3c, 0xadb5,
+       0x5542, 0x44cb, 0x7650, 0x67d9, 0x1366, 0x02ef, 0x3074, 0x21fd,
+       0xe889, 0xf900, 0xcb9b, 0xda12, 0xaead, 0xbf24, 0x8dbf, 0x9c36,
+       0x64c1, 0x7548, 0x47d3, 0x565a, 0x22e5, 0x336c, 0x01f7, 0x107e,
+       0xf808, 0xe981, 0xdb1a, 0xca93, 0xbe2c, 0xafa5, 0x9d3e, 0x8cb7,
+       0x7440, 0x65c9, 0x5752, 0x46db, 0x3264, 0x23ed, 0x1176, 0x00ff
 };
 
-/*---------------------------------------------------------------------------*/
-
 static unsigned short calc_crc_flex(unsigned char *cp, int size)
 {
-    unsigned short crc = 0xffff;
-    
-    while (size--)
-       crc = (crc << 8) ^ Crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
+       unsigned short crc = 0xffff;
 
-    return crc;
-}
+       while (size--)
+               crc = (crc << 8) ^ crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
 
-/*---------------------------------------------------------------------------*/
+       return crc;
+}
 
 static int check_crc_flex(unsigned char *cp, int size)
 {
-  unsigned short crc = 0xffff;
+       unsigned short crc = 0xffff;
 
-  if (size < 3)
-      return -1;
+       if (size < 3)
+               return -1;
 
-  while (size--)
-      crc = (crc << 8) ^ Crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
+       while (size--)
+               crc = (crc << 8) ^ crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
 
-  if ((crc & 0xffff) != 0x7070) 
-      return -1;
+       if ((crc & 0xffff) != 0x7070)
+               return -1;
 
-  return 0;
+       return 0;
 }
 
-/*---------------------------------------------------------------------------*/
+/*
+ * Standard encapsulation
+ */
 
-/* Find a free channel, and link in this `tty' line. */
-static inline struct ax_disp *ax_alloc(void)
+static int kiss_esc(unsigned char *s, unsigned char *d, int len)
 {
-       ax25_ctrl_t *axp=NULL;
-       int i;
+       unsigned char *ptr = d;
+       unsigned char c;
 
-       for (i = 0; i < ax25_maxdev; i++) {
-               axp = ax25_ctrls[i];
+       /*
+        * Send an initial END character to flush out any data that may have
+        * accumulated in the receiver due to line noise.
+        */
 
-               /* Not allocated ? */
-               if (axp == NULL)
-                       break;
+       *ptr++ = END;
 
-               /* Not in use ? */
-               if (!test_and_set_bit(AXF_INUSE, &axp->ctrl.flags))
+       while (len-- > 0) {
+               switch (c = *s++) {
+               case END:
+                       *ptr++ = ESC;
+                       *ptr++ = ESC_END;
                        break;
+               case ESC:
+                       *ptr++ = ESC;
+                       *ptr++ = ESC_ESC;
+                       break;
+               default:
+                       *ptr++ = c;
+                       break;
+               }
        }
 
-       /* Sorry, too many, all slots in use */
-       if (i >= ax25_maxdev)
-               return NULL;
+       *ptr++ = END;
+
+       return ptr - d;
+}
+
+/*
+ * MW:
+ * OK its ugly, but tell me a better solution without copying the
+ * packet to a temporary buffer :-)
+ */
+static int kiss_esc_crc(unsigned char *s, unsigned char *d, unsigned short crc,
+       int len)
+{
+       unsigned char *ptr = d;
+       unsigned char c=0;
+
+       *ptr++ = END;
+       while (len > 0) {
+               if (len > 2)
+                       c = *s++;
+               else if (len > 1)
+                       c = crc >> 8;
+               else if (len > 0)
+                       c = crc & 0xff;
+
+               len--;
 
-       /* If no channels are available, allocate one */
-       if (axp == NULL && (ax25_ctrls[i] = kmalloc(sizeof(ax25_ctrl_t), GFP_KERNEL)) != NULL) {
-               axp = ax25_ctrls[i];
+               switch (c) {
+               case END:
+                       *ptr++ = ESC;
+                       *ptr++ = ESC_END;
+                       break;
+               case ESC:
+                       *ptr++ = ESC;
+                       *ptr++ = ESC_ESC;
+                       break;
+               default:
+                       *ptr++ = c;
+                       break;
+               }
        }
-       memset(axp, 0, sizeof(ax25_ctrl_t));
-
-       /* Initialize channel control data */
-       set_bit(AXF_INUSE, &axp->ctrl.flags);
-       sprintf(axp->dev.name, "ax%d", i++);
-       axp->ctrl.tty      = NULL;
-       axp->dev.base_addr = i;
-       axp->dev.priv      = (void *)&axp->ctrl;
-       axp->dev.next      = NULL;
-       axp->dev.init      = ax25_init;
-
-       if (axp != NULL) {
-               /*
-                * register device so that it can be ifconfig'ed
-                * ax25_init() will be called as a side-effect
-                * SIDE-EFFECT WARNING: ax25_init() CLEARS axp->ctrl !
-                */
-               if (register_netdev(&axp->dev) == 0) {
-                       /* (Re-)Set the INUSE bit.   Very Important! */
-                       set_bit(AXF_INUSE, &axp->ctrl.flags);
-                       axp->ctrl.dev = &axp->dev;
-                       axp->dev.priv = (void *) &axp->ctrl;
-
-                       return &axp->ctrl;
-               } else {
-                       clear_bit(AXF_INUSE,&axp->ctrl.flags);
-                       printk(KERN_ERR "mkiss: ax_alloc() - register_netdev() failure.\n");
+       *ptr++ = END;
+
+       return ptr - d;
+}
+
+/* Send one completely decapsulated AX.25 packet to the AX.25 layer. */
+static void ax_bump(struct mkiss *ax)
+{
+       struct sk_buff *skb;
+       int count;
+
+       spin_lock_bh(&ax->buflock);
+       if (ax->rbuff[0] > 0x0f) {
+               if (ax->rbuff[0] & 0x20) {
+                       ax->crcmode = CRC_MODE_FLEX;
+                       if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
+                               ax->stats.rx_errors++;
+                               return;
+                       }
+                       ax->rcount -= 2;
+                        /* dl9sau bugfix: the trailling two bytes flexnet crc
+                         * will not be passed to the kernel. thus we have
+                         * to correct the kissparm signature, because it
+                         * indicates a crc but there's none
+                        */
+                        *ax->rbuff &= ~0x20;
                }
+       }
+       spin_unlock_bh(&ax->buflock);
+
+       count = ax->rcount;
+
+       if ((skb = dev_alloc_skb(count)) == NULL) {
+               printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n",
+                      ax->dev->name);
+               ax->stats.rx_dropped++;
+               return;
        }
 
-       return NULL;
+       spin_lock_bh(&ax->buflock);
+       memcpy(skb_put(skb,count), ax->rbuff, count);
+       spin_unlock_bh(&ax->buflock);
+       skb->protocol = ax25_type_trans(skb, ax->dev);
+       netif_rx(skb);
+       ax->dev->last_rx = jiffies;
+       ax->stats.rx_packets++;
+       ax->stats.rx_bytes += count;
 }
 
-/* Free an AX25 channel. */
-static inline void ax_free(struct ax_disp *ax)
+static void kiss_unesc(struct mkiss *ax, unsigned char s)
 {
-       /* Free all AX25 frame buffers. */
-       if (ax->rbuff)
-               kfree(ax->rbuff);
-       ax->rbuff = NULL;
-       if (ax->xbuff)
-               kfree(ax->xbuff);
-       ax->xbuff = NULL;
-       if (!test_and_clear_bit(AXF_INUSE, &ax->flags))
-               printk(KERN_ERR "mkiss: %s: ax_free for already free unit.\n", ax->dev->name);
+       switch (s) {
+       case END:
+               /* drop keeptest bit = VSV */
+               if (test_bit(AXF_KEEPTEST, &ax->flags))
+                       clear_bit(AXF_KEEPTEST, &ax->flags);
+
+               if (!test_and_clear_bit(AXF_ERROR, &ax->flags) && (ax->rcount > 2))
+                       ax_bump(ax);
+
+               clear_bit(AXF_ESCAPE, &ax->flags);
+               ax->rcount = 0;
+               return;
+
+       case ESC:
+               set_bit(AXF_ESCAPE, &ax->flags);
+               return;
+       case ESC_ESC:
+               if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
+                       s = ESC;
+               break;
+       case ESC_END:
+               if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
+                       s = END;
+               break;
+       }
+
+       spin_lock_bh(&ax->buflock);
+       if (!test_bit(AXF_ERROR, &ax->flags)) {
+               if (ax->rcount < ax->buffsize) {
+                       ax->rbuff[ax->rcount++] = s;
+                       spin_unlock_bh(&ax->buflock);
+                       return;
+               }
+
+               ax->stats.rx_over_errors++;
+               set_bit(AXF_ERROR, &ax->flags);
+       }
+       spin_unlock_bh(&ax->buflock);
+}
+
+static int ax_set_mac_address(struct net_device *dev, void *addr)
+{
+       struct sockaddr_ax25 *sa = addr;
+
+       spin_lock_irq(&dev->xmit_lock);
+       memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
+       spin_unlock_irq(&dev->xmit_lock);
+
+       return 0;
 }
 
-static void ax_changedmtu(struct ax_disp *ax)
+/*---------------------------------------------------------------------------*/
+
+static void ax_changedmtu(struct mkiss *ax)
 {
        struct net_device *dev = ax->dev;
        unsigned char *xbuff, *rbuff, *oxbuff, *orbuff;
@@ -236,7 +348,8 @@ static void ax_changedmtu(struct ax_disp *ax)
        rbuff = kmalloc(len + 4, GFP_ATOMIC);
 
        if (xbuff == NULL || rbuff == NULL)  {
-               printk(KERN_ERR "mkiss: %s: unable to grow ax25 buffers, MTU change cancelled.\n",
+               printk(KERN_ERR "mkiss: %s: unable to grow ax25 buffers, "
+                      "MTU change cancelled.\n",
                       ax->dev->name);
                dev->mtu = ax->mtu;
                if (xbuff != NULL)
@@ -258,7 +371,7 @@ static void ax_changedmtu(struct ax_disp *ax)
                        memcpy(ax->xbuff, ax->xhead, ax->xleft);
                } else  {
                        ax->xleft = 0;
-                       ax->tx_dropped++;
+                       ax->stats.tx_dropped++;
                }
        }
 
@@ -269,7 +382,7 @@ static void ax_changedmtu(struct ax_disp *ax)
                        memcpy(ax->rbuff, orbuff, ax->rcount);
                } else  {
                        ax->rcount = 0;
-                       ax->rx_over_errors++;
+                       ax->stats.rx_over_errors++;
                        set_bit(AXF_ERROR, &ax->flags);
                }
        }
@@ -279,72 +392,14 @@ static void ax_changedmtu(struct ax_disp *ax)
 
        spin_unlock_bh(&ax->buflock);
 
-       if (oxbuff != NULL)
-               kfree(oxbuff);
-       if (orbuff != NULL)
-               kfree(orbuff);
-}
-
-
-/* Set the "sending" flag.  This must be atomic. */
-static inline void ax_lock(struct ax_disp *ax)
-{
-       netif_stop_queue(ax->dev);
-}
-
-
-/* Clear the "sending" flag.  This must be atomic. */
-static inline void ax_unlock(struct ax_disp *ax)
-{
-       netif_start_queue(ax->dev);
-}
-
-/* Send one completely decapsulated AX.25 packet to the AX.25 layer. */
-static void ax_bump(struct ax_disp *ax)
-{
-       struct sk_buff *skb;
-       int count;
-
-       spin_lock_bh(&ax->buflock);
-       if (ax->rbuff[0] > 0x0f) {
-               if (ax->rbuff[0] & 0x20) {
-                       ax->crcmode = CRC_MODE_FLEX;
-                       if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
-                               ax->rx_errors++;
-                               return;
-                       }
-                       ax->rcount -= 2;
-                        /* dl9sau bugfix: the trailling two bytes flexnet crc
-                         * will not be passed to the kernel. thus we have
-                         * to correct the kissparm signature, because it
-                         * indicates a crc but there's none
-                        */
-                        *ax->rbuff &= ~0x20;
-               }
-       }
-       spin_unlock_bh(&ax->buflock);
-
-       count = ax->rcount;
-
-       if ((skb = dev_alloc_skb(count)) == NULL) {
-               printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n", ax->dev->name);
-               ax->rx_dropped++;
-               return;
-       }
-
-       spin_lock_bh(&ax->buflock);
-       memcpy(skb_put(skb,count), ax->rbuff, count);
-       spin_unlock_bh(&ax->buflock);
-       skb->protocol = ax25_type_trans(skb, ax->dev);
-       netif_rx(skb);
-       ax->dev->last_rx = jiffies;
-       ax->rx_packets++;
-       ax->rx_bytes+=count;
+       kfree(oxbuff);
+       kfree(orbuff);
 }
 
 /* Encapsulate one AX.25 packet and stuff into a TTY queue. */
-static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len)
+static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
 {
+       struct mkiss *ax = netdev_priv(dev);
        unsigned char *p;
        int actual, count;
 
@@ -354,8 +409,8 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len)
        if (len > ax->mtu) {            /* Sigh, shouldn't occur BUT ... */
                len = ax->mtu;
                printk(KERN_ERR "mkiss: %s: truncating oversized transmit packet!\n", ax->dev->name);
-               ax->tx_dropped++;
-               ax_unlock(ax);
+               ax->stats.tx_dropped++;
+               netif_start_queue(dev);
                return;
        }
 
@@ -376,10 +431,11 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len)
                 break;
        }
        
-       ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+       set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
        actual = ax->tty->driver->write(ax->tty, ax->xbuff, count);
-       ax->tx_packets++;
-       ax->tx_bytes+=actual;
+       ax->stats.tx_packets++;
+       ax->stats.tx_bytes += actual;
+
        ax->dev->trans_start = jiffies;
        ax->xleft = count - actual;
        ax->xhead = ax->xbuff + actual;
@@ -387,37 +443,10 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len)
        spin_unlock_bh(&ax->buflock);
 }
 
-/*
- * Called by the driver when there's room for more data.  If we have
- * more packets to send, we send them here.
- */
-static void ax25_write_wakeup(struct tty_struct *tty)
-{
-       int actual;
-       struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
-
-       /* First make sure we're connected. */
-       if (ax == NULL || ax->magic != AX25_MAGIC || !netif_running(ax->dev))
-               return;
-       if (ax->xleft <= 0)  {
-               /* Now serial buffer is almost free & we can start
-                * transmission of another packet
-                */
-               tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
-
-               netif_wake_queue(ax->dev);
-               return;
-       }
-
-       actual = tty->driver->write(tty, ax->xhead, ax->xleft);
-       ax->xleft -= actual;
-       ax->xhead += actual;
-}
-
 /* Encapsulate an AX.25 packet and kick it into a TTY queue. */
 static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-       struct ax_disp *ax = netdev_priv(dev);
+       struct mkiss *ax = netdev_priv(dev);
 
        if (!netif_running(dev))  {
                printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);
@@ -429,7 +458,7 @@ static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
                 * May be we must check transmitter timeout here ?
                 *      14 Oct 1994 Dmitry Gorodchanin.
                 */
-               if (jiffies - dev->trans_start  < 20 * HZ) {
+               if (time_before(jiffies, dev->trans_start + 20 * HZ)) {
                        /* 20 sec timeout not reached */
                        return 1;
                }
@@ -439,20 +468,30 @@ static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
                       "bad line quality" : "driver error");
 
                ax->xleft = 0;
-               ax->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
-               ax_unlock(ax);
+               clear_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
+               netif_start_queue(dev);
        }
 
        /* We were not busy, so we are now... :-) */
        if (skb != NULL) {
-               ax_lock(ax);
-               ax_encaps(ax, skb->data, skb->len);
+               netif_stop_queue(dev);
+               ax_encaps(dev, skb->data, skb->len);
                kfree_skb(skb);
        }
 
        return 0;
 }
 
+static int ax_open_dev(struct net_device *dev)
+{
+       struct mkiss *ax = netdev_priv(dev);
+
+       if (ax->tty == NULL)
+               return -ENODEV;
+
+       return 0;
+}
+
 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 
 /* Return the frame type ID */
@@ -481,7 +520,7 @@ static int ax_rebuild_header(struct sk_buff *skb)
 /* Open the low-level part of the AX25 channel. Easy! */
 static int ax_open(struct net_device *dev)
 {
-       struct ax_disp *ax = netdev_priv(dev);
+       struct mkiss *ax = netdev_priv(dev);
        unsigned long len;
 
        if (ax->tty == NULL)
@@ -518,7 +557,6 @@ static int ax_open(struct net_device *dev)
 
        spin_lock_init(&ax->buflock);
 
-       netif_start_queue(dev);
        return 0;
 
 noxbuff:
@@ -532,68 +570,100 @@ norbuff:
 /* Close the low-level part of the AX25 channel. Easy! */
 static int ax_close(struct net_device *dev)
 {
-       struct ax_disp *ax = netdev_priv(dev);
+       struct mkiss *ax = netdev_priv(dev);
 
-       if (ax->tty == NULL)
-               return -EBUSY;
-
-       ax->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+       if (ax->tty)
+               clear_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
 
        netif_stop_queue(dev);
 
        return 0;
 }
 
-static int ax25_receive_room(struct tty_struct *tty)
+static struct net_device_stats *ax_get_stats(struct net_device *dev)
 {
-       return 65536;  /* We can handle an infinite amount of data. :-) */
+       struct mkiss *ax = netdev_priv(dev);
+
+       return &ax->stats;
+}
+
+static void ax_setup(struct net_device *dev)
+{
+       static char ax25_bcast[AX25_ADDR_LEN] =
+               {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
+       static char ax25_test[AX25_ADDR_LEN] =
+               {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
+
+       /* Finish setting up the DEVICE info. */
+       dev->mtu             = AX_MTU;
+       dev->hard_start_xmit = ax_xmit;
+       dev->open            = ax_open_dev;
+       dev->stop            = ax_close;
+       dev->get_stats       = ax_get_stats;
+       dev->set_mac_address = ax_set_mac_address;
+       dev->hard_header_len = 0;
+       dev->addr_len        = 0;
+       dev->type            = ARPHRD_AX25;
+       dev->tx_queue_len    = 10;
+       dev->hard_header     = ax_header;
+       dev->rebuild_header  = ax_rebuild_header;
+
+       memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
+       memcpy(dev->dev_addr,  ax25_test,  AX25_ADDR_LEN);
+
+       dev->flags      = IFF_BROADCAST | IFF_MULTICAST;
 }
 
 /*
- * Handle the 'receiver data ready' interrupt.
- * This function is called by the 'tty_io' module in the kernel when
- * a block of data has been received, which can now be decapsulated
- * and sent on to the AX.25 layer for further processing.
+ * We have a potential race on dereferencing tty->disc_data, because the tty
+ * layer provides no locking at all - thus one cpu could be running
+ * sixpack_receive_buf while another calls sixpack_close, which zeroes
+ * tty->disc_data and frees the memory that sixpack_receive_buf is using.  The
+ * best way to fix this is to use a rwlock in the tty struct, but for now we
+ * use a single global rwlock for all ttys in ppp line discipline.
  */
-static void ax25_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
+static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
+
+static struct mkiss *mkiss_get(struct tty_struct *tty)
 {
-       struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
+       struct mkiss *ax;
 
-       if (ax == NULL || ax->magic != AX25_MAGIC || !netif_running(ax->dev))
-               return;
+       read_lock(&disc_data_lock);
+       ax = tty->disc_data;
+       if (ax)
+               atomic_inc(&ax->refcnt);
+       read_unlock(&disc_data_lock);
 
-       /*
-        * Argh! mtu change time! - costs us the packet part received
-        * at the change
-        */
-       if (ax->mtu != ax->dev->mtu + 73)
-               ax_changedmtu(ax);
-
-       /* Read the characters out of the buffer */
-       while (count--) {
-               if (fp != NULL && *fp++) {
-                       if (!test_and_set_bit(AXF_ERROR, &ax->flags))
-                               ax->rx_errors++;
-                       cp++;
-                       continue;
-               }
+       return ax;
+}
 
-               kiss_unesc(ax, *cp++);
-       }
+static void mkiss_put(struct mkiss *ax)
+{
+       if (atomic_dec_and_test(&ax->refcnt))
+               up(&ax->dead_sem);
 }
 
-static int ax25_open(struct tty_struct *tty)
+static int mkiss_open(struct tty_struct *tty)
 {
-       struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
+       struct net_device *dev;
+       struct mkiss *ax;
        int err;
 
-       /* First make sure we're not already connected. */
-       if (ax && ax->magic == AX25_MAGIC)
-               return -EEXIST;
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
 
-       /* OK.  Find a free AX25 channel to use. */
-       if ((ax = ax_alloc()) == NULL)
-               return -ENFILE;
+       dev = alloc_netdev(sizeof(struct mkiss), "ax%d", ax_setup);
+       if (!dev) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       ax = netdev_priv(dev);
+       ax->dev = dev;
+
+       spin_lock_init(&ax->buflock);
+       atomic_set(&ax->refcnt, 1);
+       init_MUTEX_LOCKED(&ax->dead_sem);
 
        ax->tty = tty;
        tty->disc_data = ax;
@@ -602,283 +672,212 @@ static int ax25_open(struct tty_struct *tty)
                tty->driver->flush_buffer(tty);
 
        /* Restore default settings */
-       ax->dev->type = ARPHRD_AX25;
+       dev->type = ARPHRD_AX25;
 
        /* Perform the low-level AX25 initialization. */
-       if ((err = ax_open(ax->dev)))
-               return err;
+       if ((err = ax_open(ax->dev))) {
+               goto out_free_netdev;
+       }
 
-       /* Done.  We have linked the TTY line to a channel. */
-       return ax->dev->base_addr;
-}
+       if (register_netdev(dev))
+               goto out_free_buffers;
 
-static void ax25_close(struct tty_struct *tty)
-{
-       struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
+       netif_start_queue(dev);
 
-       /* First make sure we're connected. */
-       if (ax == NULL || ax->magic != AX25_MAGIC)
-               return;
+       /* Done.  We have linked the TTY line to a channel. */
+       return 0;
 
-       unregister_netdev(ax->dev);
+out_free_buffers:
+       kfree(ax->rbuff);
+       kfree(ax->xbuff);
 
-       tty->disc_data = NULL;
-       ax->tty        = NULL;
+out_free_netdev:
+       free_netdev(dev);
 
-       ax_free(ax);
+out:
+       return err;
 }
 
-
-static struct net_device_stats *ax_get_stats(struct net_device *dev)
+static void mkiss_close(struct tty_struct *tty)
 {
-       static struct net_device_stats stats;
-       struct ax_disp *ax = netdev_priv(dev);
-
-       memset(&stats, 0, sizeof(struct net_device_stats));
-
-       stats.rx_packets     = ax->rx_packets;
-       stats.tx_packets     = ax->tx_packets;
-       stats.rx_bytes       = ax->rx_bytes;
-       stats.tx_bytes       = ax->tx_bytes;
-       stats.rx_dropped     = ax->rx_dropped;
-       stats.tx_dropped     = ax->tx_dropped;
-       stats.tx_errors      = ax->tx_errors;
-       stats.rx_errors      = ax->rx_errors;
-       stats.rx_over_errors = ax->rx_over_errors;
-
-       return &stats;
-}
+       struct mkiss *ax;
 
+       write_lock(&disc_data_lock);
+       ax = tty->disc_data;
+       tty->disc_data = NULL;
+       write_unlock(&disc_data_lock);
 
-/************************************************************************
- *                        STANDARD ENCAPSULATION                        *
- ************************************************************************/
-
-static int kiss_esc(unsigned char *s, unsigned char *d, int len)
-{
-       unsigned char *ptr = d;
-       unsigned char c;
+       if (ax == 0)
+               return;
 
        /*
-        * Send an initial END character to flush out any
-        * data that may have accumulated in the receiver
-        * due to line noise.
+        * We have now ensured that nobody can start using ap from now on, but
+        * we have to wait for all existing users to finish.
         */
+       if (!atomic_dec_and_test(&ax->refcnt))
+               down(&ax->dead_sem);
 
-       *ptr++ = END;
-
-       while (len-- > 0) {
-               switch (c = *s++) {
-                       case END:
-                               *ptr++ = ESC;
-                               *ptr++ = ESC_END;
-                               break;
-                       case ESC:
-                               *ptr++ = ESC;
-                               *ptr++ = ESC_ESC;
-                               break;
-                       default:
-                               *ptr++ = c;
-                               break;
-               }
-       }
+       unregister_netdev(ax->dev);
 
-       *ptr++ = END;
+       /* Free all AX25 frame buffers. */
+       kfree(ax->rbuff);
+       kfree(ax->xbuff);
 
-       return ptr - d;
+       ax->tty = NULL;
 }
 
-/*
- * MW:
- * OK its ugly, but tell me a better solution without copying the
- * packet to a temporary buffer :-)
- */
-static int kiss_esc_crc(unsigned char *s, unsigned char *d, unsigned short crc, int len)
+/* Perform I/O control on an active ax25 channel. */
+static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
+       unsigned int cmd, unsigned long arg)
 {
-       unsigned char *ptr = d;
-       unsigned char c=0;
-
-       *ptr++ = END;
-       while (len > 0) {
-               if (len > 2) 
-                       c = *s++;
-               else if (len > 1)
-                       c = crc >> 8;
-               else if (len > 0)
-                       c = crc & 0xff;
+       struct mkiss *ax = mkiss_get(tty);
+       struct net_device *dev = ax->dev;
+       unsigned int tmp, err;
 
-               len--;
+       /* First make sure we're connected. */
+       if (ax == NULL)
+               return -ENXIO;
 
-               switch (c) {
-                        case END:
-                                *ptr++ = ESC;
-                                *ptr++ = ESC_END;
-                                break;
-                        case ESC:
-                                *ptr++ = ESC;
-                                *ptr++ = ESC_ESC;
-                                break;
-                        default:
-                                *ptr++ = c;
-                                break;
+       switch (cmd) {
+       case SIOCGIFNAME:
+               err = copy_to_user((void __user *) arg, ax->dev->name,
+                                  strlen(ax->dev->name) + 1) ? -EFAULT : 0;
+               break;
+
+       case SIOCGIFENCAP:
+               err = put_user(4, (int __user *) arg);
+               break;
+
+       case SIOCSIFENCAP:
+               if (get_user(tmp, (int __user *) arg)) {
+                       err = -EFAULT;
+                       break;
                }
-       }
-       *ptr++ = END;
-       return ptr - d;         
-}
 
-static void kiss_unesc(struct ax_disp *ax, unsigned char s)
-{
-       switch (s) {
-               case END:
-                       /* drop keeptest bit = VSV */
-                       if (test_bit(AXF_KEEPTEST, &ax->flags))
-                               clear_bit(AXF_KEEPTEST, &ax->flags);
+               ax->mode = tmp;
+               dev->addr_len        = AX25_ADDR_LEN;
+               dev->hard_header_len = AX25_KISS_HEADER_LEN +
+                                      AX25_MAX_HEADER_LEN + 3;
+               dev->type            = ARPHRD_AX25;
 
-                       if (!test_and_clear_bit(AXF_ERROR, &ax->flags) && (ax->rcount > 2))
-                               ax_bump(ax);
+               err = 0;
+               break;
 
-                       clear_bit(AXF_ESCAPE, &ax->flags);
-                       ax->rcount = 0;
-                       return;
+       case SIOCSIFHWADDR: {
+               char addr[AX25_ADDR_LEN];
+printk(KERN_INFO "In SIOCSIFHWADDR");
 
-               case ESC:
-                       set_bit(AXF_ESCAPE, &ax->flags);
-                       return;
-               case ESC_ESC:
-                       if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
-                               s = ESC;
+               if (copy_from_user(&addr,
+                                  (void __user *) arg, AX25_ADDR_LEN)) {
+                       err = -EFAULT;
                        break;
-               case ESC_END:
-                       if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
-                               s = END;
-                       break;
-       }
-
-       spin_lock_bh(&ax->buflock);
-       if (!test_bit(AXF_ERROR, &ax->flags)) {
-               if (ax->rcount < ax->buffsize) {
-                       ax->rbuff[ax->rcount++] = s;
-                       spin_unlock_bh(&ax->buflock);
-                       return;
                }
 
-               ax->rx_over_errors++;
-               set_bit(AXF_ERROR, &ax->flags);
+               spin_lock_irq(&dev->xmit_lock);
+               memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
+               spin_unlock_irq(&dev->xmit_lock);
+
+               err = 0;
+               break;
+       }
+       default:
+               err = -ENOIOCTLCMD;
        }
-       spin_unlock_bh(&ax->buflock);
-}
 
+       mkiss_put(ax);
 
-static int ax_set_mac_address(struct net_device *dev, void __user *addr)
-{
-       if (copy_from_user(dev->dev_addr, addr, AX25_ADDR_LEN))
-               return -EFAULT;
-       return 0;
+       return err;
 }
 
-static int ax_set_dev_mac_address(struct net_device *dev, void *addr)
+/*
+ * Handle the 'receiver data ready' interrupt.
+ * This function is called by the 'tty_io' module in the kernel when
+ * a block of data has been received, which can now be decapsulated
+ * and sent on to the AX.25 layer for further processing.
+ */
+static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,
+       char *fp, int count)
 {
-       struct sockaddr *sa = addr;
-
-       memcpy(dev->dev_addr, sa->sa_data, AX25_ADDR_LEN);
+       struct mkiss *ax = mkiss_get(tty);
 
-       return 0;
-}
-
-
-/* Perform I/O control on an active ax25 channel. */
-static int ax25_disp_ioctl(struct tty_struct *tty, void *file, int cmd, void __user *arg)
-{
-       struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
-       unsigned int tmp;
+       if (!ax)
+               return;
 
-       /* First make sure we're connected. */
-       if (ax == NULL || ax->magic != AX25_MAGIC)
-               return -EINVAL;
+       /*
+        * Argh! mtu change time! - costs us the packet part received
+        * at the change
+        */
+       if (ax->mtu != ax->dev->mtu + 73)
+               ax_changedmtu(ax);
 
-       switch (cmd) {
-               case SIOCGIFNAME:
-                       if (copy_to_user(arg, ax->dev->name, strlen(ax->dev->name) + 1))
-                               return -EFAULT;
-                       return 0;
-
-               case SIOCGIFENCAP:
-                       return put_user(4, (int __user *)arg);
-
-               case SIOCSIFENCAP:
-                       if (get_user(tmp, (int __user *)arg))
-                               return -EFAULT;
-                       ax->mode = tmp;
-                       ax->dev->addr_len        = AX25_ADDR_LEN;         /* sizeof an AX.25 addr */
-                       ax->dev->hard_header_len = AX25_KISS_HEADER_LEN + AX25_MAX_HEADER_LEN + 3;
-                       ax->dev->type            = ARPHRD_AX25;
-                       return 0;
-
-                case SIOCSIFHWADDR:
-                       return ax_set_mac_address(ax->dev, arg);
+       /* Read the characters out of the buffer */
+       while (count--) {
+               if (fp != NULL && *fp++) {
+                       if (!test_and_set_bit(AXF_ERROR, &ax->flags))
+                               ax->stats.rx_errors++;
+                       cp++;
+                       continue;
+               }
 
-               default:
-                       return -ENOIOCTLCMD;
+               kiss_unesc(ax, *cp++);
        }
+
+       mkiss_put(ax);
+       if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
+           && tty->driver->unthrottle)
+               tty->driver->unthrottle(tty);
 }
 
-static int ax_open_dev(struct net_device *dev)
+static int mkiss_receive_room(struct tty_struct *tty)
 {
-       struct ax_disp *ax = netdev_priv(dev);
-
-       if (ax->tty == NULL)
-               return -ENODEV;
-
-       return 0;
+       return 65536;  /* We can handle an infinite amount of data. :-) */
 }
 
-
-/* Initialize the driver.  Called by network startup. */
-static int ax25_init(struct net_device *dev)
+/*
+ * Called by the driver when there's room for more data.  If we have
+ * more packets to send, we send them here.
+ */
+static void mkiss_write_wakeup(struct tty_struct *tty)
 {
-       struct ax_disp *ax = netdev_priv(dev);
-
-       static char ax25_bcast[AX25_ADDR_LEN] =
-               {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
-       static char ax25_test[AX25_ADDR_LEN] =
-               {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
-
-       if (ax == NULL)         /* Allocation failed ?? */
-               return -ENODEV;
+       struct mkiss *ax = mkiss_get(tty);
+       int actual;
 
-       /* Set up the "AX25 Control Block". (And clear statistics) */
-       memset(ax, 0, sizeof (struct ax_disp));
-       ax->magic  = AX25_MAGIC;
-       ax->dev    = dev;
+       if (!ax)
+               return;
 
-       /* Finish setting up the DEVICE info. */
-       dev->mtu             = AX_MTU;
-       dev->hard_start_xmit = ax_xmit;
-       dev->open            = ax_open_dev;
-       dev->stop            = ax_close;
-       dev->get_stats       = ax_get_stats;
-       dev->set_mac_address = ax_set_dev_mac_address;
-       dev->hard_header_len = 0;
-       dev->addr_len        = 0;
-       dev->type            = ARPHRD_AX25;
-       dev->tx_queue_len    = 10;
-       dev->hard_header     = ax_header;
-       dev->rebuild_header  = ax_rebuild_header;
+       if (ax->xleft <= 0)  {
+               /* Now serial buffer is almost free & we can start
+                * transmission of another packet
+                */
+               clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 
-       memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
-       memcpy(dev->dev_addr,  ax25_test,  AX25_ADDR_LEN);
+               netif_wake_queue(ax->dev);
+               goto out;
+       }
 
-       /* New-style flags. */
-       dev->flags      = IFF_BROADCAST | IFF_MULTICAST;
+       actual = tty->driver->write(tty, ax->xhead, ax->xleft);
+       ax->xleft -= actual;
+       ax->xhead += actual;
 
-       return 0;
+out:
+       mkiss_put(ax);
 }
 
+static struct tty_ldisc ax_ldisc = {
+       .magic          = TTY_LDISC_MAGIC,
+       .name           = "mkiss",
+       .open           = mkiss_open,
+       .close          = mkiss_close,
+       .ioctl          = mkiss_ioctl,
+       .receive_buf    = mkiss_receive_buf,
+       .receive_room   = mkiss_receive_room,
+       .write_wakeup   = mkiss_write_wakeup
+};
 
-/* ******************************************************************** */
-/* *                   Init MKISS driver                             * */
-/* ******************************************************************** */
+static char banner[] __initdata = KERN_INFO \
+       "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n";
+static char msg_regfail[] __initdata = KERN_ERR \
+       "mkiss: can't register line discipline (err = %d)\n";
 
 static int __init mkiss_init_driver(void)
 {
@@ -886,64 +885,27 @@ static int __init mkiss_init_driver(void)
 
        printk(banner);
 
-       if (ax25_maxdev < 4)
-         ax25_maxdev = 4; /* Sanity */
+       if ((status = tty_register_ldisc(N_AX25, &ax_ldisc)) != 0)
+               printk(msg_regfail);
 
-       if ((ax25_ctrls = kmalloc(sizeof(void *) * ax25_maxdev, GFP_KERNEL)) == NULL) {
-               printk(KERN_ERR "mkiss: Can't allocate ax25_ctrls[] array!\n");
-               return -ENOMEM;
-       }
-
-       /* Clear the pointer array, we allocate devices when we need them */
-       memset(ax25_ctrls, 0, sizeof(void*) * ax25_maxdev); /* Pointers */
-
-       /* Fill in our line protocol discipline, and register it */
-       ax_ldisc.magic          = TTY_LDISC_MAGIC;
-       ax_ldisc.name           = "mkiss";
-       ax_ldisc.open           = ax25_open;
-       ax_ldisc.close          = ax25_close;
-       ax_ldisc.ioctl          = (int (*)(struct tty_struct *, struct file *,
-                                       unsigned int, unsigned long))ax25_disp_ioctl;
-       ax_ldisc.receive_buf    = ax25_receive_buf;
-       ax_ldisc.receive_room   = ax25_receive_room;
-       ax_ldisc.write_wakeup   = ax25_write_wakeup;
-
-       if ((status = tty_register_ldisc(N_AX25, &ax_ldisc)) != 0) {
-               printk(KERN_ERR "mkiss: can't register line discipline (err = %d)\n", status);
-               kfree(ax25_ctrls);
-       }
        return status;
 }
 
+static const char msg_unregfail[] __exitdata = KERN_ERR \
+       "mkiss: can't unregister line discipline (err = %d)\n";
+
 static void __exit mkiss_exit_driver(void)
 {
-       int i;
-
-       for (i = 0; i < ax25_maxdev; i++) {
-               if (ax25_ctrls[i]) {
-                       /*
-                       * VSV = if dev->start==0, then device
-                       * unregistered while close proc.
-                       */
-                       if (netif_running(&ax25_ctrls[i]->dev))
-                               unregister_netdev(&ax25_ctrls[i]->dev);
-                       kfree(ax25_ctrls[i]);
-               }
-       }
+       int ret;
 
-       kfree(ax25_ctrls);
-       ax25_ctrls = NULL;
-
-       if ((i = tty_unregister_ldisc(N_AX25)))
-               printk(KERN_ERR "mkiss: can't unregister line discipline (err = %d)\n", i);
+       if ((ret = tty_unregister_ldisc(N_AX25)))
+               printk(msg_unregfail, ret);
 }
 
-MODULE_AUTHOR("Hans Albas PE1AYX <hans@esrac.ele.tue.nl>");
+MODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>");
 MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
-MODULE_PARM(ax25_maxdev, "i");
-MODULE_PARM_DESC(ax25_maxdev, "number of MKISS devices");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_LDISC(N_AX25);
+
 module_init(mkiss_init_driver);
 module_exit(mkiss_exit_driver);
-
index 6482d99..0de3bb9 100644 (file)
@@ -1253,7 +1253,7 @@ static int emac_init_tah(struct ocp_enet_private *fep)
                 TAH_MR_CVR | TAH_MR_ST_768 | TAH_MR_TFS_10KB | TAH_MR_DTFP |
                 TAH_MR_DIG);
 
-       iounmap(&tahp);
+       iounmap(tahp);
 
        return 0;
 }
@@ -1712,11 +1712,10 @@ struct mal_commac_ops emac_commac_ops = {
 };
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-static int emac_netpoll(struct net_device *ndev)
+static void emac_netpoll(struct net_device *ndev)
 {
        emac_rxeob_dev((void *)ndev, 0);
        emac_txeob_dev((void *)ndev, 0);
-       return 0;
 }
 #endif
 
index d520b59..49e5467 100644 (file)
@@ -499,7 +499,7 @@ static int ioc3_mdio_read(struct net_device *dev, int phy, int reg)
        ioc3_w_micr((phy << MICR_PHYADDR_SHIFT) | reg | MICR_READTRIG);
        while (ioc3_r_micr() & MICR_BUSY);
 
-       return ioc3_r_micr() & MIDR_DATA_MASK;
+       return ioc3_r_midr_r() & MIDR_DATA_MASK;
 }
 
 static void ioc3_mdio_write(struct net_device *dev, int phy, int reg, int data)
@@ -1291,7 +1291,6 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        dev->features           = NETIF_F_IP_CSUM;
 #endif
 
-       ioc3_setup_duplex(ip);
        sw_physid1 = ioc3_mdio_read(dev, ip->mii.phy_id, MII_PHYSID1);
        sw_physid2 = ioc3_mdio_read(dev, ip->mii.phy_id, MII_PHYSID2);
 
@@ -1300,6 +1299,7 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto out_stop;
 
        mii_check_media(&ip->mii, 1, 1);
+       ioc3_setup_duplex(ip);
 
        vendor = (sw_physid1 << 12) | (sw_physid2 >> 4);
        model  = (sw_physid2 >> 4) & 0x3f;
@@ -1524,7 +1524,7 @@ static void ioc3_get_drvinfo (struct net_device *dev,
        struct ethtool_drvinfo *info)
 {
        struct ioc3_private *ip = netdev_priv(dev);
-                                                                                
+
         strcpy (info->driver, IOC3_NAME);
         strcpy (info->version, IOC3_VERSION);
         strcpy (info->bus_info, pci_name(ip->pdev));
@@ -1550,7 +1550,7 @@ static int ioc3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        spin_lock_irq(&ip->ioc3_lock);
        rc = mii_ethtool_sset(&ip->mii, cmd);
        spin_unlock_irq(&ip->ioc3_lock);
-                                                                        
+
        return rc;
 }
 
index f8d3385..c83271b 100644 (file)
@@ -119,7 +119,7 @@ struct ixgb_adapter;
  * so a DMA handle can be stored along with the buffer */
 struct ixgb_buffer {
        struct sk_buff *skb;
-       uint64_t dma;
+       dma_addr_t dma;
        unsigned long time_stamp;
        uint16_t length;
        uint16_t next_to_watch;
index 3aae110..661a46b 100644 (file)
@@ -565,24 +565,6 @@ ixgb_get_ee_mac_addr(struct ixgb_hw *hw,
        }
 }
 
-/******************************************************************************
- * return the compatibility flags from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- *          compatibility flags if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_compatibility(struct ixgb_hw *hw)
-{
-       struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
-       if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
-               return (le16_to_cpu(ee_map->compatibility));
-
-       return(0);
-}
 
 /******************************************************************************
  * return the Printed Board Assembly number from EEPROM
@@ -602,81 +584,6 @@ ixgb_get_ee_pba_number(struct ixgb_hw *hw)
        return(0);
 }
 
-/******************************************************************************
- * return the Initialization Control Word 1 from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- *          Initialization Control Word 1 if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw)
-{
-       struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
-       if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
-               return (le16_to_cpu(ee_map->init_ctrl_reg_1));
-
-       return(0);
-}
-
-/******************************************************************************
- * return the Initialization Control Word 2 from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- *          Initialization Control Word 2 if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw *hw)
-{
-       struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
-       if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
-               return (le16_to_cpu(ee_map->init_ctrl_reg_2));
-
-       return(0);
-}
-
-/******************************************************************************
- * return the Subsystem Id from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- *          Subsystem Id if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_subsystem_id(struct ixgb_hw *hw)
-{
-       struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
-       if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
-               return (le16_to_cpu(ee_map->subsystem_id));
-
-       return(0);
-}
-
-/******************************************************************************
- * return the Sub Vendor Id from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- *          Sub Vendor Id if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_subvendor_id(struct ixgb_hw *hw)
-{
-       struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
-       if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
-               return (le16_to_cpu(ee_map->subvendor_id));
-
-       return(0);
-}
 
 /******************************************************************************
  * return the Device Id from EEPROM
@@ -694,81 +601,6 @@ ixgb_get_ee_device_id(struct ixgb_hw *hw)
        if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
                return (le16_to_cpu(ee_map->device_id));
 
-       return(0);
-}
-
-/******************************************************************************
- * return the Vendor Id from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- *          Device Id if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_vendor_id(struct ixgb_hw *hw)
-{
-       struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
-       if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
-               return (le16_to_cpu(ee_map->vendor_id));
-
-       return(0);
-}
-
-/******************************************************************************
- * return the Software Defined Pins Register from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- *          SDP Register if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_swdpins_reg(struct ixgb_hw *hw)
-{
-       struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
-       if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
-               return (le16_to_cpu(ee_map->swdpins_reg));
-
-       return(0);
+       return (0);
 }
 
-/******************************************************************************
- * return the D3 Power Management Bits from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- *          D3 Power Management Bits if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint8_t
-ixgb_get_ee_d3_power(struct ixgb_hw *hw)
-{
-       struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
-       if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
-               return (le16_to_cpu(ee_map->d3_power));
-
-       return(0);
-}
-
-/******************************************************************************
- * return the D0 Power Management Bits from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- *          D0 Power Management Bits if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint8_t
-ixgb_get_ee_d0_power(struct ixgb_hw *hw)
-{
-       struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
-       if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
-               return (le16_to_cpu(ee_map->d0_power));
-
-       return(0);
-}
index 3fa1138..9d026ed 100644 (file)
@@ -98,10 +98,10 @@ static struct ixgb_stats ixgb_gstrings_stats[] = {
 static int
 ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
 
        ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
-       ecmd->advertising = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
+       ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);
        ecmd->port = PORT_FIBRE;
        ecmd->transceiver = XCVR_EXTERNAL;
 
@@ -120,7 +120,7 @@ ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 static int
 ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
 
        if(ecmd->autoneg == AUTONEG_ENABLE ||
           ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)
@@ -130,6 +130,12 @@ ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
                ixgb_down(adapter, TRUE);
                ixgb_reset(adapter);
                ixgb_up(adapter);
+               /* be optimistic about our link, since we were up before */
+               adapter->link_speed = 10000;
+               adapter->link_duplex = FULL_DUPLEX;
+               netif_carrier_on(netdev);
+               netif_wake_queue(netdev);
+               
        } else
                ixgb_reset(adapter);
 
@@ -140,7 +146,7 @@ static void
 ixgb_get_pauseparam(struct net_device *netdev,
                         struct ethtool_pauseparam *pause)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        struct ixgb_hw *hw = &adapter->hw;
        
        pause->autoneg = AUTONEG_DISABLE;
@@ -159,7 +165,7 @@ static int
 ixgb_set_pauseparam(struct net_device *netdev,
                         struct ethtool_pauseparam *pause)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        struct ixgb_hw *hw = &adapter->hw;
        
        if(pause->autoneg == AUTONEG_ENABLE)
@@ -177,6 +183,11 @@ ixgb_set_pauseparam(struct net_device *netdev,
        if(netif_running(adapter->netdev)) {
                ixgb_down(adapter, TRUE);
                ixgb_up(adapter);
+               /* be optimistic about our link, since we were up before */
+               adapter->link_speed = 10000;
+               adapter->link_duplex = FULL_DUPLEX;
+               netif_carrier_on(netdev);
+               netif_wake_queue(netdev);
        } else
                ixgb_reset(adapter);
                
@@ -186,19 +197,26 @@ ixgb_set_pauseparam(struct net_device *netdev,
 static uint32_t
 ixgb_get_rx_csum(struct net_device *netdev)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
+
        return adapter->rx_csum;
 }
 
 static int
 ixgb_set_rx_csum(struct net_device *netdev, uint32_t data)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
+
        adapter->rx_csum = data;
 
        if(netif_running(netdev)) {
                ixgb_down(adapter,TRUE);
                ixgb_up(adapter);
+               /* be optimistic about our link, since we were up before */
+               adapter->link_speed = 10000;
+               adapter->link_duplex = FULL_DUPLEX;
+               netif_carrier_on(netdev);
+               netif_wake_queue(netdev);
        } else
                ixgb_reset(adapter);
        return 0;
@@ -246,14 +264,15 @@ static void
 ixgb_get_regs(struct net_device *netdev,
                   struct ethtool_regs *regs, void *p)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        struct ixgb_hw *hw = &adapter->hw;
        uint32_t *reg = p;
        uint32_t *reg_start = reg;
        uint8_t i;
 
        /* the 1 (one) below indicates an attempt at versioning, if the
-        * interface in ethtool or the driver this 1 should be incremented */
+        * interface in ethtool or the driver changes, this 1 should be
+        * incremented */
        regs->version = (1<<24) | hw->revision_id << 16 | hw->device_id;
 
        /* General Registers */
@@ -283,7 +302,8 @@ ixgb_get_regs(struct net_device *netdev,
        *reg++ = IXGB_READ_REG(hw, RAIDC);      /*  19 */
        *reg++ = IXGB_READ_REG(hw, RXCSUM);     /*  20 */
 
-       for (i = 0; i < IXGB_RAR_ENTRIES; i++) {
+       /* there are 16 RAR entries in hardware, we only use 3 */
+       for(i = 0; i < 16; i++) {
                *reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1)); /*21,...,51 */
                *reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1)); /*22,...,52 */
        }
@@ -391,7 +411,7 @@ static int
 ixgb_get_eeprom(struct net_device *netdev,
                  struct ethtool_eeprom *eeprom, uint8_t *bytes)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        struct ixgb_hw *hw = &adapter->hw;
        uint16_t *eeprom_buff;
        int i, max_len, first_word, last_word;
@@ -439,7 +459,7 @@ static int
 ixgb_set_eeprom(struct net_device *netdev,
                  struct ethtool_eeprom *eeprom, uint8_t *bytes)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        struct ixgb_hw *hw = &adapter->hw;
        uint16_t *eeprom_buff;
        void *ptr;
@@ -497,7 +517,7 @@ static void
 ixgb_get_drvinfo(struct net_device *netdev,
                   struct ethtool_drvinfo *drvinfo)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
 
        strncpy(drvinfo->driver,  ixgb_driver_name, 32);
        strncpy(drvinfo->version, ixgb_driver_version, 32);
@@ -512,7 +532,7 @@ static void
 ixgb_get_ringparam(struct net_device *netdev,
                struct ethtool_ringparam *ring)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        struct ixgb_desc_ring *txdr = &adapter->tx_ring;
        struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
 
@@ -530,7 +550,7 @@ static int
 ixgb_set_ringparam(struct net_device *netdev,
                struct ethtool_ringparam *ring)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        struct ixgb_desc_ring *txdr = &adapter->tx_ring;
        struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
        struct ixgb_desc_ring tx_old, tx_new, rx_old, rx_new;
@@ -573,6 +593,11 @@ ixgb_set_ringparam(struct net_device *netdev,
                adapter->tx_ring = tx_new;
                if((err = ixgb_up(adapter)))
                        return err;
+               /* be optimistic about our link, since we were up before */
+               adapter->link_speed = 10000;
+               adapter->link_duplex = FULL_DUPLEX;
+               netif_carrier_on(netdev);
+               netif_wake_queue(netdev);
        }
 
        return 0;
@@ -607,7 +632,7 @@ ixgb_led_blink_callback(unsigned long data)
 static int
 ixgb_phys_id(struct net_device *netdev, uint32_t data)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
 
        if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
                data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
@@ -643,7 +668,7 @@ static void
 ixgb_get_ethtool_stats(struct net_device *netdev, 
                struct ethtool_stats *stats, uint64_t *data)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        int i;
 
        ixgb_update_stats(adapter);
index 97898ef..8bcf31e 100644 (file)
@@ -822,17 +822,8 @@ extern void ixgb_clear_vfta(struct ixgb_hw *hw);
 
 /* Access functions to eeprom data */
 void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t *mac_addr);
-uint16_t ixgb_get_ee_compatibility(struct ixgb_hw *hw);
 uint32_t ixgb_get_ee_pba_number(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_subsystem_id(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_subvendor_id(struct ixgb_hw *hw);
 uint16_t ixgb_get_ee_device_id(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_vendor_id(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_swdpins_reg(struct ixgb_hw *hw);
-uint8_t ixgb_get_ee_d3_power(struct ixgb_hw *hw);
-uint8_t ixgb_get_ee_d0_power(struct ixgb_hw *hw);
 boolean_t ixgb_get_eeprom_data(struct ixgb_hw *hw);
 uint16_t ixgb_get_eeprom_word(struct ixgb_hw *hw, uint16_t index);
 
index 097b90c..5c55537 100644 (file)
 #include "ixgb.h"
 
 /* Change Log
+ * 1.0.96 04/19/05
+ * - Make needlessly global code static -- bunk@stusta.de
+ * - ethtool cleanup -- shemminger@osdl.org
+ * - Support for MODULE_VERSION -- linville@tuxdriver.com
+ * - add skb_header_cloned check to the tso path -- herbert@apana.org.au
  * 1.0.88 01/05/05
  * - include fix to the condition that determines when to quit NAPI - Robert Olsson
  * - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down
@@ -47,10 +52,9 @@ char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-
-#define DRV_VERSION "1.0.95-k2"DRIVERNAPI
+#define DRV_VERSION            "1.0.100-k2"DRIVERNAPI
 char ixgb_driver_version[] = DRV_VERSION;
-char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
+static char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
 
 /* ixgb_pci_tbl - PCI Device ID Table
  *
@@ -145,10 +149,12 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
 /* some defines for controlling descriptor fetches in h/w */
-#define RXDCTL_PTHRESH_DEFAULT 128     /* chip considers prefech below this */
-#define RXDCTL_HTHRESH_DEFAULT 16      /* chip will only prefetch if tail is 
-                                          pushed this many descriptors from head */
 #define RXDCTL_WTHRESH_DEFAULT 16      /* chip writes back at this many or RXT0 */
+#define RXDCTL_PTHRESH_DEFAULT 0               /* chip considers prefech below
+                                                * this */
+#define RXDCTL_HTHRESH_DEFAULT 0               /* chip will only prefetch if tail
+                                                * is pushed this many descriptors
+                                                * from head */
 
 /**
  * ixgb_init_module - Driver Registration Routine
@@ -376,7 +382,7 @@ ixgb_probe(struct pci_dev *pdev,
        SET_NETDEV_DEV(netdev, &pdev->dev);
 
        pci_set_drvdata(pdev, netdev);
-       adapter = netdev->priv;
+       adapter = netdev_priv(netdev);
        adapter->netdev = netdev;
        adapter->pdev = pdev;
        adapter->hw.back = adapter;
@@ -512,7 +518,7 @@ static void __devexit
 ixgb_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
 
        unregister_netdev(netdev);
 
@@ -583,7 +589,7 @@ ixgb_sw_init(struct ixgb_adapter *adapter)
 static int
 ixgb_open(struct net_device *netdev)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        int err;
 
        /* allocate transmit descriptors */
@@ -626,7 +632,7 @@ err_setup_tx:
 static int
 ixgb_close(struct net_device *netdev)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
 
        ixgb_down(adapter, TRUE);
 
@@ -1017,7 +1023,7 @@ ixgb_clean_rx_ring(struct ixgb_adapter *adapter)
 static int
 ixgb_set_mac(struct net_device *netdev, void *p)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        struct sockaddr *addr = p;
 
        if(!is_valid_ether_addr(addr->sa_data))
@@ -1043,7 +1049,7 @@ ixgb_set_mac(struct net_device *netdev, void *p)
 static void
 ixgb_set_multi(struct net_device *netdev)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        struct ixgb_hw *hw = &adapter->hw;
        struct dev_mc_list *mc_ptr;
        uint32_t rctl;
@@ -1371,7 +1377,7 @@ ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags)
 static int
 ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        unsigned int first;
        unsigned int tx_flags = 0;
        unsigned long flags;
@@ -1425,7 +1431,7 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 static void
 ixgb_tx_timeout(struct net_device *netdev)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
 
        /* Do the reset outside of interrupt context */
        schedule_work(&adapter->tx_timeout_task);
@@ -1434,7 +1440,7 @@ ixgb_tx_timeout(struct net_device *netdev)
 static void
 ixgb_tx_timeout_task(struct net_device *netdev)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
 
        ixgb_down(adapter, TRUE);
        ixgb_up(adapter);
@@ -1451,7 +1457,7 @@ ixgb_tx_timeout_task(struct net_device *netdev)
 static struct net_device_stats *
 ixgb_get_stats(struct net_device *netdev)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
 
        return &adapter->net_stats;
 }
@@ -1467,7 +1473,7 @@ ixgb_get_stats(struct net_device *netdev)
 static int
 ixgb_change_mtu(struct net_device *netdev, int new_mtu)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        int max_frame = new_mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
        int old_max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
 
@@ -1522,7 +1528,8 @@ ixgb_update_stats(struct ixgb_adapter *adapter)
 
                multi |= ((u64)IXGB_READ_REG(&adapter->hw, MPRCH) << 32);
                /* fix up multicast stats by removing broadcasts */
-               multi -= bcast;
+               if(multi >= bcast)
+                       multi -= bcast;
                
                adapter->stats.mprcl += (multi & 0xFFFFFFFF);
                adapter->stats.mprch += (multi >> 32);
@@ -1641,7 +1648,7 @@ static irqreturn_t
 ixgb_intr(int irq, void *data, struct pt_regs *regs)
 {
        struct net_device *netdev = data;
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        struct ixgb_hw *hw = &adapter->hw;
        uint32_t icr = IXGB_READ_REG(hw, ICR);
 #ifndef CONFIG_IXGB_NAPI
@@ -1688,7 +1695,7 @@ ixgb_intr(int irq, void *data, struct pt_regs *regs)
 static int
 ixgb_clean(struct net_device *netdev, int *budget)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        int work_to_do = min(*budget, netdev->quota);
        int tx_cleaned;
        int work_done = 0;
@@ -2017,7 +2024,7 @@ ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
 static void
 ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        uint32_t ctrl, rctl;
 
        ixgb_irq_disable(adapter);
@@ -2055,7 +2062,7 @@ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
 static void
 ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        uint32_t vfta, index;
 
        /* add VID to filter table */
@@ -2069,7 +2076,7 @@ ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
 static void
 ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
 {
-       struct ixgb_adapter *adapter = netdev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
        uint32_t vfta, index;
 
        ixgb_irq_disable(adapter);
index 7fec613..8423cb6 100644 (file)
@@ -1,5 +1,10 @@
 /*
- * sonic.c
+ * jazzsonic.c
+ *
+ * (C) 2005 Finn Thain
+ *
+ * Converted to DMA API, and (from the mac68k project) introduced
+ * dhd's support for 16-bit cards.
  *
  * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de)
  * 
@@ -28,8 +33,8 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
-#include <linux/bitops.h>
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/bootinfo.h>
 #include <asm/system.h>
@@ -44,22 +49,20 @@ static struct platform_device *jazz_sonic_device;
 
 #define SONIC_MEM_SIZE 0x100
 
-#define SREGS_PAD(n)    u16 n;
-
 #include "sonic.h"
 
 /*
  * Macros to access SONIC registers
  */
-#define SONIC_READ(reg) (*((volatile unsigned int *)base_addr+reg))
+#define SONIC_READ(reg) (*((volatile unsigned int *)dev->base_addr+reg))
 
 #define SONIC_WRITE(reg,val)                                           \
 do {                                                                   \
-       *((volatile unsigned int *)base_addr+(reg)) = (val);            \
+       *((volatile unsigned int *)dev->base_addr+(reg)) = (val);               \
 } while (0)
 
 
-/* use 0 for production, 1 for verification, >2 for debug */
+/* use 0 for production, 1 for verification, >1 for debug */
 #ifdef SONIC_DEBUG
 static unsigned int sonic_debug = SONIC_DEBUG;
 #else 
@@ -85,18 +88,18 @@ static unsigned short known_revisions[] =
        0xffff                  /* end of list */
 };
 
-static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr,
-                               unsigned int irq)
+static int __init sonic_probe1(struct net_device *dev)
 {
        static unsigned version_printed;
        unsigned int silicon_revision;
        unsigned int val;
-       struct sonic_local *lp;
+       struct sonic_local *lp = netdev_priv(dev);
        int err = -ENODEV;
        int i;
 
-       if (!request_mem_region(base_addr, SONIC_MEM_SIZE, jazz_sonic_string))
+       if (!request_mem_region(dev->base_addr, SONIC_MEM_SIZE, jazz_sonic_string))
                return -EBUSY;
+
        /*
         * get the Silicon Revision ID. If this is one of the known
         * one assume that we found a SONIC ethernet controller at
@@ -120,11 +123,7 @@ static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr,
        if (sonic_debug  &&  version_printed++ == 0)
                printk(version);
 
-       printk("%s: Sonic ethernet found at 0x%08lx, ", dev->name, base_addr);
-
-       /* Fill in the 'dev' fields. */
-       dev->base_addr = base_addr;
-       dev->irq = irq;
+       printk(KERN_INFO "%s: Sonic ethernet found at 0x%08lx, ", lp->device->bus_id, dev->base_addr);
 
        /*
         * Put the sonic into software reset, then
@@ -138,84 +137,44 @@ static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr,
                dev->dev_addr[i*2+1] = val >> 8;
        }
 
-       printk("HW Address ");
-       for (i = 0; i < 6; i++) {
-               printk("%2.2x", dev->dev_addr[i]);
-               if (i<5)
-                       printk(":");
-       }
-
-       printk(" IRQ %d\n", irq);
-
        err = -ENOMEM;
     
        /* Initialize the device structure. */
-       if (dev->priv == NULL) {
-               /*
-                * the memory be located in the same 64kb segment
-                */
-               lp = NULL;
-               i = 0;
-               do {
-                       lp = kmalloc(sizeof(*lp), GFP_KERNEL);
-                       if ((unsigned long) lp >> 16
-                           != ((unsigned long)lp + sizeof(*lp) ) >> 16) {
-                               /* FIXME, free the memory later */
-                               kfree(lp);
-                               lp = NULL;
-                       }
-               } while (lp == NULL && i++ < 20);
-
-               if (lp == NULL) {
-                       printk("%s: couldn't allocate memory for descriptors\n",
-                              dev->name);
-                       goto out;
-               }
 
-               memset(lp, 0, sizeof(struct sonic_local));
-
-               /* get the virtual dma address */
-               lp->cda_laddr = vdma_alloc(CPHYSADDR(lp),sizeof(*lp));
-               if (lp->cda_laddr == ~0UL) {
-                       printk("%s: couldn't get DMA page entry for "
-                              "descriptors\n", dev->name);
-                       goto out1;
-               }
-
-               lp->tda_laddr = lp->cda_laddr + sizeof (lp->cda);
-               lp->rra_laddr = lp->tda_laddr + sizeof (lp->tda);
-               lp->rda_laddr = lp->rra_laddr + sizeof (lp->rra);
-       
-               /* allocate receive buffer area */
-               /* FIXME, maybe we should use skbs */
-               lp->rba = kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL);
-               if (!lp->rba) {
-                       printk("%s: couldn't allocate receive buffers\n",
-                              dev->name);
-                       goto out2;
-               }
+       lp->dma_bitmode = SONIC_BITMODE32;
 
-               /* get virtual dma address */
-               lp->rba_laddr = vdma_alloc(CPHYSADDR(lp->rba),
-                                          SONIC_NUM_RRS * SONIC_RBSIZE);
-               if (lp->rba_laddr == ~0UL) {
-                       printk("%s: couldn't get DMA page entry for receive "
-                              "buffers\n",dev->name);
-                       goto out3;
-               }
-
-               /* now convert pointer to KSEG1 pointer */
-               lp->rba = (char *)KSEG1ADDR(lp->rba);
-               flush_cache_all();
-               dev->priv = (struct sonic_local *)KSEG1ADDR(lp);
+       /* Allocate the entire chunk of memory for the descriptors.
+           Note that this cannot cross a 64K boundary. */
+       if ((lp->descriptors = dma_alloc_coherent(lp->device,
+                               SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+                               &lp->descriptors_laddr, GFP_KERNEL)) == NULL) {
+               printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id);
+               goto out;
        }
 
-       lp = (struct sonic_local *)dev->priv;
+       /* Now set up the pointers to point to the appropriate places */
+       lp->cda = lp->descriptors;
+       lp->tda = lp->cda + (SIZEOF_SONIC_CDA
+                            * SONIC_BUS_SCALE(lp->dma_bitmode));
+       lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
+                            * SONIC_BUS_SCALE(lp->dma_bitmode));
+       lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
+                            * SONIC_BUS_SCALE(lp->dma_bitmode));
+
+       lp->cda_laddr = lp->descriptors_laddr;
+       lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA
+                            * SONIC_BUS_SCALE(lp->dma_bitmode));
+       lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
+                            * SONIC_BUS_SCALE(lp->dma_bitmode));
+       lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
+                            * SONIC_BUS_SCALE(lp->dma_bitmode));
+
        dev->open = sonic_open;
        dev->stop = sonic_close;
        dev->hard_start_xmit = sonic_send_packet;
-       dev->get_stats  = sonic_get_stats;
+       dev->get_stats = sonic_get_stats;
        dev->set_multicast_list = &sonic_multicast_list;
+       dev->tx_timeout = sonic_tx_timeout;
        dev->watchdog_timeo = TX_TIMEOUT;
 
        /*
@@ -226,14 +185,8 @@ static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr,
        SONIC_WRITE(SONIC_MPT,0xffff);
 
        return 0;
-out3:
-       kfree(lp->rba);
-out2:
-       vdma_free(lp->cda_laddr);
-out1:
-       kfree(lp);
 out:
-       release_region(base_addr, SONIC_MEM_SIZE);
+       release_region(dev->base_addr, SONIC_MEM_SIZE);
        return err;
 }
 
@@ -245,7 +198,6 @@ static int __init jazz_sonic_probe(struct device *device)
 {
        struct net_device *dev;
        struct sonic_local *lp;
-       unsigned long base_addr;
        int err = 0;
        int i;
 
@@ -255,21 +207,26 @@ static int __init jazz_sonic_probe(struct device *device)
        if (mips_machgroup != MACH_GROUP_JAZZ)
                return -ENODEV;
 
-       dev = alloc_etherdev(0);
+       dev = alloc_etherdev(sizeof(struct sonic_local));
        if (!dev)
                return -ENOMEM;
 
+       lp = netdev_priv(dev);
+       lp->device = device;
+       SET_NETDEV_DEV(dev, device);
+       SET_MODULE_OWNER(dev);
+
        netdev_boot_setup_check(dev);
-       base_addr = dev->base_addr;
 
-       if (base_addr >= KSEG0) { /* Check a single specified location. */
-               err = sonic_probe1(dev, base_addr, dev->irq);
-       } else if (base_addr != 0) { /* Don't probe at all. */
+       if (dev->base_addr >= KSEG0) { /* Check a single specified location. */
+               err = sonic_probe1(dev);
+       } else if (dev->base_addr != 0) { /* Don't probe at all. */
                err = -ENXIO;
        } else {
                for (i = 0; sonic_portlist[i].port; i++) {
-                       int io = sonic_portlist[i].port;
-                       if (sonic_probe1(dev, io, sonic_portlist[i].irq) == 0)
+                       dev->base_addr = sonic_portlist[i].port;
+                       dev->irq = sonic_portlist[i].irq;
+                       if (sonic_probe1(dev) == 0)
                                break;
                }
                if (!sonic_portlist[i].port)
@@ -281,14 +238,17 @@ static int __init jazz_sonic_probe(struct device *device)
        if (err)
                goto out1;
 
+       printk("%s: MAC ", dev->name);
+       for (i = 0; i < 6; i++) {
+               printk("%2.2x", dev->dev_addr[i]);
+               if (i < 5)
+                       printk(":");
+       }
+       printk(" IRQ %d\n", dev->irq);
+
        return 0;
 
 out1:
-       lp = dev->priv;
-       vdma_free(lp->rba_laddr);
-       kfree(lp->rba);
-       vdma_free(lp->cda_laddr);
-       kfree(lp);
        release_region(dev->base_addr, SONIC_MEM_SIZE);
 out:
        free_netdev(dev);
@@ -296,21 +256,22 @@ out:
        return err;
 }
 
-/*
- *      SONIC uses a normal IRQ
- */
-#define sonic_request_irq       request_irq
-#define sonic_free_irq          free_irq
+MODULE_DESCRIPTION("Jazz SONIC ethernet driver");
+module_param(sonic_debug, int, 0);
+MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)");
 
-#define sonic_chiptomem(x)      KSEG1ADDR(vdma_log2phys(x))
+#define SONIC_IRQ_FLAG SA_INTERRUPT
 
 #include "sonic.c"
 
 static int __devexit jazz_sonic_device_remove (struct device *device)
 {
        struct net_device *dev = device->driver_data;
+       struct sonic_local* lp = netdev_priv(dev);
 
        unregister_netdev (dev);
+       dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+                         lp->descriptors, lp->descriptors_laddr);
        release_region (dev->base_addr, SONIC_MEM_SIZE);
        free_netdev (dev);
 
@@ -323,7 +284,7 @@ static struct device_driver jazz_sonic_driver = {
        .probe  = jazz_sonic_probe,
        .remove = __devexit_p(jazz_sonic_device_remove),
 };
-                                                                                
+
 static void jazz_sonic_platform_release (struct device *device)
 {
        struct platform_device *pldev;
@@ -336,10 +297,11 @@ static void jazz_sonic_platform_release (struct device *device)
 static int __init jazz_sonic_init_module(void)
 {
        struct platform_device *pldev;
+       int err;
 
-       if (driver_register(&jazz_sonic_driver)) {
+       if ((err = driver_register(&jazz_sonic_driver))) {
                printk(KERN_ERR "Driver registration failed\n");
-               return -ENOMEM;
+               return err;
        }
 
        jazz_sonic_device = NULL;
index b33111e..690a1aa 100644 (file)
@@ -68,6 +68,7 @@ static DEFINE_PER_CPU(struct net_device_stats, loopback_stats);
  * of largesending device modulo TCP checksum, which is ignored for loopback.
  */
 
+#ifdef LOOPBACK_TSO
 static void emulate_large_send_offload(struct sk_buff *skb)
 {
        struct iphdr *iph = skb->nh.iph;
@@ -119,6 +120,7 @@ static void emulate_large_send_offload(struct sk_buff *skb)
 
        dev_kfree_skb(skb);
 }
+#endif /* LOOPBACK_TSO */
 
 /*
  * The higher levels take care of making this non-reentrant (it's
@@ -130,12 +132,13 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
 
        skb_orphan(skb);
 
-       skb->protocol=eth_type_trans(skb,dev);
-       skb->dev=dev;
+       skb->protocol = eth_type_trans(skb,dev);
+       skb->dev = dev;
 #ifndef LOOPBACK_MUST_CHECKSUM
        skb->ip_summed = CHECKSUM_UNNECESSARY;
 #endif
 
+#ifdef LOOPBACK_TSO
        if (skb_shinfo(skb)->tso_size) {
                BUG_ON(skb->protocol != htons(ETH_P_IP));
                BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
@@ -143,14 +146,14 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
                emulate_large_send_offload(skb);
                return 0;
        }
-
+#endif
        dev->last_rx = jiffies;
 
        lb_stats = &per_cpu(loopback_stats, get_cpu());
        lb_stats->rx_bytes += skb->len;
-       lb_stats->tx_bytes += skb->len;
+       lb_stats->tx_bytes = lb_stats->rx_bytes;
        lb_stats->rx_packets++;
-       lb_stats->tx_packets++;
+       lb_stats->tx_packets = lb_stats->rx_packets;
        put_cpu();
 
        netif_rx(skb);
@@ -208,13 +211,16 @@ struct net_device loopback_dev = {
        .type                   = ARPHRD_LOOPBACK,      /* 0x0001*/
        .rebuild_header         = eth_rebuild_header,
        .flags                  = IFF_LOOPBACK,
-       .features               = NETIF_F_SG|NETIF_F_FRAGLIST
-                                 |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA
-                                 |NETIF_F_LLTX,
+       .features               = NETIF_F_SG | NETIF_F_FRAGLIST
+#ifdef LOOPBACK_TSO
+                                 | NETIF_F_TSO
+#endif
+                                 | NETIF_F_NO_CSUM | NETIF_F_HIGHDMA
+                                 | NETIF_F_LLTX,
        .ethtool_ops            = &loopback_ethtool_ops,
 };
 
-/* Setup and register the of the LOOPBACK device. */
+/* Setup and register the loopback device. */
 int __init loopback_init(void)
 {
        struct net_device_stats *stats;
index be28c65..405e183 100644 (file)
@@ -1,6 +1,12 @@
 /*
  * macsonic.c
  *
+ * (C) 2005 Finn Thain
+ *
+ * Converted to DMA API, converted to unified driver model, made it work as
+ * a module again, and from the mac68k project, introduced more 32-bit cards
+ * and dhd's support for 16-bit cards.
+ *
  * (C) 1998 Alan Cox
  *
  * Debugging Andreas Ehliar, Michael Schmitz
@@ -26,8 +32,8 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/types.h>
-#include <linux/ctype.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -41,8 +47,8 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
-#include <linux/module.h>
-#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/bootinfo.h>
 #include <asm/system.h>
 #include <asm/macints.h>
 #include <asm/mac_via.h>
 
-#define SREGS_PAD(n)    u16 n;
+static char mac_sonic_string[] = "macsonic";
+static struct platform_device *mac_sonic_device;
 
 #include "sonic.h"
 
-#define SONIC_READ(reg) \
-       nubus_readl(base_addr+(reg))
-#define SONIC_WRITE(reg,val) \
-       nubus_writel((val), base_addr+(reg))
-#define sonic_read(dev, reg) \
-       nubus_readl((dev)->base_addr+(reg))
-#define sonic_write(dev, reg, val) \
-       nubus_writel((val), (dev)->base_addr+(reg))
-
+/* These should basically be bus-size and endian independent (since
+   the SONIC is at least smart enough that it uses the same endianness
+   as the host, unlike certain less enlightened Macintosh NICs) */
+#define SONIC_READ(reg) (nubus_readw(dev->base_addr + (reg * 4) \
+             + lp->reg_offset))
+#define SONIC_WRITE(reg,val) (nubus_writew(val, dev->base_addr + (reg * 4) \
+             + lp->reg_offset))
+
+/* use 0 for production, 1 for verification, >1 for debug */
+#ifdef SONIC_DEBUG
+static unsigned int sonic_debug = SONIC_DEBUG;
+#else 
+static unsigned int sonic_debug = 1;
+#endif
 
-static int sonic_debug;
 static int sonic_version_printed;
 
-static int reg_offset;
-
 extern int mac_onboard_sonic_probe(struct net_device* dev);
 extern int mac_nubus_sonic_probe(struct net_device* dev);
 
@@ -108,40 +117,6 @@ enum macsonic_type {
 
 #define SONIC_READ_PROM(addr) nubus_readb(prom_addr+addr)
 
-struct net_device * __init macsonic_probe(int unit)
-{
-       struct net_device *dev = alloc_etherdev(0);
-       int err;
-
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       if (unit >= 0)
-               sprintf(dev->name, "eth%d", unit);
-
-       SET_MODULE_OWNER(dev);
-
-       /* This will catch fatal stuff like -ENOMEM as well as success */
-       err = mac_onboard_sonic_probe(dev);
-       if (err == 0)
-               goto found;
-       if (err != -ENODEV)
-               goto out;
-       err = mac_nubus_sonic_probe(dev);
-       if (err)
-               goto out;
-found:
-       err = register_netdev(dev);
-       if (err)
-               goto out1;
-       return dev;
-out1:
-       kfree(dev->priv);
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-
 /*
  * For reversing the PROM address
  */
@@ -160,103 +135,55 @@ static inline void bit_reverse_addr(unsigned char addr[6])
 
 int __init macsonic_init(struct net_device* dev)
 {
-       struct sonic_local* lp = NULL;
-       int i;
+       struct sonic_local* lp = netdev_priv(dev);
 
        /* Allocate the entire chunk of memory for the descriptors.
            Note that this cannot cross a 64K boundary. */
-       for (i = 0; i < 20; i++) {
-               unsigned long desc_base, desc_top;
-               if((lp = kmalloc(sizeof(struct sonic_local), GFP_KERNEL | GFP_DMA)) == NULL) {
-                       printk(KERN_ERR "%s: couldn't allocate descriptor buffers\n", dev->name);
-                       return -ENOMEM;
-               }
-
-               desc_base = (unsigned long) lp;
-               desc_top = desc_base + sizeof(struct sonic_local);
-               if ((desc_top & 0xffff) >= (desc_base & 0xffff))
-                       break;
-               /* Hmm. try again (FIXME: does this actually work?) */
-               kfree(lp);
-               printk(KERN_DEBUG
-                      "%s: didn't get continguous chunk [%08lx - %08lx], trying again\n",
-                      dev->name, desc_base, desc_top);
-       }
-
-       if (lp == NULL) {
-               printk(KERN_ERR "%s: tried 20 times to allocate descriptor buffers, giving up.\n",
-                      dev->name);
+       if ((lp->descriptors = dma_alloc_coherent(lp->device,
+                   SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+                   &lp->descriptors_laddr, GFP_KERNEL)) == NULL) {
+               printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id);
                return -ENOMEM;
-       }                      
-
-       dev->priv = lp;
-
-#if 0
-       /* this code is only here as a curiousity...   mainly, where the 
-          fuck did SONIC_BUS_SCALE come from, and what was it supposed
-          to do?  the normal allocation works great for 32 bit stuffs..  */
+       }
 
        /* Now set up the pointers to point to the appropriate places */
-       lp->cda = lp->sonic_desc;
-       lp->tda = lp->cda + (SIZEOF_SONIC_CDA * SONIC_BUS_SCALE(lp->dma_bitmode));
+       lp->cda = lp->descriptors;
+       lp->tda = lp->cda + (SIZEOF_SONIC_CDA
+                            * SONIC_BUS_SCALE(lp->dma_bitmode));
        lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
-                            * SONIC_BUS_SCALE(lp->dma_bitmode));
+                            * SONIC_BUS_SCALE(lp->dma_bitmode));
        lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
-                            * SONIC_BUS_SCALE(lp->dma_bitmode));
+                            * SONIC_BUS_SCALE(lp->dma_bitmode));
 
-#endif
-       
-       memset(lp, 0, sizeof(struct sonic_local));
-
-       lp->cda_laddr = (unsigned int)&(lp->cda);
-       lp->tda_laddr = (unsigned int)lp->tda;
-       lp->rra_laddr = (unsigned int)lp->rra;
-       lp->rda_laddr = (unsigned int)lp->rda;
-
-       /* FIXME, maybe we should use skbs */
-       if ((lp->rba = (char *)
-            kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL | GFP_DMA)) == NULL) {
-               printk(KERN_ERR "%s: couldn't allocate receive buffers\n", dev->name);
-               dev->priv = NULL;
-               kfree(lp);
-               return -ENOMEM;
-       }
-
-       lp->rba_laddr = (unsigned int)lp->rba;
-
-       {
-               int rs, ds;
-
-               /* almost always 12*4096, but let's not take chances */
-               rs = ((SONIC_NUM_RRS * SONIC_RBSIZE + 4095) / 4096) * 4096;
-               /* almost always under a page, but let's not take chances */
-               ds = ((sizeof(struct sonic_local) + 4095) / 4096) * 4096;
-               kernel_set_cachemode(lp->rba, rs, IOMAP_NOCACHE_SER);
-               kernel_set_cachemode(lp, ds, IOMAP_NOCACHE_SER);
-       }
-       
-#if 0
-       flush_cache_all();
-#endif
+       lp->cda_laddr = lp->descriptors_laddr;
+       lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA
+                            * SONIC_BUS_SCALE(lp->dma_bitmode));
+       lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
+                            * SONIC_BUS_SCALE(lp->dma_bitmode));
+       lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
+                            * SONIC_BUS_SCALE(lp->dma_bitmode));
 
        dev->open = sonic_open;
        dev->stop = sonic_close;
        dev->hard_start_xmit = sonic_send_packet;
        dev->get_stats = sonic_get_stats;
        dev->set_multicast_list = &sonic_multicast_list;
+       dev->tx_timeout = sonic_tx_timeout;
+       dev->watchdog_timeo = TX_TIMEOUT;
 
        /*
         * clear tally counter
         */
-       sonic_write(dev, SONIC_CRCT, 0xffff);
-       sonic_write(dev, SONIC_FAET, 0xffff);
-       sonic_write(dev, SONIC_MPT, 0xffff);
+       SONIC_WRITE(SONIC_CRCT, 0xffff);
+       SONIC_WRITE(SONIC_FAET, 0xffff);
+       SONIC_WRITE(SONIC_MPT, 0xffff);
 
        return 0;
 }
 
 int __init mac_onboard_sonic_ethernet_addr(struct net_device* dev)
 {
+       struct sonic_local *lp = netdev_priv(dev);
        const int prom_addr = ONBOARD_SONIC_PROM_BASE;
        int i;
 
@@ -270,6 +197,7 @@ int __init mac_onboard_sonic_ethernet_addr(struct net_device* dev)
           why this is so. */
        if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
            memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+           memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
            memcmp(dev->dev_addr, "\x00\x05\x02", 3))
                bit_reverse_addr(dev->dev_addr);
        else
@@ -281,22 +209,23 @@ int __init mac_onboard_sonic_ethernet_addr(struct net_device* dev)
            the card... */
        if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
            memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+           memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
            memcmp(dev->dev_addr, "\x00\x05\x02", 3))
        {
                unsigned short val;
 
                printk(KERN_INFO "macsonic: PROM seems to be wrong, trying CAM entry 15\n");
                
-               sonic_write(dev, SONIC_CMD, SONIC_CR_RST);
-               sonic_write(dev, SONIC_CEP, 15);
+               SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
+               SONIC_WRITE(SONIC_CEP, 15);
 
-               val = sonic_read(dev, SONIC_CAP2);
+               val = SONIC_READ(SONIC_CAP2);
                dev->dev_addr[5] = val >> 8;
                dev->dev_addr[4] = val & 0xff;
-               val = sonic_read(dev, SONIC_CAP1);
+               val = SONIC_READ(SONIC_CAP1);
                dev->dev_addr[3] = val >> 8;
                dev->dev_addr[2] = val & 0xff;
-               val = sonic_read(dev, SONIC_CAP0);
+               val = SONIC_READ(SONIC_CAP0);
                dev->dev_addr[1] = val >> 8;
                dev->dev_addr[0] = val & 0xff;
                
@@ -311,6 +240,7 @@ int __init mac_onboard_sonic_ethernet_addr(struct net_device* dev)
 
        if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
            memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+           memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
            memcmp(dev->dev_addr, "\x00\x05\x02", 3))
        {
                /*
@@ -325,8 +255,9 @@ int __init mac_onboard_sonic_probe(struct net_device* dev)
 {
        /* Bwahahaha */
        static int once_is_more_than_enough;
-       int i;
-       int dma_bitmode;
+       struct sonic_local* lp = netdev_priv(dev);
+       int sr;
+       int commslot = 0;
        
        if (once_is_more_than_enough)
                return -ENODEV;
@@ -335,20 +266,18 @@ int __init mac_onboard_sonic_probe(struct net_device* dev)
        if (!MACH_IS_MAC)
                return -ENODEV;
 
-       printk(KERN_INFO "Checking for internal Macintosh ethernet (SONIC).. ");
-
        if (macintosh_config->ether_type != MAC_ETHER_SONIC)
-       {
-               printk("none.\n");
                return -ENODEV;
-       }
-
+       
+       printk(KERN_INFO "Checking for internal Macintosh ethernet (SONIC).. ");
+       
        /* Bogus probing, on the models which may or may not have
           Ethernet (BTW, the Ethernet *is* always at the same
           address, and nothing else lives there, at least if Apple's
           documentation is to be believed) */
        if (macintosh_config->ident == MAC_MODEL_Q630 ||
            macintosh_config->ident == MAC_MODEL_P588 ||
+           macintosh_config->ident == MAC_MODEL_P575 ||
            macintosh_config->ident == MAC_MODEL_C610) {
                unsigned long flags;
                int card_present;
@@ -361,13 +290,13 @@ int __init mac_onboard_sonic_probe(struct net_device* dev)
                        printk("none.\n");
                        return -ENODEV;
                }
+               commslot = 1;
        }
 
        printk("yes\n");        
 
-       /* Danger!  My arms are flailing wildly!  You *must* set this
-           before using sonic_read() */
-
+       /* Danger!  My arms are flailing wildly!  You *must* set lp->reg_offset
+        * and dev->base_addr before using SONIC_READ() or SONIC_WRITE() */
        dev->base_addr = ONBOARD_SONIC_REGISTERS;
        if (via_alt_mapping)
                dev->irq = IRQ_AUTO_3;
@@ -379,84 +308,66 @@ int __init mac_onboard_sonic_probe(struct net_device* dev)
                sonic_version_printed = 1;
        }
        printk(KERN_INFO "%s: onboard / comm-slot SONIC at 0x%08lx\n",
-              dev->name, dev->base_addr);
-
-       /* Now do a song and dance routine in an attempt to determine
-           the bus width */
+              lp->device->bus_id, dev->base_addr);
 
        /* The PowerBook's SONIC is 16 bit always. */
        if (macintosh_config->ident == MAC_MODEL_PB520) {
-               reg_offset = 0;
-               dma_bitmode = 0;
-       } else if (macintosh_config->ident == MAC_MODEL_C610) {
-               reg_offset = 0;
-               dma_bitmode = 1;
-       } else {
+               lp->reg_offset = 0;
+               lp->dma_bitmode = SONIC_BITMODE16;
+               sr = SONIC_READ(SONIC_SR);
+       } else if (commslot) {
                /* Some of the comm-slot cards are 16 bit.  But some
-                   of them are not.  The 32-bit cards use offset 2 and
-                   pad with zeroes or sometimes ones (I think...)
-                   Therefore, if we try offset 0 and get a silicon
-                   revision of 0, we assume 16 bit. */
-               int sr;
-
-               /* Technically this is not necessary since we zeroed
-                   it above */
-               reg_offset = 0;
-               dma_bitmode = 0;
-               sr = sonic_read(dev, SONIC_SR);
-               if (sr == 0 || sr == 0xffff) {
-                       reg_offset = 2;
-                       /* 83932 is 0x0004, 83934 is 0x0100 or 0x0101 */
-                       sr = sonic_read(dev, SONIC_SR);
-                       dma_bitmode = 1;
-                       
+                  of them are not.  The 32-bit cards use offset 2 and
+                  have known revisions, we try reading the revision
+                  register at offset 2, if we don't get a known revision
+                  we assume 16 bit at offset 0.  */
+               lp->reg_offset = 2;
+               lp->dma_bitmode = SONIC_BITMODE16;
+
+               sr = SONIC_READ(SONIC_SR);
+               if (sr == 0x0004 || sr == 0x0006 || sr == 0x0100 || sr == 0x0101) 
+                       /* 83932 is 0x0004 or 0x0006, 83934 is 0x0100 or 0x0101 */
+                       lp->dma_bitmode = SONIC_BITMODE32;
+               else {
+                       lp->dma_bitmode = SONIC_BITMODE16;
+                       lp->reg_offset = 0;
+                       sr = SONIC_READ(SONIC_SR);
                }
-               printk(KERN_INFO
-                      "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
-                      dev->name, sr, dma_bitmode?32:16, reg_offset);
+       } else {
+               /* All onboard cards are at offset 2 with 32 bit DMA. */
+               lp->reg_offset = 2;
+               lp->dma_bitmode = SONIC_BITMODE32;
+               sr = SONIC_READ(SONIC_SR);
        }
-       
+       printk(KERN_INFO
+              "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
+              lp->device->bus_id, sr, lp->dma_bitmode?32:16, lp->reg_offset);
 
-       /* this carries my sincere apologies -- by the time I got to updating
-          the driver, support for "reg_offsets" appeares nowhere in the sonic
-          code, going back for over a year.  Fortunately, my Mac does't seem
-          to use whatever this was.
+#if 0 /* This is sometimes useful to find out how MacOS configured the card. */
+       printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", lp->device->bus_id,
+              SONIC_READ(SONIC_DCR) & 0xffff, SONIC_READ(SONIC_DCR2) & 0xffff);
+#endif
 
-          If you know how this is supposed to be implemented, either fix it,
-          or contact me (sammy@oh.verio.com) to explain what it is. --Sam */
-          
-       if(reg_offset) {
-               printk("%s: register offset unsupported.  please fix this if you know what it is.\n", dev->name);
-               return -ENODEV;
-       }
-       
        /* Software reset, then initialize control registers. */
-       sonic_write(dev, SONIC_CMD, SONIC_CR_RST);
-       sonic_write(dev, SONIC_DCR, SONIC_DCR_BMS |
-                   SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_EXBUS |
-                   (dma_bitmode ? SONIC_DCR_DW : 0));
+       SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
+
+       SONIC_WRITE(SONIC_DCR, SONIC_DCR_EXBUS | SONIC_DCR_BMS |
+                              SONIC_DCR_RFT1  | SONIC_DCR_TFT0 |
+                              (lp->dma_bitmode ? SONIC_DCR_DW : 0));
 
        /* This *must* be written back to in order to restore the
-           extended programmable output bits */
-       sonic_write(dev, SONIC_DCR2, 0);
+        * extended programmable output bits, as it may not have been
+        * initialised since the hardware reset. */
+       SONIC_WRITE(SONIC_DCR2, 0);
 
        /* Clear *and* disable interrupts to be on the safe side */
-       sonic_write(dev, SONIC_ISR,0x7fff);
-       sonic_write(dev, SONIC_IMR,0);
+       SONIC_WRITE(SONIC_IMR, 0);
+       SONIC_WRITE(SONIC_ISR, 0x7fff);
 
        /* Now look for the MAC address. */
        if (mac_onboard_sonic_ethernet_addr(dev) != 0)
                return -ENODEV;
 
-       printk(KERN_INFO "MAC ");
-       for (i = 0; i < 6; i++) {
-               printk("%2.2x", dev->dev_addr[i]);
-               if (i < 5)
-                       printk(":");
-       }
-
-       printk(" IRQ %d\n", dev->irq);
-
        /* Shared init code */
        return macsonic_init(dev);
 }
@@ -468,8 +379,10 @@ int __init mac_nubus_sonic_ethernet_addr(struct net_device* dev,
        int i;
        for(i = 0; i < 6; i++)
                dev->dev_addr[i] = SONIC_READ_PROM(i);
-       /* For now we are going to assume that they're all bit-reversed */
-       bit_reverse_addr(dev->dev_addr);
+
+       /* Some of the addresses are bit-reversed */
+       if (id != MACSONIC_DAYNA)
+               bit_reverse_addr(dev->dev_addr);
 
        return 0;
 }
@@ -487,6 +400,15 @@ int __init macsonic_ident(struct nubus_dev* ndev)
                else
                        return MACSONIC_APPLE;
        }
+       
+       if (ndev->dr_hw == NUBUS_DRHW_SMC9194 &&
+           ndev->dr_sw == NUBUS_DRSW_DAYNA)
+               return MACSONIC_DAYNA;
+       
+       if (ndev->dr_hw == NUBUS_DRHW_SONIC_LC &&
+           ndev->dr_sw == 0) { /* huh? */
+               return MACSONIC_APPLE16;
+       }
        return -1;
 }
 
@@ -494,12 +416,12 @@ int __init mac_nubus_sonic_probe(struct net_device* dev)
 {
        static int slots;
        struct nubus_dev* ndev = NULL;
+       struct sonic_local* lp = netdev_priv(dev);
        unsigned long base_addr, prom_addr;
        u16 sonic_dcr;
-       int id;
-       int i;
-       int dma_bitmode;
-
+       int id = -1;
+       int reg_offset, dma_bitmode;
+       
        /* Find the first SONIC that hasn't been initialized already */
        while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK,
                                       NUBUS_TYPE_ETHERNET, ndev)) != NULL)
@@ -521,51 +443,52 @@ int __init mac_nubus_sonic_probe(struct net_device* dev)
        case MACSONIC_DUODOCK:
                base_addr = ndev->board->slot_addr + DUODOCK_SONIC_REGISTERS;
                prom_addr = ndev->board->slot_addr + DUODOCK_SONIC_PROM_BASE;
-               sonic_dcr = SONIC_DCR_EXBUS | SONIC_DCR_RFT0 | SONIC_DCR_RFT1
-                       | SONIC_DCR_TFT0;
+               sonic_dcr = SONIC_DCR_EXBUS | SONIC_DCR_RFT0 | SONIC_DCR_RFT1 |
+                           SONIC_DCR_TFT0;
                reg_offset = 2;
-               dma_bitmode = 1;
+               dma_bitmode = SONIC_BITMODE32;
                break;
        case MACSONIC_APPLE:
                base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
                prom_addr = ndev->board->slot_addr + APPLE_SONIC_PROM_BASE;
                sonic_dcr = SONIC_DCR_BMS | SONIC_DCR_RFT1 | SONIC_DCR_TFT0;
                reg_offset = 0;
-               dma_bitmode = 1;
+               dma_bitmode = SONIC_BITMODE32;
                break;
        case MACSONIC_APPLE16:
                base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
                prom_addr = ndev->board->slot_addr + APPLE_SONIC_PROM_BASE;
-               sonic_dcr = SONIC_DCR_EXBUS
-                       | SONIC_DCR_RFT1 | SONIC_DCR_TFT0
-                       | SONIC_DCR_PO1 | SONIC_DCR_BMS; 
+               sonic_dcr = SONIC_DCR_EXBUS | SONIC_DCR_RFT1 | SONIC_DCR_TFT0 |
+                           SONIC_DCR_PO1 | SONIC_DCR_BMS; 
                reg_offset = 0;
-               dma_bitmode = 0;
+               dma_bitmode = SONIC_BITMODE16;
                break;
        case MACSONIC_DAYNALINK:
                base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
                prom_addr = ndev->board->slot_addr + DAYNALINK_PROM_BASE;
-               sonic_dcr = SONIC_DCR_RFT1 | SONIC_DCR_TFT0
-                       | SONIC_DCR_PO1 | SONIC_DCR_BMS; 
+               sonic_dcr = SONIC_DCR_RFT1 | SONIC_DCR_TFT0 |
+                           SONIC_DCR_PO1 | SONIC_DCR_BMS; 
                reg_offset = 0;
-               dma_bitmode = 0;
+               dma_bitmode = SONIC_BITMODE16;
                break;
        case MACSONIC_DAYNA:
                base_addr = ndev->board->slot_addr + DAYNA_SONIC_REGISTERS;
                prom_addr = ndev->board->slot_addr + DAYNA_SONIC_MAC_ADDR;
-               sonic_dcr = SONIC_DCR_BMS
-                       | SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_PO1;
+               sonic_dcr = SONIC_DCR_BMS |
+                           SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_PO1;
                reg_offset = 0;
-               dma_bitmode = 0;
+               dma_bitmode = SONIC_BITMODE16;
                break;
        default:
                printk(KERN_ERR "macsonic: WTF, id is %d\n", id);
                return -ENODEV;
        }
 
-       /* Danger!  My arms are flailing wildly!  You *must* set this
-           before using sonic_read() */
+       /* Danger!  My arms are flailing wildly!  You *must* set lp->reg_offset
+        * and dev->base_addr before using SONIC_READ() or SONIC_WRITE() */
        dev->base_addr = base_addr;
+       lp->reg_offset = reg_offset;
+       lp->dma_bitmode = dma_bitmode;
        dev->irq = SLOT2IRQ(ndev->board->slot);
 
        if (!sonic_version_printed) {
@@ -573,29 +496,66 @@ int __init mac_nubus_sonic_probe(struct net_device* dev)
                sonic_version_printed = 1;
        }
        printk(KERN_INFO "%s: %s in slot %X\n",
-              dev->name, ndev->board->name, ndev->board->slot);
+              lp->device->bus_id, ndev->board->name, ndev->board->slot);
        printk(KERN_INFO "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
-              dev->name, sonic_read(dev, SONIC_SR), dma_bitmode?32:16, reg_offset);
+              lp->device->bus_id, SONIC_READ(SONIC_SR), dma_bitmode?32:16, reg_offset);
 
-       if(reg_offset) {
-               printk("%s: register offset unsupported.  please fix this if you know what it is.\n", dev->name);
-               return -ENODEV;
-       }
+#if 0 /* This is sometimes useful to find out how MacOS configured the card. */
+       printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", lp->device->bus_id,
+              SONIC_READ(SONIC_DCR) & 0xffff, SONIC_READ(SONIC_DCR2) & 0xffff);
+#endif
 
        /* Software reset, then initialize control registers. */
-       sonic_write(dev, SONIC_CMD, SONIC_CR_RST);
-       sonic_write(dev, SONIC_DCR, sonic_dcr
-                   | (dma_bitmode ? SONIC_DCR_DW : 0));
+       SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
+       SONIC_WRITE(SONIC_DCR, sonic_dcr | (dma_bitmode ? SONIC_DCR_DW : 0));
+       /* This *must* be written back to in order to restore the
+        * extended programmable output bits, since it may not have been
+        * initialised since the hardware reset. */
+       SONIC_WRITE(SONIC_DCR2, 0);
 
        /* Clear *and* disable interrupts to be on the safe side */
-       sonic_write(dev, SONIC_ISR,0x7fff);
-       sonic_write(dev, SONIC_IMR,0);
+       SONIC_WRITE(SONIC_IMR, 0);
+       SONIC_WRITE(SONIC_ISR, 0x7fff);
 
        /* Now look for the MAC address. */
        if (mac_nubus_sonic_ethernet_addr(dev, prom_addr, id) != 0)
                return -ENODEV;
 
-       printk(KERN_INFO "MAC ");
+       /* Shared init code */
+       return macsonic_init(dev);
+}
+
+static int __init mac_sonic_probe(struct device *device)
+{
+       struct net_device *dev;
+       struct sonic_local *lp;
+       int err;
+       int i;
+
+       dev = alloc_etherdev(sizeof(struct sonic_local));
+       if (!dev)
+               return -ENOMEM;
+
+       lp = netdev_priv(dev);
+       lp->device = device;
+       SET_NETDEV_DEV(dev, device);
+       SET_MODULE_OWNER(dev);
+
+       /* This will catch fatal stuff like -ENOMEM as well as success */
+       err = mac_onboard_sonic_probe(dev);
+       if (err == 0)
+               goto found;
+       if (err != -ENODEV)
+               goto out;
+       err = mac_nubus_sonic_probe(dev);
+       if (err)
+               goto out;
+found:
+       err = register_netdev(dev);
+       if (err)
+               goto out;
+
+       printk("%s: MAC ", dev->name);
        for (i = 0; i < 6; i++) {
                printk("%2.2x", dev->dev_addr[i]);
                if (i < 5)
@@ -603,55 +563,95 @@ int __init mac_nubus_sonic_probe(struct net_device* dev)
        }
        printk(" IRQ %d\n", dev->irq);
 
-       /* Shared init code */
-       return macsonic_init(dev);
-}
+       return 0;
 
-#ifdef MODULE
-static struct net_device *dev_macsonic;
+out:
+       free_netdev(dev);
 
-MODULE_PARM(sonic_debug, "i");
+       return err;
+}
+
+MODULE_DESCRIPTION("Macintosh SONIC ethernet driver");
+module_param(sonic_debug, int, 0);
 MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)");
 
-int
-init_module(void)
+#define SONIC_IRQ_FLAG IRQ_FLG_FAST
+
+#include "sonic.c"
+
+static int __devexit mac_sonic_device_remove (struct device *device)
 {
-        dev_macsonic = macsonic_probe(-1);
-       if (IS_ERR(dev_macsonic)) {
-                printk(KERN_WARNING "macsonic.c: No card found\n");
-               return PTR_ERR(dev_macsonic);
-       }
+       struct net_device *dev = device->driver_data;
+       struct sonic_local* lp = netdev_priv(dev);
+
+       unregister_netdev (dev);
+       dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+                         lp->descriptors, lp->descriptors_laddr);
+       free_netdev (dev);
+
        return 0;
 }
 
-void
-cleanup_module(void)
+static struct device_driver mac_sonic_driver = {
+       .name   = mac_sonic_string,
+       .bus    = &platform_bus_type,
+       .probe  = mac_sonic_probe,
+       .remove = __devexit_p(mac_sonic_device_remove),
+};
+
+static void mac_sonic_platform_release(struct device *device)
 {
-       unregister_netdev(dev_macsonic);
-       kfree(dev_macsonic->priv);
-       free_netdev(dev_macsonic);
+       struct platform_device *pldev;
+
+       /* free device */
+       pldev = to_platform_device (device);
+       kfree (pldev);
 }
-#endif /* MODULE */
 
+static int __init mac_sonic_init_module(void)
+{
+       struct platform_device *pldev;
+       int err;
 
-#define vdma_alloc(foo, bar) ((u32)foo)
-#define vdma_free(baz)
-#define sonic_chiptomem(bat) (bat)
-#define PHYSADDR(quux) (quux)
-#define CPHYSADDR(quux) (quux)
+       if ((err = driver_register(&mac_sonic_driver))) {
+               printk(KERN_ERR "Driver registration failed\n");
+               return err;
+       }
 
-#define sonic_request_irq       request_irq
-#define sonic_free_irq          free_irq
+       mac_sonic_device = NULL;
 
-#include "sonic.c"
+       if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) {
+               goto out_unregister;
+       }
 
-/*
- * Local variables:
- *  compile-command: "m68k-linux-gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h   -c -o macsonic.o macsonic.c"
- *  version-control: t
- *  kept-new-versions: 5
- *  c-indent-level: 8
- *  tab-width: 8
- * End:
- *
- */
+       memset(pldev, 0, sizeof (*pldev));
+       pldev->name             = mac_sonic_string;
+       pldev->id               = 0;
+       pldev->dev.release      = mac_sonic_platform_release;
+       mac_sonic_device        = pldev;
+
+       if (platform_device_register (pldev)) {
+               kfree(pldev);
+               mac_sonic_device = NULL;
+       }
+
+       return 0;
+
+out_unregister:
+       platform_device_unregister(pldev);
+
+       return -ENOMEM;
+}
+
+static void __exit mac_sonic_cleanup_module(void)
+{
+       driver_unregister(&mac_sonic_driver);
+
+       if (mac_sonic_device) {
+               platform_device_unregister(mac_sonic_device);
+               mac_sonic_device = NULL;
+       }
+}
+
+module_init(mac_sonic_init_module);
+module_exit(mac_sonic_cleanup_module);
index 0405e1f..fb6b232 100644 (file)
@@ -1157,16 +1157,20 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (!skb_shinfo(skb)->nr_frags) {
 linear:
                if (skb->ip_summed != CHECKSUM_HW) {
+                       /* Errata BTS #50, IHL must be 5 if no HW checksum */
                        pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
-                                       ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC;
+                                          ETH_TX_FIRST_DESC |
+                                          ETH_TX_LAST_DESC |
+                                          5 << ETH_TX_IHL_SHIFT;
                        pkt_info.l4i_chk = 0;
                } else {
-                       u32 ipheader = skb->nh.iph->ihl << 11;
 
                        pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
-                                       ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC |
-                                       ETH_GEN_TCP_UDP_CHECKSUM |
-                                       ETH_GEN_IP_V_4_CHECKSUM | ipheader;
+                                          ETH_TX_FIRST_DESC |
+                                          ETH_TX_LAST_DESC |
+                                          ETH_GEN_TCP_UDP_CHECKSUM |
+                                          ETH_GEN_IP_V_4_CHECKSUM |
+                                          skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
                        /* CPU already calculated pseudo header checksum. */
                        if (skb->nh.iph->protocol == IPPROTO_UDP) {
                                pkt_info.cmd_sts |= ETH_UDP_FRAME;
@@ -1193,7 +1197,6 @@ linear:
                stats->tx_bytes += pkt_info.byte_cnt;
        } else {
                unsigned int frag;
-               u32 ipheader;
 
                /* Since hardware can't handle unaligned fragments smaller
                 * than 9 bytes, if we find any, we linearize the skb
@@ -1222,12 +1225,16 @@ linear:
                                                        DMA_TO_DEVICE);
                pkt_info.l4i_chk = 0;
                pkt_info.return_info = 0;
-               pkt_info.cmd_sts = ETH_TX_FIRST_DESC;
 
-               if (skb->ip_summed == CHECKSUM_HW) {
-                       ipheader = skb->nh.iph->ihl << 11;
-                       pkt_info.cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM |
-                                       ETH_GEN_IP_V_4_CHECKSUM | ipheader;
+               if (skb->ip_summed != CHECKSUM_HW)
+                       /* Errata BTS #50, IHL must be 5 if no HW checksum */
+                       pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
+                                          5 << ETH_TX_IHL_SHIFT;
+               else {
+                       pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
+                                          ETH_GEN_TCP_UDP_CHECKSUM |
+                                          ETH_GEN_IP_V_4_CHECKSUM |
+                                          skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
                        /* CPU already calculated pseudo header checksum. */
                        if (skb->nh.iph->protocol == IPPROTO_UDP) {
                                pkt_info.cmd_sts |= ETH_UDP_FRAME;
index 57c4f8f..7678b59 100644 (file)
@@ -49,7 +49,7 @@
 /* Checksum offload for Tx works for most packets, but
  * fails if previous packet sent did not use hw csum
  */
-#undef MV643XX_CHECKSUM_OFFLOAD_TX
+#define        MV643XX_CHECKSUM_OFFLOAD_TX
 #define        MV643XX_NAPI
 #define        MV643XX_TX_FAST_REFILL
 #undef MV643XX_RX_QUEUE_FILL_ON_TASK   /* Does not work, yet */
 #define ETH_TX_ENABLE_INTERRUPT                        (BIT23)
 #define ETH_AUTO_MODE                          (BIT30)
 
+#define ETH_TX_IHL_SHIFT                       11
+
 /* typedefs */
 
 typedef enum _eth_func_ret_status {
index 4a391ea..a1ac4bd 100644 (file)
@@ -486,9 +486,9 @@ struct netdrv_private {
 MODULE_AUTHOR ("Jeff Garzik <jgarzik@pobox.com>");
 MODULE_DESCRIPTION ("Skeleton for a PCI Fast Ethernet driver");
 MODULE_LICENSE("GPL");
-MODULE_PARM (multicast_filter_limit, "i");
-MODULE_PARM (max_interrupt_work, "i");
-MODULE_PARM (media, "1-" __MODULE_STRING(8) "i");
+module_param(multicast_filter_limit, int, 0);
+module_param(max_interrupt_work, int, 0);
+module_param_array(media, int, NULL, 0);
 MODULE_PARM_DESC (multicast_filter_limit, "pci-skeleton maximum number of filtered multicast addresses");
 MODULE_PARM_DESC (max_interrupt_work, "pci-skeleton maximum events handled per interrupt");
 MODULE_PARM_DESC (media, "pci-skeleton: Bits 0-3: media type, bit 17: full duplex");
index 9d8197b..384a736 100644 (file)
@@ -134,7 +134,7 @@ typedef struct local_info_t {
     u_char mc_filter[8];
 } local_info_t;
 
-#define MC_FILTERBREAK 64
+#define MC_FILTERBREAK 8
 
 /*====================================================================*/
 /* 
@@ -1012,7 +1012,7 @@ static void fjn_reset(struct net_device *dev)
        outb(BANK_1U, ioaddr + CONFIG_1);
 
     /* set the multicast table to accept none. */
-    for (i = 0; i < 6; i++) 
+    for (i = 0; i < 8; i++) 
         outb(0x00, ioaddr + MAR_ADR + i);
 
     /* Switch to bank 2 (runtime mode) */
@@ -1269,6 +1269,16 @@ static void set_rx_mode(struct net_device *dev)
     u_long flags;
     int i;
     
+    int saved_config_0 = inb(ioaddr + CONFIG_0);
+     
+    local_irq_save(flags); 
+
+    /* Disable Tx and Rx */
+    if (sram_config == 0) 
+       outb(CONFIG0_RST, ioaddr + CONFIG_0);
+    else
+       outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
+
     if (dev->flags & IFF_PROMISC) {
        /* Unconditionally log net taps. */
        printk("%s: Promiscuous mode enabled.\n", dev->name);
@@ -1290,20 +1300,23 @@ static void set_rx_mode(struct net_device *dev)
        for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
             i++, mclist = mclist->next) {
            unsigned int bit =
-               ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f;
-           mc_filter[bit >> 3] |= (1 << bit);
+               ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 26;
+           mc_filter[bit >> 3] |= (1 << (bit & 7));
        }
+       outb(2, ioaddr + RX_MODE);      /* Use normal mode. */
     }
 
-    local_irq_save(flags); 
     if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) {
        int saved_bank = inb(ioaddr + CONFIG_1);
        /* Switch to bank 1 and set the multicast table. */
        outb(0xe4, ioaddr + CONFIG_1);
        for (i = 0; i < 8; i++)
-           outb(mc_filter[i], ioaddr + 8 + i);
+           outb(mc_filter[i], ioaddr + MAR_ADR + i);
        memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter));
        outb(saved_bank, ioaddr + CONFIG_1);
     }
+
+    outb(saved_config_0, ioaddr + CONFIG_0);
+
     local_irq_restore(flags);
 }
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
new file mode 100644 (file)
index 0000000..6a2fe35
--- /dev/null
@@ -0,0 +1,57 @@
+#
+# PHY Layer Configuration
+#
+
+menu "PHY device support"
+
+config PHYLIB
+       tristate "PHY Device support and infrastructure"
+       depends on NET_ETHERNET
+       help
+         Ethernet controllers are usually attached to PHY
+         devices.  This option provides infrastructure for
+         managing PHY devices.
+
+config PHYCONTROL
+       bool "  Support for automatically handling PHY state changes"
+       depends on PHYLIB
+       help
+         Adds code to perform all the work for keeping PHY link
+         state (speed/duplex/etc) up-to-date.  Also handles
+         interrupts.
+
+comment "MII PHY device drivers"
+       depends on PHYLIB
+
+config MARVELL_PHY
+       tristate "Drivers for Marvell PHYs"
+       depends on PHYLIB
+       ---help---
+         Currently has a driver for the 88E1011S
+       
+config DAVICOM_PHY
+       tristate "Drivers for Davicom PHYs"
+       depends on PHYLIB
+       ---help---
+         Currently supports dm9161e and dm9131
+
+config QSEMI_PHY
+       tristate "Drivers for Quality Semiconductor PHYs"
+       depends on PHYLIB
+       ---help---
+         Currently supports the qs6612
+
+config LXT_PHY
+       tristate "Drivers for the Intel LXT PHYs"
+       depends on PHYLIB
+       ---help---
+         Currently supports the lxt970, lxt971
+
+config CICADA_PHY
+       tristate "Drivers for the Cicada PHYs"
+       depends on PHYLIB
+       ---help---
+         Currently supports the cis8204
+
+endmenu
+
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
new file mode 100644 (file)
index 0000000..e4116a5
--- /dev/null
@@ -0,0 +1,10 @@
+# Makefile for Linux PHY drivers
+
+libphy-objs                    := phy.o phy_device.o mdio_bus.o
+
+obj-$(CONFIG_PHYLIB)           += libphy.o
+obj-$(CONFIG_MARVELL_PHY)      += marvell.o
+obj-$(CONFIG_DAVICOM_PHY)      += davicom.o
+obj-$(CONFIG_CICADA_PHY)       += cicada.o
+obj-$(CONFIG_LXT_PHY)          += lxt.o
+obj-$(CONFIG_QSEMI_PHY)                += qsemi.o
diff --git a/drivers/net/phy/cicada.c b/drivers/net/phy/cicada.c
new file mode 100644 (file)
index 0000000..c47fb2e
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * drivers/net/phy/cicada.c
+ *
+ * Driver for Cicada PHYs
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+/* Cicada Extended Control Register 1 */
+#define MII_CIS8201_EXT_CON1           0x17
+#define MII_CIS8201_EXTCON1_INIT       0x0000
+
+/* Cicada Interrupt Mask Register */
+#define MII_CIS8201_IMASK              0x19
+#define MII_CIS8201_IMASK_IEN          0x8000
+#define MII_CIS8201_IMASK_SPEED        0x4000
+#define MII_CIS8201_IMASK_LINK         0x2000
+#define MII_CIS8201_IMASK_DUPLEX       0x1000
+#define MII_CIS8201_IMASK_MASK         0xf000
+
+/* Cicada Interrupt Status Register */
+#define MII_CIS8201_ISTAT              0x1a
+#define MII_CIS8201_ISTAT_STATUS       0x8000
+#define MII_CIS8201_ISTAT_SPEED        0x4000
+#define MII_CIS8201_ISTAT_LINK         0x2000
+#define MII_CIS8201_ISTAT_DUPLEX       0x1000
+
+/* Cicada Auxiliary Control/Status Register */
+#define MII_CIS8201_AUX_CONSTAT        0x1c
+#define MII_CIS8201_AUXCONSTAT_INIT    0x0004
+#define MII_CIS8201_AUXCONSTAT_DUPLEX  0x0020
+#define MII_CIS8201_AUXCONSTAT_SPEED   0x0018
+#define MII_CIS8201_AUXCONSTAT_GBIT    0x0010
+#define MII_CIS8201_AUXCONSTAT_100     0x0008
+
+MODULE_DESCRIPTION("Cicadia PHY driver");
+MODULE_AUTHOR("Andy Fleming");
+MODULE_LICENSE("GPL");
+
+static int cis820x_config_init(struct phy_device *phydev)
+{
+       int err;
+
+       err = phy_write(phydev, MII_CIS8201_AUX_CONSTAT,
+                       MII_CIS8201_AUXCONSTAT_INIT);
+
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, MII_CIS8201_EXT_CON1,
+                       MII_CIS8201_EXTCON1_INIT);
+
+       return err;
+}
+
+static int cis820x_ack_interrupt(struct phy_device *phydev)
+{
+       int err = phy_read(phydev, MII_CIS8201_ISTAT);
+
+       return (err < 0) ? err : 0;
+}
+
+static int cis820x_config_intr(struct phy_device *phydev)
+{
+       int err;
+
+       if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
+               err = phy_write(phydev, MII_CIS8201_IMASK, 
+                               MII_CIS8201_IMASK_MASK);
+       else
+               err = phy_write(phydev, MII_CIS8201_IMASK, 0);
+
+       return err;
+}
+
+/* Cicada 820x */
+static struct phy_driver cis8204_driver = {
+       .phy_id         = 0x000fc440,
+       .name           = "Cicada Cis8204",
+       .phy_id_mask    = 0x000fffc0,
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_init    = &cis820x_config_init,
+       .config_aneg    = &genphy_config_aneg,
+       .read_status    = &genphy_read_status,
+       .ack_interrupt  = &cis820x_ack_interrupt,
+       .config_intr    = &cis820x_config_intr,
+       .driver         = { .owner = THIS_MODULE,},
+};
+
+static int __init cis8204_init(void)
+{
+       return phy_driver_register(&cis8204_driver);
+}
+
+static void __exit cis8204_exit(void)
+{
+       phy_driver_unregister(&cis8204_driver);
+}
+
+module_init(cis8204_init);
+module_exit(cis8204_exit);
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
new file mode 100644 (file)
index 0000000..6caf499
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * drivers/net/phy/davicom.c
+ *
+ * Driver for Davicom PHYs
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#define MII_DM9161_SCR         0x10
+#define MII_DM9161_SCR_INIT    0x0610
+
+/* DM9161 Interrupt Register */
+#define MII_DM9161_INTR        0x15
+#define MII_DM9161_INTR_PEND           0x8000
+#define MII_DM9161_INTR_DPLX_MASK      0x0800
+#define MII_DM9161_INTR_SPD_MASK       0x0400
+#define MII_DM9161_INTR_LINK_MASK      0x0200
+#define MII_DM9161_INTR_MASK           0x0100
+#define MII_DM9161_INTR_DPLX_CHANGE    0x0010
+#define MII_DM9161_INTR_SPD_CHANGE     0x0008
+#define MII_DM9161_INTR_LINK_CHANGE    0x0004
+#define MII_DM9161_INTR_INIT           0x0000
+#define MII_DM9161_INTR_STOP   \
+(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
+ | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
+
+/* DM9161 10BT Configuration/Status */
+#define MII_DM9161_10BTCSR     0x12
+#define MII_DM9161_10BTCSR_INIT        0x7800
+
+MODULE_DESCRIPTION("Davicom PHY driver");
+MODULE_AUTHOR("Andy Fleming");
+MODULE_LICENSE("GPL");
+
+
+#define DM9161_DELAY 1
+static int dm9161_config_intr(struct phy_device *phydev)
+{
+       int temp;
+
+       temp = phy_read(phydev, MII_DM9161_INTR);
+
+       if (temp < 0)
+               return temp;
+
+       if(PHY_INTERRUPT_ENABLED == phydev->interrupts )
+               temp &= ~(MII_DM9161_INTR_STOP);
+       else
+               temp |= MII_DM9161_INTR_STOP;
+
+       temp = phy_write(phydev, MII_DM9161_INTR, temp);
+
+       return temp;
+}
+
+static int dm9161_config_aneg(struct phy_device *phydev)
+{
+       int err;
+
+       /* Isolate the PHY */
+       err = phy_write(phydev, MII_BMCR, BMCR_ISOLATE);
+
+       if (err < 0)
+               return err;
+
+       /* Configure the new settings */
+       err = genphy_config_aneg(phydev);
+
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int dm9161_config_init(struct phy_device *phydev)
+{
+       int err;
+
+       /* Isolate the PHY */
+       err = phy_write(phydev, MII_BMCR, BMCR_ISOLATE);
+
+       if (err < 0)
+               return err;
+
+       /* Do not bypass the scrambler/descrambler */
+       err = phy_write(phydev, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
+
+       if (err < 0)
+               return err;
+
+       /* Clear 10BTCSR to default */
+       err = phy_write(phydev, MII_DM9161_10BTCSR, MII_DM9161_10BTCSR_INIT);
+
+       if (err < 0)
+               return err;
+
+       /* Reconnect the PHY, and enable Autonegotiation */
+       err = phy_write(phydev, MII_BMCR, BMCR_ANENABLE);
+
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int dm9161_ack_interrupt(struct phy_device *phydev)
+{
+       int err = phy_read(phydev, MII_DM9161_INTR);
+
+       return (err < 0) ? err : 0;
+}
+
+static struct phy_driver dm9161_driver = {
+       .phy_id         = 0x0181b880,
+       .name           = "Davicom DM9161E",
+       .phy_id_mask    = 0x0ffffff0,
+       .features       = PHY_BASIC_FEATURES,
+       .config_init    = dm9161_config_init,
+       .config_aneg    = dm9161_config_aneg,
+       .read_status    = genphy_read_status,
+       .driver         = { .owner = THIS_MODULE,},
+};
+
+static struct phy_driver dm9131_driver = {
+       .phy_id         = 0x00181b80,
+       .name           = "Davicom DM9131",
+       .phy_id_mask    = 0x0ffffff0,
+       .features       = PHY_BASIC_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_aneg    = genphy_config_aneg,
+       .read_status    = genphy_read_status,
+       .ack_interrupt  = dm9161_ack_interrupt,
+       .config_intr    = dm9161_config_intr,
+       .driver         = { .owner = THIS_MODULE,},
+};
+
+static int __init davicom_init(void)
+{
+       int ret;
+
+       ret = phy_driver_register(&dm9161_driver);
+       if (ret)
+               goto err1;
+
+       ret = phy_driver_register(&dm9131_driver);
+       if (ret)
+               goto err2;
+       return 0;
+
+ err2: 
+       phy_driver_unregister(&dm9161_driver);
+ err1:
+       return ret;
+}
+
+static void __exit davicom_exit(void)
+{
+       phy_driver_unregister(&dm9161_driver);
+       phy_driver_unregister(&dm9131_driver);
+}
+
+module_init(davicom_init);
+module_exit(davicom_exit);
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
new file mode 100644 (file)
index 0000000..4c84044
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * drivers/net/phy/lxt.c
+ *
+ * Driver for Intel LXT PHYs
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+/* The Level one LXT970 is used by many boards                              */
+
+#define MII_LXT970_IER       17  /* Interrupt Enable Register */
+
+#define MII_LXT970_IER_IEN     0x0002
+
+#define MII_LXT970_ISR       18  /* Interrupt Status Register */
+
+#define MII_LXT970_CONFIG    19  /* Configuration Register    */
+
+/* ------------------------------------------------------------------------- */
+/* The Level one LXT971 is used on some of my custom boards                  */
+
+/* register definitions for the 971 */
+#define MII_LXT971_IER         18  /* Interrupt Enable Register */
+#define MII_LXT971_IER_IEN     0x00f2
+
+#define MII_LXT971_ISR         19  /* Interrupt Status Register */
+
+
+MODULE_DESCRIPTION("Intel LXT PHY driver");
+MODULE_AUTHOR("Andy Fleming");
+MODULE_LICENSE("GPL");
+
+static int lxt970_ack_interrupt(struct phy_device *phydev)
+{
+       int err;
+
+       err = phy_read(phydev, MII_BMSR);
+
+       if (err < 0)
+               return err;
+
+       err = phy_read(phydev, MII_LXT970_ISR);
+
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int lxt970_config_intr(struct phy_device *phydev)
+{
+       int err;
+
+       if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
+               err = phy_write(phydev, MII_LXT970_IER, MII_LXT970_IER_IEN);
+       else
+               err = phy_write(phydev, MII_LXT970_IER, 0);
+
+       return err;
+}
+
+static int lxt970_config_init(struct phy_device *phydev)
+{
+       int err;
+
+       err = phy_write(phydev, MII_LXT970_CONFIG, 0);
+
+       return err;
+}
+
+
+static int lxt971_ack_interrupt(struct phy_device *phydev)
+{
+       int err = phy_read(phydev, MII_LXT971_ISR);
+
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int lxt971_config_intr(struct phy_device *phydev)
+{
+       int err;
+
+       if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
+               err = phy_write(phydev, MII_LXT971_IER, MII_LXT971_IER_IEN);
+       else
+               err = phy_write(phydev, MII_LXT971_IER, 0);
+
+       return err;
+}
+
+static struct phy_driver lxt970_driver = {
+       .phy_id         = 0x07810000,
+       .name           = "LXT970",
+       .phy_id_mask    = 0x0fffffff,
+       .features       = PHY_BASIC_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_init    = lxt970_config_init,
+       .config_aneg    = genphy_config_aneg,
+       .read_status    = genphy_read_status,
+       .ack_interrupt  = lxt970_ack_interrupt,
+       .config_intr    = lxt970_config_intr,
+       .driver         = { .owner = THIS_MODULE,},
+};
+
+static struct phy_driver lxt971_driver = {
+       .phy_id         = 0x0001378e,
+       .name           = "LXT971",
+       .phy_id_mask    = 0x0fffffff,
+       .features       = PHY_BASIC_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_aneg    = genphy_config_aneg,
+       .read_status    = genphy_read_status,
+       .ack_interrupt  = lxt971_ack_interrupt,
+       .config_intr    = lxt971_config_intr,
+       .driver         = { .owner = THIS_MODULE,},
+};
+
+static int __init lxt_init(void)
+{
+       int ret;
+
+       ret = phy_driver_register(&lxt970_driver);
+       if (ret)
+               goto err1;
+
+       ret = phy_driver_register(&lxt971_driver);
+       if (ret)
+               goto err2;
+       return 0;
+
+ err2: 
+       phy_driver_unregister(&lxt970_driver);
+ err1:
+       return ret;
+}
+
+static void __exit lxt_exit(void)
+{
+       phy_driver_unregister(&lxt970_driver);
+       phy_driver_unregister(&lxt971_driver);
+}
+
+module_init(lxt_init);
+module_exit(lxt_exit);
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
new file mode 100644 (file)
index 0000000..4a72b02
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * drivers/net/phy/marvell.c
+ *
+ * Driver for Marvell PHYs
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#define MII_M1011_IEVENT               0x13
+#define MII_M1011_IEVENT_CLEAR         0x0000
+
+#define MII_M1011_IMASK                        0x12
+#define MII_M1011_IMASK_INIT           0x6400
+#define MII_M1011_IMASK_CLEAR          0x0000
+
+MODULE_DESCRIPTION("Marvell PHY driver");
+MODULE_AUTHOR("Andy Fleming");
+MODULE_LICENSE("GPL");
+
+static int marvell_ack_interrupt(struct phy_device *phydev)
+{
+       int err;
+
+       /* Clear the interrupts by reading the reg */
+       err = phy_read(phydev, MII_M1011_IEVENT);
+
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int marvell_config_intr(struct phy_device *phydev)
+{
+       int err;
+
+       if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
+               err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
+       else
+               err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
+
+       return err;
+}
+
+static int marvell_config_aneg(struct phy_device *phydev)
+{
+       int err;
+
+       /* The Marvell PHY has an errata which requires
+        * that certain registers get written in order
+        * to restart autonegotiation */
+       err = phy_write(phydev, MII_BMCR, BMCR_RESET);
+
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, 0x1d, 0x1f);
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, 0x1e, 0x200c);
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, 0x1d, 0x5);
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, 0x1e, 0);
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, 0x1e, 0x100);
+       if (err < 0)
+               return err;
+
+
+       err = genphy_config_aneg(phydev);
+
+       return err;
+}
+
+
+static struct phy_driver m88e1101_driver = {
+       .phy_id         = 0x01410c00,
+       .phy_id_mask    = 0xffffff00,
+       .name           = "Marvell 88E1101",
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_aneg    = &marvell_config_aneg,
+       .read_status    = &genphy_read_status,
+       .ack_interrupt  = &marvell_ack_interrupt,
+       .config_intr    = &marvell_config_intr,
+       .driver         = { .owner = THIS_MODULE,},
+};
+
+static int __init marvell_init(void)
+{
+       return phy_driver_register(&m88e1101_driver);
+}
+
+static void __exit marvell_exit(void)
+{
+       phy_driver_unregister(&m88e1101_driver);
+}
+
+module_init(marvell_init);
+module_exit(marvell_exit);
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
new file mode 100644 (file)
index 0000000..41f62c0
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * drivers/net/phy/mdio_bus.c
+ *
+ * MDIO Bus interface
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+/* mdiobus_register 
+ *
+ * description: Called by a bus driver to bring up all the PHYs
+ *   on a given bus, and attach them to the bus
+ */
+int mdiobus_register(struct mii_bus *bus)
+{
+       int i;
+       int err = 0;
+
+       spin_lock_init(&bus->mdio_lock);
+
+       if (NULL == bus || NULL == bus->name ||
+                       NULL == bus->read ||
+                       NULL == bus->write)
+               return -EINVAL;
+
+       if (bus->reset)
+               bus->reset(bus);
+
+       for (i = 0; i < PHY_MAX_ADDR; i++) {
+               struct phy_device *phydev;
+
+               phydev = get_phy_device(bus, i);
+
+               if (IS_ERR(phydev))
+                       return PTR_ERR(phydev);
+
+               /* There's a PHY at this address
+                * We need to set:
+                * 1) IRQ
+                * 2) bus_id
+                * 3) parent
+                * 4) bus
+                * 5) mii_bus
+                * And, we need to register it */
+               if (phydev) {
+                       phydev->irq = bus->irq[i];
+
+                       phydev->dev.parent = bus->dev;
+                       phydev->dev.bus = &mdio_bus_type;
+                       sprintf(phydev->dev.bus_id, "phy%d:%d", bus->id, i);
+
+                       phydev->bus = bus;
+
+                       err = device_register(&phydev->dev);
+
+                       if (err)
+                               printk(KERN_ERR "phy %d failed to register\n",
+                                               i);
+               }
+
+               bus->phy_map[i] = phydev;
+       }
+
+       pr_info("%s: probed\n", bus->name);
+
+       return err;
+}
+EXPORT_SYMBOL(mdiobus_register);
+
+void mdiobus_unregister(struct mii_bus *bus)
+{
+       int i;
+
+       for (i = 0; i < PHY_MAX_ADDR; i++) {
+               if (bus->phy_map[i]) {
+                       device_unregister(&bus->phy_map[i]->dev);
+                       kfree(bus->phy_map[i]);
+               }
+       }
+}
+EXPORT_SYMBOL(mdiobus_unregister);
+
+/* mdio_bus_match
+ *
+ * description: Given a PHY device, and a PHY driver, return 1 if
+ *   the driver supports the device.  Otherwise, return 0
+ */
+static int mdio_bus_match(struct device *dev, struct device_driver *drv)
+{
+       struct phy_device *phydev = to_phy_device(dev);
+       struct phy_driver *phydrv = to_phy_driver(drv);
+
+       return (phydrv->phy_id == (phydev->phy_id & phydrv->phy_id_mask));
+}
+
+/* Suspend and resume.  Copied from platform_suspend and
+ * platform_resume
+ */
+static int mdio_bus_suspend(struct device * dev, u32 state)
+{
+       int ret = 0;
+       struct device_driver *drv = dev->driver;
+
+       if (drv && drv->suspend) {
+               ret = drv->suspend(dev, state, SUSPEND_DISABLE);
+               if (ret == 0)
+                       ret = drv->suspend(dev, state, SUSPEND_SAVE_STATE);
+               if (ret == 0)
+                       ret = drv->suspend(dev, state, SUSPEND_POWER_DOWN);
+       }
+       return ret;
+}
+
+static int mdio_bus_resume(struct device * dev)
+{
+       int ret = 0;
+       struct device_driver *drv = dev->driver;
+
+       if (drv && drv->resume) {
+               ret = drv->resume(dev, RESUME_POWER_ON);
+               if (ret == 0)
+                       ret = drv->resume(dev, RESUME_RESTORE_STATE);
+               if (ret == 0)
+                       ret = drv->resume(dev, RESUME_ENABLE);
+       }
+       return ret;
+}
+
+struct bus_type mdio_bus_type = {
+       .name           = "mdio_bus",
+       .match          = mdio_bus_match,
+       .suspend        = mdio_bus_suspend,
+       .resume         = mdio_bus_resume,
+};
+
+int __init mdio_bus_init(void)
+{
+       return bus_register(&mdio_bus_type);
+}
+
+void __exit mdio_bus_exit(void)
+{
+       bus_unregister(&mdio_bus_type);
+}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
new file mode 100644 (file)
index 0000000..d9e11f9
--- /dev/null
@@ -0,0 +1,871 @@
+/*
+ * drivers/net/phy/phy.c
+ *
+ * Framework for configuring and reading PHY devices
+ * Based on code in sungem_phy.c and gianfar_phy.c
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+/* Convenience function to print out the current phy status
+ */
+void phy_print_status(struct phy_device *phydev)
+{
+       pr_info("%s: Link is %s", phydev->dev.bus_id,
+                       phydev->link ? "Up" : "Down");
+       if (phydev->link)
+               printk(" - %d/%s", phydev->speed,
+                               DUPLEX_FULL == phydev->duplex ?
+                               "Full" : "Half");
+
+       printk("\n");
+}
+EXPORT_SYMBOL(phy_print_status);
+
+
+/* Convenience functions for reading/writing a given PHY
+ * register. They MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation. */
+int phy_read(struct phy_device *phydev, u16 regnum)
+{
+       int retval;
+       struct mii_bus *bus = phydev->bus;
+
+       spin_lock_bh(&bus->mdio_lock);
+       retval = bus->read(bus, phydev->addr, regnum);
+       spin_unlock_bh(&bus->mdio_lock);
+
+       return retval;
+}
+EXPORT_SYMBOL(phy_read);
+
+int phy_write(struct phy_device *phydev, u16 regnum, u16 val)
+{
+       int err;
+       struct mii_bus *bus = phydev->bus;
+
+       spin_lock_bh(&bus->mdio_lock);
+       err = bus->write(bus, phydev->addr, regnum, val);
+       spin_unlock_bh(&bus->mdio_lock);
+
+       return err;
+}
+EXPORT_SYMBOL(phy_write);
+
+
+int phy_clear_interrupt(struct phy_device *phydev)
+{
+       int err = 0;
+
+       if (phydev->drv->ack_interrupt)
+               err = phydev->drv->ack_interrupt(phydev);
+
+       return err;
+}
+
+
+int phy_config_interrupt(struct phy_device *phydev, u32 interrupts)
+{
+       int err = 0;
+
+       phydev->interrupts = interrupts;
+       if (phydev->drv->config_intr)
+               err = phydev->drv->config_intr(phydev);
+
+       return err;
+}
+
+
+/* phy_aneg_done
+ *
+ * description: Reads the status register and returns 0 either if
+ *   auto-negotiation is incomplete, or if there was an error.
+ *   Returns BMSR_ANEGCOMPLETE if auto-negotiation is done.
+ */
+static inline int phy_aneg_done(struct phy_device *phydev)
+{
+       int retval;
+
+       retval = phy_read(phydev, MII_BMSR);
+
+       return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
+}
+
+/* A structure for mapping a particular speed and duplex
+ * combination to a particular SUPPORTED and ADVERTISED value */
+struct phy_setting {
+       int speed;
+       int duplex;
+       u32 setting;
+};
+
+/* A mapping of all SUPPORTED settings to speed/duplex */
+static struct phy_setting settings[] = {
+       {
+               .speed = 10000,
+               .duplex = DUPLEX_FULL,
+               .setting = SUPPORTED_10000baseT_Full,
+       },
+       {
+               .speed = SPEED_1000,
+               .duplex = DUPLEX_FULL,
+               .setting = SUPPORTED_1000baseT_Full,
+       },
+       {
+               .speed = SPEED_1000,
+               .duplex = DUPLEX_HALF,
+               .setting = SUPPORTED_1000baseT_Half,
+       },
+       {
+               .speed = SPEED_100,
+               .duplex = DUPLEX_FULL,
+               .setting = SUPPORTED_100baseT_Full,
+       },
+       {
+               .speed = SPEED_100,
+               .duplex = DUPLEX_HALF,
+               .setting = SUPPORTED_100baseT_Half,
+       },
+       {
+               .speed = SPEED_10,
+               .duplex = DUPLEX_FULL,
+               .setting = SUPPORTED_10baseT_Full,
+       },
+       {
+               .speed = SPEED_10,
+               .duplex = DUPLEX_HALF,
+               .setting = SUPPORTED_10baseT_Half,
+       },
+};
+
+#define MAX_NUM_SETTINGS (sizeof(settings)/sizeof(struct phy_setting))
+
+/* phy_find_setting
+ *
+ * description: Searches the settings array for the setting which
+ *   matches the desired speed and duplex, and returns the index
+ *   of that setting.  Returns the index of the last setting if
+ *   none of the others match.
+ */
+static inline int phy_find_setting(int speed, int duplex)
+{
+       int idx = 0;
+
+       while (idx < ARRAY_SIZE(settings) &&
+                       (settings[idx].speed != speed ||
+                       settings[idx].duplex != duplex))
+               idx++;
+
+       return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
+}
+
+/* phy_find_valid
+ * idx: The first index in settings[] to search
+ * features: A mask of the valid settings
+ *
+ * description: Returns the index of the first valid setting less
+ *   than or equal to the one pointed to by idx, as determined by
+ *   the mask in features.  Returns the index of the last setting
+ *   if nothing else matches.
+ */
+static inline int phy_find_valid(int idx, u32 features)
+{
+       while (idx < MAX_NUM_SETTINGS && !(settings[idx].setting & features))
+               idx++;
+
+       return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
+}
+
+/* phy_sanitize_settings
+ *
+ * description: Make sure the PHY is set to supported speeds and
+ *   duplexes.  Drop down by one in this order:  1000/FULL,
+ *   1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF
+ */
+void phy_sanitize_settings(struct phy_device *phydev)
+{
+       u32 features = phydev->supported;
+       int idx;
+
+       /* Sanitize settings based on PHY capabilities */
+       if ((features & SUPPORTED_Autoneg) == 0)
+               phydev->autoneg = 0;
+
+       idx = phy_find_valid(phy_find_setting(phydev->speed, phydev->duplex),
+                       features);
+
+       phydev->speed = settings[idx].speed;
+       phydev->duplex = settings[idx].duplex;
+}
+EXPORT_SYMBOL(phy_sanitize_settings);
+
+/* phy_ethtool_sset:
+ * A generic ethtool sset function.  Handles all the details
+ *
+ * A few notes about parameter checking:
+ * - We don't set port or transceiver, so we don't care what they
+ *   were set to.
+ * - phy_start_aneg() will make sure forced settings are sane, and
+ *   choose the next best ones from the ones selected, so we don't
+ *   care if ethtool tries to give us bad values
+ *
+ * A note about the PHYCONTROL Layer.  If you turn off
+ * CONFIG_PHYCONTROL, you will need to read the PHY status
+ * registers after this function completes, and update your
+ * controller manually.
+ */
+int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
+{
+       if (cmd->phy_address != phydev->addr)
+               return -EINVAL;
+
+       /* We make sure that we don't pass unsupported
+        * values in to the PHY */
+       cmd->advertising &= phydev->supported;
+
+       /* Verify the settings we care about. */
+       if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE)
+               return -EINVAL;
+
+       if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0)
+               return -EINVAL;
+
+       if (cmd->autoneg == AUTONEG_DISABLE
+                       && ((cmd->speed != SPEED_1000
+                                       && cmd->speed != SPEED_100
+                                       && cmd->speed != SPEED_10)
+                               || (cmd->duplex != DUPLEX_HALF
+                                       && cmd->duplex != DUPLEX_FULL)))
+               return -EINVAL;
+
+       phydev->autoneg = cmd->autoneg;
+
+       phydev->speed = cmd->speed;
+
+       phydev->advertising = cmd->advertising;
+
+       if (AUTONEG_ENABLE == cmd->autoneg)
+               phydev->advertising |= ADVERTISED_Autoneg;
+       else
+               phydev->advertising &= ~ADVERTISED_Autoneg;
+
+       phydev->duplex = cmd->duplex;
+
+       /* Restart the PHY */
+       phy_start_aneg(phydev);
+
+       return 0;
+}
+
+int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)
+{
+       cmd->supported = phydev->supported;
+
+       cmd->advertising = phydev->advertising;
+
+       cmd->speed = phydev->speed;
+       cmd->duplex = phydev->duplex;
+       cmd->port = PORT_MII;
+       cmd->phy_address = phydev->addr;
+       cmd->transceiver = XCVR_EXTERNAL;
+       cmd->autoneg = phydev->autoneg;
+
+       return 0;
+}
+
+
+/* Note that this function is currently incompatible with the
+ * PHYCONTROL layer.  It changes registers without regard to
+ * current state.  Use at own risk
+ */
+int phy_mii_ioctl(struct phy_device *phydev,
+               struct mii_ioctl_data *mii_data, int cmd)
+{
+       u16 val = mii_data->val_in;
+
+       switch (cmd) {
+       case SIOCGMIIPHY:
+               mii_data->phy_id = phydev->addr;
+               break;
+       case SIOCGMIIREG:
+               mii_data->val_out = phy_read(phydev, mii_data->reg_num);
+               break;
+
+       case SIOCSMIIREG:
+               if (!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+
+               if (mii_data->phy_id == phydev->addr) {
+                       switch(mii_data->reg_num) {
+                       case MII_BMCR:
+                               if (val & (BMCR_RESET|BMCR_ANENABLE))
+                                       phydev->autoneg = AUTONEG_DISABLE;
+                               else
+                                       phydev->autoneg = AUTONEG_ENABLE;
+                               if ((!phydev->autoneg) && (val & BMCR_FULLDPLX))
+                                       phydev->duplex = DUPLEX_FULL;
+                               else
+                                       phydev->duplex = DUPLEX_HALF;
+                               break;
+                       case MII_ADVERTISE:
+                               phydev->advertising = val;
+                               break;
+                       default:
+                               /* do nothing */
+                               break;
+                       }
+               }
+
+               phy_write(phydev, mii_data->reg_num, val);
+               
+               if (mii_data->reg_num == MII_BMCR 
+                               && val & BMCR_RESET
+                               && phydev->drv->config_init)
+                       phydev->drv->config_init(phydev);
+               break;
+       }
+
+       return 0;
+}
+
+/* phy_start_aneg
+ *
+ * description: Sanitizes the settings (if we're not
+ *   autonegotiating them), and then calls the driver's
+ *   config_aneg function.  If the PHYCONTROL Layer is operating,
+ *   we change the state to reflect the beginning of
+ *   Auto-negotiation or forcing.
+ */
+int phy_start_aneg(struct phy_device *phydev)
+{
+       int err;
+
+       spin_lock(&phydev->lock);
+
+       if (AUTONEG_DISABLE == phydev->autoneg)
+               phy_sanitize_settings(phydev);
+
+       err = phydev->drv->config_aneg(phydev);
+
+#ifdef CONFIG_PHYCONTROL
+       if (err < 0)
+               goto out_unlock;
+
+       if (phydev->state != PHY_HALTED) {
+               if (AUTONEG_ENABLE == phydev->autoneg) {
+                       phydev->state = PHY_AN;
+                       phydev->link_timeout = PHY_AN_TIMEOUT;
+               } else {
+                       phydev->state = PHY_FORCING;
+                       phydev->link_timeout = PHY_FORCE_TIMEOUT;
+               }
+       }
+
+out_unlock:
+#endif
+       spin_unlock(&phydev->lock);
+       return err;
+}
+EXPORT_SYMBOL(phy_start_aneg);
+
+
+#ifdef CONFIG_PHYCONTROL
+static void phy_change(void *data);
+static void phy_timer(unsigned long data);
+
+/* phy_start_machine:
+ *
+ * description: The PHY infrastructure can run a state machine
+ *   which tracks whether the PHY is starting up, negotiating,
+ *   etc.  This function starts the timer which tracks the state
+ *   of the PHY.  If you want to be notified when the state
+ *   changes, pass in the callback, otherwise, pass NULL.  If you
+ *   want to maintain your own state machine, do not call this
+ *   function. */
+void phy_start_machine(struct phy_device *phydev,
+               void (*handler)(struct net_device *))
+{
+       phydev->adjust_state = handler;
+
+       init_timer(&phydev->phy_timer);
+       phydev->phy_timer.function = &phy_timer;
+       phydev->phy_timer.data = (unsigned long) phydev;
+       mod_timer(&phydev->phy_timer, jiffies + HZ);
+}
+
+/* phy_stop_machine
+ *
+ * description: Stops the state machine timer, sets the state to
+ *   UP (unless it wasn't up yet), and then frees the interrupt,
+ *   if it is in use. This function must be called BEFORE
+ *   phy_detach.
+ */
+void phy_stop_machine(struct phy_device *phydev)
+{
+       del_timer_sync(&phydev->phy_timer);
+
+       spin_lock(&phydev->lock);
+       if (phydev->state > PHY_UP)
+               phydev->state = PHY_UP;
+       spin_unlock(&phydev->lock);
+
+       if (phydev->irq != PHY_POLL)
+               phy_stop_interrupts(phydev);
+
+       phydev->adjust_state = NULL;
+}
+
+/* phy_force_reduction
+ *
+ * description: Reduces the speed/duplex settings by
+ *   one notch.  The order is so:
+ *   1000/FULL, 1000/HALF, 100/FULL, 100/HALF,
+ *   10/FULL, 10/HALF.  The function bottoms out at 10/HALF.
+ */
+static void phy_force_reduction(struct phy_device *phydev)
+{
+       int idx;
+
+       idx = phy_find_setting(phydev->speed, phydev->duplex);
+       
+       idx++;
+
+       idx = phy_find_valid(idx, phydev->supported);
+
+       phydev->speed = settings[idx].speed;
+       phydev->duplex = settings[idx].duplex;
+
+       pr_info("Trying %d/%s\n", phydev->speed,
+                       DUPLEX_FULL == phydev->duplex ?
+                       "FULL" : "HALF");
+}
+
+
+/* phy_error:
+ *
+ * Moves the PHY to the HALTED state in response to a read
+ * or write error, and tells the controller the link is down.
+ * Must not be called from interrupt context, or while the
+ * phydev->lock is held.
+ */
+void phy_error(struct phy_device *phydev)
+{
+       spin_lock(&phydev->lock);
+       phydev->state = PHY_HALTED;
+       spin_unlock(&phydev->lock);
+}
+
+/* phy_interrupt
+ *
+ * description: When a PHY interrupt occurs, the handler disables
+ * interrupts, and schedules a work task to clear the interrupt.
+ */
+static irqreturn_t phy_interrupt(int irq, void *phy_dat, struct pt_regs *regs)
+{
+       struct phy_device *phydev = phy_dat;
+
+       /* The MDIO bus is not allowed to be written in interrupt
+        * context, so we need to disable the irq here.  A work
+        * queue will write the PHY to disable and clear the
+        * interrupt, and then reenable the irq line. */
+       disable_irq_nosync(irq);
+
+       schedule_work(&phydev->phy_queue);
+
+       return IRQ_HANDLED;
+}
+
+/* Enable the interrupts from the PHY side */
+int phy_enable_interrupts(struct phy_device *phydev)
+{
+       int err;
+
+       err = phy_clear_interrupt(phydev);
+
+       if (err < 0)
+               return err;
+
+       err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
+
+       return err;
+}
+EXPORT_SYMBOL(phy_enable_interrupts);
+
+/* Disable the PHY interrupts from the PHY side */
+int phy_disable_interrupts(struct phy_device *phydev)
+{
+       int err;
+
+       /* Disable PHY interrupts */
+       err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
+
+       if (err)
+               goto phy_err;
+
+       /* Clear the interrupt */
+       err = phy_clear_interrupt(phydev);
+
+       if (err)
+               goto phy_err;
+
+       return 0;
+
+phy_err:
+       phy_error(phydev);
+
+       return err;
+}
+EXPORT_SYMBOL(phy_disable_interrupts);
+
+/* phy_start_interrupts
+ *
+ * description: Request the interrupt for the given PHY.  If
+ *   this fails, then we set irq to PHY_POLL.
+ *   Otherwise, we enable the interrupts in the PHY.
+ *   Returns 0 on success.
+ *   This should only be called with a valid IRQ number.
+ */
+int phy_start_interrupts(struct phy_device *phydev)
+{
+       int err = 0;
+
+       INIT_WORK(&phydev->phy_queue, phy_change, phydev);
+
+       if (request_irq(phydev->irq, phy_interrupt,
+                               SA_SHIRQ,
+                               "phy_interrupt",
+                               phydev) < 0) {
+               printk(KERN_WARNING "%s: Can't get IRQ %d (PHY)\n",
+                               phydev->bus->name,
+                               phydev->irq);
+               phydev->irq = PHY_POLL;
+               return 0;
+       }
+
+       err = phy_enable_interrupts(phydev);
+
+       return err;
+}
+EXPORT_SYMBOL(phy_start_interrupts);
+
+int phy_stop_interrupts(struct phy_device *phydev)
+{
+       int err;
+
+       err = phy_disable_interrupts(phydev);
+
+       if (err)
+               phy_error(phydev);
+
+       free_irq(phydev->irq, phydev);
+
+       return err;
+}
+EXPORT_SYMBOL(phy_stop_interrupts);
+
+
+/* Scheduled by the phy_interrupt/timer to handle PHY changes */
+static void phy_change(void *data)
+{
+       int err;
+       struct phy_device *phydev = data;
+
+       err = phy_disable_interrupts(phydev);
+
+       if (err)
+               goto phy_err;
+
+       spin_lock(&phydev->lock);
+       if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state))
+               phydev->state = PHY_CHANGELINK;
+       spin_unlock(&phydev->lock);
+
+       enable_irq(phydev->irq);
+
+       /* Reenable interrupts */
+       err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
+
+       if (err)
+               goto irq_enable_err;
+
+       return;
+
+irq_enable_err:
+       disable_irq(phydev->irq);
+phy_err:
+       phy_error(phydev);
+}
+
+/* Bring down the PHY link, and stop checking the status. */
+void phy_stop(struct phy_device *phydev)
+{
+       spin_lock(&phydev->lock);
+
+       if (PHY_HALTED == phydev->state)
+               goto out_unlock;
+
+       if (phydev->irq != PHY_POLL) {
+               /* Clear any pending interrupts */
+               phy_clear_interrupt(phydev);
+
+               /* Disable PHY Interrupts */
+               phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
+       }
+
+       phydev->state = PHY_HALTED;
+
+out_unlock:
+       spin_unlock(&phydev->lock);
+}
+
+
+/* phy_start
+ *
+ * description: Indicates the attached device's readiness to
+ *   handle PHY-related work.  Used during startup to start the
+ *   PHY, and after a call to phy_stop() to resume operation.
+ *   Also used to indicate the MDIO bus has cleared an error
+ *   condition.
+ */
+void phy_start(struct phy_device *phydev)
+{
+       spin_lock(&phydev->lock);
+
+       switch (phydev->state) {
+               case PHY_STARTING:
+                       phydev->state = PHY_PENDING;
+                       break;
+               case PHY_READY:
+                       phydev->state = PHY_UP;
+                       break;
+               case PHY_HALTED:
+                       phydev->state = PHY_RESUMING;
+               default:
+                       break;
+       }
+       spin_unlock(&phydev->lock);
+}
+EXPORT_SYMBOL(phy_stop);
+EXPORT_SYMBOL(phy_start);
+
+/* PHY timer which handles the state machine */
+static void phy_timer(unsigned long data)
+{
+       struct phy_device *phydev = (struct phy_device *)data;
+       int needs_aneg = 0;
+       int err = 0;
+
+       spin_lock(&phydev->lock);
+
+       if (phydev->adjust_state)
+               phydev->adjust_state(phydev->attached_dev);
+
+       switch(phydev->state) {
+               case PHY_DOWN:
+               case PHY_STARTING:
+               case PHY_READY:
+               case PHY_PENDING:
+                       break;
+               case PHY_UP:
+                       needs_aneg = 1;
+
+                       phydev->link_timeout = PHY_AN_TIMEOUT;
+
+                       break;
+               case PHY_AN:
+                       /* Check if negotiation is done.  Break
+                        * if there's an error */
+                       err = phy_aneg_done(phydev);
+                       if (err < 0)
+                               break;
+
+                       /* If auto-negotiation is done, we change to
+                        * either RUNNING, or NOLINK */
+                       if (err > 0) {
+                               err = phy_read_status(phydev);
+
+                               if (err)
+                                       break;
+
+                               if (phydev->link) {
+                                       phydev->state = PHY_RUNNING;
+                                       netif_carrier_on(phydev->attached_dev);
+                               } else {
+                                       phydev->state = PHY_NOLINK;
+                                       netif_carrier_off(phydev->attached_dev);
+                               }
+
+                               phydev->adjust_link(phydev->attached_dev);
+
+                       } else if (0 == phydev->link_timeout--) {
+                               /* The counter expired, so either we
+                                * switch to forced mode, or the
+                                * magic_aneg bit exists, and we try aneg
+                                * again */
+                               if (!(phydev->drv->flags & PHY_HAS_MAGICANEG)) {
+                                       int idx;
+
+                                       /* We'll start from the
+                                        * fastest speed, and work
+                                        * our way down */
+                                       idx = phy_find_valid(0,
+                                                       phydev->supported);
+
+                                       phydev->speed = settings[idx].speed;
+                                       phydev->duplex = settings[idx].duplex;
+                                       
+                                       phydev->autoneg = AUTONEG_DISABLE;
+                                       phydev->state = PHY_FORCING;
+                                       phydev->link_timeout =
+                                               PHY_FORCE_TIMEOUT;
+
+                                       pr_info("Trying %d/%s\n",
+                                                       phydev->speed,
+                                                       DUPLEX_FULL ==
+                                                       phydev->duplex ?
+                                                       "FULL" : "HALF");
+                               }
+
+                               needs_aneg = 1;
+                       }
+                       break;
+               case PHY_NOLINK:
+                       err = phy_read_status(phydev);
+
+                       if (err)
+                               break;
+
+                       if (phydev->link) {
+                               phydev->state = PHY_RUNNING;
+                               netif_carrier_on(phydev->attached_dev);
+                               phydev->adjust_link(phydev->attached_dev);
+                       }
+                       break;
+               case PHY_FORCING:
+                       err = phy_read_status(phydev);
+
+                       if (err)
+                               break;
+
+                       if (phydev->link) {
+                               phydev->state = PHY_RUNNING;
+                               netif_carrier_on(phydev->attached_dev);
+                       } else {
+                               if (0 == phydev->link_timeout--) {
+                                       phy_force_reduction(phydev);
+                                       needs_aneg = 1;
+                               }
+                       }
+
+                       phydev->adjust_link(phydev->attached_dev);
+                       break;
+               case PHY_RUNNING:
+                       /* Only register a CHANGE if we are
+                        * polling */
+                       if (PHY_POLL == phydev->irq)
+                               phydev->state = PHY_CHANGELINK;
+                       break;
+               case PHY_CHANGELINK:
+                       err = phy_read_status(phydev);
+
+                       if (err)
+                               break;
+
+                       if (phydev->link) {
+                               phydev->state = PHY_RUNNING;
+                               netif_carrier_on(phydev->attached_dev);
+                       } else {
+                               phydev->state = PHY_NOLINK;
+                               netif_carrier_off(phydev->attached_dev);
+                       }
+
+                       phydev->adjust_link(phydev->attached_dev);
+
+                       if (PHY_POLL != phydev->irq)
+                               err = phy_config_interrupt(phydev,
+                                               PHY_INTERRUPT_ENABLED);
+                       break;
+               case PHY_HALTED:
+                       if (phydev->link) {
+                               phydev->link = 0;
+                               netif_carrier_off(phydev->attached_dev);
+                               phydev->adjust_link(phydev->attached_dev);
+                       }
+                       break;
+               case PHY_RESUMING:
+
+                       err = phy_clear_interrupt(phydev);
+
+                       if (err)
+                               break;
+
+                       err = phy_config_interrupt(phydev,
+                                       PHY_INTERRUPT_ENABLED);
+
+                       if (err)
+                               break;
+
+                       if (AUTONEG_ENABLE == phydev->autoneg) {
+                               err = phy_aneg_done(phydev);
+                               if (err < 0)
+                                       break;
+
+                               /* err > 0 if AN is done.
+                                * Otherwise, it's 0, and we're
+                                * still waiting for AN */
+                               if (err > 0) {
+                                       phydev->state = PHY_RUNNING;
+                               } else {
+                                       phydev->state = PHY_AN;
+                                       phydev->link_timeout = PHY_AN_TIMEOUT;
+                               }
+                       } else
+                               phydev->state = PHY_RUNNING;
+                       break;
+       }
+
+       spin_unlock(&phydev->lock);
+
+       if (needs_aneg)
+               err = phy_start_aneg(phydev);
+
+       if (err < 0)
+               phy_error(phydev);
+
+       mod_timer(&phydev->phy_timer, jiffies + PHY_STATE_TIME * HZ);
+}
+
+#endif /* CONFIG_PHYCONTROL */
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
new file mode 100644 (file)
index 0000000..33f7bdb
--- /dev/null
@@ -0,0 +1,696 @@
+/*
+ * drivers/net/phy/phy_device.c
+ *
+ * Framework for finding and configuring PHYs.
+ * Also contains generic PHY driver
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+static struct phy_driver genphy_driver;
+extern int mdio_bus_init(void);
+extern void mdio_bus_exit(void);
+
+/* get_phy_device
+ *
+ * description: Reads the ID registers of the PHY at addr on the
+ *   bus, then allocates and returns the phy_device to
+ *   represent it.
+ */
+struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
+{
+       int phy_reg;
+       u32 phy_id;
+       struct phy_device *dev = NULL;
+
+       /* Grab the bits from PHYIR1, and put them
+        * in the upper half */
+       phy_reg = bus->read(bus, addr, MII_PHYSID1);
+
+       if (phy_reg < 0)
+               return ERR_PTR(phy_reg);
+
+       phy_id = (phy_reg & 0xffff) << 16;
+
+       /* Grab the bits from PHYIR2, and put them in the lower half */
+       phy_reg = bus->read(bus, addr, MII_PHYSID2);
+
+       if (phy_reg < 0)
+               return ERR_PTR(phy_reg);
+
+       phy_id |= (phy_reg & 0xffff);
+
+       /* If the phy_id is all Fs, there is no device there */
+       if (0xffffffff == phy_id)
+               return NULL;
+
+       /* Otherwise, we allocate the device, and initialize the
+        * default values */
+       dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
+
+       if (NULL == dev)
+               return ERR_PTR(-ENOMEM);
+
+       dev->speed = 0;
+       dev->duplex = -1;
+       dev->pause = dev->asym_pause = 0;
+       dev->link = 1;
+
+       dev->autoneg = AUTONEG_ENABLE;
+
+       dev->addr = addr;
+       dev->phy_id = phy_id;
+       dev->bus = bus;
+
+       dev->state = PHY_DOWN;
+
+       spin_lock_init(&dev->lock);
+
+       return dev;
+}
+
+#ifdef CONFIG_PHYCONTROL
+/* phy_prepare_link:
+ *
+ * description: Tells the PHY infrastructure to handle the
+ *   gory details on monitoring link status (whether through
+ *   polling or an interrupt), and to call back to the
+ *   connected device driver when the link status changes.
+ *   If you want to monitor your own link state, don't call
+ *   this function */
+void phy_prepare_link(struct phy_device *phydev,
+               void (*handler)(struct net_device *))
+{
+       phydev->adjust_link = handler;
+}
+
+/* phy_connect:
+ *
+ * description: Convenience function for connecting ethernet
+ *   devices to PHY devices.  The default behavior is for
+ *   the PHY infrastructure to handle everything, and only notify
+ *   the connected driver when the link status changes.  If you
+ *   don't want, or can't use the provided functionality, you may
+ *   choose to call only the subset of functions which provide
+ *   the desired functionality.
+ */
+struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
+               void (*handler)(struct net_device *), u32 flags)
+{
+       struct phy_device *phydev;
+
+       phydev = phy_attach(dev, phy_id, flags);
+
+       if (IS_ERR(phydev))
+               return phydev;
+
+       phy_prepare_link(phydev, handler);
+
+       phy_start_machine(phydev, NULL);
+
+       if (phydev->irq > 0)
+               phy_start_interrupts(phydev);
+
+       return phydev;
+}
+EXPORT_SYMBOL(phy_connect);
+
+void phy_disconnect(struct phy_device *phydev)
+{
+       if (phydev->irq > 0)
+               phy_stop_interrupts(phydev);
+
+       phy_stop_machine(phydev);
+       
+       phydev->adjust_link = NULL;
+
+       phy_detach(phydev);
+}
+EXPORT_SYMBOL(phy_disconnect);
+
+#endif /* CONFIG_PHYCONTROL */
+
+/* phy_attach:
+ *
+ *   description: Called by drivers to attach to a particular PHY
+ *     device. The phy_device is found, and properly hooked up
+ *     to the phy_driver.  If no driver is attached, then the
+ *     genphy_driver is used.  The phy_device is given a ptr to
+ *     the attaching device, and given a callback for link status
+ *     change.  The phy_device is returned to the attaching
+ *     driver.
+ */
+static int phy_compare_id(struct device *dev, void *data)
+{
+       return strcmp((char *)data, dev->bus_id) ? 0 : 1;
+}
+
+struct phy_device *phy_attach(struct net_device *dev,
+               const char *phy_id, u32 flags)
+{
+       struct bus_type *bus = &mdio_bus_type;
+       struct phy_device *phydev;
+       struct device *d;
+
+       /* Search the list of PHY devices on the mdio bus for the
+        * PHY with the requested name */
+       d = bus_find_device(bus, NULL, (void *)phy_id, phy_compare_id);
+
+       if (d) {
+               phydev = to_phy_device(d);
+       } else {
+               printk(KERN_ERR "%s not found\n", phy_id);
+               return ERR_PTR(-ENODEV);
+       }
+
+       /* Assume that if there is no driver, that it doesn't
+        * exist, and we should use the genphy driver. */
+       if (NULL == d->driver) {
+               int err;
+               down_write(&d->bus->subsys.rwsem);
+               d->driver = &genphy_driver.driver;
+
+               err = d->driver->probe(d);
+
+               if (err < 0)
+                       return ERR_PTR(err);
+
+               device_bind_driver(d);
+               up_write(&d->bus->subsys.rwsem);
+       }
+
+       if (phydev->attached_dev) {
+               printk(KERN_ERR "%s: %s already attached\n",
+                               dev->name, phy_id);
+               return ERR_PTR(-EBUSY);
+       }
+
+       phydev->attached_dev = dev;
+
+       phydev->dev_flags = flags;
+
+       return phydev;
+}
+EXPORT_SYMBOL(phy_attach);
+
+void phy_detach(struct phy_device *phydev)
+{
+       phydev->attached_dev = NULL;
+
+       /* If the device had no specific driver before (i.e. - it
+        * was using the generic driver), we unbind the device
+        * from the generic driver so that there's a chance a
+        * real driver could be loaded */
+       if (phydev->dev.driver == &genphy_driver.driver) {
+               down_write(&phydev->dev.bus->subsys.rwsem);
+               device_release_driver(&phydev->dev);
+               up_write(&phydev->dev.bus->subsys.rwsem);
+       }
+}
+EXPORT_SYMBOL(phy_detach);
+
+
+/* Generic PHY support and helper functions */
+
+/* genphy_config_advert
+ *
+ * description: Writes MII_ADVERTISE with the appropriate values,
+ *   after sanitizing the values to make sure we only advertise
+ *   what is supported
+ */
+int genphy_config_advert(struct phy_device *phydev)
+{
+       u32 advertise;
+       int adv;
+       int err;
+
+       /* Only allow advertising what
+        * this PHY supports */
+       phydev->advertising &= phydev->supported;
+       advertise = phydev->advertising;
+
+       /* Setup standard advertisement */
+       adv = phy_read(phydev, MII_ADVERTISE);
+
+       if (adv < 0)
+               return adv;
+
+       adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | 
+                ADVERTISE_PAUSE_ASYM);
+       if (advertise & ADVERTISED_10baseT_Half)
+               adv |= ADVERTISE_10HALF;
+       if (advertise & ADVERTISED_10baseT_Full)
+               adv |= ADVERTISE_10FULL;
+       if (advertise & ADVERTISED_100baseT_Half)
+               adv |= ADVERTISE_100HALF;
+       if (advertise & ADVERTISED_100baseT_Full)
+               adv |= ADVERTISE_100FULL;
+       if (advertise & ADVERTISED_Pause)
+               adv |= ADVERTISE_PAUSE_CAP;
+       if (advertise & ADVERTISED_Asym_Pause)
+               adv |= ADVERTISE_PAUSE_ASYM;
+
+       err = phy_write(phydev, MII_ADVERTISE, adv);
+
+       if (err < 0)
+               return err;
+
+       /* Configure gigabit if it's supported */
+       if (phydev->supported & (SUPPORTED_1000baseT_Half |
+                               SUPPORTED_1000baseT_Full)) {
+               adv = phy_read(phydev, MII_CTRL1000);
+
+               if (adv < 0)
+                       return adv;
+
+               adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+               if (advertise & SUPPORTED_1000baseT_Half)
+                       adv |= ADVERTISE_1000HALF;
+               if (advertise & SUPPORTED_1000baseT_Full)
+                       adv |= ADVERTISE_1000FULL;
+               err = phy_write(phydev, MII_CTRL1000, adv);
+
+               if (err < 0)
+                       return err;
+       }
+
+       return adv;
+}
+EXPORT_SYMBOL(genphy_config_advert);
+
+/* genphy_setup_forced
+ *
+ * description: Configures MII_BMCR to force speed/duplex
+ *   to the values in phydev. Assumes that the values are valid.
+ *   Please see phy_sanitize_settings() */
+int genphy_setup_forced(struct phy_device *phydev)
+{
+       int ctl = BMCR_RESET;
+
+       phydev->pause = phydev->asym_pause = 0;
+
+       if (SPEED_1000 == phydev->speed)
+               ctl |= BMCR_SPEED1000;
+       else if (SPEED_100 == phydev->speed)
+               ctl |= BMCR_SPEED100;
+
+       if (DUPLEX_FULL == phydev->duplex)
+               ctl |= BMCR_FULLDPLX;
+       
+       ctl = phy_write(phydev, MII_BMCR, ctl);
+
+       if (ctl < 0)
+               return ctl;
+
+       /* We just reset the device, so we'd better configure any
+        * settings the PHY requires to operate */
+       if (phydev->drv->config_init)
+               ctl = phydev->drv->config_init(phydev);
+
+       return ctl;
+}
+
+
+/* Enable and Restart Autonegotiation */
+int genphy_restart_aneg(struct phy_device *phydev)
+{
+       int ctl;
+
+       ctl = phy_read(phydev, MII_BMCR);
+
+       if (ctl < 0)
+               return ctl;
+
+       ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+
+       /* Don't isolate the PHY if we're negotiating */
+       ctl &= ~(BMCR_ISOLATE);
+
+       ctl = phy_write(phydev, MII_BMCR, ctl);
+
+       return ctl;
+}
+
+
+/* genphy_config_aneg
+ *
+ * description: If auto-negotiation is enabled, we configure the
+ *   advertising, and then restart auto-negotiation.  If it is not
+ *   enabled, then we write the BMCR
+ */
+int genphy_config_aneg(struct phy_device *phydev)
+{
+       int err = 0;
+
+       if (AUTONEG_ENABLE == phydev->autoneg) {
+               err = genphy_config_advert(phydev);
+
+               if (err < 0)
+                       return err;
+
+               err = genphy_restart_aneg(phydev);
+       } else
+               err = genphy_setup_forced(phydev);
+
+       return err;
+}
+EXPORT_SYMBOL(genphy_config_aneg);
+
+/* genphy_update_link
+ *
+ * description: Update the value in phydev->link to reflect the
+ *   current link value.  In order to do this, we need to read
+ *   the status register twice, keeping the second value
+ */
+int genphy_update_link(struct phy_device *phydev)
+{
+       int status;
+
+       /* Do a fake read */
+       status = phy_read(phydev, MII_BMSR);
+
+       if (status < 0)
+               return status;
+
+       /* Read link and autonegotiation status */
+       status = phy_read(phydev, MII_BMSR);
+
+       if (status < 0)
+               return status;
+
+       if ((status & BMSR_LSTATUS) == 0)
+               phydev->link = 0;
+       else
+               phydev->link = 1;
+
+       return 0;
+}
+
+/* genphy_read_status
+ *
+ * description: Check the link, then figure out the current state
+ *   by comparing what we advertise with what the link partner
+ *   advertises.  Start by checking the gigabit possibilities,
+ *   then move on to 10/100.
+ */
+int genphy_read_status(struct phy_device *phydev)
+{
+       int adv;
+       int err;
+       int lpa;
+       int lpagb = 0;
+
+       /* Update the link, but return if there
+        * was an error */
+       err = genphy_update_link(phydev);
+       if (err)
+               return err;
+
+       if (AUTONEG_ENABLE == phydev->autoneg) {
+               if (phydev->supported & (SUPPORTED_1000baseT_Half
+                                       | SUPPORTED_1000baseT_Full)) {
+                       lpagb = phy_read(phydev, MII_STAT1000);
+
+                       if (lpagb < 0)
+                               return lpagb;
+
+                       adv = phy_read(phydev, MII_CTRL1000);
+
+                       if (adv < 0)
+                               return adv;
+
+                       lpagb &= adv << 2;
+               }
+
+               lpa = phy_read(phydev, MII_LPA);
+
+               if (lpa < 0)
+                       return lpa;
+
+               adv = phy_read(phydev, MII_ADVERTISE);
+
+               if (adv < 0)
+                       return adv;
+
+               lpa &= adv;
+
+               phydev->speed = SPEED_10;
+               phydev->duplex = DUPLEX_HALF;
+               phydev->pause = phydev->asym_pause = 0;
+
+               if (lpagb & (LPA_1000FULL | LPA_1000HALF)) {
+                       phydev->speed = SPEED_1000;
+
+                       if (lpagb & LPA_1000FULL)
+                               phydev->duplex = DUPLEX_FULL;
+               } else if (lpa & (LPA_100FULL | LPA_100HALF)) {
+                       phydev->speed = SPEED_100;
+                       
+                       if (lpa & LPA_100FULL)
+                               phydev->duplex = DUPLEX_FULL;
+               } else
+                       if (lpa & LPA_10FULL)
+                               phydev->duplex = DUPLEX_FULL;
+
+               if (phydev->duplex == DUPLEX_FULL){
+                       phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
+                       phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
+               }
+       } else {
+               int bmcr = phy_read(phydev, MII_BMCR);
+               if (bmcr < 0)
+                       return bmcr;
+
+               if (bmcr & BMCR_FULLDPLX)
+                       phydev->duplex = DUPLEX_FULL;
+               else
+                       phydev->duplex = DUPLEX_HALF;
+
+               if (bmcr & BMCR_SPEED1000)
+                       phydev->speed = SPEED_1000;
+               else if (bmcr & BMCR_SPEED100)
+                       phydev->speed = SPEED_100;
+               else
+                       phydev->speed = SPEED_10;
+
+               phydev->pause = phydev->asym_pause = 0;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(genphy_read_status);
+
+static int genphy_config_init(struct phy_device *phydev)
+{
+       u32 val;
+       u32 features;
+
+       /* For now, I'll claim that the generic driver supports
+        * all possible port types */
+       features = (SUPPORTED_TP | SUPPORTED_MII
+                       | SUPPORTED_AUI | SUPPORTED_FIBRE |
+                       SUPPORTED_BNC);
+
+       /* Do we support autonegotiation? */
+       val = phy_read(phydev, MII_BMSR);
+
+       if (val < 0)
+               return val;
+
+       if (val & BMSR_ANEGCAPABLE)
+               features |= SUPPORTED_Autoneg;
+
+       if (val & BMSR_100FULL)
+               features |= SUPPORTED_100baseT_Full;
+       if (val & BMSR_100HALF)
+               features |= SUPPORTED_100baseT_Half;
+       if (val & BMSR_10FULL)
+               features |= SUPPORTED_10baseT_Full;
+       if (val & BMSR_10HALF)
+               features |= SUPPORTED_10baseT_Half;
+
+       if (val & BMSR_ESTATEN) {
+               val = phy_read(phydev, MII_ESTATUS);
+
+               if (val < 0)
+                       return val;
+
+               if (val & ESTATUS_1000_TFULL)
+                       features |= SUPPORTED_1000baseT_Full;
+               if (val & ESTATUS_1000_THALF)
+                       features |= SUPPORTED_1000baseT_Half;
+       }
+
+       phydev->supported = features;
+       phydev->advertising = features;
+
+       return 0;
+}
+
+
+/* phy_probe
+ *
+ * description: Take care of setting up the phy_device structure,
+ *   set the state to READY (the driver's init function should
+ *   set it to STARTING if needed).
+ */
+static int phy_probe(struct device *dev)
+{
+       struct phy_device *phydev;
+       struct phy_driver *phydrv;
+       struct device_driver *drv;
+       int err = 0;
+
+       phydev = to_phy_device(dev);
+
+       /* Make sure the driver is held.
+        * XXX -- Is this correct? */
+       drv = get_driver(phydev->dev.driver);
+       phydrv = to_phy_driver(drv);
+       phydev->drv = phydrv;
+
+       /* Disable the interrupt if the PHY doesn't support it */
+       if (!(phydrv->flags & PHY_HAS_INTERRUPT))
+               phydev->irq = PHY_POLL;
+
+       spin_lock(&phydev->lock);
+
+       /* Start out supporting everything. Eventually,
+        * a controller will attach, and may modify one
+        * or both of these values */
+       phydev->supported = phydrv->features;
+       phydev->advertising = phydrv->features;
+
+       /* Set the state to READY by default */
+       phydev->state = PHY_READY;
+
+       if (phydev->drv->probe)
+               err = phydev->drv->probe(phydev);
+
+       spin_unlock(&phydev->lock);
+
+       if (err < 0)
+               return err;
+
+       if (phydev->drv->config_init)
+               err = phydev->drv->config_init(phydev);
+
+       return err;
+}
+
+static int phy_remove(struct device *dev)
+{
+       struct phy_device *phydev;
+
+       phydev = to_phy_device(dev);
+
+       spin_lock(&phydev->lock);
+       phydev->state = PHY_DOWN;
+       spin_unlock(&phydev->lock);
+
+       if (phydev->drv->remove)
+               phydev->drv->remove(phydev);
+
+       put_driver(dev->driver);
+       phydev->drv = NULL;
+
+       return 0;
+}
+
+int phy_driver_register(struct phy_driver *new_driver)
+{
+       int retval;
+
+       memset(&new_driver->driver, 0, sizeof(new_driver->driver));
+       new_driver->driver.name = new_driver->name;
+       new_driver->driver.bus = &mdio_bus_type;
+       new_driver->driver.probe = phy_probe;
+       new_driver->driver.remove = phy_remove;
+
+       retval = driver_register(&new_driver->driver);
+
+       if (retval) {
+               printk(KERN_ERR "%s: Error %d in registering driver\n",
+                               new_driver->name, retval);
+
+               return retval;
+       }
+
+       pr_info("%s: Registered new driver\n", new_driver->name);
+
+       return 0;
+}
+EXPORT_SYMBOL(phy_driver_register);
+
+void phy_driver_unregister(struct phy_driver *drv)
+{
+       driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL(phy_driver_unregister);
+
+static struct phy_driver genphy_driver = {
+       .phy_id         = 0xffffffff,
+       .phy_id_mask    = 0xffffffff,
+       .name           = "Generic PHY",
+       .config_init    = genphy_config_init,
+       .features       = 0,
+       .config_aneg    = genphy_config_aneg,
+       .read_status    = genphy_read_status,
+       .driver         = {.owner= THIS_MODULE, },
+};
+
+static int __init phy_init(void)
+{
+       int rc;
+
+       rc = mdio_bus_init();
+       if (rc)
+               return rc;
+
+       rc = phy_driver_register(&genphy_driver);
+       if (rc)
+               mdio_bus_exit();
+
+       return rc;
+}
+
+static void __exit phy_exit(void)
+{
+       phy_driver_unregister(&genphy_driver);
+       mdio_bus_exit();
+}
+
+subsys_initcall(phy_init);
+module_exit(phy_exit);
diff --git a/drivers/net/phy/qsemi.c b/drivers/net/phy/qsemi.c
new file mode 100644 (file)
index 0000000..d461ba4
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * drivers/net/phy/qsemi.c
+ *
+ * Driver for Quality Semiconductor PHYs
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+/* ------------------------------------------------------------------------- */
+/* The Quality Semiconductor QS6612 is used on the RPX CLLF                  */
+
+/* register definitions */
+
+#define MII_QS6612_MCR         17  /* Mode Control Register      */
+#define MII_QS6612_FTR         27  /* Factory Test Register      */
+#define MII_QS6612_MCO         28  /* Misc. Control Register     */
+#define MII_QS6612_ISR         29  /* Interrupt Source Register  */
+#define MII_QS6612_IMR         30  /* Interrupt Mask Register    */
+#define MII_QS6612_IMR_INIT    0x003a
+#define MII_QS6612_PCR         31  /* 100BaseTx PHY Control Reg. */
+
+#define QS6612_PCR_AN_COMPLETE 0x1000
+#define QS6612_PCR_RLBEN       0x0200
+#define QS6612_PCR_DCREN       0x0100
+#define QS6612_PCR_4B5BEN      0x0040
+#define QS6612_PCR_TX_ISOLATE  0x0020
+#define QS6612_PCR_MLT3_DIS    0x0002
+#define QS6612_PCR_SCRM_DESCRM 0x0001
+
+MODULE_DESCRIPTION("Quality Semiconductor PHY driver");
+MODULE_AUTHOR("Andy Fleming");
+MODULE_LICENSE("GPL");
+
+/* Returns 0, unless there's a write error */
+static int qs6612_config_init(struct phy_device *phydev)
+{
+       /* The PHY powers up isolated on the RPX,
+        * so send a command to allow operation.
+        * XXX - My docs indicate this should be 0x0940
+        * ...or something.  The current value sets three
+        * reserved bits, bit 11, which specifies it should be
+        * set to one, bit 10, which specifies it should be set
+        * to 0, and bit 7, which doesn't specify.  However, my
+        * docs are preliminary, and I will leave it like this
+        * until someone more knowledgable corrects me or it.
+        * -- Andy Fleming
+        */
+       return phy_write(phydev, MII_QS6612_PCR, 0x0dc0);
+}
+
+static int qs6612_ack_interrupt(struct phy_device *phydev)
+{
+       int err;
+
+       err = phy_read(phydev, MII_QS6612_ISR);
+
+       if (err < 0)
+               return err;
+
+       err = phy_read(phydev, MII_BMSR);
+
+       if (err < 0)
+               return err;
+
+       err = phy_read(phydev, MII_EXPANSION);
+
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int qs6612_config_intr(struct phy_device *phydev)
+{
+       int err;
+       if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+               err = phy_write(phydev, MII_QS6612_IMR,
+                               MII_QS6612_IMR_INIT);
+       else
+               err = phy_write(phydev, MII_QS6612_IMR, 0);
+
+       return err;
+
+}
+
+static struct phy_driver qs6612_driver = {
+       .phy_id         = 0x00181440,
+       .name           = "QS6612",
+       .phy_id_mask    = 0xfffffff0,
+       .features       = PHY_BASIC_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_init    = qs6612_config_init,
+       .config_aneg    = genphy_config_aneg,
+       .read_status    = genphy_read_status,
+       .ack_interrupt  = qs6612_ack_interrupt,
+       .config_intr    = qs6612_config_intr,
+       .driver         = { .owner = THIS_MODULE,},
+};
+
+static int __init qs6612_init(void)
+{
+       return phy_driver_register(&qs6612_driver);
+}
+
+static void __exit qs6612_exit(void)
+{
+       phy_driver_unregister(&qs6612_driver);
+}
+
+module_init(qs6612_init);
+module_exit(qs6612_exit);
index d5afe05..f0471d1 100644 (file)
@@ -187,6 +187,7 @@ static struct pci_device_id rtl8169_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8169), },
        { PCI_DEVICE(PCI_VENDOR_ID_DLINK,       0x4300), },
        { PCI_DEVICE(0x16ec,                    0x0116), },
+       { PCI_VENDOR_ID_LINKSYS,                0x1032, PCI_ANY_ID, 0x0024, },
        {0,},
 };
 
index 7092ca6..2234a8f 100644 (file)
@@ -62,6 +62,7 @@ typedef struct _XENA_dev_config {
 #define ADAPTER_STATUS_RMAC_REMOTE_FAULT   BIT(6)
 #define ADAPTER_STATUS_RMAC_LOCAL_FAULT    BIT(7)
 #define ADAPTER_STATUS_RMAC_PCC_IDLE       vBIT(0xFF,8,8)
+#define ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE  vBIT(0x0F,8,8)
 #define ADAPTER_STATUS_RC_PRC_QUIESCENT    vBIT(0xFF,16,8)
 #define ADAPTER_STATUS_MC_DRAM_READY       BIT(24)
 #define ADAPTER_STATUS_MC_QUEUES_READY     BIT(25)
@@ -77,21 +78,34 @@ typedef struct _XENA_dev_config {
 #define ADAPTER_ECC_EN                     BIT(55)
 
        u64 serr_source;
-#define SERR_SOURCE_PIC                                        BIT(0)
-#define SERR_SOURCE_TXDMA                              BIT(1)
-#define SERR_SOURCE_RXDMA                              BIT(2)
+#define SERR_SOURCE_PIC                        BIT(0)
+#define SERR_SOURCE_TXDMA              BIT(1)
+#define SERR_SOURCE_RXDMA              BIT(2)
 #define SERR_SOURCE_MAC                 BIT(3)
 #define SERR_SOURCE_MC                  BIT(4)
 #define SERR_SOURCE_XGXS                BIT(5)
-#define        SERR_SOURCE_ANY                                 (SERR_SOURCE_PIC                | \
-                                                                               SERR_SOURCE_TXDMA       | \
-                                                                               SERR_SOURCE_RXDMA       | \
-                                                                               SERR_SOURCE_MAC         | \
-                                                                               SERR_SOURCE_MC      | \
-                                                                               SERR_SOURCE_XGXS)
-
-
-       u8 unused_0[0x800 - 0x120];
+#define        SERR_SOURCE_ANY                 (SERR_SOURCE_PIC        | \
+                                       SERR_SOURCE_TXDMA       | \
+                                       SERR_SOURCE_RXDMA       | \
+                                       SERR_SOURCE_MAC         | \
+                                       SERR_SOURCE_MC          | \
+                                       SERR_SOURCE_XGXS)
+
+       u64 pci_mode;
+#define        GET_PCI_MODE(val)               ((val & vBIT(0xF, 0, 4)) >> 60)
+#define        PCI_MODE_PCI_33                 0
+#define        PCI_MODE_PCI_66                 0x1
+#define        PCI_MODE_PCIX_M1_66             0x2
+#define        PCI_MODE_PCIX_M1_100            0x3
+#define        PCI_MODE_PCIX_M1_133            0x4
+#define        PCI_MODE_PCIX_M2_66             0x5
+#define        PCI_MODE_PCIX_M2_100            0x6
+#define        PCI_MODE_PCIX_M2_133            0x7
+#define        PCI_MODE_UNSUPPORTED            BIT(0)
+#define        PCI_MODE_32_BITS                BIT(8)
+#define        PCI_MODE_UNKNOWN_MODE           BIT(9)
+
+       u8 unused_0[0x800 - 0x128];
 
 /* PCI-X Controller registers */
        u64 pic_int_status;
@@ -153,7 +167,11 @@ typedef struct _XENA_dev_config {
        u8 unused4[0x08];
 
        u64 gpio_int_reg;
+#define GPIO_INT_REG_LINK_DOWN                 BIT(1)
+#define GPIO_INT_REG_LINK_UP                   BIT(2)
        u64 gpio_int_mask;
+#define GPIO_INT_MASK_LINK_DOWN                BIT(1)
+#define GPIO_INT_MASK_LINK_UP                  BIT(2)
        u64 gpio_alarms;
 
        u8 unused5[0x38];
@@ -223,19 +241,16 @@ typedef struct _XENA_dev_config {
        u64 xmsi_data;
 
        u64 rx_mat;
+#define RX_MAT_SET(ring, msi)                  vBIT(msi, (8 * ring), 8)
 
        u8 unused6[0x8];
 
-       u64 tx_mat0_7;
-       u64 tx_mat8_15;
-       u64 tx_mat16_23;
-       u64 tx_mat24_31;
-       u64 tx_mat32_39;
-       u64 tx_mat40_47;
-       u64 tx_mat48_55;
-       u64 tx_mat56_63;
+       u64 tx_mat0_n[0x8];
+#define TX_MAT_SET(fifo, msi)                  vBIT(msi, (8 * fifo), 8)
 
-       u8 unused_1[0x10];
+       u8 unused_1[0x8];
+       u64 stat_byte_cnt;
+#define STAT_BC(n)                              vBIT(n,4,12)
 
        /* Automated statistics collection */
        u64 stat_cfg;
@@ -246,6 +261,7 @@ typedef struct _XENA_dev_config {
 #define STAT_TRSF_PER(n)           TBD
 #define        PER_SEC                                    0x208d5
 #define        SET_UPDT_PERIOD(n)                 vBIT((PER_SEC*n),32,32)
+#define        SET_UPDT_CLICKS(val)               vBIT(val, 32, 32)
 
        u64 stat_addr;
 
@@ -267,8 +283,15 @@ typedef struct _XENA_dev_config {
 
        u64 gpio_control;
 #define GPIO_CTRL_GPIO_0               BIT(8)
+       u64 misc_control;
+#define MISC_LINK_STABILITY_PRD(val)   vBIT(val,29,3)
+
+       u8 unused7_1[0x240 - 0x208];
+
+       u64 wreq_split_mask;
+#define        WREQ_SPLIT_MASK_SET_MASK(val)   vBIT(val, 52, 12)
 
-       u8 unused7[0x600];
+       u8 unused7_2[0x800 - 0x248];
 
 /* TxDMA registers */
        u64 txdma_int_status;
@@ -290,6 +313,7 @@ typedef struct _XENA_dev_config {
 
        u64 pcc_err_reg;
 #define PCC_FB_ECC_DB_ERR              vBIT(0xFF, 16, 8)
+#define PCC_ENABLE_FOUR                        vBIT(0x0F,0,8)
 
        u64 pcc_err_mask;
        u64 pcc_err_alarm;
@@ -468,6 +492,7 @@ typedef struct _XENA_dev_config {
 #define PRC_CTRL_NO_SNOOP                      (BIT(22)|BIT(23))
 #define PRC_CTRL_NO_SNOOP_DESC                 BIT(22)
 #define PRC_CTRL_NO_SNOOP_BUFF                 BIT(23)
+#define PRC_CTRL_BIMODAL_INTERRUPT             BIT(37)
 #define PRC_CTRL_RXD_BACKOFF_INTERVAL(val)     vBIT(val,40,24)
 
        u64 prc_alarm_action;
@@ -691,6 +716,10 @@ typedef struct _XENA_dev_config {
 #define MC_ERR_REG_MIRI_CRI_ERR_0          BIT(22)
 #define MC_ERR_REG_MIRI_CRI_ERR_1          BIT(23)
 #define MC_ERR_REG_SM_ERR                  BIT(31)
+#define MC_ERR_REG_ECC_ALL_SNG            (BIT(6) | \
+                                       BIT(7) | BIT(17) | BIT(19))
+#define MC_ERR_REG_ECC_ALL_DBL            (BIT(14) | \
+                                       BIT(15) | BIT(18) | BIT(20))
        u64 mc_err_mask;
        u64 mc_err_alarm;
 
@@ -736,7 +765,19 @@ typedef struct _XENA_dev_config {
        u64 mc_rldram_test_d1;
        u8 unused24[0x300 - 0x288];
        u64 mc_rldram_test_d2;
-       u8 unused25[0x700 - 0x308];
+
+       u8 unused24_1[0x360 - 0x308];
+       u64 mc_rldram_ctrl;
+#define        MC_RLDRAM_ENABLE_ODT            BIT(7)
+
+       u8 unused24_2[0x640 - 0x368];
+       u64 mc_rldram_ref_per_herc;
+#define        MC_RLDRAM_SET_REF_PERIOD(val)   vBIT(val, 0, 16)
+
+       u8 unused24_3[0x660 - 0x648];
+       u64 mc_rldram_mrs_herc;
+
+       u8 unused25[0x700 - 0x668];
        u64 mc_debug_ctrl;
 
        u8 unused26[0x3000 - 0x2f08];
index ea638b1..7ca7822 100644 (file)
  * See the file COPYING in this distribution for more information.
  *
  * Credits:
- * Jeff Garzik         : For pointing out the improper error condition 
- *                       check in the s2io_xmit routine and also some 
- *                       issues in the Tx watch dog function. Also for
- *                       patiently answering all those innumerable 
+ * Jeff Garzik         : For pointing out the improper error condition
+ *                       check in the s2io_xmit routine and also some
+ *                       issues in the Tx watch dog function. Also for
+ *                       patiently answering all those innumerable
  *                       questions regaring the 2.6 porting issues.
  * Stephen Hemminger   : Providing proper 2.6 porting mechanism for some
  *                       macros available only in 2.6 Kernel.
- * Francois Romieu     : For pointing out all code part that were 
+ * Francois Romieu     : For pointing out all code part that were
  *                       deprecated and also styling related comments.
- * Grant Grundler      : For helping me get rid of some Architecture 
+ * Grant Grundler      : For helping me get rid of some Architecture
  *                       dependent code.
  * Christopher Hellwig : Some more 2.6 specific issues in the driver.
- *                             
+ *
  * The module loadable parameters that are supported by the driver and a brief
  * explaination of all the variables.
- * rx_ring_num : This can be used to program the number of receive rings used 
- * in the driver.                                      
- * rx_ring_len: This defines the number of descriptors each ring can have. This 
+ * rx_ring_num : This can be used to program the number of receive rings used
+ * in the driver.
+ * rx_ring_len: This defines the number of descriptors each ring can have. This
  * is also an array of size 8.
  * tx_fifo_num: This defines the number of Tx FIFOs thats used int the driver.
- * tx_fifo_len: This too is an array of 8. Each element defines the number of 
+ * tx_fifo_len: This too is an array of 8. Each element defines the number of
  * Tx descriptors that can be associated with each corresponding FIFO.
- * in PCI Configuration space.
  ************************************************************************/
 
 #include <linux/config.h>
 #include <linux/ethtool.h>
 #include <linux/version.h>
 #include <linux/workqueue.h>
+#include <linux/if_vlan.h>
 
-#include <asm/io.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/io.h>
 
 /* local include */
 #include "s2io.h"
 #include "s2io-regs.h"
 
 /* S2io Driver name & version. */
-static char s2io_driver_name[] = "s2io";
-static char s2io_driver_version[] = "Version 1.7.7.1";
+static char s2io_driver_name[] = "Neterion";
+static char s2io_driver_version[] = "Version 2.0.3.1";
+
+static inline int RXD_IS_UP2DT(RxD_t *rxdp)
+{
+       int ret;
+
+       ret = ((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
+               (GET_RXD_MARKER(rxdp->Control_2) != THE_RXD_MARK));
+
+       return ret;
+}
 
-/* 
+/*
  * Cards with following subsystem_id have a link state indication
  * problem, 600B, 600C, 600D, 640B, 640C and 640D.
  * macro below identifies these cards given the subsystem_id.
  */
-#define CARDS_WITH_FAULTY_LINK_INDICATORS(subid) \
-               (((subid >= 0x600B) && (subid <= 0x600D)) || \
-                ((subid >= 0x640B) && (subid <= 0x640D))) ? 1 : 0
+#define CARDS_WITH_FAULTY_LINK_INDICATORS(dev_type, subid) \
+       (dev_type == XFRAME_I_DEVICE) ?                 \
+               ((((subid >= 0x600B) && (subid <= 0x600D)) || \
+                ((subid >= 0x640B) && (subid <= 0x640D))) ? 1 : 0) : 0
 
 #define LINK_IS_UP(val64) (!(val64 & (ADAPTER_STATUS_RMAC_REMOTE_FAULT | \
                                      ADAPTER_STATUS_RMAC_LOCAL_FAULT)))
@@ -86,9 +97,12 @@ static char s2io_driver_version[] = "Version 1.7.7.1";
 static inline int rx_buffer_level(nic_t * sp, int rxb_size, int ring)
 {
        int level = 0;
-       if ((sp->pkt_cnt[ring] - rxb_size) > 16) {
+       mac_info_t *mac_control;
+
+       mac_control = &sp->mac_control;
+       if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16) {
                level = LOW;
-               if ((sp->pkt_cnt[ring] - rxb_size) < MAX_RXDS_PER_BLOCK) {
+               if (rxb_size <= MAX_RXDS_PER_BLOCK) {
                        level = PANIC;
                }
        }
@@ -145,6 +159,9 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
        {"rmac_pause_cnt"},
        {"rmac_accepted_ip"},
        {"rmac_err_tcp"},
+       {"\n DRIVER STATISTICS"},
+       {"single_bit_ecc_errs"},
+       {"double_bit_ecc_errs"},
 };
 
 #define S2IO_STAT_LEN sizeof(ethtool_stats_keys)/ ETH_GSTRING_LEN
@@ -153,8 +170,37 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
 #define S2IO_TEST_LEN  sizeof(s2io_gstrings) / ETH_GSTRING_LEN
 #define S2IO_STRINGS_LEN       S2IO_TEST_LEN * ETH_GSTRING_LEN
 
+#define S2IO_TIMER_CONF(timer, handle, arg, exp)               \
+                       init_timer(&timer);                     \
+                       timer.function = handle;                \
+                       timer.data = (unsigned long) arg;       \
+                       mod_timer(&timer, (jiffies + exp))      \
+
+/* Add the vlan */
+static void s2io_vlan_rx_register(struct net_device *dev,
+                                       struct vlan_group *grp)
+{
+       nic_t *nic = dev->priv;
+       unsigned long flags;
+
+       spin_lock_irqsave(&nic->tx_lock, flags);
+       nic->vlgrp = grp;
+       spin_unlock_irqrestore(&nic->tx_lock, flags);
+}
+
+/* Unregister the vlan */
+static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
+{
+       nic_t *nic = dev->priv;
+       unsigned long flags;
+
+       spin_lock_irqsave(&nic->tx_lock, flags);
+       if (nic->vlgrp)
+               nic->vlgrp->vlan_devices[vid] = NULL;
+       spin_unlock_irqrestore(&nic->tx_lock, flags);
+}
 
-/* 
+/*
  * Constants to be programmed into the Xena's registers, to configure
  * the XAUI.
  */
@@ -162,7 +208,28 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
 #define SWITCH_SIGN    0xA5A5A5A5A5A5A5A5ULL
 #define        END_SIGN        0x0
 
-static u64 default_mdio_cfg[] = {
+static u64 herc_act_dtx_cfg[] = {
+       /* Set address */
+       0x8000051536750000ULL, 0x80000515367500E0ULL,
+       /* Write data */
+       0x8000051536750004ULL, 0x80000515367500E4ULL,
+       /* Set address */
+       0x80010515003F0000ULL, 0x80010515003F00E0ULL,
+       /* Write data */
+       0x80010515003F0004ULL, 0x80010515003F00E4ULL,
+       /* Set address */
+       0x801205150D440000ULL, 0x801205150D4400E0ULL,
+       /* Write data */
+       0x801205150D440004ULL, 0x801205150D4400E4ULL,
+       /* Set address */
+       0x80020515F2100000ULL, 0x80020515F21000E0ULL,
+       /* Write data */
+       0x80020515F2100004ULL, 0x80020515F21000E4ULL,
+       /* Done */
+       END_SIGN
+};
+
+static u64 xena_mdio_cfg[] = {
        /* Reset PMA PLL */
        0xC001010000000000ULL, 0xC0010100000000E0ULL,
        0xC0010100008000E4ULL,
@@ -172,7 +239,7 @@ static u64 default_mdio_cfg[] = {
        END_SIGN
 };
 
-static u64 default_dtx_cfg[] = {
+static u64 xena_dtx_cfg[] = {
        0x8000051500000000ULL, 0x80000515000000E0ULL,
        0x80000515D93500E4ULL, 0x8001051500000000ULL,
        0x80010515000000E0ULL, 0x80010515001E00E4ULL,
@@ -196,8 +263,7 @@ static u64 default_dtx_cfg[] = {
        END_SIGN
 };
 
-
-/* 
+/*
  * Constants for Fixing the MacAddress problem seen mostly on
  * Alpha machines.
  */
@@ -226,20 +292,25 @@ static unsigned int tx_fifo_len[MAX_TX_FIFOS] =
 static unsigned int rx_ring_num = 1;
 static unsigned int rx_ring_sz[MAX_RX_RINGS] =
     {[0 ...(MAX_RX_RINGS - 1)] = 0 };
-static unsigned int Stats_refresh_time = 4;
+static unsigned int rts_frm_len[MAX_RX_RINGS] =
+    {[0 ...(MAX_RX_RINGS - 1)] = 0 };
+static unsigned int use_continuous_tx_intrs = 1;
 static unsigned int rmac_pause_time = 65535;
 static unsigned int mc_pause_threshold_q0q3 = 187;
 static unsigned int mc_pause_threshold_q4q7 = 187;
 static unsigned int shared_splits;
 static unsigned int tmac_util_period = 5;
 static unsigned int rmac_util_period = 5;
+static unsigned int bimodal = 0;
 #ifndef CONFIG_S2IO_NAPI
 static unsigned int indicate_max_pkts;
 #endif
+/* Frequency of Rx desc syncs expressed as power of 2 */
+static unsigned int rxsync_frequency = 3;
 
-/* 
+/*
  * S2IO device table.
- * This table lists all the devices that this driver supports. 
+ * This table lists all the devices that this driver supports.
  */
 static struct pci_device_id s2io_tbl[] __devinitdata = {
        {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_WIN,
@@ -247,9 +318,9 @@ static struct pci_device_id s2io_tbl[] __devinitdata = {
        {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_UNI,
         PCI_ANY_ID, PCI_ANY_ID},
        {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_WIN,
-        PCI_ANY_ID, PCI_ANY_ID},
-       {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_UNI,
-        PCI_ANY_ID, PCI_ANY_ID},
+         PCI_ANY_ID, PCI_ANY_ID},
+        {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_UNI,
+         PCI_ANY_ID, PCI_ANY_ID},
        {0,}
 };
 
@@ -268,8 +339,8 @@ static struct pci_driver s2io_driver = {
 /**
  * init_shared_mem - Allocation and Initialization of Memory
  * @nic: Device private variable.
- * Description: The function allocates all the memory areas shared 
- * between the NIC and the driver. This includes Tx descriptors, 
+ * Description: The function allocates all the memory areas shared
+ * between the NIC and the driver. This includes Tx descriptors,
  * Rx descriptors and the statistics block.
  */
 
@@ -279,11 +350,11 @@ static int init_shared_mem(struct s2io_nic *nic)
        void *tmp_v_addr, *tmp_v_addr_next;
        dma_addr_t tmp_p_addr, tmp_p_addr_next;
        RxD_block_t *pre_rxd_blk = NULL;
-       int i, j, blk_cnt;
+       int i, j, blk_cnt, rx_sz, tx_sz;
        int lst_size, lst_per_page;
        struct net_device *dev = nic->dev;
 #ifdef CONFIG_2BUFF_MODE
-       unsigned long tmp;
+       u64 tmp;
        buffAdd_t *ba;
 #endif
 
@@ -300,36 +371,41 @@ static int init_shared_mem(struct s2io_nic *nic)
                size += config->tx_cfg[i].fifo_len;
        }
        if (size > MAX_AVAILABLE_TXDS) {
-               DBG_PRINT(ERR_DBG, "%s: Total number of Tx FIFOs ",
-                         dev->name);
-               DBG_PRINT(ERR_DBG, "exceeds the maximum value ");
-               DBG_PRINT(ERR_DBG, "that can be used\n");
+               DBG_PRINT(ERR_DBG, "%s: Requested TxDs too high, ",
+                         __FUNCTION__);
+               DBG_PRINT(ERR_DBG, "Requested: %d, max supported: 8192\n", size);
                return FAILURE;
        }
 
        lst_size = (sizeof(TxD_t) * config->max_txds);
+       tx_sz = lst_size * size;
        lst_per_page = PAGE_SIZE / lst_size;
 
        for (i = 0; i < config->tx_fifo_num; i++) {
                int fifo_len = config->tx_cfg[i].fifo_len;
                int list_holder_size = fifo_len * sizeof(list_info_hold_t);
-               nic->list_info[i] = kmalloc(list_holder_size, GFP_KERNEL);
-               if (!nic->list_info[i]) {
+               mac_control->fifos[i].list_info = kmalloc(list_holder_size,
+                                                         GFP_KERNEL);
+               if (!mac_control->fifos[i].list_info) {
                        DBG_PRINT(ERR_DBG,
                                  "Malloc failed for list_info\n");
                        return -ENOMEM;
                }
-               memset(nic->list_info[i], 0, list_holder_size);
+               memset(mac_control->fifos[i].list_info, 0, list_holder_size);
        }
        for (i = 0; i < config->tx_fifo_num; i++) {
                int page_num = TXD_MEM_PAGE_CNT(config->tx_cfg[i].fifo_len,
                                                lst_per_page);
-               mac_control->tx_curr_put_info[i].offset = 0;
-               mac_control->tx_curr_put_info[i].fifo_len =
+               mac_control->fifos[i].tx_curr_put_info.offset = 0;
+               mac_control->fifos[i].tx_curr_put_info.fifo_len =
                    config->tx_cfg[i].fifo_len - 1;
-               mac_control->tx_curr_get_info[i].offset = 0;
-               mac_control->tx_curr_get_info[i].fifo_len =
+               mac_control->fifos[i].tx_curr_get_info.offset = 0;
+               mac_control->fifos[i].tx_curr_get_info.fifo_len =
                    config->tx_cfg[i].fifo_len - 1;
+               mac_control->fifos[i].fifo_no = i;
+               mac_control->fifos[i].nic = nic;
+               mac_control->fifos[i].max_txds = MAX_SKB_FRAGS;
+
                for (j = 0; j < page_num; j++) {
                        int k = 0;
                        dma_addr_t tmp_p;
@@ -345,16 +421,15 @@ static int init_shared_mem(struct s2io_nic *nic)
                        while (k < lst_per_page) {
                                int l = (j * lst_per_page) + k;
                                if (l == config->tx_cfg[i].fifo_len)
-                                       goto end_txd_alloc;
-                               nic->list_info[i][l].list_virt_addr =
+                                       break;
+                               mac_control->fifos[i].list_info[l].list_virt_addr =
                                    tmp_v + (k * lst_size);
-                               nic->list_info[i][l].list_phy_addr =
+                               mac_control->fifos[i].list_info[l].list_phy_addr =
                                    tmp_p + (k * lst_size);
                                k++;
                        }
                }
        }
-      end_txd_alloc:
 
        /* Allocation and initialization of RXDs in Rings */
        size = 0;
@@ -367,21 +442,26 @@ static int init_shared_mem(struct s2io_nic *nic)
                        return FAILURE;
                }
                size += config->rx_cfg[i].num_rxd;
-               nic->block_count[i] =
+               mac_control->rings[i].block_count =
                    config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
-               nic->pkt_cnt[i] =
-                   config->rx_cfg[i].num_rxd - nic->block_count[i];
+               mac_control->rings[i].pkt_cnt =
+                   config->rx_cfg[i].num_rxd - mac_control->rings[i].block_count;
        }
+       size = (size * (sizeof(RxD_t)));
+       rx_sz = size;
 
        for (i = 0; i < config->rx_ring_num; i++) {
-               mac_control->rx_curr_get_info[i].block_index = 0;
-               mac_control->rx_curr_get_info[i].offset = 0;
-               mac_control->rx_curr_get_info[i].ring_len =
+               mac_control->rings[i].rx_curr_get_info.block_index = 0;
+               mac_control->rings[i].rx_curr_get_info.offset = 0;
+               mac_control->rings[i].rx_curr_get_info.ring_len =
                    config->rx_cfg[i].num_rxd - 1;
-               mac_control->rx_curr_put_info[i].block_index = 0;
-               mac_control->rx_curr_put_info[i].offset = 0;
-               mac_control->rx_curr_put_info[i].ring_len =
+               mac_control->rings[i].rx_curr_put_info.block_index = 0;
+               mac_control->rings[i].rx_curr_put_info.offset = 0;
+               mac_control->rings[i].rx_curr_put_info.ring_len =
                    config->rx_cfg[i].num_rxd - 1;
+               mac_control->rings[i].nic = nic;
+               mac_control->rings[i].ring_no = i;
+
                blk_cnt =
                    config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
                /*  Allocating all the Rx blocks */
@@ -395,32 +475,36 @@ static int init_shared_mem(struct s2io_nic *nic)
                                                          &tmp_p_addr);
                        if (tmp_v_addr == NULL) {
                                /*
-                                * In case of failure, free_shared_mem() 
-                                * is called, which should free any 
-                                * memory that was alloced till the 
+                                * In case of failure, free_shared_mem()
+                                * is called, which should free any
+                                * memory that was alloced till the
                                 * failure happened.
                                 */
-                               nic->rx_blocks[i][j].block_virt_addr =
+                               mac_control->rings[i].rx_blocks[j].block_virt_addr =
                                    tmp_v_addr;
                                return -ENOMEM;
                        }
                        memset(tmp_v_addr, 0, size);
-                       nic->rx_blocks[i][j].block_virt_addr = tmp_v_addr;
-                       nic->rx_blocks[i][j].block_dma_addr = tmp_p_addr;
+                       mac_control->rings[i].rx_blocks[j].block_virt_addr =
+                               tmp_v_addr;
+                       mac_control->rings[i].rx_blocks[j].block_dma_addr =
+                               tmp_p_addr;
                }
                /* Interlinking all Rx Blocks */
                for (j = 0; j < blk_cnt; j++) {
-                       tmp_v_addr = nic->rx_blocks[i][j].block_virt_addr;
+                       tmp_v_addr =
+                               mac_control->rings[i].rx_blocks[j].block_virt_addr;
                        tmp_v_addr_next =
-                           nic->rx_blocks[i][(j + 1) %
+                               mac_control->rings[i].rx_blocks[(j + 1) %
                                              blk_cnt].block_virt_addr;
-                       tmp_p_addr = nic->rx_blocks[i][j].block_dma_addr;
+                       tmp_p_addr =
+                               mac_control->rings[i].rx_blocks[j].block_dma_addr;
                        tmp_p_addr_next =
-                           nic->rx_blocks[i][(j + 1) %
+                               mac_control->rings[i].rx_blocks[(j + 1) %
                                              blk_cnt].block_dma_addr;
 
                        pre_rxd_blk = (RxD_block_t *) tmp_v_addr;
-                       pre_rxd_blk->reserved_1 = END_OF_BLOCK; /* last RxD 
+                       pre_rxd_blk->reserved_1 = END_OF_BLOCK; /* last RxD
                                                                 * marker.
                                                                 */
 #ifndef        CONFIG_2BUFF_MODE
@@ -433,43 +517,43 @@ static int init_shared_mem(struct s2io_nic *nic)
        }
 
 #ifdef CONFIG_2BUFF_MODE
-       /* 
+       /*
         * Allocation of Storages for buffer addresses in 2BUFF mode
         * and the buffers as well.
         */
        for (i = 0; i < config->rx_ring_num; i++) {
                blk_cnt =
                    config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
-               nic->ba[i] = kmalloc((sizeof(buffAdd_t *) * blk_cnt),
+               mac_control->rings[i].ba = kmalloc((sizeof(buffAdd_t *) * blk_cnt),
                                     GFP_KERNEL);
-               if (!nic->ba[i])
+               if (!mac_control->rings[i].ba)
                        return -ENOMEM;
                for (j = 0; j < blk_cnt; j++) {
                        int k = 0;
-                       nic->ba[i][j] = kmalloc((sizeof(buffAdd_t) *
+                       mac_control->rings[i].ba[j] = kmalloc((sizeof(buffAdd_t) *
                                                 (MAX_RXDS_PER_BLOCK + 1)),
                                                GFP_KERNEL);
-                       if (!nic->ba[i][j])
+                       if (!mac_control->rings[i].ba[j])
                                return -ENOMEM;
                        while (k != MAX_RXDS_PER_BLOCK) {
-                               ba = &nic->ba[i][j][k];
+                               ba = &mac_control->rings[i].ba[j][k];
 
-                               ba->ba_0_org = kmalloc
+                               ba->ba_0_org = (void *) kmalloc
                                    (BUF0_LEN + ALIGN_SIZE, GFP_KERNEL);
                                if (!ba->ba_0_org)
                                        return -ENOMEM;
-                               tmp = (unsigned long) ba->ba_0_org;
+                               tmp = (u64) ba->ba_0_org;
                                tmp += ALIGN_SIZE;
-                               tmp &= ~((unsigned long) ALIGN_SIZE);
+                               tmp &= ~((u64) ALIGN_SIZE);
                                ba->ba_0 = (void *) tmp;
 
-                               ba->ba_1_org = kmalloc
+                               ba->ba_1_org = (void *) kmalloc
                                    (BUF1_LEN + ALIGN_SIZE, GFP_KERNEL);
                                if (!ba->ba_1_org)
                                        return -ENOMEM;
-                               tmp = (unsigned long) ba->ba_1_org;
+                               tmp = (u64) ba->ba_1_org;
                                tmp += ALIGN_SIZE;
-                               tmp &= ~((unsigned long) ALIGN_SIZE);
+                               tmp &= ~((u64) ALIGN_SIZE);
                                ba->ba_1 = (void *) tmp;
                                k++;
                        }
@@ -483,9 +567,9 @@ static int init_shared_mem(struct s2io_nic *nic)
            (nic->pdev, size, &mac_control->stats_mem_phy);
 
        if (!mac_control->stats_mem) {
-               /* 
-                * In case of failure, free_shared_mem() is called, which 
-                * should free any memory that was alloced till the 
+               /*
+                * In case of failure, free_shared_mem() is called, which
+                * should free any memory that was alloced till the
                 * failure happened.
                 */
                return -ENOMEM;
@@ -495,15 +579,14 @@ static int init_shared_mem(struct s2io_nic *nic)
        tmp_v_addr = mac_control->stats_mem;
        mac_control->stats_info = (StatInfo_t *) tmp_v_addr;
        memset(tmp_v_addr, 0, size);
-
        DBG_PRINT(INIT_DBG, "%s:Ring Mem PHY: 0x%llx\n", dev->name,
                  (unsigned long long) tmp_p_addr);
 
        return SUCCESS;
 }
 
-/**  
- * free_shared_mem - Free the allocated Memory 
+/**
+ * free_shared_mem - Free the allocated Memory
  * @nic:  Device private variable.
  * Description: This function is to free all memory locations allocated by
  * the init_shared_mem() function and return it to the kernel.
@@ -533,15 +616,19 @@ static void free_shared_mem(struct s2io_nic *nic)
                                                lst_per_page);
                for (j = 0; j < page_num; j++) {
                        int mem_blks = (j * lst_per_page);
-                       if (!nic->list_info[i][mem_blks].list_virt_addr)
+                       if ((!mac_control->fifos[i].list_info) ||
+                               (!mac_control->fifos[i].list_info[mem_blks].
+                                list_virt_addr))
                                break;
                        pci_free_consistent(nic->pdev, PAGE_SIZE,
-                                           nic->list_info[i][mem_blks].
+                                           mac_control->fifos[i].
+                                           list_info[mem_blks].
                                            list_virt_addr,
-                                           nic->list_info[i][mem_blks].
+                                           mac_control->fifos[i].
+                                           list_info[mem_blks].
                                            list_phy_addr);
                }
-               kfree(nic->list_info[i]);
+               kfree(mac_control->fifos[i].list_info);
        }
 
 #ifndef CONFIG_2BUFF_MODE
@@ -550,10 +637,12 @@ static void free_shared_mem(struct s2io_nic *nic)
        size = SIZE_OF_BLOCK;
 #endif
        for (i = 0; i < config->rx_ring_num; i++) {
-               blk_cnt = nic->block_count[i];
+               blk_cnt = mac_control->rings[i].block_count;
                for (j = 0; j < blk_cnt; j++) {
-                       tmp_v_addr = nic->rx_blocks[i][j].block_virt_addr;
-                       tmp_p_addr = nic->rx_blocks[i][j].block_dma_addr;
+                       tmp_v_addr = mac_control->rings[i].rx_blocks[j].
+                               block_virt_addr;
+                       tmp_p_addr = mac_control->rings[i].rx_blocks[j].
+                               block_dma_addr;
                        if (tmp_v_addr == NULL)
                                break;
                        pci_free_consistent(nic->pdev, size,
@@ -566,35 +655,21 @@ static void free_shared_mem(struct s2io_nic *nic)
        for (i = 0; i < config->rx_ring_num; i++) {
                blk_cnt =
                    config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
-               if (!nic->ba[i])
-                       goto end_free;
                for (j = 0; j < blk_cnt; j++) {
                        int k = 0;
-                       if (!nic->ba[i][j]) {
-                               kfree(nic->ba[i]);
-                               goto end_free;
-                       }
+                       if (!mac_control->rings[i].ba[j])
+                               continue;
                        while (k != MAX_RXDS_PER_BLOCK) {
-                               buffAdd_t *ba = &nic->ba[i][j][k];
-                               if (!ba || !ba->ba_0_org || !ba->ba_1_org)
-                               {
-                                       kfree(nic->ba[i]);
-                                       kfree(nic->ba[i][j]);
-                                       if(ba->ba_0_org)
-                                               kfree(ba->ba_0_org);
-                                       if(ba->ba_1_org)
-                                               kfree(ba->ba_1_org);
-                                       goto end_free;
-                               }
+                               buffAdd_t *ba = &mac_control->rings[i].ba[j][k];
                                kfree(ba->ba_0_org);
                                kfree(ba->ba_1_org);
                                k++;
                        }
-                       kfree(nic->ba[i][j]);
+                       kfree(mac_control->rings[i].ba[j]);
                }
-               kfree(nic->ba[i]);
+               if (mac_control->rings[i].ba)
+                       kfree(mac_control->rings[i].ba);
        }
-end_free:
 #endif
 
        if (mac_control->stats_mem) {
@@ -605,12 +680,93 @@ end_free:
        }
 }
 
-/**  
- *  init_nic - Initialization of hardware 
+/**
+ * s2io_verify_pci_mode -
+ */
+
+static int s2io_verify_pci_mode(nic_t *nic)
+{
+       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       register u64 val64 = 0;
+       int     mode;
+
+       val64 = readq(&bar0->pci_mode);
+       mode = (u8)GET_PCI_MODE(val64);
+
+       if ( val64 & PCI_MODE_UNKNOWN_MODE)
+               return -1;      /* Unknown PCI mode */
+       return mode;
+}
+
+
+/**
+ * s2io_print_pci_mode -
+ */
+static int s2io_print_pci_mode(nic_t *nic)
+{
+       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       register u64 val64 = 0;
+       int     mode;
+       struct config_param *config = &nic->config;
+
+       val64 = readq(&bar0->pci_mode);
+       mode = (u8)GET_PCI_MODE(val64);
+
+       if ( val64 & PCI_MODE_UNKNOWN_MODE)
+               return -1;      /* Unknown PCI mode */
+
+       if (val64 & PCI_MODE_32_BITS) {
+               DBG_PRINT(ERR_DBG, "%s: Device is on 32 bit ", nic->dev->name);
+       } else {
+               DBG_PRINT(ERR_DBG, "%s: Device is on 64 bit ", nic->dev->name);
+       }
+
+       switch(mode) {
+               case PCI_MODE_PCI_33:
+                       DBG_PRINT(ERR_DBG, "33MHz PCI bus\n");
+                       config->bus_speed = 33;
+                       break;
+               case PCI_MODE_PCI_66:
+                       DBG_PRINT(ERR_DBG, "66MHz PCI bus\n");
+                       config->bus_speed = 133;
+                       break;
+               case PCI_MODE_PCIX_M1_66:
+                       DBG_PRINT(ERR_DBG, "66MHz PCIX(M1) bus\n");
+                       config->bus_speed = 133; /* Herc doubles the clock rate */
+                       break;
+               case PCI_MODE_PCIX_M1_100:
+                       DBG_PRINT(ERR_DBG, "100MHz PCIX(M1) bus\n");
+                       config->bus_speed = 200;
+                       break;
+               case PCI_MODE_PCIX_M1_133:
+                       DBG_PRINT(ERR_DBG, "133MHz PCIX(M1) bus\n");
+                       config->bus_speed = 266;
+                       break;
+               case PCI_MODE_PCIX_M2_66:
+                       DBG_PRINT(ERR_DBG, "133MHz PCIX(M2) bus\n");
+                       config->bus_speed = 133;
+                       break;
+               case PCI_MODE_PCIX_M2_100:
+                       DBG_PRINT(ERR_DBG, "200MHz PCIX(M2) bus\n");
+                       config->bus_speed = 200;
+                       break;
+               case PCI_MODE_PCIX_M2_133:
+                       DBG_PRINT(ERR_DBG, "266MHz PCIX(M2) bus\n");
+                       config->bus_speed = 266;
+                       break;
+               default:
+                       return -1;      /* Unsupported bus speed */
+       }
+
+       return mode;
+}
+
+/**
+ *  init_nic - Initialization of hardware
  *  @nic: device peivate variable
- *  Description: The function sequentially configures every block 
- *  of the H/W from their reset values. 
- *  Return Value:  SUCCESS on success and 
+ *  Description: The function sequentially configures every block
+ *  of the H/W from their reset values.
+ *  Return Value:  SUCCESS on success and
  *  '-1' on failure (endian settings incorrect).
  */
 
@@ -626,21 +782,32 @@ static int init_nic(struct s2io_nic *nic)
        struct config_param *config;
        int mdio_cnt = 0, dtx_cnt = 0;
        unsigned long long mem_share;
+       int mem_size;
 
        mac_control = &nic->mac_control;
        config = &nic->config;
 
-       /* Initialize swapper control register */
-       if (s2io_set_swapper(nic)) {
+       /* to set the swapper controle on the card */
+       if(s2io_set_swapper(nic)) {
                DBG_PRINT(ERR_DBG,"ERROR: Setting Swapper failed\n");
                return -1;
        }
 
+       /*
+        * Herc requires EOI to be removed from reset before XGXS, so..
+        */
+       if (nic->device_type & XFRAME_II_DEVICE) {
+               val64 = 0xA500000000ULL;
+               writeq(val64, &bar0->sw_reset);
+               msleep(500);
+               val64 = readq(&bar0->sw_reset);
+       }
+
        /* Remove XGXS from reset state */
        val64 = 0;
        writeq(val64, &bar0->sw_reset);
-       val64 = readq(&bar0->sw_reset);
        msleep(500);
+       val64 = readq(&bar0->sw_reset);
 
        /*  Enable Receiving broadcasts */
        add = &bar0->mac_cfg;
@@ -660,48 +827,58 @@ static int init_nic(struct s2io_nic *nic)
        val64 = dev->mtu;
        writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
 
-       /* 
-        * Configuring the XAUI Interface of Xena. 
+       /*
+        * Configuring the XAUI Interface of Xena.
         * ***************************************
-        * To Configure the Xena's XAUI, one has to write a series 
-        * of 64 bit values into two registers in a particular 
-        * sequence. Hence a macro 'SWITCH_SIGN' has been defined 
-        * which will be defined in the array of configuration values 
-        * (default_dtx_cfg & default_mdio_cfg) at appropriate places 
-        * to switch writing from one regsiter to another. We continue 
+        * To Configure the Xena's XAUI, one has to write a series
+        * of 64 bit values into two registers in a particular
+        * sequence. Hence a macro 'SWITCH_SIGN' has been defined
+        * which will be defined in the array of configuration values
+        * (xena_dtx_cfg & xena_mdio_cfg) at appropriate places
+        * to switch writing from one regsiter to another. We continue
         * writing these values until we encounter the 'END_SIGN' macro.
-        * For example, After making a series of 21 writes into 
-        * dtx_control register the 'SWITCH_SIGN' appears and hence we 
+        * For example, After making a series of 21 writes into
+        * dtx_control register the 'SWITCH_SIGN' appears and hence we
         * start writing into mdio_control until we encounter END_SIGN.
         */
-       while (1) {
-             dtx_cfg:
-               while (default_dtx_cfg[dtx_cnt] != END_SIGN) {
-                       if (default_dtx_cfg[dtx_cnt] == SWITCH_SIGN) {
-                               dtx_cnt++;
-                               goto mdio_cfg;
-                       }
-                       SPECIAL_REG_WRITE(default_dtx_cfg[dtx_cnt],
+       if (nic->device_type & XFRAME_II_DEVICE) {
+               while (herc_act_dtx_cfg[dtx_cnt] != END_SIGN) {
+                       SPECIAL_REG_WRITE(herc_act_dtx_cfg[dtx_cnt],
                                          &bar0->dtx_control, UF);
-                       val64 = readq(&bar0->dtx_control);
+                       if (dtx_cnt & 0x1)
+                               msleep(1); /* Necessary!! */
                        dtx_cnt++;
                }
-             mdio_cfg:
-               while (default_mdio_cfg[mdio_cnt] != END_SIGN) {
-                       if (default_mdio_cfg[mdio_cnt] == SWITCH_SIGN) {
+       } else {
+               while (1) {
+                     dtx_cfg:
+                       while (xena_dtx_cfg[dtx_cnt] != END_SIGN) {
+                               if (xena_dtx_cfg[dtx_cnt] == SWITCH_SIGN) {
+                                       dtx_cnt++;
+                                       goto mdio_cfg;
+                               }
+                               SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt],
+                                                 &bar0->dtx_control, UF);
+                               val64 = readq(&bar0->dtx_control);
+                               dtx_cnt++;
+                       }
+                     mdio_cfg:
+                       while (xena_mdio_cfg[mdio_cnt] != END_SIGN) {
+                               if (xena_mdio_cfg[mdio_cnt] == SWITCH_SIGN) {
+                                       mdio_cnt++;
+                                       goto dtx_cfg;
+                               }
+                               SPECIAL_REG_WRITE(xena_mdio_cfg[mdio_cnt],
+                                                 &bar0->mdio_control, UF);
+                               val64 = readq(&bar0->mdio_control);
                                mdio_cnt++;
+                       }
+                       if ((xena_dtx_cfg[dtx_cnt] == END_SIGN) &&
+                           (xena_mdio_cfg[mdio_cnt] == END_SIGN)) {
+                               break;
+                       } else {
                                goto dtx_cfg;
                        }
-                       SPECIAL_REG_WRITE(default_mdio_cfg[mdio_cnt],
-                                         &bar0->mdio_control, UF);
-                       val64 = readq(&bar0->mdio_control);
-                       mdio_cnt++;
-               }
-               if ((default_dtx_cfg[dtx_cnt] == END_SIGN) &&
-                   (default_mdio_cfg[mdio_cnt] == END_SIGN)) {
-                       break;
-               } else {
-                       goto dtx_cfg;
                }
        }
 
@@ -748,12 +925,20 @@ static int init_nic(struct s2io_nic *nic)
        val64 |= BIT(0);        /* To enable the FIFO partition. */
        writeq(val64, &bar0->tx_fifo_partition_0);
 
+       /*
+        * Disable 4 PCCs for Xena1, 2 and 3 as per H/W bug
+        * SXE-008 TRANSMIT DMA ARBITRATION ISSUE.
+        */
+       if ((nic->device_type == XFRAME_I_DEVICE) &&
+               (get_xena_rev_id(nic->pdev) < 4))
+               writeq(PCC_ENABLE_FOUR, &bar0->pcc_enable);
+
        val64 = readq(&bar0->tx_fifo_partition_0);
        DBG_PRINT(INIT_DBG, "Fifo partition at: 0x%p is: 0x%llx\n",
                  &bar0->tx_fifo_partition_0, (unsigned long long) val64);
 
-       /* 
-        * Initialization of Tx_PA_CONFIG register to ignore packet 
+       /*
+        * Initialization of Tx_PA_CONFIG register to ignore packet
         * integrity checking.
         */
        val64 = readq(&bar0->tx_pa_cfg);
@@ -770,85 +955,304 @@ static int init_nic(struct s2io_nic *nic)
        }
        writeq(val64, &bar0->rx_queue_priority);
 
-       /* 
-        * Allocating equal share of memory to all the 
+       /*
+        * Allocating equal share of memory to all the
         * configured Rings.
         */
        val64 = 0;
+       if (nic->device_type & XFRAME_II_DEVICE)
+               mem_size = 32;
+       else
+               mem_size = 64;
+
        for (i = 0; i < config->rx_ring_num; i++) {
                switch (i) {
                case 0:
-                       mem_share = (64 / config->rx_ring_num +
-                                    64 % config->rx_ring_num);
+                       mem_share = (mem_size / config->rx_ring_num +
+                                    mem_size % config->rx_ring_num);
                        val64 |= RX_QUEUE_CFG_Q0_SZ(mem_share);
                        continue;
                case 1:
-                       mem_share = (64 / config->rx_ring_num);
+                       mem_share = (mem_size / config->rx_ring_num);
                        val64 |= RX_QUEUE_CFG_Q1_SZ(mem_share);
                        continue;
                case 2:
-                       mem_share = (64 / config->rx_ring_num);
+                       mem_share = (mem_size / config->rx_ring_num);
                        val64 |= RX_QUEUE_CFG_Q2_SZ(mem_share);
                        continue;
                case 3:
-                       mem_share = (64 / config->rx_ring_num);
+                       mem_share = (mem_size / config->rx_ring_num);
                        val64 |= RX_QUEUE_CFG_Q3_SZ(mem_share);
                        continue;
                case 4:
-                       mem_share = (64 / config->rx_ring_num);
+                       mem_share = (mem_size / config->rx_ring_num);
                        val64 |= RX_QUEUE_CFG_Q4_SZ(mem_share);
                        continue;
                case 5:
-                       mem_share = (64 / config->rx_ring_num);
+                       mem_share = (mem_size / config->rx_ring_num);
                        val64 |= RX_QUEUE_CFG_Q5_SZ(mem_share);
                        continue;
                case 6:
-                       mem_share = (64 / config->rx_ring_num);
+                       mem_share = (mem_size / config->rx_ring_num);
                        val64 |= RX_QUEUE_CFG_Q6_SZ(mem_share);
                        continue;
                case 7:
-                       mem_share = (64 / config->rx_ring_num);
+                       mem_share = (mem_size / config->rx_ring_num);
                        val64 |= RX_QUEUE_CFG_Q7_SZ(mem_share);
                        continue;
                }
        }
        writeq(val64, &bar0->rx_queue_cfg);
 
-       /* 
-        * Initializing the Tx round robin registers to 0.
-        * Filling Tx and Rx round robin registers as per the 
-        * number of FIFOs and Rings is still TODO.
-        */
-       writeq(0, &bar0->tx_w_round_robin_0);
-       writeq(0, &bar0->tx_w_round_robin_1);
-       writeq(0, &bar0->tx_w_round_robin_2);
-       writeq(0, &bar0->tx_w_round_robin_3);
-       writeq(0, &bar0->tx_w_round_robin_4);
-
-       /* 
-        * TODO
-        * Disable Rx steering. Hard coding all packets be steered to
-        * Queue 0 for now. 
+       /*
+        * Filling Tx round robin registers
+        * as per the number of FIFOs
         */
-       val64 = 0x8080808080808080ULL;
-       writeq(val64, &bar0->rts_qos_steering);
+       switch (config->tx_fifo_num) {
+       case 1:
+               val64 = 0x0000000000000000ULL;
+               writeq(val64, &bar0->tx_w_round_robin_0);
+               writeq(val64, &bar0->tx_w_round_robin_1);
+               writeq(val64, &bar0->tx_w_round_robin_2);
+               writeq(val64, &bar0->tx_w_round_robin_3);
+               writeq(val64, &bar0->tx_w_round_robin_4);
+               break;
+       case 2:
+               val64 = 0x0000010000010000ULL;
+               writeq(val64, &bar0->tx_w_round_robin_0);
+               val64 = 0x0100000100000100ULL;
+               writeq(val64, &bar0->tx_w_round_robin_1);
+               val64 = 0x0001000001000001ULL;
+               writeq(val64, &bar0->tx_w_round_robin_2);
+               val64 = 0x0000010000010000ULL;
+               writeq(val64, &bar0->tx_w_round_robin_3);
+               val64 = 0x0100000000000000ULL;
+               writeq(val64, &bar0->tx_w_round_robin_4);
+               break;
+       case 3:
+               val64 = 0x0001000102000001ULL;
+               writeq(val64, &bar0->tx_w_round_robin_0);
+               val64 = 0x0001020000010001ULL;
+               writeq(val64, &bar0->tx_w_round_robin_1);
+               val64 = 0x0200000100010200ULL;
+               writeq(val64, &bar0->tx_w_round_robin_2);
+               val64 = 0x0001000102000001ULL;
+               writeq(val64, &bar0->tx_w_round_robin_3);
+               val64 = 0x0001020000000000ULL;
+               writeq(val64, &bar0->tx_w_round_robin_4);
+               break;
+       case 4:
+               val64 = 0x0001020300010200ULL;
+               writeq(val64, &bar0->tx_w_round_robin_0);
+               val64 = 0x0100000102030001ULL;
+               writeq(val64, &bar0->tx_w_round_robin_1);
+               val64 = 0x0200010000010203ULL;
+               writeq(val64, &bar0->tx_w_round_robin_2);
+               val64 = 0x0001020001000001ULL;
+               writeq(val64, &bar0->tx_w_round_robin_3);
+               val64 = 0x0203000100000000ULL;
+               writeq(val64, &bar0->tx_w_round_robin_4);
+               break;
+       case 5:
+               val64 = 0x0001000203000102ULL;
+               writeq(val64, &bar0->tx_w_round_robin_0);
+               val64 = 0x0001020001030004ULL;
+               writeq(val64, &bar0->tx_w_round_robin_1);
+               val64 = 0x0001000203000102ULL;
+               writeq(val64, &bar0->tx_w_round_robin_2);
+               val64 = 0x0001020001030004ULL;
+               writeq(val64, &bar0->tx_w_round_robin_3);
+               val64 = 0x0001000000000000ULL;
+               writeq(val64, &bar0->tx_w_round_robin_4);
+               break;
+       case 6:
+               val64 = 0x0001020304000102ULL;
+               writeq(val64, &bar0->tx_w_round_robin_0);
+               val64 = 0x0304050001020001ULL;
+               writeq(val64, &bar0->tx_w_round_robin_1);
+               val64 = 0x0203000100000102ULL;
+               writeq(val64, &bar0->tx_w_round_robin_2);
+               val64 = 0x0304000102030405ULL;
+               writeq(val64, &bar0->tx_w_round_robin_3);
+               val64 = 0x0001000200000000ULL;
+               writeq(val64, &bar0->tx_w_round_robin_4);
+               break;
+       case 7:
+               val64 = 0x0001020001020300ULL;
+               writeq(val64, &bar0->tx_w_round_robin_0);
+               val64 = 0x0102030400010203ULL;
+               writeq(val64, &bar0->tx_w_round_robin_1);
+               val64 = 0x0405060001020001ULL;
+               writeq(val64, &bar0->tx_w_round_robin_2);
+               val64 = 0x0304050000010200ULL;
+               writeq(val64, &bar0->tx_w_round_robin_3);
+               val64 = 0x0102030000000000ULL;
+               writeq(val64, &bar0->tx_w_round_robin_4);
+               break;
+       case 8:
+               val64 = 0x0001020300040105ULL;
+               writeq(val64, &bar0->tx_w_round_robin_0);
+               val64 = 0x0200030106000204ULL;
+               writeq(val64, &bar0->tx_w_round_robin_1);
+               val64 = 0x0103000502010007ULL;
+               writeq(val64, &bar0->tx_w_round_robin_2);
+               val64 = 0x0304010002060500ULL;
+               writeq(val64, &bar0->tx_w_round_robin_3);
+               val64 = 0x0103020400000000ULL;
+               writeq(val64, &bar0->tx_w_round_robin_4);
+               break;
+       }
+
+       /* Filling the Rx round robin registers as per the
+        * number of Rings and steering based on QoS.
+         */
+       switch (config->rx_ring_num) {
+       case 1:
+               val64 = 0x8080808080808080ULL;
+               writeq(val64, &bar0->rts_qos_steering);
+               break;
+       case 2:
+               val64 = 0x0000010000010000ULL;
+               writeq(val64, &bar0->rx_w_round_robin_0);
+               val64 = 0x0100000100000100ULL;
+               writeq(val64, &bar0->rx_w_round_robin_1);
+               val64 = 0x0001000001000001ULL;
+               writeq(val64, &bar0->rx_w_round_robin_2);
+               val64 = 0x0000010000010000ULL;
+               writeq(val64, &bar0->rx_w_round_robin_3);
+               val64 = 0x0100000000000000ULL;
+               writeq(val64, &bar0->rx_w_round_robin_4);
+
+               val64 = 0x8080808040404040ULL;
+               writeq(val64, &bar0->rts_qos_steering);
+               break;
+       case 3:
+               val64 = 0x0001000102000001ULL;
+               writeq(val64, &bar0->rx_w_round_robin_0);
+               val64 = 0x0001020000010001ULL;
+               writeq(val64, &bar0->rx_w_round_robin_1);
+               val64 = 0x0200000100010200ULL;
+               writeq(val64, &bar0->rx_w_round_robin_2);
+               val64 = 0x0001000102000001ULL;
+               writeq(val64, &bar0->rx_w_round_robin_3);
+               val64 = 0x0001020000000000ULL;
+               writeq(val64, &bar0->rx_w_round_robin_4);
+
+               val64 = 0x8080804040402020ULL;
+               writeq(val64, &bar0->rts_qos_steering);
+               break;
+       case 4:
+               val64 = 0x0001020300010200ULL;
+               writeq(val64, &bar0->rx_w_round_robin_0);
+               val64 = 0x0100000102030001ULL;
+               writeq(val64, &bar0->rx_w_round_robin_1);
+               val64 = 0x0200010000010203ULL;
+               writeq(val64, &bar0->rx_w_round_robin_2);
+               val64 = 0x0001020001000001ULL;  
+               writeq(val64, &bar0->rx_w_round_robin_3);
+               val64 = 0x0203000100000000ULL;
+               writeq(val64, &bar0->rx_w_round_robin_4);
+
+               val64 = 0x8080404020201010ULL;
+               writeq(val64, &bar0->rts_qos_steering);
+               break;
+       case 5:
+               val64 = 0x0001000203000102ULL;
+               writeq(val64, &bar0->rx_w_round_robin_0);
+               val64 = 0x0001020001030004ULL;
+               writeq(val64, &bar0->rx_w_round_robin_1);
+               val64 = 0x0001000203000102ULL;
+               writeq(val64, &bar0->rx_w_round_robin_2);
+               val64 = 0x0001020001030004ULL;
+               writeq(val64, &bar0->rx_w_round_robin_3);
+               val64 = 0x0001000000000000ULL;
+               writeq(val64, &bar0->rx_w_round_robin_4);
+
+               val64 = 0x8080404020201008ULL;
+               writeq(val64, &bar0->rts_qos_steering);
+               break;
+       case 6:
+               val64 = 0x0001020304000102ULL;
+               writeq(val64, &bar0->rx_w_round_robin_0);
+               val64 = 0x0304050001020001ULL;
+               writeq(val64, &bar0->rx_w_round_robin_1);
+               val64 = 0x0203000100000102ULL;
+               writeq(val64, &bar0->rx_w_round_robin_2);
+               val64 = 0x0304000102030405ULL;
+               writeq(val64, &bar0->rx_w_round_robin_3);
+               val64 = 0x0001000200000000ULL;
+               writeq(val64, &bar0->rx_w_round_robin_4);
+
+               val64 = 0x8080404020100804ULL;
+               writeq(val64, &bar0->rts_qos_steering);
+               break;
+       case 7:
+               val64 = 0x0001020001020300ULL;
+               writeq(val64, &bar0->rx_w_round_robin_0);
+               val64 = 0x0102030400010203ULL;
+               writeq(val64, &bar0->rx_w_round_robin_1);
+               val64 = 0x0405060001020001ULL;
+               writeq(val64, &bar0->rx_w_round_robin_2);
+               val64 = 0x0304050000010200ULL;
+               writeq(val64, &bar0->rx_w_round_robin_3);
+               val64 = 0x0102030000000000ULL;
+               writeq(val64, &bar0->rx_w_round_robin_4);
+
+               val64 = 0x8080402010080402ULL;
+               writeq(val64, &bar0->rts_qos_steering);
+               break;
+       case 8:
+               val64 = 0x0001020300040105ULL;
+               writeq(val64, &bar0->rx_w_round_robin_0);
+               val64 = 0x0200030106000204ULL;
+               writeq(val64, &bar0->rx_w_round_robin_1);
+               val64 = 0x0103000502010007ULL;
+               writeq(val64, &bar0->rx_w_round_robin_2);
+               val64 = 0x0304010002060500ULL;
+               writeq(val64, &bar0->rx_w_round_robin_3);
+               val64 = 0x0103020400000000ULL;
+               writeq(val64, &bar0->rx_w_round_robin_4);
+
+               val64 = 0x8040201008040201ULL;
+               writeq(val64, &bar0->rts_qos_steering);
+               break;
+       }
 
        /* UDP Fix */
        val64 = 0;
-       for (i = 1; i < 8; i++)
+       for (i = 0; i < 8; i++)
                writeq(val64, &bar0->rts_frm_len_n[i]);
 
-       /* Set rts_frm_len register for fifo 0 */
-       writeq(MAC_RTS_FRM_LEN_SET(dev->mtu + 22),
-              &bar0->rts_frm_len_n[0]);
+       /* Set the default rts frame length for the rings configured */
+       val64 = MAC_RTS_FRM_LEN_SET(dev->mtu+22);
+       for (i = 0 ; i < config->rx_ring_num ; i++)
+               writeq(val64, &bar0->rts_frm_len_n[i]);
+
+       /* Set the frame length for the configured rings
+        * desired by the user
+        */
+       for (i = 0; i < config->rx_ring_num; i++) {
+               /* If rts_frm_len[i] == 0 then it is assumed that user not
+                * specified frame length steering.
+                * If the user provides the frame length then program
+                * the rts_frm_len register for those values or else
+                * leave it as it is.
+                */
+               if (rts_frm_len[i] != 0) {
+                       writeq(MAC_RTS_FRM_LEN_SET(rts_frm_len[i]),
+                               &bar0->rts_frm_len_n[i]);
+               }
+       }
 
-       /* Enable statistics */
+       /* Program statistics memory */
        writeq(mac_control->stats_mem_phy, &bar0->stat_addr);
-       val64 = SET_UPDT_PERIOD(Stats_refresh_time) |
-           STAT_CFG_STAT_RO | STAT_CFG_STAT_EN;
-       writeq(val64, &bar0->stat_cfg);
 
-       /* 
+       if (nic->device_type == XFRAME_II_DEVICE) {
+               val64 = STAT_BC(0x320);
+               writeq(val64, &bar0->stat_byte_cnt);
+       }
+
+       /*
         * Initializing the sampling rate for the device to calculate the
         * bandwidth utilization.
         */
@@ -857,30 +1261,38 @@ static int init_nic(struct s2io_nic *nic)
        writeq(val64, &bar0->mac_link_util);
 
 
-       /* 
-        * Initializing the Transmit and Receive Traffic Interrupt 
+       /*
+        * Initializing the Transmit and Receive Traffic Interrupt
         * Scheme.
         */
-       /* TTI Initialization. Default Tx timer gets us about
+       /*
+        * TTI Initialization. Default Tx timer gets us about
         * 250 interrupts per sec. Continuous interrupts are enabled
         * by default.
         */
-       val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078) |
-           TTI_DATA1_MEM_TX_URNG_A(0xA) |
+       if (nic->device_type == XFRAME_II_DEVICE) {
+               int count = (nic->config.bus_speed * 125)/2;
+               val64 = TTI_DATA1_MEM_TX_TIMER_VAL(count);
+       } else {
+
+               val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078);
+       }
+       val64 |= TTI_DATA1_MEM_TX_URNG_A(0xA) |
            TTI_DATA1_MEM_TX_URNG_B(0x10) |
-           TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN |
-               TTI_DATA1_MEM_TX_TIMER_CI_EN;
+           TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN;
+               if (use_continuous_tx_intrs)
+                       val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN;
        writeq(val64, &bar0->tti_data1_mem);
 
        val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) |
            TTI_DATA2_MEM_TX_UFC_B(0x20) |
-           TTI_DATA2_MEM_TX_UFC_C(0x40) | TTI_DATA2_MEM_TX_UFC_D(0x80);
+           TTI_DATA2_MEM_TX_UFC_C(0x70) | TTI_DATA2_MEM_TX_UFC_D(0x80);
        writeq(val64, &bar0->tti_data2_mem);
 
        val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD;
        writeq(val64, &bar0->tti_command_mem);
 
-       /* 
+       /*
         * Once the operation completes, the Strobe bit of the command
         * register will be reset. We poll for this particular condition
         * We wait for a maximum of 500ms for the operation to complete,
@@ -901,52 +1313,97 @@ static int init_nic(struct s2io_nic *nic)
                time++;
        }
 
-       /* RTI Initialization */
-       val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF) |
-           RTI_DATA1_MEM_RX_URNG_A(0xA) |
-           RTI_DATA1_MEM_RX_URNG_B(0x10) |
-           RTI_DATA1_MEM_RX_URNG_C(0x30) | RTI_DATA1_MEM_RX_TIMER_AC_EN;
+       if (nic->config.bimodal) {
+               int k = 0;
+               for (k = 0; k < config->rx_ring_num; k++) {
+                       val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD;
+                       val64 |= TTI_CMD_MEM_OFFSET(0x38+k);
+                       writeq(val64, &bar0->tti_command_mem);
+
+               /*
+                * Once the operation completes, the Strobe bit of the command
+                * register will be reset. We poll for this particular condition
+                * We wait for a maximum of 500ms for the operation to complete,
+                * if it's not complete by then we return error.
+               */
+                       time = 0;
+                       while (TRUE) {
+                               val64 = readq(&bar0->tti_command_mem);
+                               if (!(val64 & TTI_CMD_MEM_STROBE_NEW_CMD)) {
+                                       break;
+                               }
+                               if (time > 10) {
+                                       DBG_PRINT(ERR_DBG,
+                                               "%s: TTI init Failed\n",
+                                       dev->name);
+                                       return -1;
+                               }
+                               time++;
+                               msleep(50);
+                       }
+               }
+       } else {
 
-       writeq(val64, &bar0->rti_data1_mem);
+               /* RTI Initialization */
+               if (nic->device_type == XFRAME_II_DEVICE) {
+                       /*
+                        * Programmed to generate Apprx 500 Intrs per
+                        * second
+                        */
+                       int count = (nic->config.bus_speed * 125)/4;
+                       val64 = RTI_DATA1_MEM_RX_TIMER_VAL(count);
+               } else {
+                       val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF);
+               }
+               val64 |= RTI_DATA1_MEM_RX_URNG_A(0xA) |
+                   RTI_DATA1_MEM_RX_URNG_B(0x10) |
+                   RTI_DATA1_MEM_RX_URNG_C(0x30) | RTI_DATA1_MEM_RX_TIMER_AC_EN;
 
-       val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
-           RTI_DATA2_MEM_RX_UFC_B(0x2) |
-           RTI_DATA2_MEM_RX_UFC_C(0x40) | RTI_DATA2_MEM_RX_UFC_D(0x80);
-       writeq(val64, &bar0->rti_data2_mem);
+               writeq(val64, &bar0->rti_data1_mem);
 
-       val64 = RTI_CMD_MEM_WE | RTI_CMD_MEM_STROBE_NEW_CMD;
-       writeq(val64, &bar0->rti_command_mem);
+               val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
+                   RTI_DATA2_MEM_RX_UFC_B(0x2) |
+                   RTI_DATA2_MEM_RX_UFC_C(0x40) | RTI_DATA2_MEM_RX_UFC_D(0x80);
+               writeq(val64, &bar0->rti_data2_mem);
 
-       /* 
-        * Once the operation completes, the Strobe bit of the command
-        * register will be reset. We poll for this particular condition
-        * We wait for a maximum of 500ms for the operation to complete,
-        * if it's not complete by then we return error.
-        */
-       time = 0;
-       while (TRUE) {
-               val64 = readq(&bar0->rti_command_mem);
-               if (!(val64 & TTI_CMD_MEM_STROBE_NEW_CMD)) {
-                       break;
-               }
-               if (time > 10) {
-                       DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n",
-                                 dev->name);
-                       return -1;
+               for (i = 0; i < config->rx_ring_num; i++) {
+                       val64 = RTI_CMD_MEM_WE | RTI_CMD_MEM_STROBE_NEW_CMD
+                                       | RTI_CMD_MEM_OFFSET(i);
+                       writeq(val64, &bar0->rti_command_mem);
+
+                       /*
+                        * Once the operation completes, the Strobe bit of the
+                        * command register will be reset. We poll for this
+                        * particular condition. We wait for a maximum of 500ms
+                        * for the operation to complete, if it's not complete
+                        * by then we return error.
+                        */
+                       time = 0;
+                       while (TRUE) {
+                               val64 = readq(&bar0->rti_command_mem);
+                               if (!(val64 & RTI_CMD_MEM_STROBE_NEW_CMD)) {
+                                       break;
+                               }
+                               if (time > 10) {
+                                       DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n",
+                                                 dev->name);
+                                       return -1;
+                               }
+                               time++;
+                               msleep(50);
+                       }
                }
-               time++;
-               msleep(50);
        }
 
-       /* 
-        * Initializing proper values as Pause threshold into all 
+       /*
+        * Initializing proper values as Pause threshold into all
         * the 8 Queues on Rx side.
         */
        writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q0q3);
        writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q4q7);
 
        /* Disable RMAC PAD STRIPPING */
-       add = &bar0->mac_cfg;
+       add = (void *) &bar0->mac_cfg;
        val64 = readq(&bar0->mac_cfg);
        val64 &= ~(MAC_CFG_RMAC_STRIP_PAD);
        writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
@@ -955,8 +1412,8 @@ static int init_nic(struct s2io_nic *nic)
        writel((u32) (val64 >> 32), (add + 4));
        val64 = readq(&bar0->mac_cfg);
 
-       /* 
-        * Set the time value to be inserted in the pause frame 
+       /*
+        * Set the time value to be inserted in the pause frame
         * generated by xena.
         */
        val64 = readq(&bar0->rmac_pause_cfg);
@@ -964,7 +1421,7 @@ static int init_nic(struct s2io_nic *nic)
        val64 |= RMAC_PAUSE_HG_PTIME(nic->mac_control.rmac_pause_time);
        writeq(val64, &bar0->rmac_pause_cfg);
 
-       /* 
+       /*
         * Set the Threshold Limit for Generating the pause frame
         * If the amount of data in any Queue exceeds ratio of
         * (mac_control.mc_pause_threshold_q0q3 or q4q7)/256
@@ -988,25 +1445,54 @@ static int init_nic(struct s2io_nic *nic)
        }
        writeq(val64, &bar0->mc_pause_thresh_q4q7);
 
-       /* 
-        * TxDMA will stop Read request if the number of read split has 
+       /*
+        * TxDMA will stop Read request if the number of read split has
         * exceeded the limit pointed by shared_splits
         */
        val64 = readq(&bar0->pic_control);
        val64 |= PIC_CNTL_SHARED_SPLITS(shared_splits);
        writeq(val64, &bar0->pic_control);
 
+       /*
+        * Programming the Herc to split every write transaction
+        * that does not start on an ADB to reduce disconnects.
+        */
+       if (nic->device_type == XFRAME_II_DEVICE) {
+               val64 = WREQ_SPLIT_MASK_SET_MASK(255);
+               writeq(val64, &bar0->wreq_split_mask);
+       }
+
+       /* Setting Link stability period to 64 ms */ 
+       if (nic->device_type == XFRAME_II_DEVICE) {
+               val64 = MISC_LINK_STABILITY_PRD(3);
+               writeq(val64, &bar0->misc_control);
+       }
+
        return SUCCESS;
 }
+#define LINK_UP_DOWN_INTERRUPT         1
+#define MAC_RMAC_ERR_TIMER             2
 
-/**  
- *  en_dis_able_nic_intrs - Enable or Disable the interrupts 
+#if defined(CONFIG_MSI_MODE) || defined(CONFIG_MSIX_MODE)
+#define s2io_link_fault_indication(x) MAC_RMAC_ERR_TIMER
+#else
+int s2io_link_fault_indication(nic_t *nic)
+{
+       if (nic->device_type == XFRAME_II_DEVICE)
+               return LINK_UP_DOWN_INTERRUPT;
+       else
+               return MAC_RMAC_ERR_TIMER;
+}
+#endif
+
+/**
+ *  en_dis_able_nic_intrs - Enable or Disable the interrupts
  *  @nic: device private variable,
  *  @mask: A mask indicating which Intr block must be modified and,
  *  @flag: A flag indicating whether to enable or disable the Intrs.
  *  Description: This function will either disable or enable the interrupts
- *  depending on the flag argument. The mask argument can be used to 
- *  enable/disable any Intr block. 
+ *  depending on the flag argument. The mask argument can be used to
+ *  enable/disable any Intr block.
  *  Return Value: NONE.
  */
 
@@ -1024,20 +1510,31 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
                        temp64 = readq(&bar0->general_int_mask);
                        temp64 &= ~((u64) val64);
                        writeq(temp64, &bar0->general_int_mask);
-                       /*  
-                        * Disabled all PCIX, Flash, MDIO, IIC and GPIO
-                        * interrupts for now. 
-                        * TODO 
+                       /*
+                        * If Hercules adapter enable GPIO otherwise
+                        * disabled all PCIX, Flash, MDIO, IIC and GPIO
+                        * interrupts for now.
+                        * TODO
                         */
-                       writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
-                       /* 
+                       if (s2io_link_fault_indication(nic) ==
+                                       LINK_UP_DOWN_INTERRUPT ) {
+                               temp64 = readq(&bar0->pic_int_mask);
+                               temp64 &= ~((u64) PIC_INT_GPIO);
+                               writeq(temp64, &bar0->pic_int_mask);
+                               temp64 = readq(&bar0->gpio_int_mask);
+                               temp64 &= ~((u64) GPIO_INT_MASK_LINK_UP);
+                               writeq(temp64, &bar0->gpio_int_mask);
+                       } else {
+                               writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
+                       }
+                       /*
                         * No MSI Support is available presently, so TTI and
                         * RTI interrupts are also disabled.
                         */
                } else if (flag == DISABLE_INTRS) {
-                       /*  
-                        * Disable PIC Intrs in the general 
-                        * intr mask register 
+                       /*
+                        * Disable PIC Intrs in the general
+                        * intr mask register
                         */
                        writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
                        temp64 = readq(&bar0->general_int_mask);
@@ -1055,27 +1552,27 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
                        temp64 = readq(&bar0->general_int_mask);
                        temp64 &= ~((u64) val64);
                        writeq(temp64, &bar0->general_int_mask);
-                       /* 
-                        * Keep all interrupts other than PFC interrupt 
+                       /*
+                        * Keep all interrupts other than PFC interrupt
                         * and PCC interrupt disabled in DMA level.
                         */
                        val64 = DISABLE_ALL_INTRS & ~(TXDMA_PFC_INT_M |
                                                      TXDMA_PCC_INT_M);
                        writeq(val64, &bar0->txdma_int_mask);
-                       /* 
-                        * Enable only the MISC error 1 interrupt in PFC block 
+                       /*
+                        * Enable only the MISC error 1 interrupt in PFC block
                         */
                        val64 = DISABLE_ALL_INTRS & (~PFC_MISC_ERR_1);
                        writeq(val64, &bar0->pfc_err_mask);
-                       /* 
-                        * Enable only the FB_ECC error interrupt in PCC block 
+                       /*
+                        * Enable only the FB_ECC error interrupt in PCC block
                         */
                        val64 = DISABLE_ALL_INTRS & (~PCC_FB_ECC_ERR);
                        writeq(val64, &bar0->pcc_err_mask);
                } else if (flag == DISABLE_INTRS) {
-                       /* 
-                        * Disable TxDMA Intrs in the general intr mask 
-                        * register 
+                       /*
+                        * Disable TxDMA Intrs in the general intr mask
+                        * register
                         */
                        writeq(DISABLE_ALL_INTRS, &bar0->txdma_int_mask);
                        writeq(DISABLE_ALL_INTRS, &bar0->pfc_err_mask);
@@ -1093,15 +1590,15 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
                        temp64 = readq(&bar0->general_int_mask);
                        temp64 &= ~((u64) val64);
                        writeq(temp64, &bar0->general_int_mask);
-                       /* 
-                        * All RxDMA block interrupts are disabled for now 
-                        * TODO 
+                       /*
+                        * All RxDMA block interrupts are disabled for now
+                        * TODO
                         */
                        writeq(DISABLE_ALL_INTRS, &bar0->rxdma_int_mask);
                } else if (flag == DISABLE_INTRS) {
-                       /*  
-                        * Disable RxDMA Intrs in the general intr mask 
-                        * register 
+                       /*
+                        * Disable RxDMA Intrs in the general intr mask
+                        * register
                         */
                        writeq(DISABLE_ALL_INTRS, &bar0->rxdma_int_mask);
                        temp64 = readq(&bar0->general_int_mask);
@@ -1118,22 +1615,13 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
                        temp64 = readq(&bar0->general_int_mask);
                        temp64 &= ~((u64) val64);
                        writeq(temp64, &bar0->general_int_mask);
-                       /* 
-                        * All MAC block error interrupts are disabled for now 
-                        * except the link status change interrupt.
+                       /*
+                        * All MAC block error interrupts are disabled for now
                         * TODO
                         */
-                       val64 = MAC_INT_STATUS_RMAC_INT;
-                       temp64 = readq(&bar0->mac_int_mask);
-                       temp64 &= ~((u64) val64);
-                       writeq(temp64, &bar0->mac_int_mask);
-
-                       val64 = readq(&bar0->mac_rmac_err_mask);
-                       val64 &= ~((u64) RMAC_LINK_STATE_CHANGE_INT);
-                       writeq(val64, &bar0->mac_rmac_err_mask);
                } else if (flag == DISABLE_INTRS) {
-                       /*  
-                        * Disable MAC Intrs in the general intr mask register 
+                       /*
+                        * Disable MAC Intrs in the general intr mask register
                         */
                        writeq(DISABLE_ALL_INTRS, &bar0->mac_int_mask);
                        writeq(DISABLE_ALL_INTRS,
@@ -1152,14 +1640,14 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
                        temp64 = readq(&bar0->general_int_mask);
                        temp64 &= ~((u64) val64);
                        writeq(temp64, &bar0->general_int_mask);
-                       /* 
+                       /*
                         * All XGXS block error interrupts are disabled for now
-                        * TODO 
+                        * TODO
                         */
                        writeq(DISABLE_ALL_INTRS, &bar0->xgxs_int_mask);
                } else if (flag == DISABLE_INTRS) {
-                       /*  
-                        * Disable MC Intrs in the general intr mask register 
+                       /*
+                        * Disable MC Intrs in the general intr mask register
                         */
                        writeq(DISABLE_ALL_INTRS, &bar0->xgxs_int_mask);
                        temp64 = readq(&bar0->general_int_mask);
@@ -1175,11 +1663,11 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
                        temp64 = readq(&bar0->general_int_mask);
                        temp64 &= ~((u64) val64);
                        writeq(temp64, &bar0->general_int_mask);
-                       /* 
-                        * All MC block error interrupts are disabled for now
-                        * TODO 
+                       /*
+                        * Enable all MC Intrs.
                         */
-                       writeq(DISABLE_ALL_INTRS, &bar0->mc_int_mask);
+                       writeq(0x0, &bar0->mc_int_mask);
+                       writeq(0x0, &bar0->mc_err_mask);
                } else if (flag == DISABLE_INTRS) {
                        /*
                         * Disable MC Intrs in the general intr mask register
@@ -1199,14 +1687,14 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
                        temp64 = readq(&bar0->general_int_mask);
                        temp64 &= ~((u64) val64);
                        writeq(temp64, &bar0->general_int_mask);
-                       /* 
+                       /*
                         * Enable all the Tx side interrupts
-                        * writing 0 Enables all 64 TX interrupt levels 
+                        * writing 0 Enables all 64 TX interrupt levels
                         */
                        writeq(0x0, &bar0->tx_traffic_mask);
                } else if (flag == DISABLE_INTRS) {
-                       /* 
-                        * Disable Tx Traffic Intrs in the general intr mask 
+                       /*
+                        * Disable Tx Traffic Intrs in the general intr mask
                         * register.
                         */
                        writeq(DISABLE_ALL_INTRS, &bar0->tx_traffic_mask);
@@ -1226,8 +1714,8 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
                        /* writing 0 Enables all 8 RX interrupt levels */
                        writeq(0x0, &bar0->rx_traffic_mask);
                } else if (flag == DISABLE_INTRS) {
-                       /*  
-                        * Disable Rx Traffic Intrs in the general intr mask 
+                       /*
+                        * Disable Rx Traffic Intrs in the general intr mask
                         * register.
                         */
                        writeq(DISABLE_ALL_INTRS, &bar0->rx_traffic_mask);
@@ -1238,24 +1726,66 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
        }
 }
 
-/**  
- *  verify_xena_quiescence - Checks whether the H/W is ready 
+static int check_prc_pcc_state(u64 val64, int flag, int rev_id, int herc)
+{
+       int ret = 0;
+
+       if (flag == FALSE) {
+               if ((!herc && (rev_id >= 4)) || herc) {
+                       if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) &&
+                           ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
+                            ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
+                               ret = 1;
+                       }
+               }else {
+                       if (!(val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) &&
+                           ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
+                            ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
+                               ret = 1;
+                       }
+               }
+       } else {
+               if ((!herc && (rev_id >= 4)) || herc) {
+                       if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) ==
+                            ADAPTER_STATUS_RMAC_PCC_IDLE) &&
+                           (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ||
+                            ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
+                             ADAPTER_STATUS_RC_PRC_QUIESCENT))) {
+                               ret = 1;
+                       }
+               } else {
+                       if (((val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) ==
+                            ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) &&
+                           (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ||
+                            ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
+                             ADAPTER_STATUS_RC_PRC_QUIESCENT))) {
+                               ret = 1;
+                       }
+               }
+       }
+
+       return ret;
+}
+/**
+ *  verify_xena_quiescence - Checks whether the H/W is ready
  *  @val64 :  Value read from adapter status register.
  *  @flag : indicates if the adapter enable bit was ever written once
  *  before.
  *  Description: Returns whether the H/W is ready to go or not. Depending
- *  on whether adapter enable bit was written or not the comparison 
+ *  on whether adapter enable bit was written or not the comparison
  *  differs and the calling function passes the input argument flag to
  *  indicate this.
- *  Return: 1 If xena is quiescence 
+ *  Return: 1 If xena is quiescence
  *          0 If Xena is not quiescence
  */
 
-static int verify_xena_quiescence(u64 val64, int flag)
+static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag)
 {
-       int ret = 0;
+       int ret = 0, herc;
        u64 tmp64 = ~((u64) val64);
+       int rev_id = get_xena_rev_id(sp->pdev);
 
+       herc = (sp->device_type == XFRAME_II_DEVICE);
        if (!
            (tmp64 &
             (ADAPTER_STATUS_TDMA_READY | ADAPTER_STATUS_RDMA_READY |
@@ -1263,25 +1793,7 @@ static int verify_xena_quiescence(u64 val64, int flag)
              ADAPTER_STATUS_PIC_QUIESCENT | ADAPTER_STATUS_MC_DRAM_READY |
              ADAPTER_STATUS_MC_QUEUES_READY | ADAPTER_STATUS_M_PLL_LOCK |
              ADAPTER_STATUS_P_PLL_LOCK))) {
-               if (flag == FALSE) {
-                       if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) &&
-                           ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
-                            ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
-
-                               ret = 1;
-
-                       }
-               } else {
-                       if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) ==
-                            ADAPTER_STATUS_RMAC_PCC_IDLE) &&
-                           (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ||
-                            ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
-                             ADAPTER_STATUS_RC_PRC_QUIESCENT))) {
-
-                               ret = 1;
-
-                       }
-               }
+               ret = check_prc_pcc_state(val64, flag, rev_id, herc);
        }
 
        return ret;
@@ -1290,12 +1802,12 @@ static int verify_xena_quiescence(u64 val64, int flag)
 /**
  * fix_mac_address -  Fix for Mac addr problem on Alpha platforms
  * @sp: Pointer to device specifc structure
- * Description : 
+ * Description :
  * New procedure to clear mac address reading  problems on Alpha platforms
  *
  */
 
-static void fix_mac_address(nic_t * sp)
+void fix_mac_address(nic_t * sp)
 {
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
        u64 val64;
@@ -1303,20 +1815,21 @@ static void fix_mac_address(nic_t * sp)
 
        while (fix_mac[i] != END_SIGN) {
                writeq(fix_mac[i++], &bar0->gpio_control);
+               udelay(10);
                val64 = readq(&bar0->gpio_control);
        }
 }
 
 /**
- *  start_nic - Turns the device on   
+ *  start_nic - Turns the device on
  *  @nic : device private variable.
- *  Description: 
- *  This function actually turns the device on. Before this  function is 
- *  called,all Registers are configured from their reset states 
- *  and shared memory is allocated but the NIC is still quiescent. On 
+ *  Description:
+ *  This function actually turns the device on. Before this  function is
+ *  called,all Registers are configured from their reset states
+ *  and shared memory is allocated but the NIC is still quiescent. On
  *  calling this function, the device interrupts are cleared and the NIC is
  *  literally switched on by writing into the adapter control register.
- *  Return Value: 
+ *  Return Value:
  *  SUCCESS on success and -1 on failure.
  */
 
@@ -1325,8 +1838,8 @@ static int start_nic(struct s2io_nic *nic)
        XENA_dev_config_t __iomem *bar0 = nic->bar0;
        struct net_device *dev = nic->dev;
        register u64 val64 = 0;
-       u16 interruptible, i;
-       u16 subid;
+       u16 interruptible;
+       u16 subid, i;
        mac_info_t *mac_control;
        struct config_param *config;
 
@@ -1335,10 +1848,12 @@ static int start_nic(struct s2io_nic *nic)
 
        /*  PRC Initialization and configuration */
        for (i = 0; i < config->rx_ring_num; i++) {
-               writeq((u64) nic->rx_blocks[i][0].block_dma_addr,
+               writeq((u64) mac_control->rings[i].rx_blocks[0].block_dma_addr,
                       &bar0->prc_rxd0_n[i]);
 
                val64 = readq(&bar0->prc_ctrl_n[i]);
+               if (nic->config.bimodal)
+                       val64 |= PRC_CTRL_BIMODAL_INTERRUPT;
 #ifndef CONFIG_2BUFF_MODE
                val64 |= PRC_CTRL_RC_ENABLED;
 #else
@@ -1354,7 +1869,7 @@ static int start_nic(struct s2io_nic *nic)
        writeq(val64, &bar0->rx_pa_cfg);
 #endif
 
-       /* 
+       /*
         * Enabling MC-RLDRAM. After enabling the device, we timeout
         * for around 100ms, which is approximately the time required
         * for the device to be ready for operation.
@@ -1364,27 +1879,27 @@ static int start_nic(struct s2io_nic *nic)
        SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_mrs, UF);
        val64 = readq(&bar0->mc_rldram_mrs);
 
-       msleep(100);                    /* Delay by around 100 ms. */
+       msleep(100);    /* Delay by around 100 ms. */
 
        /* Enabling ECC Protection. */
        val64 = readq(&bar0->adapter_control);
        val64 &= ~ADAPTER_ECC_EN;
        writeq(val64, &bar0->adapter_control);
 
-       /* 
-        * Clearing any possible Link state change interrupts that 
+       /*
+        * Clearing any possible Link state change interrupts that
         * could have popped up just before Enabling the card.
         */
        val64 = readq(&bar0->mac_rmac_err_reg);
        if (val64)
                writeq(val64, &bar0->mac_rmac_err_reg);
 
-       /* 
-        * Verify if the device is ready to be enabled, if so enable 
+       /*
+        * Verify if the device is ready to be enabled, if so enable
         * it.
         */
        val64 = readq(&bar0->adapter_status);
-       if (!verify_xena_quiescence(val64, nic->device_enabled_once)) {
+       if (!verify_xena_quiescence(nic, val64, nic->device_enabled_once)) {
                DBG_PRINT(ERR_DBG, "%s: device is not ready, ", dev->name);
                DBG_PRINT(ERR_DBG, "Adapter status reads: 0x%llx\n",
                          (unsigned long long) val64);
@@ -1392,16 +1907,18 @@ static int start_nic(struct s2io_nic *nic)
        }
 
        /*  Enable select interrupts */
-       interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR |
-           RX_MAC_INTR;
+       interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
+       interruptible |= TX_PIC_INTR | RX_PIC_INTR;
+       interruptible |= TX_MAC_INTR | RX_MAC_INTR;
+
        en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
 
-       /* 
+       /*
         * With some switches, link might be already up at this point.
-        * Because of this weird behavior, when we enable laser, 
-        * we may not get link. We need to handle this. We cannot 
-        * figure out which switch is misbehaving. So we are forced to 
-        * make a global change. 
+        * Because of this weird behavior, when we enable laser,
+        * we may not get link. We need to handle this. We cannot
+        * figure out which switch is misbehaving. So we are forced to
+        * make a global change.
         */
 
        /* Enabling Laser. */
@@ -1411,44 +1928,30 @@ static int start_nic(struct s2io_nic *nic)
 
        /* SXE-002: Initialize link and activity LED */
        subid = nic->pdev->subsystem_device;
-       if ((subid & 0xFF) >= 0x07) {
+       if (((subid & 0xFF) >= 0x07) &&
+           (nic->device_type == XFRAME_I_DEVICE)) {
                val64 = readq(&bar0->gpio_control);
                val64 |= 0x0000800000000000ULL;
                writeq(val64, &bar0->gpio_control);
                val64 = 0x0411040400000000ULL;
-               writeq(val64, (void __iomem *) bar0 + 0x2700);
+               writeq(val64, (void __iomem *) ((u8 *) bar0 + 0x2700));
        }
 
-       /* 
-        * Don't see link state interrupts on certain switches, so 
+       /*
+        * Don't see link state interrupts on certain switches, so
         * directly scheduling a link state task from here.
         */
        schedule_work(&nic->set_link_task);
 
-       /* 
-        * Here we are performing soft reset on XGXS to 
-        * force link down. Since link is already up, we will get
-        * link state change interrupt after this reset
-        */
-       SPECIAL_REG_WRITE(0x80010515001E0000ULL, &bar0->dtx_control, UF);
-       val64 = readq(&bar0->dtx_control);
-       udelay(50);
-       SPECIAL_REG_WRITE(0x80010515001E00E0ULL, &bar0->dtx_control, UF);
-       val64 = readq(&bar0->dtx_control);
-       udelay(50);
-       SPECIAL_REG_WRITE(0x80070515001F00E4ULL, &bar0->dtx_control, UF);
-       val64 = readq(&bar0->dtx_control);
-       udelay(50);
-
        return SUCCESS;
 }
 
-/** 
- *  free_tx_buffers - Free all queued Tx buffers 
+/**
+ *  free_tx_buffers - Free all queued Tx buffers
  *  @nic : device private variable.
- *  Description: 
+ *  Description:
  *  Free all queued Tx buffers.
- *  Return Value: void 
+ *  Return Value: void
 */
 
 static void free_tx_buffers(struct s2io_nic *nic)
@@ -1459,39 +1962,61 @@ static void free_tx_buffers(struct s2io_nic *nic)
        int i, j;
        mac_info_t *mac_control;
        struct config_param *config;
-       int cnt = 0;
+       int cnt = 0, frg_cnt;
 
        mac_control = &nic->mac_control;
        config = &nic->config;
 
        for (i = 0; i < config->tx_fifo_num; i++) {
                for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) {
-                       txdp = (TxD_t *) nic->list_info[i][j].
+                       txdp = (TxD_t *) mac_control->fifos[i].list_info[j].
                            list_virt_addr;
                        skb =
                            (struct sk_buff *) ((unsigned long) txdp->
                                                Host_Control);
                        if (skb == NULL) {
-                               memset(txdp, 0, sizeof(TxD_t));
+                               memset(txdp, 0, sizeof(TxD_t) *
+                                      config->max_txds);
                                continue;
                        }
+                       frg_cnt = skb_shinfo(skb)->nr_frags;
+                       pci_unmap_single(nic->pdev, (dma_addr_t)
+                                        txdp->Buffer_Pointer,
+                                        skb->len - skb->data_len,
+                                        PCI_DMA_TODEVICE);
+                       if (frg_cnt) {
+                               TxD_t *temp;
+                               temp = txdp;
+                               txdp++;
+                               for (j = 0; j < frg_cnt; j++, txdp++) {
+                                       skb_frag_t *frag =
+                                           &skb_shinfo(skb)->frags[j];
+                                       pci_unmap_page(nic->pdev,
+                                                      (dma_addr_t)
+                                                      txdp->
+                                                      Buffer_Pointer,
+                                                      frag->size,
+                                                      PCI_DMA_TODEVICE);
+                               }
+                               txdp = temp;
+                       }
                        dev_kfree_skb(skb);
-                       memset(txdp, 0, sizeof(TxD_t));
+                       memset(txdp, 0, sizeof(TxD_t) * config->max_txds);
                        cnt++;
                }
                DBG_PRINT(INTR_DBG,
                          "%s:forcibly freeing %d skbs on FIFO%d\n",
                          dev->name, cnt, i);
-               mac_control->tx_curr_get_info[i].offset = 0;
-               mac_control->tx_curr_put_info[i].offset = 0;
+               mac_control->fifos[i].tx_curr_get_info.offset = 0;
+               mac_control->fifos[i].tx_curr_put_info.offset = 0;
        }
 }
 
-/**  
- *   stop_nic -  To stop the nic  
+/**
+ *   stop_nic -  To stop the nic
  *   @nic ; device private variable.
- *   Description: 
- *   This function does exactly the opposite of what the start_nic() 
+ *   Description:
+ *   This function does exactly the opposite of what the start_nic()
  *   function does. This function is called to stop the device.
  *   Return Value:
  *   void.
@@ -1509,8 +2034,9 @@ static void stop_nic(struct s2io_nic *nic)
        config = &nic->config;
 
        /*  Disable all interrupts */
-       interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR |
-           RX_MAC_INTR;
+       interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
+       interruptible |= TX_PIC_INTR | RX_PIC_INTR;
+       interruptible |= TX_MAC_INTR | RX_MAC_INTR;
        en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS);
 
        /*  Disable PRCs */
@@ -1521,11 +2047,11 @@ static void stop_nic(struct s2io_nic *nic)
        }
 }
 
-/**  
- *  fill_rx_buffers - Allocates the Rx side skbs 
+/**
+ *  fill_rx_buffers - Allocates the Rx side skbs
  *  @nic:  device private variable
- *  @ring_no: ring number 
- *  Description: 
+ *  @ring_no: ring number
+ *  Description:
  *  The function allocates Rx side skbs and puts the physical
  *  address of these buffers into the RxD buffer pointers, so that the NIC
  *  can DMA the received frame into these locations.
@@ -1533,8 +2059,8 @@ static void stop_nic(struct s2io_nic *nic)
  *  1. single buffer,
  *  2. three buffer and
  *  3. Five buffer modes.
- *  Each mode defines how many fragments the received frame will be split 
- *  up into by the NIC. The frame is split into L3 header, L4 Header, 
+ *  Each mode defines how many fragments the received frame will be split
+ *  up into by the NIC. The frame is split into L3 header, L4 Header,
  *  L4 payload in three buffer mode and in 5 buffer mode, L4 payload itself
  *  is split into 3 fragments. As of now only single buffer mode is
  *  supported.
@@ -1542,7 +2068,7 @@ static void stop_nic(struct s2io_nic *nic)
  *  SUCCESS on success or an appropriate -ve value on failure.
  */
 
-static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
+int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
 {
        struct net_device *dev = nic->dev;
        struct sk_buff *skb;
@@ -1550,34 +2076,35 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
        int off, off1, size, block_no, block_no1;
        int offset, offset1;
        u32 alloc_tab = 0;
-       u32 alloc_cnt = nic->pkt_cnt[ring_no] -
-           atomic_read(&nic->rx_bufs_left[ring_no]);
+       u32 alloc_cnt;
        mac_info_t *mac_control;
        struct config_param *config;
 #ifdef CONFIG_2BUFF_MODE
        RxD_t *rxdpnext;
        int nextblk;
-       unsigned long tmp;
+       u64 tmp;
        buffAdd_t *ba;
        dma_addr_t rxdpphys;
 #endif
 #ifndef CONFIG_S2IO_NAPI
        unsigned long flags;
 #endif
+       RxD_t *first_rxdp = NULL;
 
        mac_control = &nic->mac_control;
        config = &nic->config;
-
+       alloc_cnt = mac_control->rings[ring_no].pkt_cnt -
+           atomic_read(&nic->rx_bufs_left[ring_no]);
        size = dev->mtu + HEADER_ETHERNET_II_802_3_SIZE +
            HEADER_802_2_SIZE + HEADER_SNAP_SIZE;
 
        while (alloc_tab < alloc_cnt) {
-               block_no = mac_control->rx_curr_put_info[ring_no].
+               block_no = mac_control->rings[ring_no].rx_curr_put_info.
                    block_index;
-               block_no1 = mac_control->rx_curr_get_info[ring_no].
+               block_no1 = mac_control->rings[ring_no].rx_curr_get_info.
                    block_index;
-               off = mac_control->rx_curr_put_info[ring_no].offset;
-               off1 = mac_control->rx_curr_get_info[ring_no].offset;
+               off = mac_control->rings[ring_no].rx_curr_put_info.offset;
+               off1 = mac_control->rings[ring_no].rx_curr_get_info.offset;
 #ifndef CONFIG_2BUFF_MODE
                offset = block_no * (MAX_RXDS_PER_BLOCK + 1) + off;
                offset1 = block_no1 * (MAX_RXDS_PER_BLOCK + 1) + off1;
@@ -1586,7 +2113,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                offset1 = block_no1 * (MAX_RXDS_PER_BLOCK) + off1;
 #endif
 
-               rxdp = nic->rx_blocks[ring_no][block_no].
+               rxdp = mac_control->rings[ring_no].rx_blocks[block_no].
                    block_virt_addr + off;
                if ((offset == offset1) && (rxdp->Host_Control)) {
                        DBG_PRINT(INTR_DBG, "%s: Get and Put", dev->name);
@@ -1595,15 +2122,15 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                }
 #ifndef        CONFIG_2BUFF_MODE
                if (rxdp->Control_1 == END_OF_BLOCK) {
-                       mac_control->rx_curr_put_info[ring_no].
+                       mac_control->rings[ring_no].rx_curr_put_info.
                            block_index++;
-                       mac_control->rx_curr_put_info[ring_no].
-                           block_index %= nic->block_count[ring_no];
-                       block_no = mac_control->rx_curr_put_info
-                           [ring_no].block_index;
+                       mac_control->rings[ring_no].rx_curr_put_info.
+                           block_index %= mac_control->rings[ring_no].block_count;
+                       block_no = mac_control->rings[ring_no].rx_curr_put_info.
+                               block_index;
                        off++;
                        off %= (MAX_RXDS_PER_BLOCK + 1);
-                       mac_control->rx_curr_put_info[ring_no].offset =
+                       mac_control->rings[ring_no].rx_curr_put_info.offset =
                            off;
                        rxdp = (RxD_t *) ((unsigned long) rxdp->Control_2);
                        DBG_PRINT(INTR_DBG, "%s: Next block at: %p\n",
@@ -1611,30 +2138,30 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                }
 #ifndef CONFIG_S2IO_NAPI
                spin_lock_irqsave(&nic->put_lock, flags);
-               nic->put_pos[ring_no] =
+               mac_control->rings[ring_no].put_pos =
                    (block_no * (MAX_RXDS_PER_BLOCK + 1)) + off;
                spin_unlock_irqrestore(&nic->put_lock, flags);
 #endif
 #else
                if (rxdp->Host_Control == END_OF_BLOCK) {
-                       mac_control->rx_curr_put_info[ring_no].
+                       mac_control->rings[ring_no].rx_curr_put_info.
                            block_index++;
-                       mac_control->rx_curr_put_info[ring_no].
-                           block_index %= nic->block_count[ring_no];
-                       block_no = mac_control->rx_curr_put_info
-                           [ring_no].block_index;
+                       mac_control->rings[ring_no].rx_curr_put_info.block_index
+                           %= mac_control->rings[ring_no].block_count;
+                       block_no = mac_control->rings[ring_no].rx_curr_put_info
+                           .block_index;
                        off = 0;
                        DBG_PRINT(INTR_DBG, "%s: block%d at: 0x%llx\n",
                                  dev->name, block_no,
                                  (unsigned long long) rxdp->Control_1);
-                       mac_control->rx_curr_put_info[ring_no].offset =
+                       mac_control->rings[ring_no].rx_curr_put_info.offset =
                            off;
-                       rxdp = nic->rx_blocks[ring_no][block_no].
+                       rxdp = mac_control->rings[ring_no].rx_blocks[block_no].
                            block_virt_addr;
                }
 #ifndef CONFIG_S2IO_NAPI
                spin_lock_irqsave(&nic->put_lock, flags);
-               nic->put_pos[ring_no] = (block_no *
+               mac_control->rings[ring_no].put_pos = (block_no *
                                         (MAX_RXDS_PER_BLOCK + 1)) + off;
                spin_unlock_irqrestore(&nic->put_lock, flags);
 #endif
@@ -1646,27 +2173,27 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                if (rxdp->Control_2 & BIT(0))
 #endif
                {
-                       mac_control->rx_curr_put_info[ring_no].
+                       mac_control->rings[ring_no].rx_curr_put_info.
                            offset = off;
                        goto end;
                }
 #ifdef CONFIG_2BUFF_MODE
-               /* 
-                * RxDs Spanning cache lines will be replenished only 
-                * if the succeeding RxD is also owned by Host. It 
-                * will always be the ((8*i)+3) and ((8*i)+6) 
-                * descriptors for the 48 byte descriptor. The offending 
+               /*
+                * RxDs Spanning cache lines will be replenished only
+                * if the succeeding RxD is also owned by Host. It
+                * will always be the ((8*i)+3) and ((8*i)+6)
+                * descriptors for the 48 byte descriptor. The offending
                 * decsriptor is of-course the 3rd descriptor.
                 */
-               rxdpphys = nic->rx_blocks[ring_no][block_no].
+               rxdpphys = mac_control->rings[ring_no].rx_blocks[block_no].
                    block_dma_addr + (off * sizeof(RxD_t));
                if (((u64) (rxdpphys)) % 128 > 80) {
-                       rxdpnext = nic->rx_blocks[ring_no][block_no].
+                       rxdpnext = mac_control->rings[ring_no].rx_blocks[block_no].
                            block_virt_addr + (off + 1);
                        if (rxdpnext->Host_Control == END_OF_BLOCK) {
                                nextblk = (block_no + 1) %
-                                   (nic->block_count[ring_no]);
-                               rxdpnext = nic->rx_blocks[ring_no]
+                                   (mac_control->rings[ring_no].block_count);
+                               rxdpnext = mac_control->rings[ring_no].rx_blocks
                                    [nextblk].block_virt_addr;
                        }
                        if (rxdpnext->Control_2 & BIT(0))
@@ -1682,6 +2209,10 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                if (!skb) {
                        DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name);
                        DBG_PRINT(ERR_DBG, "memory to allocate SKBs\n");
+                       if (first_rxdp) {
+                               wmb();
+                               first_rxdp->Control_1 |= RXD_OWN_XENA;
+                       }
                        return -ENOMEM;
                }
 #ifndef        CONFIG_2BUFF_MODE
@@ -1692,12 +2223,13 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                rxdp->Control_2 &= (~MASK_BUFFER0_SIZE);
                rxdp->Control_2 |= SET_BUFFER0_SIZE(size);
                rxdp->Host_Control = (unsigned long) (skb);
-               rxdp->Control_1 |= RXD_OWN_XENA;
+               if (alloc_tab & ((1 << rxsync_frequency) - 1))
+                       rxdp->Control_1 |= RXD_OWN_XENA;
                off++;
                off %= (MAX_RXDS_PER_BLOCK + 1);
-               mac_control->rx_curr_put_info[ring_no].offset = off;
+               mac_control->rings[ring_no].rx_curr_put_info.offset = off;
 #else
-               ba = &nic->ba[ring_no][block_no][off];
+               ba = &mac_control->rings[ring_no].ba[block_no][off];
                skb_reserve(skb, BUF0_LEN);
                tmp = ((unsigned long) skb->data & ALIGN_SIZE);
                if (tmp)
@@ -1719,22 +2251,41 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                rxdp->Control_2 |= SET_BUFFER1_SIZE(1); /* dummy. */
                rxdp->Control_2 |= BIT(0);      /* Set Buffer_Empty bit. */
                rxdp->Host_Control = (u64) ((unsigned long) (skb));
-               rxdp->Control_1 |= RXD_OWN_XENA;
+               if (alloc_tab & ((1 << rxsync_frequency) - 1))
+                       rxdp->Control_1 |= RXD_OWN_XENA;
                off++;
-               mac_control->rx_curr_put_info[ring_no].offset = off;
+               mac_control->rings[ring_no].rx_curr_put_info.offset = off;
 #endif
+               rxdp->Control_2 |= SET_RXD_MARKER;
+
+               if (!(alloc_tab & ((1 << rxsync_frequency) - 1))) {
+                       if (first_rxdp) {
+                               wmb();
+                               first_rxdp->Control_1 |= RXD_OWN_XENA;
+                       }
+                       first_rxdp = rxdp;
+               }
                atomic_inc(&nic->rx_bufs_left[ring_no]);
                alloc_tab++;
        }
 
       end:
+       /* Transfer ownership of first descriptor to adapter just before
+        * exiting. Before that, use memory barrier so that ownership
+        * and other fields are seen by adapter correctly.
+        */
+       if (first_rxdp) {
+               wmb();
+               first_rxdp->Control_1 |= RXD_OWN_XENA;
+       }
+
        return SUCCESS;
 }
 
 /**
- *  free_rx_buffers - Frees all Rx buffers   
+ *  free_rx_buffers - Frees all Rx buffers
  *  @sp: device private variable.
- *  Description: 
+ *  Description:
  *  This function will free all Rx buffers allocated by host.
  *  Return Value:
  *  NONE.
@@ -1758,7 +2309,8 @@ static void free_rx_buffers(struct s2io_nic *sp)
        for (i = 0; i < config->rx_ring_num; i++) {
                for (j = 0, blk = 0; j < config->rx_cfg[i].num_rxd; j++) {
                        off = j % (MAX_RXDS_PER_BLOCK + 1);
-                       rxdp = sp->rx_blocks[i][blk].block_virt_addr + off;
+                       rxdp = mac_control->rings[i].rx_blocks[blk].
+                               block_virt_addr + off;
 
 #ifndef CONFIG_2BUFF_MODE
                        if (rxdp->Control_1 == END_OF_BLOCK) {
@@ -1793,7 +2345,7 @@ static void free_rx_buffers(struct s2io_nic *sp)
                                                 HEADER_SNAP_SIZE,
                                                 PCI_DMA_FROMDEVICE);
 #else
-                               ba = &sp->ba[i][blk][off];
+                               ba = &mac_control->rings[i].ba[blk][off];
                                pci_unmap_single(sp->pdev, (dma_addr_t)
                                                 rxdp->Buffer0_ptr,
                                                 BUF0_LEN,
@@ -1813,10 +2365,10 @@ static void free_rx_buffers(struct s2io_nic *sp)
                        }
                        memset(rxdp, 0, sizeof(RxD_t));
                }
-               mac_control->rx_curr_put_info[i].block_index = 0;
-               mac_control->rx_curr_get_info[i].block_index = 0;
-               mac_control->rx_curr_put_info[i].offset = 0;
-               mac_control->rx_curr_get_info[i].offset = 0;
+               mac_control->rings[i].rx_curr_put_info.block_index = 0;
+               mac_control->rings[i].rx_curr_get_info.block_index = 0;
+               mac_control->rings[i].rx_curr_put_info.offset = 0;
+               mac_control->rings[i].rx_curr_get_info.offset = 0;
                atomic_set(&sp->rx_bufs_left[i], 0);
                DBG_PRINT(INIT_DBG, "%s:Freed 0x%x Rx Buffers on ring%d\n",
                          dev->name, buf_cnt, i);
@@ -1826,7 +2378,7 @@ static void free_rx_buffers(struct s2io_nic *sp)
 /**
  * s2io_poll - Rx interrupt handler for NAPI support
  * @dev : pointer to the device structure.
- * @budget : The number of packets that were budgeted to be processed 
+ * @budget : The number of packets that were budgeted to be processed
  * during  one pass through the 'Poll" function.
  * Description:
  * Comes into picture only if NAPI support has been incorporated. It does
@@ -1836,160 +2388,36 @@ static void free_rx_buffers(struct s2io_nic *sp)
  * 0 on success and 1 if there are No Rx packets to be processed.
  */
 
-#ifdef CONFIG_S2IO_NAPI
+#if defined(CONFIG_S2IO_NAPI)
 static int s2io_poll(struct net_device *dev, int *budget)
 {
        nic_t *nic = dev->priv;
-       XENA_dev_config_t __iomem *bar0 = nic->bar0;
-       int pkts_to_process = *budget, pkt_cnt = 0;
-       register u64 val64 = 0;
-       rx_curr_get_info_t get_info, put_info;
-       int i, get_block, put_block, get_offset, put_offset, ring_bufs;
-#ifndef CONFIG_2BUFF_MODE
-       u16 val16, cksum;
-#endif
-       struct sk_buff *skb;
-       RxD_t *rxdp;
+       int pkt_cnt = 0, org_pkts_to_process;
        mac_info_t *mac_control;
        struct config_param *config;
-#ifdef CONFIG_2BUFF_MODE
-       buffAdd_t *ba;
-#endif
+       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       u64 val64;
+       int i;
 
+       atomic_inc(&nic->isr_cnt);
        mac_control = &nic->mac_control;
        config = &nic->config;
 
-       if (pkts_to_process > dev->quota)
-               pkts_to_process = dev->quota;
+       nic->pkts_to_process = *budget;
+       if (nic->pkts_to_process > dev->quota)
+               nic->pkts_to_process = dev->quota;
+       org_pkts_to_process = nic->pkts_to_process;
 
        val64 = readq(&bar0->rx_traffic_int);
        writeq(val64, &bar0->rx_traffic_int);
 
        for (i = 0; i < config->rx_ring_num; i++) {
-               get_info = mac_control->rx_curr_get_info[i];
-               get_block = get_info.block_index;
-               put_info = mac_control->rx_curr_put_info[i];
-               put_block = put_info.block_index;
-               ring_bufs = config->rx_cfg[i].num_rxd;
-               rxdp = nic->rx_blocks[i][get_block].block_virt_addr +
-                   get_info.offset;
-#ifndef        CONFIG_2BUFF_MODE
-               get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
-                   get_info.offset;
-               put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) +
-                   put_info.offset;
-               while ((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
-                      (((get_offset + 1) % ring_bufs) != put_offset)) {
-                       if (--pkts_to_process < 0) {
-                               goto no_rx;
-                       }
-                       if (rxdp->Control_1 == END_OF_BLOCK) {
-                               rxdp =
-                                   (RxD_t *) ((unsigned long) rxdp->
-                                              Control_2);
-                               get_info.offset++;
-                               get_info.offset %=
-                                   (MAX_RXDS_PER_BLOCK + 1);
-                               get_block++;
-                               get_block %= nic->block_count[i];
-                               mac_control->rx_curr_get_info[i].
-                                   offset = get_info.offset;
-                               mac_control->rx_curr_get_info[i].
-                                   block_index = get_block;
-                               continue;
-                       }
-                       get_offset =
-                           (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
-                           get_info.offset;
-                       skb =
-                           (struct sk_buff *) ((unsigned long) rxdp->
-                                               Host_Control);
-                       if (skb == NULL) {
-                               DBG_PRINT(ERR_DBG, "%s: The skb is ",
-                                         dev->name);
-                               DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
-                               goto no_rx;
-                       }
-                       val64 = RXD_GET_BUFFER0_SIZE(rxdp->Control_2);
-                       val16 = (u16) (val64 >> 48);
-                       cksum = RXD_GET_L4_CKSUM(rxdp->Control_1);
-                       pci_unmap_single(nic->pdev, (dma_addr_t)
-                                        rxdp->Buffer0_ptr,
-                                        dev->mtu +
-                                        HEADER_ETHERNET_II_802_3_SIZE +
-                                        HEADER_802_2_SIZE +
-                                        HEADER_SNAP_SIZE,
-                                        PCI_DMA_FROMDEVICE);
-                       rx_osm_handler(nic, val16, rxdp, i);
-                       pkt_cnt++;
-                       get_info.offset++;
-                       get_info.offset %= (MAX_RXDS_PER_BLOCK + 1);
-                       rxdp =
-                           nic->rx_blocks[i][get_block].block_virt_addr +
-                           get_info.offset;
-                       mac_control->rx_curr_get_info[i].offset =
-                           get_info.offset;
+               rx_intr_handler(&mac_control->rings[i]);
+               pkt_cnt = org_pkts_to_process - nic->pkts_to_process;
+               if (!nic->pkts_to_process) {
+                       /* Quota for the current iteration has been met */
+                       goto no_rx;
                }
-#else
-               get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
-                   get_info.offset;
-               put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) +
-                   put_info.offset;
-               while (((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
-                       !(rxdp->Control_2 & BIT(0))) &&
-                      (((get_offset + 1) % ring_bufs) != put_offset)) {
-                       if (--pkts_to_process < 0) {
-                               goto no_rx;
-                       }
-                       skb = (struct sk_buff *) ((unsigned long)
-                                                 rxdp->Host_Control);
-                       if (skb == NULL) {
-                               DBG_PRINT(ERR_DBG, "%s: The skb is ",
-                                         dev->name);
-                               DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
-                               goto no_rx;
-                       }
-
-                       pci_unmap_single(nic->pdev, (dma_addr_t)
-                                        rxdp->Buffer0_ptr,
-                                        BUF0_LEN, PCI_DMA_FROMDEVICE);
-                       pci_unmap_single(nic->pdev, (dma_addr_t)
-                                        rxdp->Buffer1_ptr,
-                                        BUF1_LEN, PCI_DMA_FROMDEVICE);
-                       pci_unmap_single(nic->pdev, (dma_addr_t)
-                                        rxdp->Buffer2_ptr,
-                                        dev->mtu + BUF0_LEN + 4,
-                                        PCI_DMA_FROMDEVICE);
-                       ba = &nic->ba[i][get_block][get_info.offset];
-
-                       rx_osm_handler(nic, rxdp, i, ba);
-
-                       get_info.offset++;
-                       mac_control->rx_curr_get_info[i].offset =
-                           get_info.offset;
-                       rxdp =
-                           nic->rx_blocks[i][get_block].block_virt_addr +
-                           get_info.offset;
-
-                       if (get_info.offset &&
-                           (!(get_info.offset % MAX_RXDS_PER_BLOCK))) {
-                               get_info.offset = 0;
-                               mac_control->rx_curr_get_info[i].
-                                   offset = get_info.offset;
-                               get_block++;
-                               get_block %= nic->block_count[i];
-                               mac_control->rx_curr_get_info[i].
-                                   block_index = get_block;
-                               rxdp =
-                                   nic->rx_blocks[i][get_block].
-                                   block_virt_addr;
-                       }
-                       get_offset =
-                           (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
-                           get_info.offset;
-                       pkt_cnt++;
-               }
-#endif
        }
        if (!pkt_cnt)
                pkt_cnt = 1;
@@ -2007,9 +2435,10 @@ static int s2io_poll(struct net_device *dev, int *budget)
        }
        /* Re enable the Rx interrupts. */
        en_dis_able_nic_intrs(nic, RX_TRAFFIC_INTR, ENABLE_INTRS);
+       atomic_dec(&nic->isr_cnt);
        return 0;
 
-      no_rx:
+no_rx:
        dev->quota -= pkt_cnt;
        *budget -= pkt_cnt;
 
@@ -2020,279 +2449,204 @@ static int s2io_poll(struct net_device *dev, int *budget)
                        break;
                }
        }
+       atomic_dec(&nic->isr_cnt);
        return 1;
 }
-#else
-/**  
+#endif
+
+/**
  *  rx_intr_handler - Rx interrupt handler
  *  @nic: device private variable.
- *  Description: 
- *  If the interrupt is because of a received frame or if the 
+ *  Description:
+ *  If the interrupt is because of a received frame or if the
  *  receive ring contains fresh as yet un-processed frames,this function is
- *  called. It picks out the RxD at which place the last Rx processing had 
- *  stopped and sends the skb to the OSM's Rx handler and then increments 
+ *  called. It picks out the RxD at which place the last Rx processing had
+ *  stopped and sends the skb to the OSM's Rx handler and then increments
  *  the offset.
  *  Return Value:
  *  NONE.
  */
-
-static void rx_intr_handler(struct s2io_nic *nic)
+static void rx_intr_handler(ring_info_t *ring_data)
 {
+       nic_t *nic = ring_data->nic;
        struct net_device *dev = (struct net_device *) nic->dev;
-       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       int get_block, get_offset, put_block, put_offset, ring_bufs;
        rx_curr_get_info_t get_info, put_info;
        RxD_t *rxdp;
        struct sk_buff *skb;
-#ifndef CONFIG_2BUFF_MODE
-       u16 val16, cksum;
-#endif
-       register u64 val64 = 0;
-       int get_block, get_offset, put_block, put_offset, ring_bufs;
-       int i, pkt_cnt = 0;
-       mac_info_t *mac_control;
-       struct config_param *config;
-#ifdef CONFIG_2BUFF_MODE
-       buffAdd_t *ba;
+#ifndef CONFIG_S2IO_NAPI
+       int pkt_cnt = 0;
 #endif
+       spin_lock(&nic->rx_lock);
+       if (atomic_read(&nic->card_state) == CARD_DOWN) {
+               DBG_PRINT(ERR_DBG, "%s: %s going down for reset\n",
+                         __FUNCTION__, dev->name);
+               spin_unlock(&nic->rx_lock);
+       }
 
-       mac_control = &nic->mac_control;
-       config = &nic->config;
-
-       /* 
-        * rx_traffic_int reg is an R1 register, hence we read and write back 
-        * the samevalue in the register to clear it.
-        */
-       val64 = readq(&bar0->rx_traffic_int);
-       writeq(val64, &bar0->rx_traffic_int);
-
-       for (i = 0; i < config->rx_ring_num; i++) {
-               get_info = mac_control->rx_curr_get_info[i];
-               get_block = get_info.block_index;
-               put_info = mac_control->rx_curr_put_info[i];
-               put_block = put_info.block_index;
-               ring_bufs = config->rx_cfg[i].num_rxd;
-               rxdp = nic->rx_blocks[i][get_block].block_virt_addr +
+       get_info = ring_data->rx_curr_get_info;
+       get_block = get_info.block_index;
+       put_info = ring_data->rx_curr_put_info;
+       put_block = put_info.block_index;
+       ring_bufs = get_info.ring_len+1;
+       rxdp = ring_data->rx_blocks[get_block].block_virt_addr +
                    get_info.offset;
-#ifndef        CONFIG_2BUFF_MODE
-               get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
-                   get_info.offset;
-               spin_lock(&nic->put_lock);
-               put_offset = nic->put_pos[i];
-               spin_unlock(&nic->put_lock);
-               while ((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
-                      (((get_offset + 1) % ring_bufs) != put_offset)) {
-                       if (rxdp->Control_1 == END_OF_BLOCK) {
-                               rxdp = (RxD_t *) ((unsigned long)
-                                                 rxdp->Control_2);
-                               get_info.offset++;
-                               get_info.offset %=
-                                   (MAX_RXDS_PER_BLOCK + 1);
-                               get_block++;
-                               get_block %= nic->block_count[i];
-                               mac_control->rx_curr_get_info[i].
-                                   offset = get_info.offset;
-                               mac_control->rx_curr_get_info[i].
-                                   block_index = get_block;
-                               continue;
-                       }
-                       get_offset =
-                           (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
-                           get_info.offset;
-                       skb = (struct sk_buff *) ((unsigned long)
-                                                 rxdp->Host_Control);
-                       if (skb == NULL) {
-                               DBG_PRINT(ERR_DBG, "%s: The skb is ",
-                                         dev->name);
-                               DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
-                               return;
-                       }
-                       val64 = RXD_GET_BUFFER0_SIZE(rxdp->Control_2);
-                       val16 = (u16) (val64 >> 48);
-                       cksum = RXD_GET_L4_CKSUM(rxdp->Control_1);
-                       pci_unmap_single(nic->pdev, (dma_addr_t)
-                                        rxdp->Buffer0_ptr,
-                                        dev->mtu +
-                                        HEADER_ETHERNET_II_802_3_SIZE +
-                                        HEADER_802_2_SIZE +
-                                        HEADER_SNAP_SIZE,
-                                        PCI_DMA_FROMDEVICE);
-                       rx_osm_handler(nic, val16, rxdp, i);
-                       get_info.offset++;
-                       get_info.offset %= (MAX_RXDS_PER_BLOCK + 1);
-                       rxdp =
-                           nic->rx_blocks[i][get_block].block_virt_addr +
-                           get_info.offset;
-                       mac_control->rx_curr_get_info[i].offset =
-                           get_info.offset;
-                       pkt_cnt++;
-                       if ((indicate_max_pkts)
-                           && (pkt_cnt > indicate_max_pkts))
-                               break;
+       get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
+               get_info.offset;
+#ifndef CONFIG_S2IO_NAPI
+       spin_lock(&nic->put_lock);
+       put_offset = ring_data->put_pos;
+       spin_unlock(&nic->put_lock);
+#else
+       put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) +
+               put_info.offset;
+#endif
+       while (RXD_IS_UP2DT(rxdp) &&
+              (((get_offset + 1) % ring_bufs) != put_offset)) {
+               skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control);
+               if (skb == NULL) {
+                       DBG_PRINT(ERR_DBG, "%s: The skb is ",
+                                 dev->name);
+                       DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
+                       spin_unlock(&nic->rx_lock);
+                       return;
                }
+#ifndef CONFIG_2BUFF_MODE
+               pci_unmap_single(nic->pdev, (dma_addr_t)
+                                rxdp->Buffer0_ptr,
+                                dev->mtu +
+                                HEADER_ETHERNET_II_802_3_SIZE +
+                                HEADER_802_2_SIZE +
+                                HEADER_SNAP_SIZE,
+                                PCI_DMA_FROMDEVICE);
 #else
-               get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
+               pci_unmap_single(nic->pdev, (dma_addr_t)
+                                rxdp->Buffer0_ptr,
+                                BUF0_LEN, PCI_DMA_FROMDEVICE);
+               pci_unmap_single(nic->pdev, (dma_addr_t)
+                                rxdp->Buffer1_ptr,
+                                BUF1_LEN, PCI_DMA_FROMDEVICE);
+               pci_unmap_single(nic->pdev, (dma_addr_t)
+                                rxdp->Buffer2_ptr,
+                                dev->mtu + BUF0_LEN + 4,
+                                PCI_DMA_FROMDEVICE);
+#endif
+               rx_osm_handler(ring_data, rxdp);
+               get_info.offset++;
+               ring_data->rx_curr_get_info.offset =
                    get_info.offset;
-               spin_lock(&nic->put_lock);
-               put_offset = nic->put_pos[i];
-               spin_unlock(&nic->put_lock);
-               while (((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
-                       !(rxdp->Control_2 & BIT(0))) &&
-                      (((get_offset + 1) % ring_bufs) != put_offset)) {
-                       skb = (struct sk_buff *) ((unsigned long)
-                                                 rxdp->Host_Control);
-                       if (skb == NULL) {
-                               DBG_PRINT(ERR_DBG, "%s: The skb is ",
-                                         dev->name);
-                               DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
-                               return;
-                       }
-
-                       pci_unmap_single(nic->pdev, (dma_addr_t)
-                                        rxdp->Buffer0_ptr,
-                                        BUF0_LEN, PCI_DMA_FROMDEVICE);
-                       pci_unmap_single(nic->pdev, (dma_addr_t)
-                                        rxdp->Buffer1_ptr,
-                                        BUF1_LEN, PCI_DMA_FROMDEVICE);
-                       pci_unmap_single(nic->pdev, (dma_addr_t)
-                                        rxdp->Buffer2_ptr,
-                                        dev->mtu + BUF0_LEN + 4,
-                                        PCI_DMA_FROMDEVICE);
-                       ba = &nic->ba[i][get_block][get_info.offset];
-
-                       rx_osm_handler(nic, rxdp, i, ba);
-
-                       get_info.offset++;
-                       mac_control->rx_curr_get_info[i].offset =
-                           get_info.offset;
-                       rxdp =
-                           nic->rx_blocks[i][get_block].block_virt_addr +
-                           get_info.offset;
+               rxdp = ring_data->rx_blocks[get_block].block_virt_addr +
+                   get_info.offset;
+               if (get_info.offset &&
+                   (!(get_info.offset % MAX_RXDS_PER_BLOCK))) {
+                       get_info.offset = 0;
+                       ring_data->rx_curr_get_info.offset
+                           = get_info.offset;
+                       get_block++;
+                       get_block %= ring_data->block_count;
+                       ring_data->rx_curr_get_info.block_index
+                           = get_block;
+                       rxdp = ring_data->rx_blocks[get_block].block_virt_addr;
+               }
 
-                       if (get_info.offset &&
-                           (!(get_info.offset % MAX_RXDS_PER_BLOCK))) {
-                               get_info.offset = 0;
-                               mac_control->rx_curr_get_info[i].
-                                   offset = get_info.offset;
-                               get_block++;
-                               get_block %= nic->block_count[i];
-                               mac_control->rx_curr_get_info[i].
-                                   block_index = get_block;
-                               rxdp =
-                                   nic->rx_blocks[i][get_block].
-                                   block_virt_addr;
-                       }
-                       get_offset =
-                           (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
+               get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
                            get_info.offset;
-                       pkt_cnt++;
-                       if ((indicate_max_pkts)
-                           && (pkt_cnt > indicate_max_pkts))
-                               break;
-               }
-#endif
+#ifdef CONFIG_S2IO_NAPI
+               nic->pkts_to_process -= 1;
+               if (!nic->pkts_to_process)
+                       break;
+#else
+               pkt_cnt++;
                if ((indicate_max_pkts) && (pkt_cnt > indicate_max_pkts))
                        break;
+#endif
        }
+       spin_unlock(&nic->rx_lock);
 }
-#endif
-/**  
+
+/**
  *  tx_intr_handler - Transmit interrupt handler
  *  @nic : device private variable
- *  Description: 
- *  If an interrupt was raised to indicate DMA complete of the 
- *  Tx packet, this function is called. It identifies the last TxD 
- *  whose buffer was freed and frees all skbs whose data have already 
+ *  Description:
+ *  If an interrupt was raised to indicate DMA complete of the
+ *  Tx packet, this function is called. It identifies the last TxD
+ *  whose buffer was freed and frees all skbs whose data have already
  *  DMA'ed into the NICs internal memory.
  *  Return Value:
  *  NONE
  */
 
-static void tx_intr_handler(struct s2io_nic *nic)
+static void tx_intr_handler(fifo_info_t *fifo_data)
 {
-       XENA_dev_config_t __iomem *bar0 = nic->bar0;
+       nic_t *nic = fifo_data->nic;
        struct net_device *dev = (struct net_device *) nic->dev;
        tx_curr_get_info_t get_info, put_info;
        struct sk_buff *skb;
        TxD_t *txdlp;
-       register u64 val64 = 0;
-       int i;
        u16 j, frg_cnt;
-       mac_info_t *mac_control;
-       struct config_param *config;
-
-       mac_control = &nic->mac_control;
-       config = &nic->config;
 
-       /* 
-        * tx_traffic_int reg is an R1 register, hence we read and write 
-        * back the samevalue in the register to clear it.
-        */
-       val64 = readq(&bar0->tx_traffic_int);
-       writeq(val64, &bar0->tx_traffic_int);
-
-       for (i = 0; i < config->tx_fifo_num; i++) {
-               get_info = mac_control->tx_curr_get_info[i];
-               put_info = mac_control->tx_curr_put_info[i];
-               txdlp = (TxD_t *) nic->list_info[i][get_info.offset].
-                   list_virt_addr;
-               while ((!(txdlp->Control_1 & TXD_LIST_OWN_XENA)) &&
-                      (get_info.offset != put_info.offset) &&
-                      (txdlp->Host_Control)) {
-                       /* Check for TxD errors */
-                       if (txdlp->Control_1 & TXD_T_CODE) {
-                               unsigned long long err;
-                               err = txdlp->Control_1 & TXD_T_CODE;
-                               DBG_PRINT(ERR_DBG, "***TxD error %llx\n",
-                                         err);
-                       }
-
-                       skb = (struct sk_buff *) ((unsigned long)
-                                                 txdlp->Host_Control);
-                       if (skb == NULL) {
-                               DBG_PRINT(ERR_DBG, "%s: Null skb ",
-                                         dev->name);
-                               DBG_PRINT(ERR_DBG, "in Tx Free Intr\n");
-                               return;
-                       }
-                       nic->tx_pkt_count++;
+       get_info = fifo_data->tx_curr_get_info;
+       put_info = fifo_data->tx_curr_put_info;
+       txdlp = (TxD_t *) fifo_data->list_info[get_info.offset].
+           list_virt_addr;
+       while ((!(txdlp->Control_1 & TXD_LIST_OWN_XENA)) &&
+              (get_info.offset != put_info.offset) &&
+              (txdlp->Host_Control)) {
+               /* Check for TxD errors */
+               if (txdlp->Control_1 & TXD_T_CODE) {
+                       unsigned long long err;
+                       err = txdlp->Control_1 & TXD_T_CODE;
+                       DBG_PRINT(ERR_DBG, "***TxD error %llx\n",
+                                 err);
+               }
 
-                       frg_cnt = skb_shinfo(skb)->nr_frags;
+               skb = (struct sk_buff *) ((unsigned long)
+                               txdlp->Host_Control);
+               if (skb == NULL) {
+                       DBG_PRINT(ERR_DBG, "%s: Null skb ",
+                       __FUNCTION__);
+                       DBG_PRINT(ERR_DBG, "in Tx Free Intr\n");
+                       return;
+               }
 
-                       /*  For unfragmented skb */
-                       pci_unmap_single(nic->pdev, (dma_addr_t)
-                                        txdlp->Buffer_Pointer,
-                                        skb->len - skb->data_len,
-                                        PCI_DMA_TODEVICE);
-                       if (frg_cnt) {
-                               TxD_t *temp = txdlp;
-                               txdlp++;
-                               for (j = 0; j < frg_cnt; j++, txdlp++) {
-                                       skb_frag_t *frag =
-                                           &skb_shinfo(skb)->frags[j];
-                                       pci_unmap_page(nic->pdev,
-                                                      (dma_addr_t)
-                                                      txdlp->
-                                                      Buffer_Pointer,
-                                                      frag->size,
-                                                      PCI_DMA_TODEVICE);
-                               }
-                               txdlp = temp;
+               frg_cnt = skb_shinfo(skb)->nr_frags;
+               nic->tx_pkt_count++;
+
+               pci_unmap_single(nic->pdev, (dma_addr_t)
+                                txdlp->Buffer_Pointer,
+                                skb->len - skb->data_len,
+                                PCI_DMA_TODEVICE);
+               if (frg_cnt) {
+                       TxD_t *temp;
+                       temp = txdlp;
+                       txdlp++;
+                       for (j = 0; j < frg_cnt; j++, txdlp++) {
+                               skb_frag_t *frag =
+                                   &skb_shinfo(skb)->frags[j];
+                               if (!txdlp->Buffer_Pointer)
+                                       break;
+                               pci_unmap_page(nic->pdev,
+                                              (dma_addr_t)
+                                              txdlp->
+                                              Buffer_Pointer,
+                                              frag->size,
+                                              PCI_DMA_TODEVICE);
                        }
-                       memset(txdlp, 0,
-                              (sizeof(TxD_t) * config->max_txds));
-
-                       /* Updating the statistics block */
-                       nic->stats.tx_packets++;
-                       nic->stats.tx_bytes += skb->len;
-                       dev_kfree_skb_irq(skb);
-
-                       get_info.offset++;
-                       get_info.offset %= get_info.fifo_len + 1;
-                       txdlp = (TxD_t *) nic->list_info[i]
-                           [get_info.offset].list_virt_addr;
-                       mac_control->tx_curr_get_info[i].offset =
-                           get_info.offset;
+                       txdlp = temp;
                }
+               memset(txdlp, 0,
+                      (sizeof(TxD_t) * fifo_data->max_txds));
+
+               /* Updating the statistics block */
+               nic->stats.tx_bytes += skb->len;
+               dev_kfree_skb_irq(skb);
+
+               get_info.offset++;
+               get_info.offset %= get_info.fifo_len + 1;
+               txdlp = (TxD_t *) fifo_data->list_info
+                   [get_info.offset].list_virt_addr;
+               fifo_data->tx_curr_get_info.offset =
+                   get_info.offset;
        }
 
        spin_lock(&nic->tx_lock);
@@ -2301,13 +2655,13 @@ static void tx_intr_handler(struct s2io_nic *nic)
        spin_unlock(&nic->tx_lock);
 }
 
-/**  
+/**
  *  alarm_intr_handler - Alarm Interrrupt handler
  *  @nic: device private variable
- *  Description: If the interrupt was neither because of Rx packet or Tx 
+ *  Description: If the interrupt was neither because of Rx packet or Tx
  *  complete, this function is called. If the interrupt was to indicate
- *  a loss of link, the OSM link status handler is invoked for any other 
- *  alarm interrupt the block that raised the interrupt is displayed 
+ *  a loss of link, the OSM link status handler is invoked for any other
+ *  alarm interrupt the block that raised the interrupt is displayed
  *  and a H/W reset is issued.
  *  Return Value:
  *  NONE
@@ -2320,10 +2674,32 @@ static void alarm_intr_handler(struct s2io_nic *nic)
        register u64 val64 = 0, err_reg = 0;
 
        /* Handling link status change error Intr */
-       err_reg = readq(&bar0->mac_rmac_err_reg);
-       writeq(err_reg, &bar0->mac_rmac_err_reg);
-       if (err_reg & RMAC_LINK_STATE_CHANGE_INT) {
-               schedule_work(&nic->set_link_task);
+       if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
+               err_reg = readq(&bar0->mac_rmac_err_reg);
+               writeq(err_reg, &bar0->mac_rmac_err_reg);
+               if (err_reg & RMAC_LINK_STATE_CHANGE_INT) {
+                       schedule_work(&nic->set_link_task);
+               }
+       }
+
+       /* Handling Ecc errors */
+       val64 = readq(&bar0->mc_err_reg);
+       writeq(val64, &bar0->mc_err_reg);
+       if (val64 & (MC_ERR_REG_ECC_ALL_SNG | MC_ERR_REG_ECC_ALL_DBL)) {
+               if (val64 & MC_ERR_REG_ECC_ALL_DBL) {
+                       nic->mac_control.stats_info->sw_stat.
+                               double_ecc_errs++;
+                       DBG_PRINT(ERR_DBG, "%s: Device indicates ",
+                                 dev->name);
+                       DBG_PRINT(ERR_DBG, "double ECC error!!\n");
+                       if (nic->device_type != XFRAME_II_DEVICE) {
+                               netif_stop_queue(dev);
+                               schedule_work(&nic->rst_timer_task);
+                       }
+               } else {
+                       nic->mac_control.stats_info->sw_stat.
+                               single_ecc_errs++;
+               }
        }
 
        /* In case of a serious error, the device will be Reset. */
@@ -2338,7 +2714,7 @@ static void alarm_intr_handler(struct s2io_nic *nic)
        /*
         * Also as mentioned in the latest Errata sheets if the PCC_FB_ECC
         * Error occurs, the adapter will be recycled by disabling the
-        * adapter enable bit and enabling it again after the device 
+        * adapter enable bit and enabling it again after the device
         * becomes Quiescent.
         */
        val64 = readq(&bar0->pcc_err_reg);
@@ -2354,18 +2730,18 @@ static void alarm_intr_handler(struct s2io_nic *nic)
        /* Other type of interrupts are not being handled now,  TODO */
 }
 
-/** 
+/**
  *  wait_for_cmd_complete - waits for a command to complete.
- *  @sp : private member of the device structure, which is a pointer to the 
+ *  @sp : private member of the device structure, which is a pointer to the
  *  s2io_nic structure.
- *  Description: Function that waits for a command to Write into RMAC 
- *  ADDR DATA registers to be completed and returns either success or 
- *  error depending on whether the command was complete or not. 
+ *  Description: Function that waits for a command to Write into RMAC
+ *  ADDR DATA registers to be completed and returns either success or
+ *  error depending on whether the command was complete or not.
  *  Return value:
  *   SUCCESS on success and FAILURE on failure.
  */
 
-static int wait_for_cmd_complete(nic_t * sp)
+int wait_for_cmd_complete(nic_t * sp)
 {
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
        int ret = FAILURE, cnt = 0;
@@ -2385,29 +2761,32 @@ static int wait_for_cmd_complete(nic_t * sp)
        return ret;
 }
 
-/** 
- *  s2io_reset - Resets the card. 
+/**
+ *  s2io_reset - Resets the card.
  *  @sp : private member of the device structure.
  *  Description: Function to Reset the card. This function then also
- *  restores the previously saved PCI configuration space registers as 
+ *  restores the previously saved PCI configuration space registers as
  *  the card reset also resets the configuration space.
  *  Return value:
  *  void.
  */
 
-static void s2io_reset(nic_t * sp)
+void s2io_reset(nic_t * sp)
 {
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
        u64 val64;
-       u16 subid;
+       u16 subid, pci_cmd;
+
+       /* Back up  the PCI-X CMD reg, dont want to lose MMRBC, OST settings */
+       pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(pci_cmd));
 
        val64 = SW_RESET_ALL;
        writeq(val64, &bar0->sw_reset);
 
-       /* 
-        * At this stage, if the PCI write is indeed completed, the 
-        * card is reset and so is the PCI Config space of the device. 
-        * So a read cannot be issued at this stage on any of the 
+       /*
+        * At this stage, if the PCI write is indeed completed, the
+        * card is reset and so is the PCI Config space of the device.
+        * So a read cannot be issued at this stage on any of the
         * registers to ensure the write into "sw_reset" register
         * has gone through.
         * Question: Is there any system call that will explicitly force
@@ -2418,42 +2797,72 @@ static void s2io_reset(nic_t * sp)
         */
        msleep(250);
 
-       /* Restore the PCI state saved during initializarion. */
+       /* Restore the PCI state saved during initialization. */
        pci_restore_state(sp->pdev);
+       pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
+                                    pci_cmd);
        s2io_init_pci(sp);
 
-       msleep(250);
+       msleep(250);
+
+       /* Set swapper to enable I/O register access */
+       s2io_set_swapper(sp);
+
+       /* Clear certain PCI/PCI-X fields after reset */
+       if (sp->device_type == XFRAME_II_DEVICE) {
+               /* Clear parity err detect bit */
+               pci_write_config_word(sp->pdev, PCI_STATUS, 0x8000);
+
+               /* Clearing PCIX Ecc status register */
+               pci_write_config_dword(sp->pdev, 0x68, 0x7C);
+
+               /* Clearing PCI_STATUS error reflected here */
+               writeq(BIT(62), &bar0->txpic_int_reg);
+       }
+
+       /* Reset device statistics maintained by OS */
+       memset(&sp->stats, 0, sizeof (struct net_device_stats));
 
        /* SXE-002: Configure link and activity LED to turn it off */
        subid = sp->pdev->subsystem_device;
-       if ((subid & 0xFF) >= 0x07) {
+       if (((subid & 0xFF) >= 0x07) &&
+           (sp->device_type == XFRAME_I_DEVICE)) {
                val64 = readq(&bar0->gpio_control);
                val64 |= 0x0000800000000000ULL;
                writeq(val64, &bar0->gpio_control);
                val64 = 0x0411040400000000ULL;
-               writeq(val64, (void __iomem *) bar0 + 0x2700);
+               writeq(val64, (void __iomem *) ((u8 *) bar0 + 0x2700));
+       }
+
+       /*
+        * Clear spurious ECC interrupts that would have occured on
+        * XFRAME II cards after reset.
+        */
+       if (sp->device_type == XFRAME_II_DEVICE) {
+               val64 = readq(&bar0->pcc_err_reg);
+               writeq(val64, &bar0->pcc_err_reg);
        }
 
        sp->device_enabled_once = FALSE;
 }
 
 /**
- *  s2io_set_swapper - to set the swapper controle on the card 
- *  @sp : private member of the device structure, 
+ *  s2io_set_swapper - to set the swapper controle on the card
+ *  @sp : private member of the device structure,
  *  pointer to the s2io_nic structure.
- *  Description: Function to set the swapper control on the card 
+ *  Description: Function to set the swapper control on the card
  *  correctly depending on the 'endianness' of the system.
  *  Return value:
  *  SUCCESS on success and FAILURE on failure.
  */
 
-static int s2io_set_swapper(nic_t * sp)
+int s2io_set_swapper(nic_t * sp)
 {
        struct net_device *dev = sp->dev;
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
        u64 val64, valt, valr;
 
-       /* 
+       /*
         * Set proper endian settings and verify the same by reading
         * the PIF Feed-back register.
         */
@@ -2505,8 +2914,9 @@ static int s2io_set_swapper(nic_t * sp)
                        i++;
                }
                if(i == 4) {
+                       unsigned long long x = val64;
                        DBG_PRINT(ERR_DBG, "Write failed, Xmsi_addr ");
-                       DBG_PRINT(ERR_DBG, "reads:0x%llx\n",val64);
+                       DBG_PRINT(ERR_DBG, "reads:0x%llx\n", x);
                        return FAILURE;
                }
        }
@@ -2514,8 +2924,8 @@ static int s2io_set_swapper(nic_t * sp)
        val64 &= 0xFFFF000000000000ULL;
 
 #ifdef  __BIG_ENDIAN
-       /* 
-        * The device by default set to a big endian format, so a 
+       /*
+        * The device by default set to a big endian format, so a
         * big endian driver need not set anything.
         */
        val64 |= (SWAPPER_CTRL_TXP_FE |
@@ -2531,9 +2941,9 @@ static int s2io_set_swapper(nic_t * sp)
                 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
        writeq(val64, &bar0->swapper_ctrl);
 #else
-       /* 
+       /*
         * Initially we enable all bits to make it accessible by the
-        * driver, then we selectively enable only those bits that 
+        * driver, then we selectively enable only those bits that
         * we want to set.
         */
        val64 |= (SWAPPER_CTRL_TXP_FE |
@@ -2555,8 +2965,8 @@ static int s2io_set_swapper(nic_t * sp)
 #endif
        val64 = readq(&bar0->swapper_ctrl);
 
-       /* 
-        * Verifying if endian settings are accurate by reading a 
+       /*
+        * Verifying if endian settings are accurate by reading a
         * feedback register.
         */
        val64 = readq(&bar0->pif_rd_swapper_fb);
@@ -2576,55 +2986,63 @@ static int s2io_set_swapper(nic_t * sp)
  * Functions defined below concern the OS part of the driver *
  * ********************************************************* */
 
-/**  
+/**
  *  s2io_open - open entry point of the driver
  *  @dev : pointer to the device structure.
  *  Description:
  *  This function is the open entry point of the driver. It mainly calls a
  *  function to allocate Rx buffers and inserts them into the buffer
- *  descriptors and then enables the Rx part of the NIC. 
+ *  descriptors and then enables the Rx part of the NIC.
  *  Return value:
  *  0 on success and an appropriate (-)ve integer as defined in errno.h
  *   file on failure.
  */
 
-static int s2io_open(struct net_device *dev)
+int s2io_open(struct net_device *dev)
 {
        nic_t *sp = dev->priv;
        int err = 0;
 
-       /* 
-        * Make sure you have link off by default every time 
+       /*
+        * Make sure you have link off by default every time
         * Nic is initialized
         */
        netif_carrier_off(dev);
-       sp->last_link_state = LINK_DOWN;
+       sp->last_link_state = 0;
 
        /* Initialize H/W and enable interrupts */
        if (s2io_card_up(sp)) {
                DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n",
                          dev->name);
-               return -ENODEV;
+               err = -ENODEV;
+               goto hw_init_failed;
        }
 
        /* After proper initialization of H/W, register ISR */
-       err = request_irq((int) sp->irq, s2io_isr, SA_SHIRQ,
+       err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ,
                          sp->name, dev);
        if (err) {
-               s2io_reset(sp);
                DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
                          dev->name);
-               return err;
+               goto isr_registration_failed;
        }
 
        if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) {
                DBG_PRINT(ERR_DBG, "Set Mac Address Failed\n");
-               s2io_reset(sp);
-               return -ENODEV;
+               err = -ENODEV;
+               goto setting_mac_address_failed;
        }
 
        netif_start_queue(dev);
        return 0;
+
+setting_mac_address_failed:
+       free_irq(sp->pdev->irq, dev);
+isr_registration_failed:
+       del_timer_sync(&sp->alarm_timer);
+       s2io_reset(sp);
+hw_init_failed:
+       return err;
 }
 
 /**
@@ -2640,16 +3058,15 @@ static int s2io_open(struct net_device *dev)
  *  file on failure.
  */
 
-static int s2io_close(struct net_device *dev)
+int s2io_close(struct net_device *dev)
 {
        nic_t *sp = dev->priv;
-
        flush_scheduled_work();
        netif_stop_queue(dev);
        /* Reset card, kill tasklet and free Tx and Rx buffers. */
        s2io_card_down(sp);
 
-       free_irq(dev->irq, dev);
+       free_irq(sp->pdev->irq, dev);
        sp->device_close_flag = TRUE;   /* Device is shut down. */
        return 0;
 }
@@ -2667,7 +3084,7 @@ static int s2io_close(struct net_device *dev)
  *  0 on success & 1 on failure.
  */
 
-static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        nic_t *sp = dev->priv;
        u16 frg_cnt, frg_len, i, queue, queue_len, put_off, get_off;
@@ -2678,29 +3095,39 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 #ifdef NETIF_F_TSO
        int mss;
 #endif
+       u16 vlan_tag = 0;
+       int vlan_priority = 0;
        mac_info_t *mac_control;
        struct config_param *config;
-       XENA_dev_config_t __iomem *bar0 = sp->bar0;
 
        mac_control = &sp->mac_control;
        config = &sp->config;
 
-       DBG_PRINT(TX_DBG, "%s: In S2IO Tx routine\n", dev->name);
+       DBG_PRINT(TX_DBG, "%s: In Neterion Tx routine\n", dev->name);
        spin_lock_irqsave(&sp->tx_lock, flags);
-
        if (atomic_read(&sp->card_state) == CARD_DOWN) {
-               DBG_PRINT(ERR_DBG, "%s: Card going down for reset\n",
+               DBG_PRINT(TX_DBG, "%s: Card going down for reset\n",
                          dev->name);
                spin_unlock_irqrestore(&sp->tx_lock, flags);
-               return 1;
+               dev_kfree_skb(skb);
+               return 0;
        }
 
        queue = 0;
-       put_off = (u16) mac_control->tx_curr_put_info[queue].offset;
-       get_off = (u16) mac_control->tx_curr_get_info[queue].offset;
-       txdp = (TxD_t *) sp->list_info[queue][put_off].list_virt_addr;
 
-       queue_len = mac_control->tx_curr_put_info[queue].fifo_len + 1;
+       /* Get Fifo number to Transmit based on vlan priority */
+       if (sp->vlgrp && vlan_tx_tag_present(skb)) {
+               vlan_tag = vlan_tx_tag_get(skb);
+               vlan_priority = vlan_tag >> 13;
+               queue = config->fifo_mapping[vlan_priority];
+       }
+
+       put_off = (u16) mac_control->fifos[queue].tx_curr_put_info.offset;
+       get_off = (u16) mac_control->fifos[queue].tx_curr_get_info.offset;
+       txdp = (TxD_t *) mac_control->fifos[queue].list_info[put_off].
+               list_virt_addr;
+
+       queue_len = mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1;
        /* Avoid "put" pointer going beyond "get" pointer */
        if (txdp->Host_Control || (((put_off + 1) % queue_len) == get_off)) {
                DBG_PRINT(ERR_DBG, "Error in xmit, No free TXDs.\n");
@@ -2709,6 +3136,15 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
                spin_unlock_irqrestore(&sp->tx_lock, flags);
                return 0;
        }
+
+       /* A buffer with no data will be dropped */
+       if (!skb->len) {
+               DBG_PRINT(TX_DBG, "%s:Buffer has no data..\n", dev->name);
+               dev_kfree_skb(skb);
+               spin_unlock_irqrestore(&sp->tx_lock, flags);
+               return 0;
+       }
+
 #ifdef NETIF_F_TSO
        mss = skb_shinfo(skb)->tso_size;
        if (mss) {
@@ -2720,9 +3156,9 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
        frg_cnt = skb_shinfo(skb)->nr_frags;
        frg_len = skb->len - skb->data_len;
 
-       txdp->Host_Control = (unsigned long) skb;
        txdp->Buffer_Pointer = pci_map_single
            (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE);
+       txdp->Host_Control = (unsigned long) skb;
        if (skb->ip_summed == CHECKSUM_HW) {
                txdp->Control_2 |=
                    (TXD_TX_CKO_IPV4_EN | TXD_TX_CKO_TCP_EN |
@@ -2731,6 +3167,11 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 
        txdp->Control_2 |= config->tx_intr_type;
 
+       if (sp->vlgrp && vlan_tx_tag_present(skb)) {
+               txdp->Control_2 |= TXD_VLAN_ENABLE;
+               txdp->Control_2 |= TXD_VLAN_TAG(vlan_tag);
+       }
+
        txdp->Control_1 |= (TXD_BUFFER0_SIZE(frg_len) |
                            TXD_GATHER_CODE_FIRST);
        txdp->Control_1 |= TXD_LIST_OWN_XENA;
@@ -2738,6 +3179,9 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
        /* For fragmented SKB. */
        for (i = 0; i < frg_cnt; i++) {
                skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+               /* A '0' length fragment will be ignored */
+               if (!frag->size)
+                       continue;
                txdp++;
                txdp->Buffer_Pointer = (u64) pci_map_page
                    (sp->pdev, frag->page, frag->page_offset,
@@ -2747,23 +3191,23 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
        txdp->Control_1 |= TXD_GATHER_CODE_LAST;
 
        tx_fifo = mac_control->tx_FIFO_start[queue];
-       val64 = sp->list_info[queue][put_off].list_phy_addr;
+       val64 = mac_control->fifos[queue].list_info[put_off].list_phy_addr;
        writeq(val64, &tx_fifo->TxDL_Pointer);
 
        val64 = (TX_FIFO_LAST_TXD_NUM(frg_cnt) | TX_FIFO_FIRST_LIST |
                 TX_FIFO_LAST_LIST);
+
 #ifdef NETIF_F_TSO
        if (mss)
                val64 |= TX_FIFO_SPECIAL_FUNC;
 #endif
        writeq(val64, &tx_fifo->List_Control);
 
-       /* Perform a PCI read to flush previous writes */
-       val64 = readq(&bar0->general_int_status);
+       mmiowb();
 
        put_off++;
-       put_off %= mac_control->tx_curr_put_info[queue].fifo_len + 1;
-       mac_control->tx_curr_put_info[queue].offset = put_off;
+       put_off %= mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1;
+       mac_control->fifos[queue].tx_curr_put_info.offset = put_off;
 
        /* Avoid "put" pointer going beyond "get" pointer */
        if (((put_off + 1) % queue_len) == get_off) {
@@ -2779,18 +3223,74 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
+static void
+s2io_alarm_handle(unsigned long data)
+{
+       nic_t *sp = (nic_t *)data;
+
+       alarm_intr_handler(sp);
+       mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
+}
+
+static void s2io_txpic_intr_handle(nic_t *sp)
+{
+       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0;
+       u64 val64;
+
+       val64 = readq(&bar0->pic_int_status);
+       if (val64 & PIC_INT_GPIO) {
+               val64 = readq(&bar0->gpio_int_reg);
+               if ((val64 & GPIO_INT_REG_LINK_DOWN) &&
+                   (val64 & GPIO_INT_REG_LINK_UP)) {
+                       val64 |=  GPIO_INT_REG_LINK_DOWN;
+                       val64 |= GPIO_INT_REG_LINK_UP;
+                       writeq(val64, &bar0->gpio_int_reg);
+                       goto masking;
+               }
+
+               if (((sp->last_link_state == LINK_UP) &&
+                       (val64 & GPIO_INT_REG_LINK_DOWN)) ||
+               ((sp->last_link_state == LINK_DOWN) &&
+               (val64 & GPIO_INT_REG_LINK_UP))) {
+                       val64 = readq(&bar0->gpio_int_mask);
+                       val64 |=  GPIO_INT_MASK_LINK_DOWN;
+                       val64 |= GPIO_INT_MASK_LINK_UP;
+                       writeq(val64, &bar0->gpio_int_mask);
+                       s2io_set_link((unsigned long)sp);
+               }
+masking:
+               if (sp->last_link_state == LINK_UP) {
+                       /*enable down interrupt */
+                       val64 = readq(&bar0->gpio_int_mask);
+                       /* unmasks link down intr */
+                       val64 &=  ~GPIO_INT_MASK_LINK_DOWN;
+                       /* masks link up intr */
+                       val64 |= GPIO_INT_MASK_LINK_UP;
+                       writeq(val64, &bar0->gpio_int_mask);
+               } else {
+                       /*enable UP Interrupt */
+                       val64 = readq(&bar0->gpio_int_mask);
+                       /* unmasks link up interrupt */
+                       val64 &= ~GPIO_INT_MASK_LINK_UP;
+                       /* masks link down interrupt */
+                       val64 |=  GPIO_INT_MASK_LINK_DOWN;
+                       writeq(val64, &bar0->gpio_int_mask);
+               }
+       }
+}
+
 /**
  *  s2io_isr - ISR handler of the device .
  *  @irq: the irq of the device.
  *  @dev_id: a void pointer to the dev structure of the NIC.
  *  @pt_regs: pointer to the registers pushed on the stack.
- *  Description:  This function is the ISR handler of the device. It 
- *  identifies the reason for the interrupt and calls the relevant 
- *  service routines. As a contongency measure, this ISR allocates the 
+ *  Description:  This function is the ISR handler of the device. It
+ *  identifies the reason for the interrupt and calls the relevant
+ *  service routines. As a contongency measure, this ISR allocates the
  *  recv buffers, if their numbers are below the panic value which is
  *  presently set to 25% of the original number of rcv buffers allocated.
  *  Return value:
- *   IRQ_HANDLED: will be returned if IRQ was handled by this routine 
+ *   IRQ_HANDLED: will be returned if IRQ was handled by this routine
  *   IRQ_NONE: will be returned if interrupt is not from our device
  */
 static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
@@ -2798,40 +3298,31 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
        struct net_device *dev = (struct net_device *) dev_id;
        nic_t *sp = dev->priv;
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
-#ifndef CONFIG_S2IO_NAPI
-       int i, ret;
-#endif
-       u64 reason = 0;
+       int i;
+       u64 reason = 0, val64;
        mac_info_t *mac_control;
        struct config_param *config;
 
+       atomic_inc(&sp->isr_cnt);
        mac_control = &sp->mac_control;
        config = &sp->config;
 
-       /* 
+       /*
         * Identify the cause for interrupt and call the appropriate
         * interrupt handler. Causes for the interrupt could be;
         * 1. Rx of packet.
         * 2. Tx complete.
         * 3. Link down.
-        * 4. Error in any functional blocks of the NIC. 
+        * 4. Error in any functional blocks of the NIC.
         */
        reason = readq(&bar0->general_int_status);
 
        if (!reason) {
                /* The interrupt was not raised by Xena. */
+               atomic_dec(&sp->isr_cnt);
                return IRQ_NONE;
        }
 
-       /* If Intr is because of Tx Traffic */
-       if (reason & GEN_INTR_TXTRAFFIC) {
-               tx_intr_handler(sp);
-       }
-
-       /* If Intr is because of an error */
-       if (reason & (GEN_ERROR_INTR))
-               alarm_intr_handler(sp);
-
 #ifdef CONFIG_S2IO_NAPI
        if (reason & GEN_INTR_RXTRAFFIC) {
                if (netif_rx_schedule_prep(dev)) {
@@ -2843,17 +3334,43 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
 #else
        /* If Intr is because of Rx Traffic */
        if (reason & GEN_INTR_RXTRAFFIC) {
-               rx_intr_handler(sp);
+               /*
+                * rx_traffic_int reg is an R1 register, writing all 1's
+                * will ensure that the actual interrupt causing bit get's
+                * cleared and hence a read can be avoided.
+                */
+               val64 = 0xFFFFFFFFFFFFFFFFULL;
+               writeq(val64, &bar0->rx_traffic_int);
+               for (i = 0; i < config->rx_ring_num; i++) {
+                       rx_intr_handler(&mac_control->rings[i]);
+               }
        }
 #endif
 
-       /* 
-        * If the Rx buffer count is below the panic threshold then 
-        * reallocate the buffers from the interrupt handler itself, 
+       /* If Intr is because of Tx Traffic */
+       if (reason & GEN_INTR_TXTRAFFIC) {
+               /*
+                * tx_traffic_int reg is an R1 register, writing all 1's
+                * will ensure that the actual interrupt causing bit get's
+                * cleared and hence a read can be avoided.
+                */
+               val64 = 0xFFFFFFFFFFFFFFFFULL;
+               writeq(val64, &bar0->tx_traffic_int);
+
+               for (i = 0; i < config->tx_fifo_num; i++)
+                       tx_intr_handler(&mac_control->fifos[i]);
+       }
+
+       if (reason & GEN_INTR_TXPIC)
+               s2io_txpic_intr_handle(sp);
+       /*
+        * If the Rx buffer count is below the panic threshold then
+        * reallocate the buffers from the interrupt handler itself,
         * else schedule a tasklet to reallocate the buffers.
         */
 #ifndef CONFIG_S2IO_NAPI
        for (i = 0; i < config->rx_ring_num; i++) {
+               int ret;
                int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
                int level = rx_buffer_level(sp, rxb_size, i);
 
@@ -2865,6 +3382,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
                                          dev->name);
                                DBG_PRINT(ERR_DBG, " in ISR!!\n");
                                clear_bit(0, (&sp->tasklet_status));
+                               atomic_dec(&sp->isr_cnt);
                                return IRQ_HANDLED;
                        }
                        clear_bit(0, (&sp->tasklet_status));
@@ -2874,33 +3392,69 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
        }
 #endif
 
+       atomic_dec(&sp->isr_cnt);
        return IRQ_HANDLED;
 }
 
 /**
- *  s2io_get_stats - Updates the device statistics structure. 
+ * s2io_updt_stats -
+ */
+static void s2io_updt_stats(nic_t *sp)
+{
+       XENA_dev_config_t __iomem *bar0 = sp->bar0;
+       u64 val64;
+       int cnt = 0;
+
+       if (atomic_read(&sp->card_state) == CARD_UP) {
+               /* Apprx 30us on a 133 MHz bus */
+               val64 = SET_UPDT_CLICKS(10) |
+                       STAT_CFG_ONE_SHOT_EN | STAT_CFG_STAT_EN;
+               writeq(val64, &bar0->stat_cfg);
+               do {
+                       udelay(100);
+                       val64 = readq(&bar0->stat_cfg);
+                       if (!(val64 & BIT(0)))
+                               break;
+                       cnt++;
+                       if (cnt == 5)
+                               break; /* Updt failed */
+               } while(1);
+       }
+}
+
+/**
+ *  s2io_get_stats - Updates the device statistics structure.
  *  @dev : pointer to the device structure.
  *  Description:
- *  This function updates the device statistics structure in the s2io_nic 
+ *  This function updates the device statistics structure in the s2io_nic
  *  structure and returns a pointer to the same.
  *  Return value:
  *  pointer to the updated net_device_stats structure.
  */
 
-static struct net_device_stats *s2io_get_stats(struct net_device *dev)
+struct net_device_stats *s2io_get_stats(struct net_device *dev)
 {
        nic_t *sp = dev->priv;
        mac_info_t *mac_control;
        struct config_param *config;
 
+
        mac_control = &sp->mac_control;
        config = &sp->config;
 
-       sp->stats.tx_errors = mac_control->stats_info->tmac_any_err_frms;
-       sp->stats.rx_errors = mac_control->stats_info->rmac_drop_frms;
-       sp->stats.multicast = mac_control->stats_info->rmac_vld_mcst_frms;
+       /* Configure Stats for immediate updt */
+       s2io_updt_stats(sp);
+
+       sp->stats.tx_packets =
+               le32_to_cpu(mac_control->stats_info->tmac_frms);
+       sp->stats.tx_errors =
+               le32_to_cpu(mac_control->stats_info->tmac_any_err_frms);
+       sp->stats.rx_errors =
+               le32_to_cpu(mac_control->stats_info->rmac_drop_frms);
+       sp->stats.multicast =
+               le32_to_cpu(mac_control->stats_info->rmac_vld_mcst_frms);
        sp->stats.rx_length_errors =
-           mac_control->stats_info->rmac_long_frms;
+               le32_to_cpu(mac_control->stats_info->rmac_long_frms);
 
        return (&sp->stats);
 }
@@ -2909,8 +3463,8 @@ static struct net_device_stats *s2io_get_stats(struct net_device *dev)
  *  s2io_set_multicast - entry point for multicast address enable/disable.
  *  @dev : pointer to the device structure
  *  Description:
- *  This function is a driver entry point which gets called by the kernel 
- *  whenever multicast addresses must be enabled/disabled. This also gets 
+ *  This function is a driver entry point which gets called by the kernel
+ *  whenever multicast addresses must be enabled/disabled. This also gets
  *  called to set/reset promiscuous mode. Depending on the deivce flag, we
  *  determine, if multicast address must be enabled or if promiscuous mode
  *  is to be disabled etc.
@@ -2948,6 +3502,8 @@ static void s2io_set_multicast(struct net_device *dev)
                /*  Disable all Multicast addresses */
                writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr),
                       &bar0->rmac_addr_data0_mem);
+               writeq(RMAC_ADDR_DATA1_MEM_MASK(0x0),
+                      &bar0->rmac_addr_data1_mem);
                val64 = RMAC_ADDR_CMD_MEM_WE |
                    RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
                    RMAC_ADDR_CMD_MEM_OFFSET(sp->all_multi_pos);
@@ -3010,7 +3566,7 @@ static void s2io_set_multicast(struct net_device *dev)
                        writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr),
                               &bar0->rmac_addr_data0_mem);
                        writeq(RMAC_ADDR_DATA1_MEM_MASK(0ULL),
-                               &bar0->rmac_addr_data1_mem);
+                               &bar0->rmac_addr_data1_mem);
                        val64 = RMAC_ADDR_CMD_MEM_WE |
                            RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
                            RMAC_ADDR_CMD_MEM_OFFSET
@@ -3039,8 +3595,7 @@ static void s2io_set_multicast(struct net_device *dev)
                        writeq(RMAC_ADDR_DATA0_MEM_ADDR(mac_addr),
                               &bar0->rmac_addr_data0_mem);
                        writeq(RMAC_ADDR_DATA1_MEM_MASK(0ULL),
-                               &bar0->rmac_addr_data1_mem);
-
+                               &bar0->rmac_addr_data1_mem);
                        val64 = RMAC_ADDR_CMD_MEM_WE |
                            RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
                            RMAC_ADDR_CMD_MEM_OFFSET
@@ -3059,12 +3614,12 @@ static void s2io_set_multicast(struct net_device *dev)
 }
 
 /**
- *  s2io_set_mac_addr - Programs the Xframe mac address 
+ *  s2io_set_mac_addr - Programs the Xframe mac address
  *  @dev : pointer to the device structure.
  *  @addr: a uchar pointer to the new mac address which is to be set.
- *  Description : This procedure will program the Xframe to receive 
+ *  Description : This procedure will program the Xframe to receive
  *  frames with new Mac Address
- *  Return value: SUCCESS on success and an appropriate (-)ve integer 
+ *  Return value: SUCCESS on success and an appropriate (-)ve integer
  *  as defined in errno.h file on failure.
  */
 
@@ -3075,10 +3630,10 @@ int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
        register u64 val64, mac_addr = 0;
        int i;
 
-       /* 
+       /*
         * Set the new MAC address as the new unicast filter and reflect this
         * change on the device address registered with the OS. It will be
-        * at offset 0. 
+        * at offset 0.
         */
        for (i = 0; i < ETH_ALEN; i++) {
                mac_addr <<= 8;
@@ -3102,12 +3657,12 @@ int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
 }
 
 /**
- * s2io_ethtool_sset - Sets different link parameters. 
+ * s2io_ethtool_sset - Sets different link parameters.
  * @sp : private member of the device structure, which is a pointer to the  * s2io_nic structure.
  * @info: pointer to the structure with parameters given by ethtool to set
  * link information.
  * Description:
- * The function sets different link parameters provided by the user onto 
+ * The function sets different link parameters provided by the user onto
  * the NIC.
  * Return value:
  * 0 on success.
@@ -3129,7 +3684,7 @@ static int s2io_ethtool_sset(struct net_device *dev,
 }
 
 /**
- * s2io_ethtol_gset - Return link specific information. 
+ * s2io_ethtol_gset - Return link specific information.
  * @sp : private member of the device structure, pointer to the
  *      s2io_nic structure.
  * @info : pointer to the structure with parameters given by ethtool
@@ -3161,8 +3716,8 @@ static int s2io_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info)
 }
 
 /**
- * s2io_ethtool_gdrvinfo - Returns driver specific information. 
- * @sp : private member of the device structure, which is a pointer to the 
+ * s2io_ethtool_gdrvinfo - Returns driver specific information.
+ * @sp : private member of the device structure, which is a pointer to the
  * s2io_nic structure.
  * @info : pointer to the structure with parameters given by ethtool to
  * return driver information.
@@ -3190,9 +3745,9 @@ static void s2io_ethtool_gdrvinfo(struct net_device *dev,
 
 /**
  *  s2io_ethtool_gregs - dumps the entire space of Xfame into the buffer.
- *  @sp: private member of the device structure, which is a pointer to the 
+ *  @sp: private member of the device structure, which is a pointer to the
  *  s2io_nic structure.
- *  @regs : pointer to the structure with parameters given by ethtool for 
+ *  @regs : pointer to the structure with parameters given by ethtool for
  *  dumping the registers.
  *  @reg_space: The input argumnet into which all the registers are dumped.
  *  Description:
@@ -3221,11 +3776,11 @@ static void s2io_ethtool_gregs(struct net_device *dev,
 
 /**
  *  s2io_phy_id  - timer function that alternates adapter LED.
- *  @data : address of the private member of the device structure, which 
+ *  @data : address of the private member of the device structure, which
  *  is a pointer to the s2io_nic structure, provided as an u32.
- * Description: This is actually the timer function that alternates the 
- * adapter LED bit of the adapter control bit to set/reset every time on 
- * invocation. The timer is set for 1/2 a second, hence tha NIC blinks 
+ * Description: This is actually the timer function that alternates the
+ * adapter LED bit of the adapter control bit to set/reset every time on
+ * invocation. The timer is set for 1/2 a second, hence tha NIC blinks
  *  once every second.
 */
 static void s2io_phy_id(unsigned long data)
@@ -3236,7 +3791,8 @@ static void s2io_phy_id(unsigned long data)
        u16 subid;
 
        subid = sp->pdev->subsystem_device;
-       if ((subid & 0xFF) >= 0x07) {
+       if ((sp->device_type == XFRAME_II_DEVICE) ||
+                  ((subid & 0xFF) >= 0x07)) {
                val64 = readq(&bar0->gpio_control);
                val64 ^= GPIO_CTRL_GPIO_0;
                writeq(val64, &bar0->gpio_control);
@@ -3253,12 +3809,12 @@ static void s2io_phy_id(unsigned long data)
  * s2io_ethtool_idnic - To physically identify the nic on the system.
  * @sp : private member of the device structure, which is a pointer to the
  * s2io_nic structure.
- * @id : pointer to the structure with identification parameters given by 
+ * @id : pointer to the structure with identification parameters given by
  * ethtool.
  * Description: Used to physically identify the NIC on the system.
- * The Link LED will blink for a time specified by the user for 
+ * The Link LED will blink for a time specified by the user for
  * identification.
- * NOTE: The Link has to be Up to be able to blink the LED. Hence 
+ * NOTE: The Link has to be Up to be able to blink the LED. Hence
  * identification is possible only if it's link is up.
  * Return value:
  * int , returns 0 on success
@@ -3273,7 +3829,8 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data)
 
        subid = sp->pdev->subsystem_device;
        last_gpio_ctrl_val = readq(&bar0->gpio_control);
-       if ((subid & 0xFF) < 0x07) {
+       if ((sp->device_type == XFRAME_I_DEVICE) &&
+               ((subid & 0xFF) < 0x07)) {
                val64 = readq(&bar0->adapter_control);
                if (!(val64 & ADAPTER_CNTL_EN)) {
                        printk(KERN_ERR
@@ -3288,12 +3845,12 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data)
        }
        mod_timer(&sp->id_timer, jiffies);
        if (data)
-               msleep(data * 1000);
+               msleep_interruptible(data * HZ);
        else
-               msleep(0xFFFFFFFF);
+               msleep_interruptible(MAX_FLICKER_TIME);
        del_timer_sync(&sp->id_timer);
 
-       if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) {
+       if (CARDS_WITH_FAULTY_LINK_INDICATORS(sp->device_type, subid)) {
                writeq(last_gpio_ctrl_val, &bar0->gpio_control);
                last_gpio_ctrl_val = readq(&bar0->gpio_control);
        }
@@ -3303,7 +3860,8 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data)
 
 /**
  * s2io_ethtool_getpause_data -Pause frame frame generation and reception.
- * @sp : private member of the device structure, which is a pointer to the  * s2io_nic structure.
+ * @sp : private member of the device structure, which is a pointer to the
+ *     s2io_nic structure.
  * @ep : pointer to the structure with pause parameters given by ethtool.
  * Description:
  * Returns the Pause frame generation and reception capability of the NIC.
@@ -3327,7 +3885,7 @@ static void s2io_ethtool_getpause_data(struct net_device *dev,
 
 /**
  * s2io_ethtool_setpause_data -  set/reset pause frame generation.
- * @sp : private member of the device structure, which is a pointer to the 
+ * @sp : private member of the device structure, which is a pointer to the
  *      s2io_nic structure.
  * @ep : pointer to the structure with pause parameters given by ethtool.
  * Description:
@@ -3338,7 +3896,7 @@ static void s2io_ethtool_getpause_data(struct net_device *dev,
  */
 
 static int s2io_ethtool_setpause_data(struct net_device *dev,
-                                     struct ethtool_pauseparam *ep)
+                              struct ethtool_pauseparam *ep)
 {
        u64 val64;
        nic_t *sp = dev->priv;
@@ -3359,13 +3917,13 @@ static int s2io_ethtool_setpause_data(struct net_device *dev,
 
 /**
  * read_eeprom - reads 4 bytes of data from user given offset.
- * @sp : private member of the device structure, which is a pointer to the 
+ * @sp : private member of the device structure, which is a pointer to the
  *      s2io_nic structure.
  * @off : offset at which the data must be written
  * @data : Its an output parameter where the data read at the given
- *     offset is stored.
+ *     offset is stored.
  * Description:
- * Will read 4 bytes of data from the user given offset and return the 
+ * Will read 4 bytes of data from the user given offset and return the
  * read data.
  * NOTE: Will allow to read only part of the EEPROM visible through the
  *   I2C bus.
@@ -3406,7 +3964,7 @@ static int read_eeprom(nic_t * sp, int off, u32 * data)
  *       s2io_nic structure.
  *  @off : offset at which the data must be written
  *  @data : The data that is to be written
- *  @cnt : Number of bytes of the data that are actually to be written into 
+ *  @cnt : Number of bytes of the data that are actually to be written into
  *  the Eeprom. (max of 3)
  * Description:
  *  Actually writes the relevant part of the data value into the Eeprom
@@ -3443,7 +4001,7 @@ static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)
 /**
  *  s2io_ethtool_geeprom  - reads the value stored in the Eeprom.
  *  @sp : private member of the device structure, which is a pointer to the *       s2io_nic structure.
- *  @eeprom : pointer to the user level structure provided by ethtool, 
+ *  @eeprom : pointer to the user level structure provided by ethtool,
  *  containing all relevant information.
  *  @data_buf : user defined value to be written into Eeprom.
  *  Description: Reads the values stored in the Eeprom at given offset
@@ -3454,7 +4012,7 @@ static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)
  */
 
 static int s2io_ethtool_geeprom(struct net_device *dev,
-                               struct ethtool_eeprom *eeprom, u8 * data_buf)
+                        struct ethtool_eeprom *eeprom, u8 * data_buf)
 {
        u32 data, i, valid;
        nic_t *sp = dev->priv;
@@ -3479,7 +4037,7 @@ static int s2io_ethtool_geeprom(struct net_device *dev,
  *  s2io_ethtool_seeprom - tries to write the user provided value in Eeprom
  *  @sp : private member of the device structure, which is a pointer to the
  *  s2io_nic structure.
- *  @eeprom : pointer to the user level structure provided by ethtool, 
+ *  @eeprom : pointer to the user level structure provided by ethtool,
  *  containing all relevant information.
  *  @data_buf ; user defined value to be written into Eeprom.
  *  Description:
@@ -3527,8 +4085,8 @@ static int s2io_ethtool_seeprom(struct net_device *dev,
 }
 
 /**
- * s2io_register_test - reads and writes into all clock domains. 
- * @sp : private member of the device structure, which is a pointer to the 
+ * s2io_register_test - reads and writes into all clock domains.
+ * @sp : private member of the device structure, which is a pointer to the
  * s2io_nic structure.
  * @data : variable that returns the result of each of the test conducted b
  * by the driver.
@@ -3545,8 +4103,8 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
        u64 val64 = 0;
        int fail = 0;
 
-       val64 = readq(&bar0->pcc_enable);
-       if (val64 != 0xff00000000000000ULL) {
+       val64 = readq(&bar0->pif_rd_swapper_fb);
+       if (val64 != 0x123456789abcdefULL) {
                fail = 1;
                DBG_PRINT(INFO_DBG, "Read Test level 1 fails\n");
        }
@@ -3590,13 +4148,13 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
 }
 
 /**
- * s2io_eeprom_test - to verify that EEprom in the xena can be programmed. 
+ * s2io_eeprom_test - to verify that EEprom in the xena can be programmed.
  * @sp : private member of the device structure, which is a pointer to the
  * s2io_nic structure.
  * @data:variable that returns the result of each of the test conducted by
  * the driver.
  * Description:
- * Verify that EEPROM in the xena can be programmed using I2C_CONTROL 
+ * Verify that EEPROM in the xena can be programmed using I2C_CONTROL
  * register.
  * Return value:
  * 0 on success.
@@ -3661,14 +4219,14 @@ static int s2io_eeprom_test(nic_t * sp, uint64_t * data)
 
 /**
  * s2io_bist_test - invokes the MemBist test of the card .
- * @sp : private member of the device structure, which is a pointer to the 
+ * @sp : private member of the device structure, which is a pointer to the
  * s2io_nic structure.
- * @data:variable that returns the result of each of the test conducted by 
+ * @data:variable that returns the result of each of the test conducted by
  * the driver.
  * Description:
  * This invokes the MemBist test of the card. We give around
  * 2 secs time for the Test to complete. If it's still not complete
- * within this peiod, we consider that the test failed. 
+ * within this peiod, we consider that the test failed.
  * Return value:
  * 0 on success and -1 on failure.
  */
@@ -3697,13 +4255,13 @@ static int s2io_bist_test(nic_t * sp, uint64_t * data)
 }
 
 /**
- * s2io-link_test - verifies the link state of the nic  
- * @sp ; private member of the device structure, which is a pointer to the 
+ * s2io-link_test - verifies the link state of the nic
+ * @sp ; private member of the device structure, which is a pointer to the
  * s2io_nic structure.
  * @data: variable that returns the result of each of the test conducted by
  * the driver.
  * Description:
- * The function verifies the link state of the NIC and updates the input 
+ * The function verifies the link state of the NIC and updates the input
  * argument 'data' appropriately.
  * Return value:
  * 0 on success.
@@ -3722,13 +4280,13 @@ static int s2io_link_test(nic_t * sp, uint64_t * data)
 }
 
 /**
- * s2io_rldram_test - offline test for access to the RldRam chip on the NIC 
- * @sp - private member of the device structure, which is a pointer to the  
+ * s2io_rldram_test - offline test for access to the RldRam chip on the NIC
+ * @sp - private member of the device structure, which is a pointer to the
  * s2io_nic structure.
- * @data - variable that returns the result of each of the test 
+ * @data - variable that returns the result of each of the test
  * conducted by the driver.
  * Description:
- *  This is one of the offline test that tests the read and write 
+ *  This is one of the offline test that tests the read and write
  *  access to the RldRam chip on the NIC.
  * Return value:
  *  0 on success.
@@ -3833,7 +4391,7 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
  *  s2io_nic structure.
  *  @ethtest : pointer to a ethtool command specific structure that will be
  *  returned to the user.
- *  @data : variable that returns the result of each of the test 
+ *  @data : variable that returns the result of each of the test
  * conducted by the driver.
  * Description:
  *  This function conducts 6 tests ( 4 offline and 2 online) to determine
@@ -3851,23 +4409,18 @@ static void s2io_ethtool_test(struct net_device *dev,
 
        if (ethtest->flags == ETH_TEST_FL_OFFLINE) {
                /* Offline Tests. */
-               if (orig_state) {
+               if (orig_state)
                        s2io_close(sp->dev);
-                       s2io_set_swapper(sp);
-               } else
-                       s2io_set_swapper(sp);
 
                if (s2io_register_test(sp, &data[0]))
                        ethtest->flags |= ETH_TEST_FL_FAILED;
 
                s2io_reset(sp);
-               s2io_set_swapper(sp);
 
                if (s2io_rldram_test(sp, &data[3]))
                        ethtest->flags |= ETH_TEST_FL_FAILED;
 
                s2io_reset(sp);
-               s2io_set_swapper(sp);
 
                if (s2io_eeprom_test(sp, &data[1]))
                        ethtest->flags |= ETH_TEST_FL_FAILED;
@@ -3910,61 +4463,111 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
        nic_t *sp = dev->priv;
        StatInfo_t *stat_info = sp->mac_control.stats_info;
 
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_data_octets);
+       s2io_updt_stats(sp);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_frms_oflow) << 32  |
+               le32_to_cpu(stat_info->tmac_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_data_octets_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_data_octets);
        tmp_stats[i++] = le64_to_cpu(stat_info->tmac_drop_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_mcst_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_bcst_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_mcst_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_mcst_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_bcst_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_bcst_frms);
        tmp_stats[i++] = le64_to_cpu(stat_info->tmac_pause_ctrl_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_any_err_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_any_err_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_any_err_frms);
        tmp_stats[i++] = le64_to_cpu(stat_info->tmac_vld_ip_octets);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_vld_ip);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_drop_ip);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_icmp);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_rst_tcp);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_vld_ip_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_vld_ip);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_drop_ip_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_drop_ip);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_icmp_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_icmp);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->tmac_rst_tcp_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_rst_tcp);
        tmp_stats[i++] = le64_to_cpu(stat_info->tmac_tcp);
-       tmp_stats[i++] = le32_to_cpu(stat_info->tmac_udp);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_data_octets);
+       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->tmac_udp_oflow) << 32 |
+               le32_to_cpu(stat_info->tmac_udp);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_vld_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_vld_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_data_octets_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_data_octets);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_fcs_err_frms);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_drop_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_mcst_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_bcst_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_vld_mcst_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_vld_mcst_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_vld_bcst_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_vld_bcst_frms);
        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_in_rng_len_err_frms);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_long_frms);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_pause_ctrl_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_discarded_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_usized_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_osized_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_frag_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_jabber_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_ip);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_discarded_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_discarded_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_usized_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_usized_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_osized_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_osized_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_frag_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_frag_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_jabber_frms_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_jabber_frms);
+       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_ip_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_ip);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ip_octets);
        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_hdr_err_ip);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_drop_ip);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_icmp);
+       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_drop_ip_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_drop_ip);
+       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_icmp_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_icmp);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_tcp);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_udp);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_drp_udp);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_pause_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_accepted_ip);
+       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_udp_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_udp);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_err_drp_udp_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_err_drp_udp);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_pause_cnt_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_pause_cnt);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_accepted_ip_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_accepted_ip);
        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_tcp);
+       tmp_stats[i++] = 0;
+       tmp_stats[i++] = stat_info->sw_stat.single_ecc_errs;
+       tmp_stats[i++] = stat_info->sw_stat.double_ecc_errs;
 }
 
-static int s2io_ethtool_get_regs_len(struct net_device *dev)
+int s2io_ethtool_get_regs_len(struct net_device *dev)
 {
        return (XENA_REG_SPACE);
 }
 
 
-static u32 s2io_ethtool_get_rx_csum(struct net_device * dev)
+u32 s2io_ethtool_get_rx_csum(struct net_device * dev)
 {
        nic_t *sp = dev->priv;
 
        return (sp->rx_csum);
 }
-
-static int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
+int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
 {
        nic_t *sp = dev->priv;
 
@@ -3975,19 +4578,17 @@ static int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
 
        return 0;
 }
-
-static int s2io_get_eeprom_len(struct net_device *dev)
+int s2io_get_eeprom_len(struct net_device *dev)
 {
        return (XENA_EEPROM_SPACE);
 }
 
-static int s2io_ethtool_self_test_count(struct net_device *dev)
+int s2io_ethtool_self_test_count(struct net_device *dev)
 {
        return (S2IO_TEST_LEN);
 }
-
-static void s2io_ethtool_get_strings(struct net_device *dev,
-                                    u32 stringset, u8 * data)
+void s2io_ethtool_get_strings(struct net_device *dev,
+                             u32 stringset, u8 * data)
 {
        switch (stringset) {
        case ETH_SS_TEST:
@@ -3998,13 +4599,12 @@ static void s2io_ethtool_get_strings(struct net_device *dev,
                       sizeof(ethtool_stats_keys));
        }
 }
-
 static int s2io_ethtool_get_stats_count(struct net_device *dev)
 {
        return (S2IO_STAT_LEN);
 }
 
-static int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
+int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
 {
        if (data)
                dev->features |= NETIF_F_IP_CSUM;
@@ -4046,21 +4646,18 @@ static struct ethtool_ops netdev_ethtool_ops = {
 };
 
 /**
- *  s2io_ioctl - Entry point for the Ioctl 
+ *  s2io_ioctl - Entry point for the Ioctl
  *  @dev :  Device pointer.
  *  @ifr :  An IOCTL specefic structure, that can contain a pointer to
  *  a proprietary structure used to pass information to the driver.
  *  @cmd :  This is used to distinguish between the different commands that
  *  can be passed to the IOCTL functions.
  *  Description:
- *  This function has support for ethtool, adding multiple MAC addresses on 
- *  the NIC and some DBG commands for the util tool.
- *  Return value:
- *  Currently the IOCTL supports no operations, hence by default this
- *  function returns OP NOT SUPPORTED value.
+ *  Currently there are no special functionality supported in IOCTL, hence
+ *  function always return EOPNOTSUPPORTED
  */
 
-static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
        return -EOPNOTSUPP;
 }
@@ -4076,17 +4673,9 @@ static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
  *   file on failure.
  */
 
-static int s2io_change_mtu(struct net_device *dev, int new_mtu)
+int s2io_change_mtu(struct net_device *dev, int new_mtu)
 {
        nic_t *sp = dev->priv;
-       XENA_dev_config_t __iomem *bar0 = sp->bar0;
-       register u64 val64;
-
-       if (netif_running(dev)) {
-               DBG_PRINT(ERR_DBG, "%s: Must be stopped to ", dev->name);
-               DBG_PRINT(ERR_DBG, "change its MTU \n");
-               return -EBUSY;
-       }
 
        if ((new_mtu < MIN_MTU) || (new_mtu > S2IO_JUMBO_SIZE)) {
                DBG_PRINT(ERR_DBG, "%s: MTU size is invalid.\n",
@@ -4094,11 +4683,22 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
                return -EPERM;
        }
 
-       /* Set the new MTU into the PYLD register of the NIC */
-       val64 = new_mtu;
-       writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
-
        dev->mtu = new_mtu;
+       if (netif_running(dev)) {
+               s2io_card_down(sp);
+               netif_stop_queue(dev);
+               if (s2io_card_up(sp)) {
+                       DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
+                                 __FUNCTION__);
+               }
+               if (netif_queue_stopped(dev))
+                       netif_wake_queue(dev);
+       } else { /* Device is down */
+               XENA_dev_config_t __iomem *bar0 = sp->bar0;
+               u64 val64 = new_mtu;
+
+               writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
+       }
 
        return 0;
 }
@@ -4108,9 +4708,9 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
  *  @dev_adr : address of the device structure in dma_addr_t format.
  *  Description:
  *  This is the tasklet or the bottom half of the ISR. This is
- *  an extension of the ISR which is scheduled by the scheduler to be run 
+ *  an extension of the ISR which is scheduled by the scheduler to be run
  *  when the load on the CPU is low. All low priority tasks of the ISR can
- *  be pushed into the tasklet. For now the tasklet is used only to 
+ *  be pushed into the tasklet. For now the tasklet is used only to
  *  replenish the Rx buffers in the Rx buffer descriptors.
  *  Return value:
  *  void.
@@ -4166,19 +4766,22 @@ static void s2io_set_link(unsigned long data)
        }
 
        subid = nic->pdev->subsystem_device;
-       /* 
-        * Allow a small delay for the NICs self initiated 
-        * cleanup to complete.
-        */
-       msleep(100);
+       if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
+               /*
+                * Allow a small delay for the NICs self initiated
+                * cleanup to complete.
+                */
+               msleep(100);
+       }
 
        val64 = readq(&bar0->adapter_status);
-       if (verify_xena_quiescence(val64, nic->device_enabled_once)) {
+       if (verify_xena_quiescence(nic, val64, nic->device_enabled_once)) {
                if (LINK_IS_UP(val64)) {
                        val64 = readq(&bar0->adapter_control);
                        val64 |= ADAPTER_CNTL_EN;
                        writeq(val64, &bar0->adapter_control);
-                       if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) {
+                       if (CARDS_WITH_FAULTY_LINK_INDICATORS(nic->device_type,
+                                                            subid)) {
                                val64 = readq(&bar0->gpio_control);
                                val64 |= GPIO_CTRL_GPIO_0;
                                writeq(val64, &bar0->gpio_control);
@@ -4187,20 +4790,24 @@ static void s2io_set_link(unsigned long data)
                                val64 |= ADAPTER_LED_ON;
                                writeq(val64, &bar0->adapter_control);
                        }
-                       val64 = readq(&bar0->adapter_status);
-                       if (!LINK_IS_UP(val64)) {
-                               DBG_PRINT(ERR_DBG, "%s:", dev->name);
-                               DBG_PRINT(ERR_DBG, " Link down");
-                               DBG_PRINT(ERR_DBG, "after ");
-                               DBG_PRINT(ERR_DBG, "enabling ");
-                               DBG_PRINT(ERR_DBG, "device \n");
+                       if (s2io_link_fault_indication(nic) ==
+                                               MAC_RMAC_ERR_TIMER) {
+                               val64 = readq(&bar0->adapter_status);
+                               if (!LINK_IS_UP(val64)) {
+                                       DBG_PRINT(ERR_DBG, "%s:", dev->name);
+                                       DBG_PRINT(ERR_DBG, " Link down");
+                                       DBG_PRINT(ERR_DBG, "after ");
+                                       DBG_PRINT(ERR_DBG, "enabling ");
+                                       DBG_PRINT(ERR_DBG, "device \n");
+                               }
                        }
                        if (nic->device_enabled_once == FALSE) {
                                nic->device_enabled_once = TRUE;
                        }
                        s2io_link(nic, LINK_UP);
                } else {
-                       if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) {
+                       if (CARDS_WITH_FAULTY_LINK_INDICATORS(nic->device_type,
+                                                             subid)) {
                                val64 = readq(&bar0->gpio_control);
                                val64 &= ~GPIO_CTRL_GPIO_0;
                                writeq(val64, &bar0->gpio_control);
@@ -4223,9 +4830,11 @@ static void s2io_card_down(nic_t * sp)
        unsigned long flags;
        register u64 val64 = 0;
 
+       del_timer_sync(&sp->alarm_timer);
        /* If s2io_set_link task is executing, wait till it completes. */
-       while (test_and_set_bit(0, &(sp->link_state)))
+       while (test_and_set_bit(0, &(sp->link_state))) {
                msleep(50);
+       }
        atomic_set(&sp->card_state, CARD_DOWN);
 
        /* disable Tx and Rx traffic on the NIC */
@@ -4237,7 +4846,7 @@ static void s2io_card_down(nic_t * sp)
        /* Check if the device is Quiescent and then Reset the NIC */
        do {
                val64 = readq(&bar0->adapter_status);
-               if (verify_xena_quiescence(val64, sp->device_enabled_once)) {
+               if (verify_xena_quiescence(sp, val64, sp->device_enabled_once)) {
                        break;
                }
 
@@ -4251,14 +4860,27 @@ static void s2io_card_down(nic_t * sp)
                        break;
                }
        } while (1);
-       spin_lock_irqsave(&sp->tx_lock, flags);
        s2io_reset(sp);
 
-       /* Free all unused Tx and Rx buffers */
+       /* Waiting till all Interrupt handlers are complete */
+       cnt = 0;
+       do {
+               msleep(10);
+               if (!atomic_read(&sp->isr_cnt))
+                       break;
+               cnt++;
+       } while(cnt < 5);
+
+       spin_lock_irqsave(&sp->tx_lock, flags);
+       /* Free all Tx buffers */
        free_tx_buffers(sp);
+       spin_unlock_irqrestore(&sp->tx_lock, flags);
+
+       /* Free all Rx buffers */
+       spin_lock_irqsave(&sp->rx_lock, flags);
        free_rx_buffers(sp);
+       spin_unlock_irqrestore(&sp->rx_lock, flags);
 
-       spin_unlock_irqrestore(&sp->tx_lock, flags);
        clear_bit(0, &(sp->link_state));
 }
 
@@ -4276,8 +4898,8 @@ static int s2io_card_up(nic_t * sp)
                return -ENODEV;
        }
 
-       /* 
-        * Initializing the Rx buffers. For now we are considering only 1 
+       /*
+        * Initializing the Rx buffers. For now we are considering only 1
         * Rx ring and initializing buffers into 30 Rx blocks
         */
        mac_control = &sp->mac_control;
@@ -4311,16 +4933,18 @@ static int s2io_card_up(nic_t * sp)
                return -ENODEV;
        }
 
+       S2IO_TIMER_CONF(sp->alarm_timer, s2io_alarm_handle, sp, (HZ/2));
+
        atomic_set(&sp->card_state, CARD_UP);
        return 0;
 }
 
-/** 
+/**
  * s2io_restart_nic - Resets the NIC.
  * @data : long pointer to the device private structure
  * Description:
  * This function is scheduled to be run by the s2io_tx_watchdog
- * function after 0.5 secs to reset the NIC. The idea is to reduce 
+ * function after 0.5 secs to reset the NIC. The idea is to reduce
  * the run time of the watch dog routine which is run holding a
  * spin lock.
  */
@@ -4338,10 +4962,11 @@ static void s2io_restart_nic(unsigned long data)
        netif_wake_queue(dev);
        DBG_PRINT(ERR_DBG, "%s: was reset by Tx watchdog timer\n",
                  dev->name);
+
 }
 
-/** 
- *  s2io_tx_watchdog - Watchdog for transmit side. 
+/**
+ *  s2io_tx_watchdog - Watchdog for transmit side.
  *  @dev : Pointer to net device structure
  *  Description:
  *  This function is triggered if the Tx Queue is stopped
@@ -4369,7 +4994,7 @@ static void s2io_tx_watchdog(struct net_device *dev)
  *   @len : length of the packet
  *   @cksum : FCS checksum of the frame.
  *   @ring_no : the ring from which this RxD was extracted.
- *   Description: 
+ *   Description:
  *   This function is called by the Tx interrupt serivce routine to perform
  *   some OS related operations on the SKB before passing it to the upper
  *   layers. It mainly checks if the checksum is OK, if so adds it to the
@@ -4379,35 +5004,68 @@ static void s2io_tx_watchdog(struct net_device *dev)
  *   Return value:
  *   SUCCESS on success and -1 on failure.
  */
-#ifndef CONFIG_2BUFF_MODE
-static int rx_osm_handler(nic_t * sp, u16 len, RxD_t * rxdp, int ring_no)
-#else
-static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,
-                         buffAdd_t * ba)
-#endif
+static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
 {
+       nic_t *sp = ring_data->nic;
        struct net_device *dev = (struct net_device *) sp->dev;
-       struct sk_buff *skb =
-           (struct sk_buff *) ((unsigned long) rxdp->Host_Control);
+       struct sk_buff *skb = (struct sk_buff *)
+               ((unsigned long) rxdp->Host_Control);
+       int ring_no = ring_data->ring_no;
        u16 l3_csum, l4_csum;
 #ifdef CONFIG_2BUFF_MODE
-       int buf0_len, buf2_len;
+       int buf0_len = RXD_GET_BUFFER0_SIZE(rxdp->Control_2);
+       int buf2_len = RXD_GET_BUFFER2_SIZE(rxdp->Control_2);
+       int get_block = ring_data->rx_curr_get_info.block_index;
+       int get_off = ring_data->rx_curr_get_info.offset;
+       buffAdd_t *ba = &ring_data->ba[get_block][get_off];
        unsigned char *buff;
+#else
+       u16 len = (u16) ((RXD_GET_BUFFER0_SIZE(rxdp->Control_2)) >> 48);;
+#endif
+       skb->dev = dev;
+       if (rxdp->Control_1 & RXD_T_CODE) {
+               unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
+               DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n",
+                         dev->name, err);
+               dev_kfree_skb(skb);
+               sp->stats.rx_crc_errors++;
+               atomic_dec(&sp->rx_bufs_left[ring_no]);
+               rxdp->Host_Control = 0;
+               return 0;
+       }
+
+       /* Updating statistics */
+       rxdp->Host_Control = 0;
+       sp->rx_pkt_count++;
+       sp->stats.rx_packets++;
+#ifndef CONFIG_2BUFF_MODE
+       sp->stats.rx_bytes += len;
+#else
+       sp->stats.rx_bytes += buf0_len + buf2_len;
 #endif
 
-       l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1);
-       if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && (sp->rx_csum)) {
+#ifndef CONFIG_2BUFF_MODE
+       skb_put(skb, len);
+#else
+       buff = skb_push(skb, buf0_len);
+       memcpy(buff, ba->ba_0, buf0_len);
+       skb_put(skb, buf2_len);
+#endif
+
+       if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) &&
+           (sp->rx_csum)) {
+               l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1);
                l4_csum = RXD_GET_L4_CKSUM(rxdp->Control_1);
                if ((l3_csum == L3_CKSUM_OK) && (l4_csum == L4_CKSUM_OK)) {
-                       /* 
+                       /*
                         * NIC verifies if the Checksum of the received
                         * frame is Ok or not and accordingly returns
                         * a flag in the RxD.
                         */
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                } else {
-                       /* 
-                        * Packet with erroneous checksum, let the 
+                       /*
+                        * Packet with erroneous checksum, let the
                         * upper layers deal with it.
                         */
                        skb->ip_summed = CHECKSUM_NONE;
@@ -4416,44 +5074,26 @@ static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,
                skb->ip_summed = CHECKSUM_NONE;
        }
 
-       if (rxdp->Control_1 & RXD_T_CODE) {
-               unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
-               DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n",
-                         dev->name, err);
-       }
-#ifdef CONFIG_2BUFF_MODE
-       buf0_len = RXD_GET_BUFFER0_SIZE(rxdp->Control_2);
-       buf2_len = RXD_GET_BUFFER2_SIZE(rxdp->Control_2);
-#endif
-
-       skb->dev = dev;
-#ifndef CONFIG_2BUFF_MODE
-       skb_put(skb, len);
-       skb->protocol = eth_type_trans(skb, dev);
-#else
-       buff = skb_push(skb, buf0_len);
-       memcpy(buff, ba->ba_0, buf0_len);
-       skb_put(skb, buf2_len);
        skb->protocol = eth_type_trans(skb, dev);
-#endif
-
 #ifdef CONFIG_S2IO_NAPI
-       netif_receive_skb(skb);
+       if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) {
+               /* Queueing the vlan frame to the upper layer */
+               vlan_hwaccel_receive_skb(skb, sp->vlgrp,
+                       RXD_GET_VLAN_TAG(rxdp->Control_2));
+       } else {
+               netif_receive_skb(skb);
+       }
 #else
-       netif_rx(skb);
+       if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) {
+               /* Queueing the vlan frame to the upper layer */
+               vlan_hwaccel_rx(skb, sp->vlgrp,
+                       RXD_GET_VLAN_TAG(rxdp->Control_2));
+       } else {
+               netif_rx(skb);
+       }
 #endif
-
        dev->last_rx = jiffies;
-       sp->rx_pkt_count++;
-       sp->stats.rx_packets++;
-#ifndef CONFIG_2BUFF_MODE
-       sp->stats.rx_bytes += len;
-#else
-       sp->stats.rx_bytes += buf0_len + buf2_len;
-#endif
-
        atomic_dec(&sp->rx_bufs_left[ring_no]);
-       rxdp->Host_Control = 0;
        return SUCCESS;
 }
 
@@ -4464,13 +5104,13 @@ static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,
  *  @link : inidicates whether link is UP/DOWN.
  *  Description:
  *  This function stops/starts the Tx queue depending on whether the link
- *  status of the NIC is is down or up. This is called by the Alarm 
- *  interrupt handler whenever a link change interrupt comes up. 
+ *  status of the NIC is is down or up. This is called by the Alarm
+ *  interrupt handler whenever a link change interrupt comes up.
  *  Return value:
  *  void.
  */
 
-static void s2io_link(nic_t * sp, int link)
+void s2io_link(nic_t * sp, int link)
 {
        struct net_device *dev = (struct net_device *) sp->dev;
 
@@ -4487,8 +5127,25 @@ static void s2io_link(nic_t * sp, int link)
 }
 
 /**
- *  s2io_init_pci -Initialization of PCI and PCI-X configuration registers . 
- *  @sp : private member of the device structure, which is a pointer to the 
+ *  get_xena_rev_id - to identify revision ID of xena.
+ *  @pdev : PCI Dev structure
+ *  Description:
+ *  Function to identify the Revision ID of xena.
+ *  Return value:
+ *  returns the revision ID of the device.
+ */
+
+int get_xena_rev_id(struct pci_dev *pdev)
+{
+       u8 id = 0;
+       int ret;
+       ret = pci_read_config_byte(pdev, PCI_REVISION_ID, (u8 *) & id);
+       return id;
+}
+
+/**
+ *  s2io_init_pci -Initialization of PCI and PCI-X configuration registers .
+ *  @sp : private member of the device structure, which is a pointer to the
  *  s2io_nic structure.
  *  Description:
  *  This function initializes a few of the PCI and PCI-X configuration registers
@@ -4499,15 +5156,15 @@ static void s2io_link(nic_t * sp, int link)
 
 static void s2io_init_pci(nic_t * sp)
 {
-       u16 pci_cmd = 0;
+       u16 pci_cmd = 0, pcix_cmd = 0;
 
        /* Enable Data Parity Error Recovery in PCI-X command register. */
        pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
-                            &(sp->pcix_cmd));
+                            &(pcix_cmd));
        pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
-                             (sp->pcix_cmd | 1));
+                             (pcix_cmd | 1));
        pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
-                            &(sp->pcix_cmd));
+                            &(pcix_cmd));
 
        /* Set the PErr Response bit in PCI command register. */
        pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
@@ -4515,53 +5172,43 @@ static void s2io_init_pci(nic_t * sp)
                              (pci_cmd | PCI_COMMAND_PARITY));
        pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
 
-       /* Set MMRB count to 1024 in PCI-X Command register. */
-       sp->pcix_cmd &= 0xFFF3;
-       pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, (sp->pcix_cmd | (0x1 << 2)));    /* MMRBC 1K */
-       pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
-                            &(sp->pcix_cmd));
-
-       /*  Setting Maximum outstanding splits based on system type. */
-       sp->pcix_cmd &= 0xFF8F;
-
-       sp->pcix_cmd |= XENA_MAX_OUTSTANDING_SPLITS(0x1);       /* 2 splits. */
-       pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
-                             sp->pcix_cmd);
-       pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
-                            &(sp->pcix_cmd));
        /* Forcibly disabling relaxed ordering capability of the card. */
-       sp->pcix_cmd &= 0xfffd;
+       pcix_cmd &= 0xfffd;
        pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
-                             sp->pcix_cmd);
+                             pcix_cmd);
        pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
-                            &(sp->pcix_cmd));
+                            &(pcix_cmd));
 }
 
 MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>");
 MODULE_LICENSE("GPL");
 module_param(tx_fifo_num, int, 0);
-module_param_array(tx_fifo_len, int, NULL, 0);
 module_param(rx_ring_num, int, 0);
-module_param_array(rx_ring_sz, int, NULL, 0);
-module_param(Stats_refresh_time, int, 0);
+module_param_array(tx_fifo_len, uint, NULL, 0);
+module_param_array(rx_ring_sz, uint, NULL, 0);
+module_param_array(rts_frm_len, uint, NULL, 0);
+module_param(use_continuous_tx_intrs, int, 1);
 module_param(rmac_pause_time, int, 0);
 module_param(mc_pause_threshold_q0q3, int, 0);
 module_param(mc_pause_threshold_q4q7, int, 0);
 module_param(shared_splits, int, 0);
 module_param(tmac_util_period, int, 0);
 module_param(rmac_util_period, int, 0);
+module_param(bimodal, bool, 0);
 #ifndef CONFIG_S2IO_NAPI
 module_param(indicate_max_pkts, int, 0);
 #endif
+module_param(rxsync_frequency, int, 0);
+
 /**
- *  s2io_init_nic - Initialization of the adapter . 
+ *  s2io_init_nic - Initialization of the adapter .
  *  @pdev : structure containing the PCI related information of the device.
  *  @pre: List of PCI devices supported by the driver listed in s2io_tbl.
  *  Description:
  *  The function initializes an adapter identified by the pci_dec structure.
- *  All OS related initialization including memory and device structure and 
- *  initlaization of the device private variable is done. Also the swapper 
- *  control register is initialized to enable read and write into the I/O 
+ *  All OS related initialization including memory and device structure and
+ *  initlaization of the device private variable is done. Also the swapper
+ *  control register is initialized to enable read and write into the I/O
  *  registers of the device.
  *  Return value:
  *  returns 0 on success and negative on failure.
@@ -4572,7 +5219,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 {
        nic_t *sp;
        struct net_device *dev;
-       char *dev_name = "S2IO 10GE NIC";
        int i, j, ret;
        int dma_flag = FALSE;
        u32 mac_up, mac_down;
@@ -4581,10 +5227,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        u16 subid;
        mac_info_t *mac_control;
        struct config_param *config;
+       int mode;
 
-
-       DBG_PRINT(ERR_DBG, "Loading S2IO driver with %s\n",
-               s2io_driver_version);
+#ifdef CONFIG_S2IO_NAPI
+       DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n");
+#endif
 
        if ((ret = pci_enable_device(pdev))) {
                DBG_PRINT(ERR_DBG,
@@ -4595,7 +5242,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
                DBG_PRINT(INIT_DBG, "s2io_init_nic: Using 64bit DMA\n");
                dma_flag = TRUE;
-
                if (pci_set_consistent_dma_mask
                    (pdev, DMA_64BIT_MASK)) {
                        DBG_PRINT(ERR_DBG,
@@ -4635,34 +5281,41 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        memset(sp, 0, sizeof(nic_t));
        sp->dev = dev;
        sp->pdev = pdev;
-       sp->vendor_id = pdev->vendor;
-       sp->device_id = pdev->device;
        sp->high_dma_flag = dma_flag;
-       sp->irq = pdev->irq;
        sp->device_enabled_once = FALSE;
-       strcpy(sp->name, dev_name);
+
+       if ((pdev->device == PCI_DEVICE_ID_HERC_WIN) ||
+               (pdev->device == PCI_DEVICE_ID_HERC_UNI))
+               sp->device_type = XFRAME_II_DEVICE;
+       else
+               sp->device_type = XFRAME_I_DEVICE;
 
        /* Initialize some PCI/PCI-X fields of the NIC. */
        s2io_init_pci(sp);
 
-       /* 
+       /*
         * Setting the device configuration parameters.
-        * Most of these parameters can be specified by the user during 
-        * module insertion as they are module loadable parameters. If 
-        * these parameters are not not specified during load time, they 
+        * Most of these parameters can be specified by the user during
+        * module insertion as they are module loadable parameters. If
+        * these parameters are not not specified during load time, they
         * are initialized with default values.
         */
        mac_control = &sp->mac_control;
        config = &sp->config;
 
        /* Tx side parameters. */
-       tx_fifo_len[0] = DEFAULT_FIFO_LEN;      /* Default value. */
+       if (tx_fifo_len[0] == 0)
+               tx_fifo_len[0] = DEFAULT_FIFO_LEN; /* Default value. */
        config->tx_fifo_num = tx_fifo_num;
        for (i = 0; i < MAX_TX_FIFOS; i++) {
                config->tx_cfg[i].fifo_len = tx_fifo_len[i];
                config->tx_cfg[i].fifo_priority = i;
        }
 
+       /* mapping the QoS priority to the configured fifos */
+       for (i = 0; i < MAX_TX_FIFOS; i++)
+               config->fifo_mapping[i] = fifo_map[config->tx_fifo_num][i];
+
        config->tx_intr_type = TXD_INT_TYPE_UTILZ;
        for (i = 0; i < config->tx_fifo_num; i++) {
                config->tx_cfg[i].f_no_snoop =
@@ -4675,7 +5328,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        config->max_txds = MAX_SKB_FRAGS;
 
        /* Rx side parameters. */
-       rx_ring_sz[0] = SMALL_BLK_CNT;  /* Default value. */
+       if (rx_ring_sz[0] == 0)
+               rx_ring_sz[0] = SMALL_BLK_CNT; /* Default value. */
        config->rx_ring_num = rx_ring_num;
        for (i = 0; i < MAX_RX_RINGS; i++) {
                config->rx_cfg[i].num_rxd = rx_ring_sz[i] *
@@ -4699,10 +5353,13 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        for (i = 0; i < config->rx_ring_num; i++)
                atomic_set(&sp->rx_bufs_left[i], 0);
 
+       /* Initialize the number of ISRs currently running */
+       atomic_set(&sp->isr_cnt, 0);
+
        /*  initialize the shared memory used by the NIC and the host */
        if (init_shared_mem(sp)) {
                DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n",
-                         dev->name);
+                         __FUNCTION__);
                ret = -ENOMEM;
                goto mem_alloc_failed;
        }
@@ -4743,13 +5400,17 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        dev->do_ioctl = &s2io_ioctl;
        dev->change_mtu = &s2io_change_mtu;
        SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
+       dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+       dev->vlan_rx_register = s2io_vlan_rx_register;
+       dev->vlan_rx_kill_vid = (void *)s2io_vlan_rx_kill_vid;
+
        /*
         * will use eth_mac_addr() for  dev->set_mac_address
         * mac address will be set every time dev->open() is called
         */
-#ifdef CONFIG_S2IO_NAPI
+#if defined(CONFIG_S2IO_NAPI)
        dev->poll = s2io_poll;
-       dev->weight = 90;
+       dev->weight = 32;
 #endif
 
        dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
@@ -4776,22 +5437,28 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
                goto set_swap_failed;
        }
 
-       /* Fix for all "FFs" MAC address problems observed on Alpha platforms */
-       fix_mac_address(sp);
-       s2io_reset(sp);
+       /* Verify if the Herc works on the slot its placed into */
+       if (sp->device_type & XFRAME_II_DEVICE) {
+               mode = s2io_verify_pci_mode(sp);
+               if (mode < 0) {
+                       DBG_PRINT(ERR_DBG, "%s: ", __FUNCTION__);
+                       DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode\n");
+                       ret = -EBADSLT;
+                       goto set_swap_failed;
+               }
+       }
 
-       /*
-        * Setting swapper control on the NIC, so the MAC address can be read.
-        */
-       if (s2io_set_swapper(sp)) {
-               DBG_PRINT(ERR_DBG,
-                         "%s: S2IO: swapper settings are wrong\n",
-                         dev->name);
-               ret = -EAGAIN;
-               goto set_swap_failed;
+       /* Not needed for Herc */
+       if (sp->device_type & XFRAME_I_DEVICE) {
+               /*
+                * Fix for all "FFs" MAC address problems observed on
+                * Alpha platforms
+                */
+               fix_mac_address(sp);
+               s2io_reset(sp);
        }
 
-       /*  
+       /*
         * MAC address initialization.
         * For now only one mac address will be read and used.
         */
@@ -4814,37 +5481,28 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        sp->def_mac_addr[0].mac_addr[5] = (u8) (mac_down >> 16);
        sp->def_mac_addr[0].mac_addr[4] = (u8) (mac_down >> 24);
 
-       DBG_PRINT(INIT_DBG,
-                 "DEFAULT MAC ADDR:0x%02x-%02x-%02x-%02x-%02x-%02x\n",
-                 sp->def_mac_addr[0].mac_addr[0],
-                 sp->def_mac_addr[0].mac_addr[1],
-                 sp->def_mac_addr[0].mac_addr[2],
-                 sp->def_mac_addr[0].mac_addr[3],
-                 sp->def_mac_addr[0].mac_addr[4],
-                 sp->def_mac_addr[0].mac_addr[5]);
-
        /*  Set the factory defined MAC address initially   */
        dev->addr_len = ETH_ALEN;
        memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN);
 
        /*
-        * Initialize the tasklet status and link state flags 
-        * and the card statte parameter
+        * Initialize the tasklet status and link state flags
+        * and the card state parameter
         */
        atomic_set(&(sp->card_state), 0);
        sp->tasklet_status = 0;
        sp->link_state = 0;
 
-
        /* Initialize spinlocks */
        spin_lock_init(&sp->tx_lock);
 #ifndef CONFIG_S2IO_NAPI
        spin_lock_init(&sp->put_lock);
 #endif
+       spin_lock_init(&sp->rx_lock);
 
-       /* 
-        * SXE-002: Configure link and activity LED to init state 
-        * on driver load. 
+       /*
+        * SXE-002: Configure link and activity LED to init state
+        * on driver load.
         */
        subid = sp->pdev->subsystem_device;
        if ((subid & 0xFF) >= 0x07) {
@@ -4864,13 +5522,61 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
                goto register_failed;
        }
 
-       /* 
-        * Make Link state as off at this point, when the Link change 
-        * interrupt comes the state will be automatically changed to 
+       if (sp->device_type & XFRAME_II_DEVICE) {
+               DBG_PRINT(ERR_DBG, "%s: Neterion Xframe II 10GbE adapter ",
+                         dev->name);
+               DBG_PRINT(ERR_DBG, "(rev %d), Driver %s\n",
+                               get_xena_rev_id(sp->pdev),
+                               s2io_driver_version);
+               DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
+                         sp->def_mac_addr[0].mac_addr[0],
+                         sp->def_mac_addr[0].mac_addr[1],
+                         sp->def_mac_addr[0].mac_addr[2],
+                         sp->def_mac_addr[0].mac_addr[3],
+                         sp->def_mac_addr[0].mac_addr[4],
+                         sp->def_mac_addr[0].mac_addr[5]);
+               mode = s2io_print_pci_mode(sp);
+               if (mode < 0) {
+                       DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode ");
+                       ret = -EBADSLT;
+                       goto set_swap_failed;
+               }
+       } else {
+               DBG_PRINT(ERR_DBG, "%s: Neterion Xframe I 10GbE adapter ",
+                         dev->name);
+               DBG_PRINT(ERR_DBG, "(rev %d), Driver %s\n",
+                                       get_xena_rev_id(sp->pdev),
+                                       s2io_driver_version);
+               DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
+                         sp->def_mac_addr[0].mac_addr[0],
+                         sp->def_mac_addr[0].mac_addr[1],
+                         sp->def_mac_addr[0].mac_addr[2],
+                         sp->def_mac_addr[0].mac_addr[3],
+                         sp->def_mac_addr[0].mac_addr[4],
+                         sp->def_mac_addr[0].mac_addr[5]);
+       }
+
+       /* Initialize device name */
+       strcpy(sp->name, dev->name);
+       if (sp->device_type & XFRAME_II_DEVICE)
+               strcat(sp->name, ": Neterion Xframe II 10GbE adapter");
+       else
+               strcat(sp->name, ": Neterion Xframe I 10GbE adapter");
+
+       /* Initialize bimodal Interrupts */
+       sp->config.bimodal = bimodal;
+       if (!(sp->device_type & XFRAME_II_DEVICE) && bimodal) {
+               sp->config.bimodal = 0;
+               DBG_PRINT(ERR_DBG,"%s:Bimodal intr not supported by Xframe I\n",
+                       dev->name);
+       }
+
+       /*
+        * Make Link state as off at this point, when the Link change
+        * interrupt comes the state will be automatically changed to
         * the right state.
         */
        netif_carrier_off(dev);
-       sp->last_link_state = LINK_DOWN;
 
        return 0;
 
@@ -4891,11 +5597,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 }
 
 /**
- * s2io_rem_nic - Free the PCI device 
+ * s2io_rem_nic - Free the PCI device
  * @pdev: structure containing the PCI related information of the device.
- * Description: This function is called by the Pci subsystem to release a 
+ * Description: This function is called by the Pci subsystem to release a
  * PCI device and free up all resource held up by the device. This could
- * be in response to a Hot plug event or when the driver is to be removed 
+ * be in response to a Hot plug event or when the driver is to be removed
  * from memory.
  */
 
@@ -4919,7 +5625,6 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
        pci_disable_device(pdev);
        pci_release_regions(pdev);
        pci_set_drvdata(pdev, NULL);
-
        free_netdev(dev);
 }
 
@@ -4935,11 +5640,11 @@ int __init s2io_starter(void)
 }
 
 /**
- * s2io_closer - Cleanup routine for the driver 
+ * s2io_closer - Cleanup routine for the driver
  * Description: This function is the cleanup routine for the driver. It unregist * ers the driver.
  */
 
-static void s2io_closer(void)
+void s2io_closer(void)
 {
        pci_unregister_driver(&s2io_driver);
        DBG_PRINT(INIT_DBG, "cleanup done\n");
index 1711c8c..5d92707 100644 (file)
@@ -31,6 +31,9 @@
 #define SUCCESS 0
 #define FAILURE -1
 
+/* Maximum time to flicker LED when asked to identify NIC using ethtool */
+#define MAX_FLICKER_TIME       60000 /* 60 Secs */
+
 /* Maximum outstanding splits to be configured into xena. */
 typedef enum xena_max_outstanding_splits {
        XENA_ONE_SPLIT_TRANSACTION = 0,
@@ -45,10 +48,10 @@ typedef enum xena_max_outstanding_splits {
 #define XENA_MAX_OUTSTANDING_SPLITS(n) (n << 4)
 
 /*  OS concerned variables and constants */
-#define WATCH_DOG_TIMEOUT      5*HZ
-#define EFILL                          0x1234
-#define ALIGN_SIZE                     127
-#define        PCIX_COMMAND_REGISTER   0x62
+#define WATCH_DOG_TIMEOUT              15*HZ
+#define EFILL                          0x1234
+#define ALIGN_SIZE                     127
+#define        PCIX_COMMAND_REGISTER           0x62
 
 /*
  * Debug related variables.
@@ -61,7 +64,7 @@ typedef enum xena_max_outstanding_splits {
 #define        INTR_DBG        4
 
 /* Global variable that defines the present debug level of the driver. */
-static int debug_level = ERR_DBG;      /* Default level. */
+int debug_level = ERR_DBG;     /* Default level. */
 
 /* DEBUG message print. */
 #define DBG_PRINT(dbg_level, args...)  if(!(debug_level<dbg_level)) printk(args)
@@ -71,6 +74,12 @@ static int debug_level = ERR_DBG;    /* Default level. */
 #define L4_CKSUM_OK 0xFFFF
 #define S2IO_JUMBO_SIZE 9600
 
+/* Driver statistics maintained by driver */
+typedef struct {
+       unsigned long long single_ecc_errs;
+       unsigned long long double_ecc_errs;
+} swStat_t;
+
 /* The statistics block of Xena */
 typedef struct stat_block {
 /* Tx MAC statistics counters. */
@@ -186,12 +195,90 @@ typedef struct stat_block {
        u32 rxd_rd_cnt;
        u32 rxf_wr_cnt;
        u32 txf_rd_cnt;
+
+/* Tx MAC statistics overflow counters. */
+       u32 tmac_data_octets_oflow;
+       u32 tmac_frms_oflow;
+       u32 tmac_bcst_frms_oflow;
+       u32 tmac_mcst_frms_oflow;
+       u32 tmac_ucst_frms_oflow;
+       u32 tmac_ttl_octets_oflow;
+       u32 tmac_any_err_frms_oflow;
+       u32 tmac_nucst_frms_oflow;
+       u64 tmac_vlan_frms;
+       u32 tmac_drop_ip_oflow;
+       u32 tmac_vld_ip_oflow;
+       u32 tmac_rst_tcp_oflow;
+       u32 tmac_icmp_oflow;
+       u32 tpa_unknown_protocol;
+       u32 tmac_udp_oflow;
+       u32 reserved_10;
+       u32 tpa_parse_failure;
+
+/* Rx MAC Statistics overflow counters. */
+       u32 rmac_data_octets_oflow;
+       u32 rmac_vld_frms_oflow;
+       u32 rmac_vld_bcst_frms_oflow;
+       u32 rmac_vld_mcst_frms_oflow;
+       u32 rmac_accepted_ucst_frms_oflow;
+       u32 rmac_ttl_octets_oflow;
+       u32 rmac_discarded_frms_oflow;
+       u32 rmac_accepted_nucst_frms_oflow;
+       u32 rmac_usized_frms_oflow;
+       u32 rmac_drop_events_oflow;
+       u32 rmac_frag_frms_oflow;
+       u32 rmac_osized_frms_oflow;
+       u32 rmac_ip_oflow;
+       u32 rmac_jabber_frms_oflow;
+       u32 rmac_icmp_oflow;
+       u32 rmac_drop_ip_oflow;
+       u32 rmac_err_drp_udp_oflow;
+       u32 rmac_udp_oflow;
+       u32 reserved_11;
+       u32 rmac_pause_cnt_oflow;
+       u64 rmac_ttl_1519_4095_frms;
+       u64 rmac_ttl_4096_8191_frms;
+       u64 rmac_ttl_8192_max_frms;
+       u64 rmac_ttl_gt_max_frms;
+       u64 rmac_osized_alt_frms;
+       u64 rmac_jabber_alt_frms;
+       u64 rmac_gt_max_alt_frms;
+       u64 rmac_vlan_frms;
+       u32 rmac_len_discard;
+       u32 rmac_fcs_discard;
+       u32 rmac_pf_discard;
+       u32 rmac_da_discard;
+       u32 rmac_red_discard;
+       u32 rmac_rts_discard;
+       u32 reserved_12;
+       u32 rmac_ingm_full_discard;
+       u32 reserved_13;
+       u32 rmac_accepted_ip_oflow;
+       u32 reserved_14;
+       u32 link_fault_cnt;
+       swStat_t sw_stat;
 } StatInfo_t;
 
-/* Structures representing different init time configuration
+/*
+ * Structures representing different init time configuration
  * parameters of the NIC.
  */
 
+#define MAX_TX_FIFOS 8
+#define MAX_RX_RINGS 8
+
+/* FIFO mappings for all possible number of fifos configured */
+int fifo_map[][MAX_TX_FIFOS] = {
+       {0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 0, 0, 1, 1, 1, 1},
+       {0, 0, 0, 1, 1, 1, 2, 2},
+       {0, 0, 1, 1, 2, 2, 3, 3},
+       {0, 0, 1, 1, 2, 2, 3, 4},
+       {0, 0, 1, 1, 2, 3, 4, 5},
+       {0, 0, 1, 2, 3, 4, 5, 6},
+       {0, 1, 2, 3, 4, 5, 6, 7},
+};
+
 /* Maintains Per FIFO related information. */
 typedef struct tx_fifo_config {
 #define        MAX_AVAILABLE_TXDS      8192
@@ -237,14 +324,14 @@ typedef struct rx_ring_config {
 #define NO_SNOOP_RXD_BUFFER         0x02
 } rx_ring_config_t;
 
-/* This structure provides contains values of the tunable parameters 
- * of the H/W 
+/* This structure provides contains values of the tunable parameters
+ * of the H/W
  */
 struct config_param {
 /* Tx Side */
        u32 tx_fifo_num;        /*Number of Tx FIFOs */
-#define MAX_TX_FIFOS 8
 
+       u8 fifo_mapping[MAX_TX_FIFOS];
        tx_fifo_config_t tx_cfg[MAX_TX_FIFOS];  /*Per-Tx FIFO config */
        u32 max_txds;           /*Max no. of Tx buffer descriptor per TxDL */
        u64 tx_intr_type;
@@ -252,10 +339,10 @@ struct config_param {
 
 /* Rx Side */
        u32 rx_ring_num;        /*Number of receive rings */
-#define MAX_RX_RINGS 8
 #define MAX_RX_BLOCKS_PER_RING  150
 
        rx_ring_config_t rx_cfg[MAX_RX_RINGS];  /*Per-Rx Ring config */
+       u8 bimodal;             /*Flag for setting bimodal interrupts*/
 
 #define HEADER_ETHERNET_II_802_3_SIZE 14
 #define HEADER_802_2_SIZE              3
@@ -269,6 +356,7 @@ struct config_param {
 #define MAX_PYLD_JUMBO              9600
 #define MAX_MTU_JUMBO               (MAX_PYLD_JUMBO+18)
 #define MAX_MTU_JUMBO_VLAN          (MAX_PYLD_JUMBO+22)
+       u16 bus_speed;
 };
 
 /* Structure representing MAC Addrs */
@@ -277,7 +365,7 @@ typedef struct mac_addr {
 } macaddr_t;
 
 /* Structure that represent every FIFO element in the BAR1
- * Address location. 
+ * Address location.
  */
 typedef struct _TxFIFO_element {
        u64 TxDL_Pointer;
@@ -339,6 +427,7 @@ typedef struct _RxD_t {
 #define RXD_FRAME_PROTO         vBIT(0xFFFF,24,8)
 #define RXD_FRAME_PROTO_IPV4    BIT(27)
 #define RXD_FRAME_PROTO_IPV6    BIT(28)
+#define RXD_FRAME_IP_FRAG      BIT(29)
 #define RXD_FRAME_PROTO_TCP     BIT(30)
 #define RXD_FRAME_PROTO_UDP     BIT(31)
 #define TCP_OR_UDP_FRAME        (RXD_FRAME_PROTO_TCP | RXD_FRAME_PROTO_UDP)
@@ -346,11 +435,15 @@ typedef struct _RxD_t {
 #define RXD_GET_L4_CKSUM(val)   ((u16)(val) & 0xFFFF)
 
        u64 Control_2;
+#define        THE_RXD_MARK            0x3
+#define        SET_RXD_MARKER          vBIT(THE_RXD_MARK, 0, 2)
+#define        GET_RXD_MARKER(ctrl)    ((ctrl & SET_RXD_MARKER) >> 62)
+
 #ifndef CONFIG_2BUFF_MODE
-#define MASK_BUFFER0_SIZE       vBIT(0xFFFF,0,16)
-#define SET_BUFFER0_SIZE(val)   vBIT(val,0,16)
+#define MASK_BUFFER0_SIZE       vBIT(0x3FFF,2,14)
+#define SET_BUFFER0_SIZE(val)   vBIT(val,2,14)
 #else
-#define MASK_BUFFER0_SIZE       vBIT(0xFF,0,16)
+#define MASK_BUFFER0_SIZE       vBIT(0xFF,2,14)
 #define MASK_BUFFER1_SIZE       vBIT(0xFFFF,16,16)
 #define MASK_BUFFER2_SIZE       vBIT(0xFFFF,32,16)
 #define SET_BUFFER0_SIZE(val)   vBIT(val,8,8)
@@ -363,7 +456,7 @@ typedef struct _RxD_t {
 #define SET_NUM_TAG(val)       vBIT(val,16,32)
 
 #ifndef CONFIG_2BUFF_MODE
-#define RXD_GET_BUFFER0_SIZE(Control_2) (u64)((Control_2 & vBIT(0xFFFF,0,16)))
+#define RXD_GET_BUFFER0_SIZE(Control_2) (u64)((Control_2 & vBIT(0x3FFF,2,14)))
 #else
 #define RXD_GET_BUFFER0_SIZE(Control_2) (u8)((Control_2 & MASK_BUFFER0_SIZE) \
                                                        >> 48)
@@ -382,7 +475,7 @@ typedef struct _RxD_t {
 #endif
 } RxD_t;
 
-/* Structure that represents the Rx descriptor block which contains 
+/* Structure that represents the Rx descriptor block which contains
  * 128 Rx descriptors.
  */
 #ifndef CONFIG_2BUFF_MODE
@@ -392,11 +485,11 @@ typedef struct _RxD_block {
 
        u64 reserved_0;
 #define END_OF_BLOCK    0xFEFFFFFFFFFFFFFFULL
-       u64 reserved_1;         /* 0xFEFFFFFFFFFFFFFF to mark last 
+       u64 reserved_1;         /* 0xFEFFFFFFFFFFFFFF to mark last
                                 * Rxd in this blk */
        u64 reserved_2_pNext_RxD_block; /* Logical ptr to next */
        u64 pNext_RxD_Blk_physical;     /* Buff0_ptr.In a 32 bit arch
-                                        * the upper 32 bits should 
+                                        * the upper 32 bits should
                                         * be 0 */
 } RxD_block_t;
 #else
@@ -405,13 +498,13 @@ typedef struct _RxD_block {
        RxD_t rxd[MAX_RXDS_PER_BLOCK];
 
 #define END_OF_BLOCK    0xFEFFFFFFFFFFFFFFULL
-       u64 reserved_1;         /* 0xFEFFFFFFFFFFFFFF to mark last Rxd 
+       u64 reserved_1;         /* 0xFEFFFFFFFFFFFFFF to mark last Rxd
                                 * in this blk */
        u64 pNext_RxD_Blk_physical;     /* Phy ponter to next blk. */
 } RxD_block_t;
 #define SIZE_OF_BLOCK  4096
 
-/* Structure to hold virtual addresses of Buf0 and Buf1 in 
+/* Structure to hold virtual addresses of Buf0 and Buf1 in
  * 2buf mode. */
 typedef struct bufAdd {
        void *ba_0_org;
@@ -423,8 +516,8 @@ typedef struct bufAdd {
 
 /* Structure which stores all the MAC control parameters */
 
-/* This structure stores the offset of the RxD in the ring 
- * from which the Rx Interrupt processor can start picking 
+/* This structure stores the offset of the RxD in the ring
+ * from which the Rx Interrupt processor can start picking
  * up the RxDs for processing.
  */
 typedef struct _rx_curr_get_info_t {
@@ -436,7 +529,7 @@ typedef struct _rx_curr_get_info_t {
 typedef rx_curr_get_info_t rx_curr_put_info_t;
 
 /* This structure stores the offset of the TxDl in the FIFO
- * from which the Tx Interrupt processor can start picking 
+ * from which the Tx Interrupt processor can start picking
  * up the TxDLs for send complete interrupt processing.
  */
 typedef struct {
@@ -446,32 +539,96 @@ typedef struct {
 
 typedef tx_curr_get_info_t tx_curr_put_info_t;
 
-/* Infomation related to the Tx and Rx FIFOs and Rings of Xena
- * is maintained in this structure.
- */
-typedef struct mac_info {
-/* rx side stuff */
-       /* Put pointer info which indictes which RxD has to be replenished 
+/* Structure that holds the Phy and virt addresses of the Blocks */
+typedef struct rx_block_info {
+       RxD_t *block_virt_addr;
+       dma_addr_t block_dma_addr;
+} rx_block_info_t;
+
+/* pre declaration of the nic structure */
+typedef struct s2io_nic nic_t;
+
+/* Ring specific structure */
+typedef struct ring_info {
+       /* The ring number */
+       int ring_no;
+
+       /*
+        *  Place holders for the virtual and physical addresses of
+        *  all the Rx Blocks
+        */
+       rx_block_info_t rx_blocks[MAX_RX_BLOCKS_PER_RING];
+       int block_count;
+       int pkt_cnt;
+
+       /*
+        * Put pointer info which indictes which RxD has to be replenished
         * with a new buffer.
         */
-       rx_curr_put_info_t rx_curr_put_info[MAX_RX_RINGS];
+       rx_curr_put_info_t rx_curr_put_info;
 
-       /* Get pointer info which indictes which is the last RxD that was 
+       /*
+        * Get pointer info which indictes which is the last RxD that was
         * processed by the driver.
         */
-       rx_curr_get_info_t rx_curr_get_info[MAX_RX_RINGS];
+       rx_curr_get_info_t rx_curr_get_info;
 
-       u16 rmac_pause_time;
-       u16 mc_pause_threshold_q0q3;
-       u16 mc_pause_threshold_q4q7;
+#ifndef CONFIG_S2IO_NAPI
+       /* Index to the absolute position of the put pointer of Rx ring */
+       int put_pos;
+#endif
+
+#ifdef CONFIG_2BUFF_MODE
+       /* Buffer Address store. */
+       buffAdd_t **ba;
+#endif
+       nic_t *nic;
+} ring_info_t;
 
+/* Fifo specific structure */
+typedef struct fifo_info {
+       /* FIFO number */
+       int fifo_no;
+
+       /* Maximum TxDs per TxDL */
+       int max_txds;
+
+       /* Place holder of all the TX List's Phy and Virt addresses. */
+       list_info_hold_t *list_info;
+
+       /*
+        * Current offset within the tx FIFO where driver would write
+        * new Tx frame
+        */
+       tx_curr_put_info_t tx_curr_put_info;
+
+       /*
+        * Current offset within tx FIFO from where the driver would start freeing
+        * the buffers
+        */
+       tx_curr_get_info_t tx_curr_get_info;
+
+       nic_t *nic;
+}fifo_info_t;
+
+/* Infomation related to the Tx and Rx FIFOs and Rings of Xena
+ * is maintained in this structure.
+ */
+typedef struct mac_info {
 /* tx side stuff */
        /* logical pointer of start of each Tx FIFO */
        TxFIFO_element_t __iomem *tx_FIFO_start[MAX_TX_FIFOS];
 
-/* Current offset within tx_FIFO_start, where driver would write new Tx frame*/
-       tx_curr_put_info_t tx_curr_put_info[MAX_TX_FIFOS];
-       tx_curr_get_info_t tx_curr_get_info[MAX_TX_FIFOS];
+       /* Fifo specific structure */
+       fifo_info_t fifos[MAX_TX_FIFOS];
+
+/* rx side stuff */
+       /* Ring specific structure */
+       ring_info_t rings[MAX_RX_RINGS];
+
+       u16 rmac_pause_time;
+       u16 mc_pause_threshold_q0q3;
+       u16 mc_pause_threshold_q4q7;
 
        void *stats_mem;        /* orignal pointer to allocated mem */
        dma_addr_t stats_mem_phy;       /* Physical address of the stat block */
@@ -485,12 +642,6 @@ typedef struct {
        int usage_cnt;
 } usr_addr_t;
 
-/* Structure that holds the Phy and virt addresses of the Blocks */
-typedef struct rx_block_info {
-       RxD_t *block_virt_addr;
-       dma_addr_t block_dma_addr;
-} rx_block_info_t;
-
 /* Default Tunable parameters of the NIC. */
 #define DEFAULT_FIFO_LEN 4096
 #define SMALL_RXD_CNT  30 * (MAX_RXDS_PER_BLOCK+1)
@@ -499,7 +650,20 @@ typedef struct rx_block_info {
 #define LARGE_BLK_CNT  100
 
 /* Structure representing one instance of the NIC */
-typedef struct s2io_nic {
+struct s2io_nic {
+#ifdef CONFIG_S2IO_NAPI
+       /*
+        * Count of packets to be processed in a given iteration, it will be indicated
+        * by the quota field of the device structure when NAPI is enabled.
+        */
+       int pkts_to_process;
+#endif
+       struct net_device *dev;
+       mac_info_t mac_control;
+       struct config_param config;
+       struct pci_dev *pdev;
+       void __iomem *bar0;
+       void __iomem *bar1;
 #define MAX_MAC_SUPPORTED   16
 #define MAX_SUPPORTED_MULTICASTS MAX_MAC_SUPPORTED
 
@@ -507,33 +671,20 @@ typedef struct s2io_nic {
        macaddr_t pre_mac_addr[MAX_MAC_SUPPORTED];
 
        struct net_device_stats stats;
-       void __iomem *bar0;
-       void __iomem *bar1;
-       struct config_param config;
-       mac_info_t mac_control;
        int high_dma_flag;
        int device_close_flag;
        int device_enabled_once;
 
-       char name[32];
+       char name[50];
        struct tasklet_struct task;
        volatile unsigned long tasklet_status;
-       struct timer_list timer;
-       struct net_device *dev;
-       struct pci_dev *pdev;
 
-       u16 vendor_id;
-       u16 device_id;
-       u16 ccmd;
-       u32 cbar0_1;
-       u32 cbar0_2;
-       u32 cbar1_1;
-       u32 cbar1_2;
-       u32 cirq;
-       u8 cache_line;
-       u32 rom_expansion;
-       u16 pcix_cmd;
-       u32 irq;
+       /* Timer that handles I/O errors/exceptions */
+       struct timer_list alarm_timer;
+
+       /* Space to back up the PCI config space */
+       u32 config_space[256 / sizeof(u32)];
+
        atomic_t rx_bufs_left[MAX_RX_RINGS];
 
        spinlock_t tx_lock;
@@ -558,27 +709,11 @@ typedef struct s2io_nic {
        u16 tx_err_count;
        u16 rx_err_count;
 
-#ifndef CONFIG_S2IO_NAPI
-       /* Index to the absolute position of the put pointer of Rx ring. */
-       int put_pos[MAX_RX_RINGS];
-#endif
-
-       /*
-        *  Place holders for the virtual and physical addresses of 
-        *  all the Rx Blocks
-        */
-       rx_block_info_t rx_blocks[MAX_RX_RINGS][MAX_RX_BLOCKS_PER_RING];
-       int block_count[MAX_RX_RINGS];
-       int pkt_cnt[MAX_RX_RINGS];
-
-       /* Place holder of all the TX List's Phy and Virt addresses. */
-       list_info_hold_t *list_info[MAX_TX_FIFOS];
-
        /*  Id timer, used to blink NIC to physically identify NIC. */
        struct timer_list id_timer;
 
        /*  Restart timer, used to restart NIC if the device is stuck and
-        *  a schedule task that will set the correct Link state once the 
+        *  a schedule task that will set the correct Link state once the
         *  NIC's PHY has stabilized after a state change.
         */
 #ifdef INIT_TQUEUE
@@ -589,12 +724,12 @@ typedef struct s2io_nic {
        struct work_struct set_link_task;
 #endif
 
-       /* Flag that can be used to turn on or turn off the Rx checksum 
+       /* Flag that can be used to turn on or turn off the Rx checksum
         * offload feature.
         */
        int rx_csum;
 
-       /*  after blink, the adapter must be restored with original 
+       /*  after blink, the adapter must be restored with original
         *  values.
         */
        u64 adapt_ctrl_org;
@@ -604,16 +739,19 @@ typedef struct s2io_nic {
 #define        LINK_DOWN       1
 #define        LINK_UP         2
 
-#ifdef CONFIG_2BUFF_MODE
-       /* Buffer Address store. */
-       buffAdd_t **ba[MAX_RX_RINGS];
-#endif
        int task_flag;
 #define CARD_DOWN 1
 #define CARD_UP 2
        atomic_t card_state;
        volatile unsigned long link_state;
-} nic_t;
+       struct vlan_group *vlgrp;
+#define XFRAME_I_DEVICE                1
+#define XFRAME_II_DEVICE       2
+       u8 device_type;
+
+       spinlock_t      rx_lock;
+       atomic_t        isr_cnt;
+};
 
 #define RESET_ERROR 1;
 #define CMD_ERROR   2;
@@ -622,9 +760,10 @@ typedef struct s2io_nic {
 #ifndef readq
 static inline u64 readq(void __iomem *addr)
 {
-       u64 ret = readl(addr + 4);
-       ret <<= 32;
-       ret |= readl(addr);
+       u64 ret = 0;
+       ret = readl(addr + 4);
+       (u64) ret <<= 32;
+       (u64) ret |= readl(addr);
 
        return ret;
 }
@@ -637,10 +776,10 @@ static inline void writeq(u64 val, void __iomem *addr)
        writel((u32) (val >> 32), (addr + 4));
 }
 
-/* In 32 bit modes, some registers have to be written in a 
+/* In 32 bit modes, some registers have to be written in a
  * particular order to expect correct hardware operation. The
- * macro SPECIAL_REG_WRITE is used to perform such ordered 
- * writes. Defines UF (Upper First) and LF (Lower First) will 
+ * macro SPECIAL_REG_WRITE is used to perform such ordered
+ * writes. Defines UF (Upper First) and LF (Lower First) will
  * be used to specify the required write order.
  */
 #define UF     1
@@ -716,6 +855,7 @@ static inline void SPECIAL_REG_WRITE(u64 val, void __iomem *addr, int order)
 #define        PCC_FB_ECC_ERR     vBIT(0xff, 16, 8)    /* Interrupt to indicate
                                                   PCC_FB_ECC Error. */
 
+#define RXD_GET_VLAN_TAG(Control_2) (u16)(Control_2 & MASK_VLAN_TAG)
 /*
  * Prototype declaration.
  */
@@ -725,36 +865,30 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev);
 static int init_shared_mem(struct s2io_nic *sp);
 static void free_shared_mem(struct s2io_nic *sp);
 static int init_nic(struct s2io_nic *nic);
-#ifndef CONFIG_S2IO_NAPI
-static void rx_intr_handler(struct s2io_nic *sp);
-#endif
-static void tx_intr_handler(struct s2io_nic *sp);
+static void rx_intr_handler(ring_info_t *ring_data);
+static void tx_intr_handler(fifo_info_t *fifo_data);
 static void alarm_intr_handler(struct s2io_nic *sp);
 
 static int s2io_starter(void);
-static void s2io_closer(void);
+void s2io_closer(void);
 static void s2io_tx_watchdog(struct net_device *dev);
 static void s2io_tasklet(unsigned long dev_addr);
 static void s2io_set_multicast(struct net_device *dev);
-#ifndef CONFIG_2BUFF_MODE
-static int rx_osm_handler(nic_t * sp, u16 len, RxD_t * rxdp, int ring_no);
-#else
-static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,
-                         buffAdd_t * ba);
-#endif
-static void s2io_link(nic_t * sp, int link);
-static void s2io_reset(nic_t * sp);
-#ifdef CONFIG_S2IO_NAPI
+static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp);
+void s2io_link(nic_t * sp, int link);
+void s2io_reset(nic_t * sp);
+#if defined(CONFIG_S2IO_NAPI)
 static int s2io_poll(struct net_device *dev, int *budget);
 #endif
 static void s2io_init_pci(nic_t * sp);
-static int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
+int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
+static void s2io_alarm_handle(unsigned long data);
 static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs);
-static int verify_xena_quiescence(u64 val64, int flag);
+static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag);
 static struct ethtool_ops netdev_ethtool_ops;
 static void s2io_set_link(unsigned long data);
-static int s2io_set_swapper(nic_t * sp);
-static void s2io_card_down(nic_t * nic);
-static int s2io_card_up(nic_t * nic);
-
+int s2io_set_swapper(nic_t * sp);
+static void s2io_card_down(nic_t *nic);
+static int s2io_card_up(nic_t *nic);
+int get_xena_rev_id(struct pci_dev *pdev);
 #endif                         /* _S2IO_H */
index 82570ec..6ee4771 100644 (file)
@@ -5133,6 +5133,84 @@ static void __devexit skge_remove_one(struct pci_dev *pdev)
        kfree(pAC);
 }
 
+#ifdef CONFIG_PM
+static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       DEV_NET *pNet = netdev_priv(dev);
+       SK_AC *pAC = pNet->pAC;
+       struct net_device *otherdev = pAC->dev[1];
+
+       if (netif_running(dev)) {
+               netif_carrier_off(dev);
+               DoPrintInterfaceChange = SK_FALSE;
+               SkDrvDeInitAdapter(pAC, 0);  /* performs SkGeClose */
+               netif_device_detach(dev);
+       }
+       if (otherdev != dev) {
+               if (netif_running(otherdev)) {
+                       netif_carrier_off(otherdev);
+                       DoPrintInterfaceChange = SK_FALSE;
+                       SkDrvDeInitAdapter(pAC, 1);  /* performs SkGeClose */
+                       netif_device_detach(otherdev);
+               }
+       }
+
+       pci_save_state(pdev);
+       pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+       if (pAC->AllocFlag & SK_ALLOC_IRQ) {
+               free_irq(dev->irq, dev);
+       }
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+       return 0;
+}
+
+static int skge_resume(struct pci_dev *pdev)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       DEV_NET *pNet = netdev_priv(dev);
+       SK_AC *pAC = pNet->pAC;
+       struct net_device *otherdev = pAC->dev[1];
+       int ret;
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       pci_enable_device(pdev);
+       pci_set_master(pdev);
+       if (pAC->GIni.GIMacsFound == 2)
+               ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev);
+       else
+               ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, pAC->Name, dev);
+       if (ret) {
+               printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq);
+               pAC->AllocFlag &= ~SK_ALLOC_IRQ;
+               dev->irq = 0;
+               pci_disable_device(pdev);
+               return -EBUSY;
+       }
+
+       netif_device_attach(dev);
+       if (netif_running(dev)) {
+               DoPrintInterfaceChange = SK_FALSE;
+               SkDrvInitAdapter(pAC, 0);    /* first device  */
+       }
+       if (otherdev != dev) {
+               netif_device_attach(otherdev);
+               if (netif_running(otherdev)) {
+                       DoPrintInterfaceChange = SK_FALSE;
+                       SkDrvInitAdapter(pAC, 1);    /* second device  */
+               }
+       }
+
+       return 0;
+}
+#else
+#define skge_suspend NULL
+#define skge_resume NULL
+#endif
+
 static struct pci_device_id skge_pci_tbl[] = {
        { PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
        { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
@@ -5158,6 +5236,8 @@ static struct pci_driver skge_driver = {
        .id_table       = skge_pci_tbl,
        .probe          = skge_probe_one,
        .remove         = __devexit_p(skge_remove_one),
+       .suspend        = skge_suspend,
+       .resume         = skge_resume,
 };
 
 static int __init skge_init(void)
index df44834..6cb49dd 100644 (file)
@@ -2016,7 +2016,7 @@ SK_IOC    IoC)            /* IO context */
         * we set the PHY to coma mode and switch to D3 power state.
         */
        if (pAC->GIni.GIYukonLite &&
-               pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
+               pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
 
                /* for all ports switch PHY to coma mode */
                for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
index 94a09de..42d2d96 100644 (file)
@@ -1065,7 +1065,7 @@ int               Port)   /* Port Index (MAC_1 + n) */
        
        /* WA code for COMA mode */
        if (pAC->GIni.GIYukonLite &&
-               pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
+               pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
                
                SK_IN32(IoC, B2_GP_IO, &DWord);
 
@@ -1110,7 +1110,7 @@ int               Port)   /* Port Index (MAC_1 + n) */
 
        /* WA code for COMA mode */
        if (pAC->GIni.GIYukonLite &&
-               pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
+               pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
                
                SK_IN32(IoC, B2_GP_IO, &DWord);
 
@@ -2126,7 +2126,7 @@ SK_U8     Mode)           /* low power mode */
        int             Ret = 0;
 
        if (pAC->GIni.GIYukonLite &&
-           pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
+           pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
 
                /* save current power mode */
                LastMode = pAC->GIni.GP[Port].PPhyPowerState;
@@ -2253,7 +2253,7 @@ int               Port)           /* Port Index (e.g. MAC_1) */
        int             Ret = 0;
 
        if (pAC->GIni.GIYukonLite &&
-               pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
+               pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
 
                /* save current power mode */
                LastMode = pAC->GIni.GP[Port].PPhyPowerState;
index 5cacc7a..d7c9851 100644 (file)
@@ -42,7 +42,7 @@
 #include "skge.h"
 
 #define DRV_NAME               "skge"
-#define DRV_VERSION            "0.7"
+#define DRV_VERSION            "0.9"
 #define PFX                    DRV_NAME " "
 
 #define DEFAULT_TX_RING_SIZE   128
@@ -55,7 +55,7 @@
 #define ETH_JUMBO_MTU          9000
 #define TX_WATCHDOG            (5 * HZ)
 #define NAPI_WEIGHT            64
-#define BLINK_HZ               (HZ/4)
+#define BLINK_MS               250
 
 MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
 MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
@@ -75,13 +75,12 @@ static const struct pci_device_id skge_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B) },
        { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) },
        { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) },
-       { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx  */
        { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */
        { PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) },
-       { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1032) },
        { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1064) },
+       { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
        { 0 }
 };
 MODULE_DEVICE_TABLE(pci, skge_id_table);
@@ -190,7 +189,7 @@ static u32 skge_supported_modes(const struct skge_hw *hw)
 {
        u32 supported;
 
-       if (iscopper(hw)) {
+       if (hw->copper) {
                supported = SUPPORTED_10baseT_Half
                        | SUPPORTED_10baseT_Full
                        | SUPPORTED_100baseT_Half
@@ -223,7 +222,7 @@ static int skge_get_settings(struct net_device *dev,
        ecmd->transceiver = XCVR_INTERNAL;
        ecmd->supported = skge_supported_modes(hw);
 
-       if (iscopper(hw)) {
+       if (hw->copper) {
                ecmd->port = PORT_TP;
                ecmd->phy_address = hw->phy_addr;
        } else
@@ -249,7 +248,7 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
        } else {
                u32 setting;
 
-               switch(ecmd->speed) {
+               switch (ecmd->speed) {
                case SPEED_1000:
                        if (ecmd->duplex == DUPLEX_FULL)
                                setting = SUPPORTED_1000baseT_Full;
@@ -620,84 +619,98 @@ static int skge_set_coalesce(struct net_device *dev,
        return 0;
 }
 
-static void skge_led_on(struct skge_hw *hw, int port)
+enum led_mode { LED_MODE_OFF, LED_MODE_ON, LED_MODE_TST };
+static void skge_led(struct skge_port *skge, enum led_mode mode)
 {
+       struct skge_hw *hw = skge->hw;
+       int port = skge->port;
+
+       spin_lock_bh(&hw->phy_lock);
        if (hw->chip_id == CHIP_ID_GENESIS) {
-               skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON);
-               skge_write8(hw, B0_LED, LED_STAT_ON);
+               switch (mode) {
+               case LED_MODE_OFF:
+                       xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
+                       skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
+                       skge_write32(hw, SK_REG(port, RX_LED_VAL), 0);
+                       skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF);
+                       break;
 
-               skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON);
-               skge_write32(hw, SK_REG(port, RX_LED_VAL), 100);
-               skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
+               case LED_MODE_ON:
+                       skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON);
+                       skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON);
 
-               /* For Broadcom Phy only */
-               xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
-       } else {
-               gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
-               gm_phy_write(hw, port, PHY_MARV_LED_OVER,
-                                 PHY_M_LED_MO_DUP(MO_LED_ON)  |
-                                 PHY_M_LED_MO_10(MO_LED_ON)   |
-                                 PHY_M_LED_MO_100(MO_LED_ON)  |
-                                 PHY_M_LED_MO_1000(MO_LED_ON) |
-                                 PHY_M_LED_MO_RX(MO_LED_ON));
-       }
-}
+                       skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
+                       skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START);
 
-static void skge_led_off(struct skge_hw *hw, int port)
-{
-       if (hw->chip_id == CHIP_ID_GENESIS) {
-               skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
-               skge_write8(hw, B0_LED, LED_STAT_OFF);
+                       break;
 
-               skge_write32(hw, SK_REG(port, RX_LED_VAL), 0);
-               skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF);
+               case LED_MODE_TST:
+                       skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON);
+                       skge_write32(hw, SK_REG(port, RX_LED_VAL), 100);
+                       skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
 
-               /* Broadcom only */
-               xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
+                       xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
+                       break;
+               }
        } else {
-               gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
-               gm_phy_write(hw, port, PHY_MARV_LED_OVER,
-                                 PHY_M_LED_MO_DUP(MO_LED_OFF)  |
-                                 PHY_M_LED_MO_10(MO_LED_OFF)   |
-                                 PHY_M_LED_MO_100(MO_LED_OFF)  |
-                                 PHY_M_LED_MO_1000(MO_LED_OFF) |
-                                 PHY_M_LED_MO_RX(MO_LED_OFF));
+               switch (mode) {
+               case LED_MODE_OFF:
+                       gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+                       gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+                                    PHY_M_LED_MO_DUP(MO_LED_OFF)  |
+                                    PHY_M_LED_MO_10(MO_LED_OFF)   |
+                                    PHY_M_LED_MO_100(MO_LED_OFF)  |
+                                    PHY_M_LED_MO_1000(MO_LED_OFF) |
+                                    PHY_M_LED_MO_RX(MO_LED_OFF));
+                       break;
+               case LED_MODE_ON:
+                       gm_phy_write(hw, port, PHY_MARV_LED_CTRL,
+                                    PHY_M_LED_PULS_DUR(PULS_170MS) |
+                                    PHY_M_LED_BLINK_RT(BLINK_84MS) |
+                                    PHY_M_LEDC_TX_CTRL |
+                                    PHY_M_LEDC_DP_CTRL);
+               
+                       gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+                                    PHY_M_LED_MO_RX(MO_LED_OFF) |
+                                    (skge->speed == SPEED_100 ?
+                                     PHY_M_LED_MO_100(MO_LED_ON) : 0));
+                       break;
+               case LED_MODE_TST:
+                       gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+                       gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+                                    PHY_M_LED_MO_DUP(MO_LED_ON)  |
+                                    PHY_M_LED_MO_10(MO_LED_ON)   |
+                                    PHY_M_LED_MO_100(MO_LED_ON)  |
+                                    PHY_M_LED_MO_1000(MO_LED_ON) |
+                                    PHY_M_LED_MO_RX(MO_LED_ON));
+               }
        }
-}
-
-static void skge_blink_timer(unsigned long data)
-{
-       struct skge_port *skge = (struct skge_port *) data;
-       struct skge_hw *hw = skge->hw;
-       unsigned long flags;
-
-       spin_lock_irqsave(&hw->phy_lock, flags);
-       if (skge->blink_on)
-               skge_led_on(hw, skge->port);
-       else
-               skge_led_off(hw, skge->port);
-       spin_unlock_irqrestore(&hw->phy_lock, flags);
-
-       skge->blink_on = !skge->blink_on;
-       mod_timer(&skge->led_blink, jiffies + BLINK_HZ);
+       spin_unlock_bh(&hw->phy_lock);
 }
 
 /* blink LED's for finding board */
 static int skge_phys_id(struct net_device *dev, u32 data)
 {
        struct skge_port *skge = netdev_priv(dev);
+       unsigned long ms;
+       enum led_mode mode = LED_MODE_TST;
 
        if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
-               data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
+               ms = jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT / HZ) * 1000;
+       else
+               ms = data * 1000;
 
-       /* start blinking */
-       skge->blink_on = 1;
-       mod_timer(&skge->led_blink, jiffies+1);
+       while (ms > 0) {
+               skge_led(skge, mode);
+               mode ^= LED_MODE_TST;
 
-       msleep_interruptible(data * 1000);
-       del_timer_sync(&skge->led_blink);
+               if (msleep_interruptible(BLINK_MS))
+                       break;
+               ms -= BLINK_MS;
+       }
 
-       skge_led_off(skge->hw, skge->port);
+       /* back to regular LED state */
+       skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF);
 
        return 0;
 }
@@ -863,6 +876,9 @@ static int skge_rx_fill(struct skge_port *skge)
 
 static void skge_link_up(struct skge_port *skge)
 {
+       skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), 
+                   LED_BLK_OFF|LED_SYNC_OFF|LED_ON);
+
        netif_carrier_on(skge->netdev);
        if (skge->tx_avail > MAX_SKB_FRAGS + 1)
                netif_wake_queue(skge->netdev);
@@ -881,6 +897,7 @@ static void skge_link_up(struct skge_port *skge)
 
 static void skge_link_down(struct skge_port *skge)
 {
+       skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
        netif_carrier_off(skge->netdev);
        netif_stop_queue(skge->netdev);
 
@@ -1028,7 +1045,7 @@ static void bcom_check_link(struct skge_hw *hw, int port)
                        }
 
                        /* Check Duplex mismatch */
-                       switch(aux & PHY_B_AS_AN_RES_MSK) {
+                       switch (aux & PHY_B_AS_AN_RES_MSK) {
                        case PHY_B_RES_1000FD:
                                skge->duplex = DUPLEX_FULL;
                                break;
@@ -1099,7 +1116,7 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo)
        r |=  XM_MMU_NO_PRE;
        xm_write16(hw, port, XM_MMU_CMD,r);
 
-       switch(id1) {
+       switch (id1) {
        case PHY_BCOM_ID1_C0:
                /*
                 * Workaround BCOM Errata for the C0 type.
@@ -1194,13 +1211,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
        xm_write16(hw, port, XM_STAT_CMD,
                        XM_SC_CLR_RXC | XM_SC_CLR_TXC);
 
-       /* initialize Rx, Tx and Link LED */
-       skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON);
-       skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON);
-
-       skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
-       skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START);
-
        /* Unreset the XMAC. */
        skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
 
@@ -1209,7 +1219,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
         * namely for the 1000baseTX cards that use the XMAC's
         * GMII mode.
         */
-       spin_lock_bh(&hw->phy_lock);
        /* Take external Phy out of reset */
        r = skge_read32(hw, B2_GP_IO);
        if (port == 0)
@@ -1219,7 +1228,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
 
        skge_write32(hw, B2_GP_IO, r);
        skge_read32(hw, B2_GP_IO);
-       spin_unlock_bh(&hw->phy_lock);
 
        /* Enable GMII interfac */
        xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
@@ -1569,7 +1577,6 @@ static void yukon_init(struct skge_hw *hw, int port)
 {
        struct skge_port *skge = netdev_priv(hw->dev[port]);
        u16 ctrl, ct1000, adv;
-       u16 ledctrl, ledover;
 
        pr_debug("yukon_init\n");
        if (skge->autoneg == AUTONEG_ENABLE) {
@@ -1596,7 +1603,7 @@ static void yukon_init(struct skge_hw *hw, int port)
        adv = PHY_AN_CSMA;
 
        if (skge->autoneg == AUTONEG_ENABLE) {
-               if (iscopper(hw)) {
+               if (hw->copper) {
                        if (skge->advertising & ADVERTISED_1000baseT_Full)
                                ct1000 |= PHY_M_1000C_AFD;
                        if (skge->advertising & ADVERTISED_1000baseT_Half)
@@ -1641,32 +1648,11 @@ static void yukon_init(struct skge_hw *hw, int port)
        gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
        gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
 
-       /* Setup Phy LED's */
-       ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS);
-       ledover = 0;
-
-       ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL;
-
-       /* turn off the Rx LED (LED_RX) */
-       ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
-
-       /* disable blink mode (LED_DUPLEX) on collisions */
-       ctrl |= PHY_M_LEDC_DP_CTRL;
-       gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
-
-       if (skge->autoneg == AUTONEG_DISABLE || skge->speed == SPEED_100) {
-               /* turn on 100 Mbps LED (LED_LINK100) */
-               ledover |= PHY_M_LED_MO_100(MO_LED_ON);
-       }
-
-       if (ledover)
-               gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
-
        /* Enable phy interrupt on autonegotiation complete (or link up) */
        if (skge->autoneg == AUTONEG_ENABLE)
-               gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
+               gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_MSK);
        else
-               gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+               gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK);
 }
 
 static void yukon_reset(struct skge_hw *hw, int port)
@@ -1691,7 +1677,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
 
        /* WA code for COMA mode -- set PHY reset */
        if (hw->chip_id == CHIP_ID_YUKON_LITE &&
-           hw->chip_rev == CHIP_REV_YU_LITE_A3)
+           hw->chip_rev >= CHIP_REV_YU_LITE_A3)
                skge_write32(hw, B2_GP_IO,
                             (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9));
 
@@ -1701,7 +1687,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
 
        /* WA code for COMA mode -- clear PHY reset */
        if (hw->chip_id == CHIP_ID_YUKON_LITE &&
-           hw->chip_rev == CHIP_REV_YU_LITE_A3)
+           hw->chip_rev >= CHIP_REV_YU_LITE_A3)
                skge_write32(hw, B2_GP_IO,
                             (skge_read32(hw, B2_GP_IO) | GP_DIR_9)
                             & ~GP_IO_9);
@@ -1709,7 +1695,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
        /* Set hardware config mode */
        reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
                GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE;
-       reg |= iscopper(hw) ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB;
+       reg |= hw->copper ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB;
 
        /* Clear GMC reset */
        skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_SET);
@@ -1745,9 +1731,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
        gma_write16(hw, port, GM_GP_CTRL, reg);
        skge_read16(hw, GMAC_IRQ_SRC);
 
-       spin_lock_bh(&hw->phy_lock);
        yukon_init(hw, port);
-       spin_unlock_bh(&hw->phy_lock);
 
        /* MIB clear */
        reg = gma_read16(hw, port, GM_PHY_ADDR);
@@ -1796,11 +1780,16 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
        skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK);
        reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
        if (hw->chip_id == CHIP_ID_YUKON_LITE &&
-           hw->chip_rev == CHIP_REV_YU_LITE_A3)
+           hw->chip_rev >= CHIP_REV_YU_LITE_A3)
                reg &= ~GMF_RX_F_FL_ON;
        skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
        skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg);
-       skge_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
+       /*
+        * because Pause Packet Truncation in GMAC is not working
+        * we have to increase the Flush Threshold to 64 bytes
+        * in order to flush pause packets in Rx FIFO on Yukon-1
+        */
+       skge_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1);
 
        /* Configure Tx MAC FIFO */
        skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
@@ -1813,19 +1802,19 @@ static void yukon_stop(struct skge_port *skge)
        int port = skge->port;
 
        if (hw->chip_id == CHIP_ID_YUKON_LITE &&
-           hw->chip_rev == CHIP_REV_YU_LITE_A3) {
+           hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
                skge_write32(hw, B2_GP_IO,
                             skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9);
        }
 
        gma_write16(hw, port, GM_GP_CTRL,
                         gma_read16(hw, port, GM_GP_CTRL)
-                        & ~(GM_GPCR_RX_ENA|GM_GPCR_RX_ENA));
+                        & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA));
        gma_read16(hw, port, GM_GP_CTRL);
 
        /* set GPHY Control reset */
-       gma_write32(hw, port, GPHY_CTRL, GPC_RST_SET);
-       gma_write32(hw, port, GMAC_CTRL, GMC_RST_SET);
+       skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+       skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
 }
 
 static void yukon_get_stats(struct skge_port *skge, u64 *data)
@@ -1856,11 +1845,12 @@ static void yukon_mac_intr(struct skge_hw *hw, int port)
 
        if (status & GM_IS_RX_FF_OR) {
                ++skge->net_stats.rx_fifo_errors;
-               gma_write8(hw, port, RX_GMF_CTRL_T, GMF_CLI_RX_FO);
+               skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO);
        }
+
        if (status & GM_IS_TX_FF_UR) {
                ++skge->net_stats.tx_fifo_errors;
-               gma_write8(hw, port, TX_GMF_CTRL_T, GMF_CLI_TX_FU);
+               skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU);
        }
 
 }
@@ -1896,7 +1886,7 @@ static void yukon_link_up(struct skge_port *skge)
        reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
        gma_write16(hw, port, GM_GP_CTRL, reg);
 
-       gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+       gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK);
        skge_link_up(skge);
 }
 
@@ -1904,12 +1894,14 @@ static void yukon_link_down(struct skge_port *skge)
 {
        struct skge_hw *hw = skge->hw;
        int port = skge->port;
+       u16 ctrl;
 
        pr_debug("yukon_link_down\n");
        gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
-       gm_phy_write(hw, port, GM_GP_CTRL,
-                         gm_phy_read(hw, port, GM_GP_CTRL)
-                         & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA));
+
+       ctrl = gma_read16(hw, port, GM_GP_CTRL);
+       ctrl &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
+       gma_write16(hw, port, GM_GP_CTRL, ctrl);
 
        if (skge->flow_control == FLOW_MODE_REM_SEND) {
                /* restore Asymmetric Pause bit */
@@ -2097,10 +2089,12 @@ static int skge_up(struct net_device *dev)
        skge_write32(hw, B0_IMSK, hw->intr_mask);
 
        /* Initialze MAC */
+       spin_lock_bh(&hw->phy_lock);
        if (hw->chip_id == CHIP_ID_GENESIS)
                genesis_mac_init(hw, port);
        else
                yukon_mac_init(hw, port);
+       spin_unlock_bh(&hw->phy_lock);
 
        /* Configure RAMbuffers */
        chunk = hw->ram_size / ((hw->ports + 1)*2);
@@ -2116,6 +2110,7 @@ static int skge_up(struct net_device *dev)
        /* Start receiver BMU */
        wmb();
        skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
+       skge_led(skge, LED_MODE_ON);
 
        pr_debug("skge_up completed\n");
        return 0;
@@ -2140,8 +2135,6 @@ static int skge_down(struct net_device *dev)
 
        netif_stop_queue(dev);
 
-       del_timer_sync(&skge->led_blink);
-
        /* Stop transmitter */
        skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
        skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
@@ -2175,15 +2168,12 @@ static int skge_down(struct net_device *dev)
        if (hw->chip_id == CHIP_ID_GENESIS) {
                skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET);
                skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET);
-               skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_STOP);
-               skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_STOP);
        } else {
                skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
                skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
        }
 
-       /* turn off led's */
-       skge_write16(hw, B0_LED, LED_STAT_OFF);
+       skge_led(skge, LED_MODE_OFF);
 
        skge_tx_clean(skge);
        skge_rx_clean(skge);
@@ -2633,11 +2623,17 @@ static inline void skge_tx_intr(struct net_device *dev)
        spin_unlock(&skge->tx_lock);
 }
 
+/* Parity errors seem to happen when Genesis is connected to a switch
+ * with no other ports present. Heartbeat error??
+ */
 static void skge_mac_parity(struct skge_hw *hw, int port)
 {
-       printk(KERN_ERR PFX "%s: mac data parity error\n",
-              hw->dev[port] ? hw->dev[port]->name
-              : (port == 0 ? "(port A)": "(port B"));
+       struct net_device *dev = hw->dev[port];
+
+       if (dev) {
+               struct skge_port *skge = netdev_priv(dev);
+               ++skge->net_stats.tx_heartbeat_errors;
+       }
 
        if (hw->chip_id == CHIP_ID_GENESIS)
                skge_write16(hw, SK_REG(port, TX_MFF_CTRL1),
@@ -2683,18 +2679,6 @@ static void skge_error_irq(struct skge_hw *hw)
                /* Timestamp (unused) overflow */
                if (hwstatus & IS_IRQ_TIST_OV)
                        skge_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
-
-               if (hwstatus & IS_IRQ_SENSOR) {
-                       /* no sensors on 32-bit Yukon */
-                       if (!(skge_read16(hw, B0_CTST) & CS_BUS_SLOT_SZ)) {
-                               printk(KERN_ERR PFX "ignoring bogus sensor interrups\n");
-                               skge_write32(hw, B0_HWE_IMSK,
-                                            IS_ERR_MSK & ~IS_IRQ_SENSOR);
-                       } else
-                               printk(KERN_WARNING PFX "sensor interrupt\n");
-               }
-
-
        }
 
        if (hwstatus & IS_RAM_RD_PAR) {
@@ -2725,9 +2709,10 @@ static void skge_error_irq(struct skge_hw *hw)
 
                skge_pci_clear(hw);
 
+               /* if error still set then just ignore it */
                hwstatus = skge_read32(hw, B0_HWE_ISRC);
                if (hwstatus & IS_IRQ_STAT) {
-                       printk(KERN_WARNING PFX "IRQ status %x: still set ignoring hardware errors\n",
+                       pr_debug("IRQ status %x: still set ignoring hardware errors\n",
                               hwstatus);
                        hw->intr_mask &= ~IS_HW_ERR;
                }
@@ -2889,7 +2874,7 @@ static const char *skge_board_name(const struct skge_hw *hw)
 static int skge_reset(struct skge_hw *hw)
 {
        u16 ctst;
-       u8 t8, mac_cfg;
+       u8 t8, mac_cfg, pmd_type, phy_type;
        int i;
 
        ctst = skge_read16(hw, B0_CTST);
@@ -2908,18 +2893,19 @@ static int skge_reset(struct skge_hw *hw)
                     ctst & (CS_CLK_RUN_HOT|CS_CLK_RUN_RST|CS_CLK_RUN_ENA));
 
        hw->chip_id = skge_read8(hw, B2_CHIP_ID);
-       hw->phy_type = skge_read8(hw, B2_E_1) & 0xf;
-       hw->pmd_type = skge_read8(hw, B2_PMD_TYP);
+       phy_type = skge_read8(hw, B2_E_1) & 0xf;
+       pmd_type = skge_read8(hw, B2_PMD_TYP);
+       hw->copper = (pmd_type == 'T' || pmd_type == '1');
 
        switch (hw->chip_id) {
        case CHIP_ID_GENESIS:
-               switch (hw->phy_type) {
+               switch (phy_type) {
                case SK_PHY_BCOM:
                        hw->phy_addr = PHY_ADDR_BCOM;
                        break;
                default:
                        printk(KERN_ERR PFX "%s: unsupported phy type 0x%x\n",
-                              pci_name(hw->pdev), hw->phy_type);
+                              pci_name(hw->pdev), phy_type);
                        return -EOPNOTSUPP;
                }
                break;
@@ -2927,13 +2913,10 @@ static int skge_reset(struct skge_hw *hw)
        case CHIP_ID_YUKON:
        case CHIP_ID_YUKON_LITE:
        case CHIP_ID_YUKON_LP:
-               if (hw->phy_type < SK_PHY_MARV_COPPER && hw->pmd_type != 'S')
-                       hw->phy_type = SK_PHY_MARV_COPPER;
+               if (phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S')
+                       hw->copper = 1;
 
                hw->phy_addr = PHY_ADDR_MARV;
-               if (!iscopper(hw))
-                       hw->phy_type = SK_PHY_MARV_FIBER;
-
                break;
 
        default:
@@ -2961,12 +2944,20 @@ static int skge_reset(struct skge_hw *hw)
        else
                hw->ram_size = t8 * 4096;
 
+       hw->intr_mask = IS_HW_ERR | IS_EXT_REG;
        if (hw->chip_id == CHIP_ID_GENESIS)
                genesis_init(hw);
        else {
                /* switch power to VCC (WA for VAUX problem) */
                skge_write8(hw, B0_POWER_CTRL,
                            PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON);
+               /* avoid boards with stuck Hardware error bits */
+               if ((skge_read32(hw, B0_ISRC) & IS_HW_ERR) &&
+                   (skge_read32(hw, B0_HWE_ISRC) & IS_IRQ_SENSOR)) {
+                       printk(KERN_WARNING PFX "stuck hardware sensor bit\n");
+                       hw->intr_mask &= ~IS_HW_ERR;
+               }
+
                for (i = 0; i < hw->ports; i++) {
                        skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
                        skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
@@ -3007,7 +2998,6 @@ static int skge_reset(struct skge_hw *hw)
        skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, 100));
        skge_write32(hw, B2_IRQM_CTRL, TIM_START);
 
-       hw->intr_mask = IS_HW_ERR | IS_EXT_REG;
        skge_write32(hw, B0_IMSK, hw->intr_mask);
 
        if (hw->chip_id != CHIP_ID_GENESIS)
@@ -3083,10 +3073,6 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
 
        spin_lock_init(&skge->tx_lock);
 
-       init_timer(&skge->led_blink);
-       skge->led_blink.function = skge_blink_timer;
-       skge->led_blink.data = (unsigned long) skge;
-
        if (hw->chip_id != CHIP_ID_GENESIS) {
                dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
                skge->rx_csum = 1;
index fced3d2..f1680be 100644 (file)
@@ -214,8 +214,6 @@ enum {
 
 /*     B2_IRQM_HWE_MSK 32 bit  IRQ Moderation HW Error Mask */
 enum {
-       IS_ERR_MSK      = 0x00003fff,/*                 All Error bits */
-
        IS_IRQ_TIST_OV  = 1<<13, /* Time Stamp Timer Overflow (YUKON only) */
        IS_IRQ_SENSOR   = 1<<12, /* IRQ from Sensor (YUKON only) */
        IS_IRQ_MST_ERR  = 1<<11, /* IRQ master error detected */
@@ -230,6 +228,12 @@ enum {
        IS_M2_PAR_ERR   = 1<<2, /* MAC 2 Parity Error */
        IS_R1_PAR_ERR   = 1<<1, /* Queue R1 Parity Error */
        IS_R2_PAR_ERR   = 1<<0, /* Queue R2 Parity Error */
+
+       IS_ERR_MSK      = IS_IRQ_MST_ERR | IS_IRQ_STAT
+                       | IS_NO_STAT_M1 | IS_NO_STAT_M2
+                       | IS_RAM_RD_PAR | IS_RAM_WR_PAR
+                       | IS_M1_PAR_ERR | IS_M2_PAR_ERR
+                       | IS_R1_PAR_ERR | IS_R2_PAR_ERR,
 };
 
 /*     B2_TST_CTRL1     8 bit  Test Control Register 1 */
@@ -1449,10 +1453,12 @@ enum {
        PHY_M_IS_DTE_CHANGE     = 1<<2, /* DTE Power Det. Status Changed */
        PHY_M_IS_POL_CHANGE     = 1<<1, /* Polarity Changed */
        PHY_M_IS_JABBER         = 1<<0, /* Jabber */
-};
 
-#define PHY_M_DEF_MSK  ( PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE | \
-                         PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR)
+       PHY_M_IS_DEF_MSK        = PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE |
+                                 PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR,
+
+       PHY_M_IS_AN_MSK         = PHY_M_IS_AN_ERROR | PHY_M_IS_AN_COMPL,
+};
 
 /*****  PHY_MARV_EXT_CTRL      16 bit r/w      Ext. PHY Specific Ctrl *****/
 enum {
@@ -1509,7 +1515,7 @@ enum {
        PHY_M_LEDC_TX_C_MSB     = 1<<0, /* Tx Control (MSB, 88E1111 only) */
 };
 
-#define PHY_M_LED_PULS_DUR(x)  (       ((x)<<12) & PHY_M_LEDC_PULS_MSK)
+#define PHY_M_LED_PULS_DUR(x)  (((x)<<12) & PHY_M_LEDC_PULS_MSK)
 
 enum {
        PULS_NO_STR     = 0,/* no pulse stretching */
@@ -1522,7 +1528,7 @@ enum {
        PULS_1300MS     = 7,/* 1.3 s to 2.7 s */
 };
 
-#define PHY_M_LED_BLINK_RT(x)  (       ((x)<<8) & PHY_M_LEDC_BL_R_MSK)
+#define PHY_M_LED_BLINK_RT(x)  (((x)<<8) & PHY_M_LEDC_BL_R_MSK)
 
 enum {
        BLINK_42MS      = 0,/* 42 ms */
@@ -1602,9 +1608,9 @@ enum {
        PHY_M_FELP_LED0_MSK = 0xf, /* Bit  3.. 0: LED0 Mask (SPEED) */
 };
 
-#define PHY_M_FELP_LED2_CTRL(x)        (       ((x)<<8) & PHY_M_FELP_LED2_MSK)
-#define PHY_M_FELP_LED1_CTRL(x)        (       ((x)<<4) & PHY_M_FELP_LED1_MSK)
-#define PHY_M_FELP_LED0_CTRL(x)        (       ((x)<<0) & PHY_M_FELP_LED0_MSK)
+#define PHY_M_FELP_LED2_CTRL(x)        (((x)<<8) & PHY_M_FELP_LED2_MSK)
+#define PHY_M_FELP_LED1_CTRL(x)        (((x)<<4) & PHY_M_FELP_LED1_MSK)
+#define PHY_M_FELP_LED0_CTRL(x)        (((x)<<0) & PHY_M_FELP_LED0_MSK)
 
 enum {
        LED_PAR_CTRL_COLX       = 0x00,
@@ -1640,7 +1646,7 @@ enum {
        PHY_M_MAC_MD_COPPER     = 5,/* Copper only */
        PHY_M_MAC_MD_1000BX     = 7,/* 1000Base-X only */
 };
-#define PHY_M_MAC_MODE_SEL(x)  (       ((x)<<7) & PHY_M_MAC_MD_MSK)
+#define PHY_M_MAC_MODE_SEL(x)  (((x)<<7) & PHY_M_MAC_MD_MSK)
 
 /*****  PHY_MARV_PHY_CTRL (page 3)             16 bit r/w      LED Control Reg. *****/
 enum {
@@ -1650,10 +1656,10 @@ enum {
        PHY_M_LEDC_STA0_MSK     = 0xf, /* Bit  3.. 0: STAT0 LED Ctrl. Mask */
 };
 
-#define PHY_M_LEDC_LOS_CTRL(x) (       ((x)<<12) & PHY_M_LEDC_LOS_MSK)
-#define PHY_M_LEDC_INIT_CTRL(x)        (       ((x)<<8) & PHY_M_LEDC_INIT_MSK)
-#define PHY_M_LEDC_STA1_CTRL(x)        (       ((x)<<4) & PHY_M_LEDC_STA1_MSK)
-#define PHY_M_LEDC_STA0_CTRL(x)        (       ((x)<<0) & PHY_M_LEDC_STA0_MSK)
+#define PHY_M_LEDC_LOS_CTRL(x) (((x)<<12) & PHY_M_LEDC_LOS_MSK)
+#define PHY_M_LEDC_INIT_CTRL(x)        (((x)<<8) & PHY_M_LEDC_INIT_MSK)
+#define PHY_M_LEDC_STA1_CTRL(x)        (((x)<<4) & PHY_M_LEDC_STA1_MSK)
+#define PHY_M_LEDC_STA0_CTRL(x)        (((x)<<0) & PHY_M_LEDC_STA0_MSK)
 
 /* GMAC registers  */
 /* Port Registers */
@@ -2454,24 +2460,17 @@ struct skge_hw {
 
        u8                   chip_id;
        u8                   chip_rev;
-       u8                   phy_type;
-       u8                   pmd_type;
-       u16                  phy_addr;
+       u8                   copper;
        u8                   ports;
 
        u32                  ram_size;
        u32                  ram_offset;
+       u16                  phy_addr;
 
        struct tasklet_struct ext_tasklet;
        spinlock_t           phy_lock;
 };
 
-
-static inline int iscopper(const struct skge_hw *hw)
-{
-       return (hw->pmd_type == 'T');
-}
-
 enum {
        FLOW_MODE_NONE          = 0, /* No Flow-Control */
        FLOW_MODE_LOC_SEND      = 1, /* Local station sends PAUSE */
@@ -2505,8 +2504,6 @@ struct skge_port {
        dma_addr_t           dma;
        unsigned long        mem_size;
        unsigned int         rx_buf_size;
-
-       struct timer_list    led_blink;
 };
 
 
@@ -2606,17 +2603,6 @@ static inline void gma_write16(const struct skge_hw *hw, int port, int r, u16 v)
        skge_write16(hw, SK_GMAC_REG(port,r), v);
 }
 
-static inline void gma_write32(const struct skge_hw *hw, int port, int r, u32 v)
-{
-       skge_write16(hw, SK_GMAC_REG(port, r), (u16) v);
-       skge_write32(hw, SK_GMAC_REG(port, r+4), (u16)(v >> 16));
-}
-
-static inline void gma_write8(const struct skge_hw *hw, int port, int r, u8 v)
-{
-       skge_write8(hw, SK_GMAC_REG(port,r), v);
-}
-
 static inline void gma_set_addr(struct skge_hw *hw, int port, int reg,
                                    const u8 *addr)
 {
index 6d9dae6..ba8593a 100644 (file)
@@ -68,6 +68,7 @@ static const char version[] =
 #include <linux/etherdevice.h>
 
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/system.h>
 
 #include "8390.h"
index 7089d86..a9b06b8 100644 (file)
@@ -188,7 +188,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define        SMC_IRQ_TRIGGER_TYPE (( \
                   machine_is_omap_h2() \
                || machine_is_omap_h3() \
-               || (machine_is_omap_innovator() && !cpu_is_omap150()) \
+               || (machine_is_omap_innovator() && !cpu_is_omap1510()) \
        ) ? IRQT_FALLING : IRQT_RISING)
 
 
index cdc9cc8..90b818a 100644 (file)
@@ -1,6 +1,11 @@
 /*
  * sonic.c
  *
+ * (C) 2005 Finn Thain
+ *
+ * Converted to DMA API, added zero-copy buffer handling, and
+ * (from the mac68k project) introduced dhd's support for 16-bit cards.
+ *
  * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de)
  * 
  * This driver is based on work from Andreas Busse, but most of
  * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
  *
  *    Core code included by system sonic drivers
+ *
+ * And... partially rewritten again by David Huggins-Daines in order
+ * to cope with screwed up Macintosh NICs that may or may not use
+ * 16-bit DMA.
+ *
+ * (C) 1999 David Huggins-Daines <dhd@debian.org>
+ *
  */
 
 /*
  * Sources: Olivetti M700-10 Risc Personal Computer hardware handbook,
  * National Semiconductors data sheet for the DP83932B Sonic Ethernet
  * controller, and the files "8390.c" and "skeleton.c" in this directory.
+ *
+ * Additional sources: Nat Semi data sheet for the DP83932C and Nat Semi
+ * Application Note AN-746, the files "lance.c" and "ibmlana.c". See also
+ * the NetBSD file "sys/arch/mac68k/dev/if_sn.c".
  */
 
 
@@ -28,6 +44,9 @@
  */
 static int sonic_open(struct net_device *dev)
 {
+       struct sonic_local *lp = netdev_priv(dev);
+       int i;
+       
        if (sonic_debug > 2)
                printk("sonic_open: initializing sonic driver.\n");
 
@@ -40,14 +59,59 @@ static int sonic_open(struct net_device *dev)
  * This means that during execution of the handler interrupt are disabled
  * covering another bug otherwise corrupting data.  This doesn't mean
  * this glue works ok under all situations.
+ *
+ * Note (dhd): this also appears to prevent lockups on the Macintrash
+ * when more than one Ethernet card is installed (knock on wood)
+ *
+ * Note (fthain): whether the above is still true is anyones guess. Certainly
+ * the buffer handling algorithms will not tolerate re-entrance without some
+ * mutual exclusion added. Anyway, the memcpy has now been eliminated from the
+ * rx code to make this a faster "fast interrupt".
  */
-//    if (sonic_request_irq(dev->irq, &sonic_interrupt, 0, "sonic", dev)) {
-       if (sonic_request_irq(dev->irq, &sonic_interrupt, SA_INTERRUPT,
-                             "sonic", dev)) {
-               printk("\n%s: unable to get IRQ %d .\n", dev->name, dev->irq);
+       if (request_irq(dev->irq, &sonic_interrupt, SONIC_IRQ_FLAG, "sonic", dev)) {
+               printk(KERN_ERR "\n%s: unable to get IRQ %d .\n", dev->name, dev->irq);
                return -EAGAIN;
        }
 
+       for (i = 0; i < SONIC_NUM_RRS; i++) {
+               struct sk_buff *skb = dev_alloc_skb(SONIC_RBSIZE + 2);
+               if (skb == NULL) {
+                       while(i > 0) { /* free any that were allocated successfully */
+                               i--;
+                               dev_kfree_skb(lp->rx_skb[i]);
+                               lp->rx_skb[i] = NULL;
+                       }
+                       printk(KERN_ERR "%s: couldn't allocate receive buffers\n",
+                              dev->name);
+                       return -ENOMEM;
+               }
+               skb->dev = dev;
+               /* align IP header unless DMA requires otherwise */
+               if (SONIC_BUS_SCALE(lp->dma_bitmode) == 2)
+                       skb_reserve(skb, 2);
+               lp->rx_skb[i] = skb;
+       }
+
+       for (i = 0; i < SONIC_NUM_RRS; i++) {
+               dma_addr_t laddr = dma_map_single(lp->device, skb_put(lp->rx_skb[i], SONIC_RBSIZE),
+                                                 SONIC_RBSIZE, DMA_FROM_DEVICE);
+               if (!laddr) {
+                       while(i > 0) { /* free any that were mapped successfully */
+                               i--;
+                               dma_unmap_single(lp->device, lp->rx_laddr[i], SONIC_RBSIZE, DMA_FROM_DEVICE);
+                               lp->rx_laddr[i] = (dma_addr_t)0;
+                       }
+                       for (i = 0; i < SONIC_NUM_RRS; i++) {
+                               dev_kfree_skb(lp->rx_skb[i]);
+                               lp->rx_skb[i] = NULL;
+                       }
+                       printk(KERN_ERR "%s: couldn't map rx DMA buffers\n",
+                              dev->name);
+                       return -ENOMEM;
+               }
+               lp->rx_laddr[i] = laddr;
+       }
+
        /*
         * Initialize the SONIC
         */
@@ -67,7 +131,8 @@ static int sonic_open(struct net_device *dev)
  */
 static int sonic_close(struct net_device *dev)
 {
-       unsigned int base_addr = dev->base_addr;
+       struct sonic_local *lp = netdev_priv(dev);
+       int i;
 
        if (sonic_debug > 2)
                printk("sonic_close\n");
@@ -77,20 +142,56 @@ static int sonic_close(struct net_device *dev)
        /*
         * stop the SONIC, disable interrupts
         */
-       SONIC_WRITE(SONIC_ISR, 0x7fff);
        SONIC_WRITE(SONIC_IMR, 0);
+       SONIC_WRITE(SONIC_ISR, 0x7fff);
        SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
 
-       sonic_free_irq(dev->irq, dev);  /* release the IRQ */
+       /* unmap and free skbs that haven't been transmitted */
+       for (i = 0; i < SONIC_NUM_TDS; i++) {
+               if(lp->tx_laddr[i]) {
+                       dma_unmap_single(lp->device, lp->tx_laddr[i], lp->tx_len[i], DMA_TO_DEVICE);
+                       lp->tx_laddr[i] = (dma_addr_t)0;
+               }
+               if(lp->tx_skb[i]) {
+                       dev_kfree_skb(lp->tx_skb[i]);
+                       lp->tx_skb[i] = NULL;
+               }
+       }
+
+       /* unmap and free the receive buffers */
+       for (i = 0; i < SONIC_NUM_RRS; i++) {
+               if(lp->rx_laddr[i]) {
+                       dma_unmap_single(lp->device, lp->rx_laddr[i], SONIC_RBSIZE, DMA_FROM_DEVICE);
+                       lp->rx_laddr[i] = (dma_addr_t)0;
+               }
+               if(lp->rx_skb[i]) {
+                       dev_kfree_skb(lp->rx_skb[i]);
+                       lp->rx_skb[i] = NULL;
+               }
+       }
+
+       free_irq(dev->irq, dev);        /* release the IRQ */
 
        return 0;
 }
 
 static void sonic_tx_timeout(struct net_device *dev)
 {
-       struct sonic_local *lp = (struct sonic_local *) dev->priv;
-       printk("%s: transmit timed out.\n", dev->name);
-
+       struct sonic_local *lp = netdev_priv(dev);
+       int i;
+       /* Stop the interrupts for this */
+       SONIC_WRITE(SONIC_IMR, 0);
+       /* We could resend the original skbs. Easier to re-initialise. */
+       for (i = 0; i < SONIC_NUM_TDS; i++) {
+               if(lp->tx_laddr[i]) {
+                       dma_unmap_single(lp->device, lp->tx_laddr[i], lp->tx_len[i], DMA_TO_DEVICE);
+                       lp->tx_laddr[i] = (dma_addr_t)0;
+               }
+               if(lp->tx_skb[i]) {
+                       dev_kfree_skb(lp->tx_skb[i]);
+                       lp->tx_skb[i] = NULL;
+               }
+       }
        /* Try to restart the adaptor. */
        sonic_init(dev);
        lp->stats.tx_errors++;
@@ -100,60 +201,92 @@ static void sonic_tx_timeout(struct net_device *dev)
 
 /*
  * transmit packet
+ *
+ * Appends new TD during transmission thus avoiding any TX interrupts
+ * until we run out of TDs.
+ * This routine interacts closely with the ISR in that it may,
+ *   set tx_skb[i]
+ *   reset the status flags of the new TD
+ *   set and reset EOL flags
+ *   stop the tx queue
+ * The ISR interacts with this routine in various ways. It may,
+ *   reset tx_skb[i]
+ *   test the EOL and status flags of the TDs
+ *   wake the tx queue
+ * Concurrently with all of this, the SONIC is potentially writing to
+ * the status flags of the TDs.
+ * Until some mutual exclusion is added, this code will not work with SMP. However,
+ * MIPS Jazz machines and m68k Macs were all uni-processor machines.
  */
+
 static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
-       struct sonic_local *lp = (struct sonic_local *) dev->priv;
-       unsigned int base_addr = dev->base_addr;
-       unsigned int laddr;
-       int entry, length;
-
-       netif_stop_queue(dev);
+       struct sonic_local *lp = netdev_priv(dev);
+       dma_addr_t laddr;
+       int length;
+       int entry = lp->next_tx;
 
        if (sonic_debug > 2)
                printk("sonic_send_packet: skb=%p, dev=%p\n", skb, dev);
 
+       length = skb->len;
+       if (length < ETH_ZLEN) {
+               skb = skb_padto(skb, ETH_ZLEN);
+               if (skb == NULL)
+                       return 0;
+               length = ETH_ZLEN;
+       }
+
        /*
         * Map the packet data into the logical DMA address space
         */
-       if ((laddr = vdma_alloc(CPHYSADDR(skb->data), skb->len)) == ~0UL) {
-               printk("%s: no VDMA entry for transmit available.\n",
-                      dev->name);
+
+       laddr = dma_map_single(lp->device, skb->data, length, DMA_TO_DEVICE);
+       if (!laddr) {
+               printk(KERN_ERR "%s: failed to map tx DMA buffer.\n", dev->name);
                dev_kfree_skb(skb);
-               netif_start_queue(dev);
                return 1;
        }
-       entry = lp->cur_tx & SONIC_TDS_MASK;
+   
+       sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0);       /* clear status */
+       sonic_tda_put(dev, entry, SONIC_TD_FRAG_COUNT, 1);   /* single fragment */
+       sonic_tda_put(dev, entry, SONIC_TD_PKTSIZE, length); /* length of packet */
+       sonic_tda_put(dev, entry, SONIC_TD_FRAG_PTR_L, laddr & 0xffff);
+       sonic_tda_put(dev, entry, SONIC_TD_FRAG_PTR_H, laddr >> 16);
+       sonic_tda_put(dev, entry, SONIC_TD_FRAG_SIZE, length);
+       sonic_tda_put(dev, entry, SONIC_TD_LINK,
+               sonic_tda_get(dev, entry, SONIC_TD_LINK) | SONIC_EOL);
+
+       /*
+        * Must set tx_skb[entry] only after clearing status, and
+        * before clearing EOL and before stopping queue
+        */
+       wmb();
+       lp->tx_len[entry] = length;
        lp->tx_laddr[entry] = laddr;
        lp->tx_skb[entry] = skb;
 
-       length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
-       flush_cache_all();
+       wmb();
+       sonic_tda_put(dev, lp->eol_tx, SONIC_TD_LINK,
+                                 sonic_tda_get(dev, lp->eol_tx, SONIC_TD_LINK) & ~SONIC_EOL);
+       lp->eol_tx = entry;
 
-       /*
-        * Setup the transmit descriptor and issue the transmit command.
-        */
-       lp->tda[entry].tx_status = 0;   /* clear status */
-       lp->tda[entry].tx_frag_count = 1;       /* single fragment */
-       lp->tda[entry].tx_pktsize = length;     /* length of packet */
-       lp->tda[entry].tx_frag_ptr_l = laddr & 0xffff;
-       lp->tda[entry].tx_frag_ptr_h = laddr >> 16;
-       lp->tda[entry].tx_frag_size = length;
-       lp->cur_tx++;
-       lp->stats.tx_bytes += length;
+       lp->next_tx = (entry + 1) & SONIC_TDS_MASK;
+       if (lp->tx_skb[lp->next_tx] != NULL) {
+               /* The ring is full, the ISR has yet to process the next TD. */
+               if (sonic_debug > 3)
+                       printk("%s: stopping queue\n", dev->name);
+               netif_stop_queue(dev);
+               /* after this packet, wait for ISR to free up some TDAs */
+       } else netif_start_queue(dev);
 
        if (sonic_debug > 2)
-               printk("sonic_send_packet: issueing Tx command\n");
+               printk("sonic_send_packet: issuing Tx command\n");
 
        SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP);
 
        dev->trans_start = jiffies;
 
-       if (lp->cur_tx < lp->dirty_tx + SONIC_NUM_TDS)
-               netif_start_queue(dev);
-       else
-               lp->tx_full = 1;
-
        return 0;
 }
 
@@ -164,175 +297,199 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
 static irqreturn_t sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct net_device *dev = (struct net_device *) dev_id;
-       unsigned int base_addr = dev->base_addr;
-       struct sonic_local *lp;
+       struct sonic_local *lp = netdev_priv(dev);
        int status;
 
        if (dev == NULL) {
-               printk("sonic_interrupt: irq %d for unknown device.\n", irq);
+               printk(KERN_ERR "sonic_interrupt: irq %d for unknown device.\n", irq);
                return IRQ_NONE;
        }
 
-       lp = (struct sonic_local *) dev->priv;
-
-       status = SONIC_READ(SONIC_ISR);
-       SONIC_WRITE(SONIC_ISR, 0x7fff); /* clear all bits */
-
-       if (sonic_debug > 2)
-               printk("sonic_interrupt: ISR=%x\n", status);
-
-       if (status & SONIC_INT_PKTRX) {
-               sonic_rx(dev);  /* got packet(s) */
-       }
-
-       if (status & SONIC_INT_TXDN) {
-               int dirty_tx = lp->dirty_tx;
-
-               while (dirty_tx < lp->cur_tx) {
-                       int entry = dirty_tx & SONIC_TDS_MASK;
-                       int status = lp->tda[entry].tx_status;
+       if (!(status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT))
+               return IRQ_NONE;
 
-                       if (sonic_debug > 3)
-                               printk
-                                   ("sonic_interrupt: status %d, cur_tx %d, dirty_tx %d\n",
-                                    status, lp->cur_tx, lp->dirty_tx);
+       do {
+               if (status & SONIC_INT_PKTRX) {
+                       if (sonic_debug > 2)
+                               printk("%s: packet rx\n", dev->name);
+                       sonic_rx(dev);  /* got packet(s) */
+                       SONIC_WRITE(SONIC_ISR, SONIC_INT_PKTRX); /* clear the interrupt */
+               }
 
-                       if (status == 0) {
-                               /* It still hasn't been Txed, kick the sonic again */
-                               SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP);
-                               break;
-                       }
+               if (status & SONIC_INT_TXDN) {
+                       int entry = lp->cur_tx;
+                       int td_status;
+                       int freed_some = 0;
 
-                       /* put back EOL and free descriptor */
-                       lp->tda[entry].tx_frag_count = 0;
-                       lp->tda[entry].tx_status = 0;
-
-                       if (status & 0x0001)
-                               lp->stats.tx_packets++;
-                       else {
-                               lp->stats.tx_errors++;
-                               if (status & 0x0642)
-                                       lp->stats.tx_aborted_errors++;
-                               if (status & 0x0180)
-                                       lp->stats.tx_carrier_errors++;
-                               if (status & 0x0020)
-                                       lp->stats.tx_window_errors++;
-                               if (status & 0x0004)
-                                       lp->stats.tx_fifo_errors++;
-                       }
+                       /* At this point, cur_tx is the index of a TD that is one of:
+                        *   unallocated/freed                          (status set   & tx_skb[entry] clear)
+                        *   allocated and sent                         (status set   & tx_skb[entry] set  )
+                        *   allocated and not yet sent                 (status clear & tx_skb[entry] set  )
+                        *   still being allocated by sonic_send_packet (status clear & tx_skb[entry] clear)
+                        */
 
-                       /* We must free the original skb */
-                       if (lp->tx_skb[entry]) {
+                       if (sonic_debug > 2)
+                               printk("%s: tx done\n", dev->name);
+
+                       while (lp->tx_skb[entry] != NULL) {
+                               if ((td_status = sonic_tda_get(dev, entry, SONIC_TD_STATUS)) == 0)
+                                       break;
+
+                               if (td_status & 0x0001) {
+                                       lp->stats.tx_packets++;
+                                       lp->stats.tx_bytes += sonic_tda_get(dev, entry, SONIC_TD_PKTSIZE);
+                               } else {
+                                       lp->stats.tx_errors++;
+                                       if (td_status & 0x0642)
+                                               lp->stats.tx_aborted_errors++;
+                                       if (td_status & 0x0180)
+                                               lp->stats.tx_carrier_errors++;
+                                       if (td_status & 0x0020)
+                                               lp->stats.tx_window_errors++;
+                                       if (td_status & 0x0004)
+                                               lp->stats.tx_fifo_errors++;
+                               }
+
+                               /* We must free the original skb */
                                dev_kfree_skb_irq(lp->tx_skb[entry]);
-                               lp->tx_skb[entry] = 0;
+                               lp->tx_skb[entry] = NULL;
+                               /* and unmap DMA buffer */
+                               dma_unmap_single(lp->device, lp->tx_laddr[entry], lp->tx_len[entry], DMA_TO_DEVICE);
+                               lp->tx_laddr[entry] = (dma_addr_t)0;
+                               freed_some = 1;
+
+                               if (sonic_tda_get(dev, entry, SONIC_TD_LINK) & SONIC_EOL) {
+                                       entry = (entry + 1) & SONIC_TDS_MASK;
+                                       break;
+                               }
+                               entry = (entry + 1) & SONIC_TDS_MASK;
                        }
-                       /* and the VDMA address */
-                       vdma_free(lp->tx_laddr[entry]);
-                       dirty_tx++;
-               }
 
-               if (lp->tx_full
-                   && dirty_tx + SONIC_NUM_TDS > lp->cur_tx + 2) {
-                       /* The ring is no longer full, clear tbusy. */
-                       lp->tx_full = 0;
-                       netif_wake_queue(dev);
+                       if (freed_some || lp->tx_skb[entry] == NULL)
+                               netif_wake_queue(dev);  /* The ring is no longer full */
+                       lp->cur_tx = entry;
+                       SONIC_WRITE(SONIC_ISR, SONIC_INT_TXDN); /* clear the interrupt */
                }
 
-               lp->dirty_tx = dirty_tx;
-       }
+               /*
+                * check error conditions
+                */
+               if (status & SONIC_INT_RFO) {
+                       if (sonic_debug > 1)
+                               printk("%s: rx fifo overrun\n", dev->name);
+                       lp->stats.rx_fifo_errors++;
+                       SONIC_WRITE(SONIC_ISR, SONIC_INT_RFO); /* clear the interrupt */
+               }
+               if (status & SONIC_INT_RDE) {
+                       if (sonic_debug > 1)
+                               printk("%s: rx descriptors exhausted\n", dev->name);
+                       lp->stats.rx_dropped++;
+                       SONIC_WRITE(SONIC_ISR, SONIC_INT_RDE); /* clear the interrupt */
+               }
+               if (status & SONIC_INT_RBAE) {
+                       if (sonic_debug > 1)
+                               printk("%s: rx buffer area exceeded\n", dev->name);
+                       lp->stats.rx_dropped++;
+                       SONIC_WRITE(SONIC_ISR, SONIC_INT_RBAE); /* clear the interrupt */
+               }
 
-       /*
-        * check error conditions
-        */
-       if (status & SONIC_INT_RFO) {
-               printk("%s: receive fifo underrun\n", dev->name);
-               lp->stats.rx_fifo_errors++;
-       }
-       if (status & SONIC_INT_RDE) {
-               printk("%s: receive descriptors exhausted\n", dev->name);
-               lp->stats.rx_dropped++;
-       }
-       if (status & SONIC_INT_RBE) {
-               printk("%s: receive buffer exhausted\n", dev->name);
-               lp->stats.rx_dropped++;
-       }
-       if (status & SONIC_INT_RBAE) {
-               printk("%s: receive buffer area exhausted\n", dev->name);
-               lp->stats.rx_dropped++;
-       }
+               /* counter overruns; all counters are 16bit wide */
+               if (status & SONIC_INT_FAE) {
+                       lp->stats.rx_frame_errors += 65536;
+                       SONIC_WRITE(SONIC_ISR, SONIC_INT_FAE); /* clear the interrupt */
+               }
+               if (status & SONIC_INT_CRC) {
+                       lp->stats.rx_crc_errors += 65536;
+                       SONIC_WRITE(SONIC_ISR, SONIC_INT_CRC); /* clear the interrupt */
+               }
+               if (status & SONIC_INT_MP) {
+                       lp->stats.rx_missed_errors += 65536;
+                       SONIC_WRITE(SONIC_ISR, SONIC_INT_MP); /* clear the interrupt */
+               }
 
-       /* counter overruns; all counters are 16bit wide */
-       if (status & SONIC_INT_FAE)
-               lp->stats.rx_frame_errors += 65536;
-       if (status & SONIC_INT_CRC)
-               lp->stats.rx_crc_errors += 65536;
-       if (status & SONIC_INT_MP)
-               lp->stats.rx_missed_errors += 65536;
+               /* transmit error */
+               if (status & SONIC_INT_TXER) {
+                       if ((SONIC_READ(SONIC_TCR) & SONIC_TCR_FU) && (sonic_debug > 2))
+                               printk(KERN_ERR "%s: tx fifo underrun\n", dev->name);
+                       SONIC_WRITE(SONIC_ISR, SONIC_INT_TXER); /* clear the interrupt */
+               }
 
-       /* transmit error */
-       if (status & SONIC_INT_TXER)
-               lp->stats.tx_errors++;
+               /* bus retry */
+               if (status & SONIC_INT_BR) {
+                       printk(KERN_ERR "%s: Bus retry occurred! Device interrupt disabled.\n",
+                               dev->name);
+                       /* ... to help debug DMA problems causing endless interrupts. */
+                       /* Bounce the eth interface to turn on the interrupt again. */
+                       SONIC_WRITE(SONIC_IMR, 0);
+                       SONIC_WRITE(SONIC_ISR, SONIC_INT_BR); /* clear the interrupt */
+               }
 
-       /*
-        * clear interrupt bits and return
-        */
-       SONIC_WRITE(SONIC_ISR, status);
+               /* load CAM done */
+               if (status & SONIC_INT_LCD)
+                       SONIC_WRITE(SONIC_ISR, SONIC_INT_LCD); /* clear the interrupt */
+       } while((status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT));
        return IRQ_HANDLED;
 }
 
 /*
- * We have a good packet(s), get it/them out of the buffers.
+ * We have a good packet(s), pass it/them up the network stack.
  */
 static void sonic_rx(struct net_device *dev)
 {
-       unsigned int base_addr = dev->base_addr;
-       struct sonic_local *lp = (struct sonic_local *) dev->priv;
-       sonic_rd_t *rd = &lp->rda[lp->cur_rx & SONIC_RDS_MASK];
+       struct sonic_local *lp = netdev_priv(dev);
        int status;
-
-       while (rd->in_use == 0) {
-               struct sk_buff *skb;
+       int entry = lp->cur_rx;
+
+       while (sonic_rda_get(dev, entry, SONIC_RD_IN_USE) == 0) {
+               struct sk_buff *used_skb;
+               struct sk_buff *new_skb;
+               dma_addr_t new_laddr;
+               u16 bufadr_l;
+               u16 bufadr_h;
                int pkt_len;
-               unsigned char *pkt_ptr;
 
-               status = rd->rx_status;
-               if (sonic_debug > 3)
-                       printk("status %x, cur_rx %d, cur_rra %x\n",
-                              status, lp->cur_rx, lp->cur_rra);
+               status = sonic_rda_get(dev, entry, SONIC_RD_STATUS);
                if (status & SONIC_RCR_PRX) {
-                       pkt_len = rd->rx_pktlen;
-                       pkt_ptr =
-                           (char *)
-                           sonic_chiptomem((rd->rx_pktptr_h << 16) +
-                                           rd->rx_pktptr_l);
-
-                       if (sonic_debug > 3)
-                               printk
-                                   ("pktptr %p (rba %p) h:%x l:%x, bsize h:%x l:%x\n",
-                                    pkt_ptr, lp->rba, rd->rx_pktptr_h,
-                                    rd->rx_pktptr_l,
-                                    SONIC_READ(SONIC_RBWC1),
-                                    SONIC_READ(SONIC_RBWC0));
-
                        /* Malloc up new buffer. */
-                       skb = dev_alloc_skb(pkt_len + 2);
-                       if (skb == NULL) {
-                               printk
-                                   ("%s: Memory squeeze, dropping packet.\n",
-                                    dev->name);
+                       new_skb = dev_alloc_skb(SONIC_RBSIZE + 2);
+                       if (new_skb == NULL) {
+                               printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n", dev->name);
+                               lp->stats.rx_dropped++;
+                               break;
+                       }
+                       new_skb->dev = dev;
+                       /* provide 16 byte IP header alignment unless DMA requires otherwise */
+                       if(SONIC_BUS_SCALE(lp->dma_bitmode) == 2)
+                               skb_reserve(new_skb, 2); 
+
+                       new_laddr = dma_map_single(lp->device, skb_put(new_skb, SONIC_RBSIZE),
+                                              SONIC_RBSIZE, DMA_FROM_DEVICE);
+                       if (!new_laddr) {
+                               dev_kfree_skb(new_skb);
+                               printk(KERN_ERR "%s: Failed to map rx buffer, dropping packet.\n", dev->name);
                                lp->stats.rx_dropped++;
                                break;
                        }
-                       skb->dev = dev;
-                       skb_reserve(skb, 2);    /* 16 byte align */
-                       skb_put(skb, pkt_len);  /* Make room */
-                       eth_copy_and_sum(skb, pkt_ptr, pkt_len, 0);
-                       skb->protocol = eth_type_trans(skb, dev);
-                       netif_rx(skb);  /* pass the packet to upper layers */
+
+                       /* now we have a new skb to replace it, pass the used one up the stack */
+                       dma_unmap_single(lp->device, lp->rx_laddr[entry], SONIC_RBSIZE, DMA_FROM_DEVICE);
+                       used_skb = lp->rx_skb[entry];
+                       pkt_len = sonic_rda_get(dev, entry, SONIC_RD_PKTLEN);
+                       skb_trim(used_skb, pkt_len);
+                       used_skb->protocol = eth_type_trans(used_skb, dev);
+                       netif_rx(used_skb);
                        dev->last_rx = jiffies;
                        lp->stats.rx_packets++;
                        lp->stats.rx_bytes += pkt_len;
 
+                       /* and insert the new skb */
+                       lp->rx_laddr[entry] = new_laddr;
+                       lp->rx_skb[entry] = new_skb;
+
+                       bufadr_l = (unsigned long)new_laddr & 0xffff;
+                       bufadr_h = (unsigned long)new_laddr >> 16;
+                       sonic_rra_put(dev, entry, SONIC_RR_BUFADR_L, bufadr_l);
+                       sonic_rra_put(dev, entry, SONIC_RR_BUFADR_H, bufadr_h);
                } else {
                        /* This should only happen, if we enable accepting broken packets. */
                        lp->stats.rx_errors++;
@@ -341,29 +498,35 @@ static void sonic_rx(struct net_device *dev)
                        if (status & SONIC_RCR_CRCR)
                                lp->stats.rx_crc_errors++;
                }
-
-               rd->in_use = 1;
-               rd = &lp->rda[(++lp->cur_rx) & SONIC_RDS_MASK];
-               /* now give back the buffer to the receive buffer area */
                if (status & SONIC_RCR_LPKT) {
                        /*
-                        * this was the last packet out of the current receice buffer
+                        * this was the last packet out of the current receive buffer
                         * give the buffer back to the SONIC
                         */
-                       lp->cur_rra += sizeof(sonic_rr_t);
-                       if (lp->cur_rra >
-                           (lp->rra_laddr +
-                            (SONIC_NUM_RRS -
-                             1) * sizeof(sonic_rr_t))) lp->cur_rra =
-                                   lp->rra_laddr;
-                       SONIC_WRITE(SONIC_RWP, lp->cur_rra & 0xffff);
+                       lp->cur_rwp += SIZEOF_SONIC_RR * SONIC_BUS_SCALE(lp->dma_bitmode);
+                       if (lp->cur_rwp >= lp->rra_end) lp->cur_rwp = lp->rra_laddr & 0xffff;
+                       SONIC_WRITE(SONIC_RWP, lp->cur_rwp);
+                       if (SONIC_READ(SONIC_ISR) & SONIC_INT_RBE) {
+                               if (sonic_debug > 2)
+                                       printk("%s: rx buffer exhausted\n", dev->name);
+                               SONIC_WRITE(SONIC_ISR, SONIC_INT_RBE); /* clear the flag */
+                       }
                } else
-                       printk
-                           ("%s: rx desc without RCR_LPKT. Shouldn't happen !?\n",
+                       printk(KERN_ERR "%s: rx desc without RCR_LPKT. Shouldn't happen !?\n",
                             dev->name);
+               /*
+                * give back the descriptor
+                */
+               sonic_rda_put(dev, entry, SONIC_RD_LINK,
+                       sonic_rda_get(dev, entry, SONIC_RD_LINK) | SONIC_EOL);
+               sonic_rda_put(dev, entry, SONIC_RD_IN_USE, 1);
+               sonic_rda_put(dev, lp->eol_rx, SONIC_RD_LINK,
+                       sonic_rda_get(dev, lp->eol_rx, SONIC_RD_LINK) & ~SONIC_EOL);
+               lp->eol_rx = entry;
+               lp->cur_rx = entry = (entry + 1) & SONIC_RDS_MASK;
        }
        /*
-        * If any worth-while packets have been received, dev_rint()
+        * If any worth-while packets have been received, netif_rx()
         * has done a mark_bh(NET_BH) for us and will work on them
         * when we get to the bottom-half routine.
         */
@@ -376,8 +539,7 @@ static void sonic_rx(struct net_device *dev)
  */
 static struct net_device_stats *sonic_get_stats(struct net_device *dev)
 {
-       struct sonic_local *lp = (struct sonic_local *) dev->priv;
-       unsigned int base_addr = dev->base_addr;
+       struct sonic_local *lp = netdev_priv(dev);
 
        /* read the tally counter from the SONIC and reset them */
        lp->stats.rx_crc_errors += SONIC_READ(SONIC_CRCT);
@@ -396,8 +558,7 @@ static struct net_device_stats *sonic_get_stats(struct net_device *dev)
  */
 static void sonic_multicast_list(struct net_device *dev)
 {
-       struct sonic_local *lp = (struct sonic_local *) dev->priv;
-       unsigned int base_addr = dev->base_addr;
+       struct sonic_local *lp = netdev_priv(dev);
        unsigned int rcr;
        struct dev_mc_list *dmi = dev->mc_list;
        unsigned char *addr;
@@ -413,20 +574,15 @@ static void sonic_multicast_list(struct net_device *dev)
                        rcr |= SONIC_RCR_AMC;
                } else {
                        if (sonic_debug > 2)
-                               printk
-                                   ("sonic_multicast_list: mc_count %d\n",
-                                    dev->mc_count);
-                       lp->cda.cam_enable = 1; /* always enable our own address */
+                               printk("sonic_multicast_list: mc_count %d\n", dev->mc_count);
+                       sonic_set_cam_enable(dev, 1);  /* always enable our own address */
                        for (i = 1; i <= dev->mc_count; i++) {
                                addr = dmi->dmi_addr;
                                dmi = dmi->next;
-                               lp->cda.cam_desc[i].cam_cap0 =
-                                   addr[1] << 8 | addr[0];
-                               lp->cda.cam_desc[i].cam_cap1 =
-                                   addr[3] << 8 | addr[2];
-                               lp->cda.cam_desc[i].cam_cap2 =
-                                   addr[5] << 8 | addr[4];
-                               lp->cda.cam_enable |= (1 << i);
+                               sonic_cda_put(dev, i, SONIC_CD_CAP0, addr[1] << 8 | addr[0]);
+                               sonic_cda_put(dev, i, SONIC_CD_CAP1, addr[3] << 8 | addr[2]);
+                               sonic_cda_put(dev, i, SONIC_CD_CAP2, addr[5] << 8 | addr[4]);
+                               sonic_set_cam_enable(dev, sonic_get_cam_enable(dev) | (1 << i));
                        }
                        SONIC_WRITE(SONIC_CDC, 16);
                        /* issue Load CAM command */
@@ -447,19 +603,16 @@ static void sonic_multicast_list(struct net_device *dev)
  */
 static int sonic_init(struct net_device *dev)
 {
-       unsigned int base_addr = dev->base_addr;
        unsigned int cmd;
-       struct sonic_local *lp = (struct sonic_local *) dev->priv;
-       unsigned int rra_start;
-       unsigned int rra_end;
+       struct sonic_local *lp = netdev_priv(dev);
        int i;
 
        /*
         * put the Sonic into software-reset mode and
         * disable all interrupts
         */
-       SONIC_WRITE(SONIC_ISR, 0x7fff);
        SONIC_WRITE(SONIC_IMR, 0);
+       SONIC_WRITE(SONIC_ISR, 0x7fff);
        SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
 
        /*
@@ -475,34 +628,32 @@ static int sonic_init(struct net_device *dev)
        if (sonic_debug > 2)
                printk("sonic_init: initialize receive resource area\n");
 
-       rra_start = lp->rra_laddr & 0xffff;
-       rra_end =
-           (rra_start + (SONIC_NUM_RRS * sizeof(sonic_rr_t))) & 0xffff;
-
        for (i = 0; i < SONIC_NUM_RRS; i++) {
-               lp->rra[i].rx_bufadr_l =
-                   (lp->rba_laddr + i * SONIC_RBSIZE) & 0xffff;
-               lp->rra[i].rx_bufadr_h =
-                   (lp->rba_laddr + i * SONIC_RBSIZE) >> 16;
-               lp->rra[i].rx_bufsize_l = SONIC_RBSIZE >> 1;
-               lp->rra[i].rx_bufsize_h = 0;
+               u16 bufadr_l = (unsigned long)lp->rx_laddr[i] & 0xffff;
+               u16 bufadr_h = (unsigned long)lp->rx_laddr[i] >> 16;
+               sonic_rra_put(dev, i, SONIC_RR_BUFADR_L, bufadr_l);
+               sonic_rra_put(dev, i, SONIC_RR_BUFADR_H, bufadr_h);
+               sonic_rra_put(dev, i, SONIC_RR_BUFSIZE_L, SONIC_RBSIZE >> 1);
+               sonic_rra_put(dev, i, SONIC_RR_BUFSIZE_H, 0);
        }
 
        /* initialize all RRA registers */
-       SONIC_WRITE(SONIC_RSA, rra_start);
-       SONIC_WRITE(SONIC_REA, rra_end);
-       SONIC_WRITE(SONIC_RRP, rra_start);
-       SONIC_WRITE(SONIC_RWP, rra_end);
+       lp->rra_end = (lp->rra_laddr + SONIC_NUM_RRS * SIZEOF_SONIC_RR *
+                                       SONIC_BUS_SCALE(lp->dma_bitmode)) & 0xffff;
+       lp->cur_rwp = (lp->rra_laddr + (SONIC_NUM_RRS - 1) * SIZEOF_SONIC_RR *
+                                       SONIC_BUS_SCALE(lp->dma_bitmode)) & 0xffff;
+  
+       SONIC_WRITE(SONIC_RSA, lp->rra_laddr & 0xffff);
+       SONIC_WRITE(SONIC_REA, lp->rra_end);
+       SONIC_WRITE(SONIC_RRP, lp->rra_laddr & 0xffff);
+       SONIC_WRITE(SONIC_RWP, lp->cur_rwp);
        SONIC_WRITE(SONIC_URRA, lp->rra_laddr >> 16);
-       SONIC_WRITE(SONIC_EOBC, (SONIC_RBSIZE - 2) >> 1);
-
-       lp->cur_rra =
-           lp->rra_laddr + (SONIC_NUM_RRS - 1) * sizeof(sonic_rr_t);
+       SONIC_WRITE(SONIC_EOBC, (SONIC_RBSIZE >> 1) - (lp->dma_bitmode ? 2 : 1));
 
        /* load the resource pointers */
        if (sonic_debug > 3)
-               printk("sonic_init: issueing RRRA command\n");
-
+               printk("sonic_init: issuing RRRA command\n");
+  
        SONIC_WRITE(SONIC_CMD, SONIC_CR_RRRA);
        i = 0;
        while (i++ < 100) {
@@ -511,27 +662,30 @@ static int sonic_init(struct net_device *dev)
        }
 
        if (sonic_debug > 2)
-               printk("sonic_init: status=%x\n", SONIC_READ(SONIC_CMD));
-
+               printk("sonic_init: status=%x i=%d\n", SONIC_READ(SONIC_CMD), i);
+    
        /*
         * Initialize the receive descriptors so that they
         * become a circular linked list, ie. let the last
         * descriptor point to the first again.
         */
        if (sonic_debug > 2)
-               printk("sonic_init: initialize receive descriptors\n");
-       for (i = 0; i < SONIC_NUM_RDS; i++) {
-               lp->rda[i].rx_status = 0;
-               lp->rda[i].rx_pktlen = 0;
-               lp->rda[i].rx_pktptr_l = 0;
-               lp->rda[i].rx_pktptr_h = 0;
-               lp->rda[i].rx_seqno = 0;
-               lp->rda[i].in_use = 1;
-               lp->rda[i].link =
-                   lp->rda_laddr + (i + 1) * sizeof(sonic_rd_t);
+               printk("sonic_init: initialize receive descriptors\n");      
+       for (i=0; i<SONIC_NUM_RDS; i++) {
+               sonic_rda_put(dev, i, SONIC_RD_STATUS, 0);
+               sonic_rda_put(dev, i, SONIC_RD_PKTLEN, 0);
+               sonic_rda_put(dev, i, SONIC_RD_PKTPTR_L, 0);
+               sonic_rda_put(dev, i, SONIC_RD_PKTPTR_H, 0);
+               sonic_rda_put(dev, i, SONIC_RD_SEQNO, 0);
+               sonic_rda_put(dev, i, SONIC_RD_IN_USE, 1);
+               sonic_rda_put(dev, i, SONIC_RD_LINK,
+                       lp->rda_laddr +
+                       ((i+1) * SIZEOF_SONIC_RD * SONIC_BUS_SCALE(lp->dma_bitmode)));
        }
        /* fix last descriptor */
-       lp->rda[SONIC_NUM_RDS - 1].link = lp->rda_laddr;
+       sonic_rda_put(dev, SONIC_NUM_RDS - 1, SONIC_RD_LINK,
+               (lp->rda_laddr & 0xffff) | SONIC_EOL);
+       lp->eol_rx = SONIC_NUM_RDS - 1;
        lp->cur_rx = 0;
        SONIC_WRITE(SONIC_URDA, lp->rda_laddr >> 16);
        SONIC_WRITE(SONIC_CRDA, lp->rda_laddr & 0xffff);
@@ -542,34 +696,34 @@ static int sonic_init(struct net_device *dev)
        if (sonic_debug > 2)
                printk("sonic_init: initialize transmit descriptors\n");
        for (i = 0; i < SONIC_NUM_TDS; i++) {
-               lp->tda[i].tx_status = 0;
-               lp->tda[i].tx_config = 0;
-               lp->tda[i].tx_pktsize = 0;
-               lp->tda[i].tx_frag_count = 0;
-               lp->tda[i].link =
-                   (lp->tda_laddr +
-                    (i + 1) * sizeof(sonic_td_t)) | SONIC_END_OF_LINKS;
+               sonic_tda_put(dev, i, SONIC_TD_STATUS, 0);
+               sonic_tda_put(dev, i, SONIC_TD_CONFIG, 0);
+               sonic_tda_put(dev, i, SONIC_TD_PKTSIZE, 0);
+               sonic_tda_put(dev, i, SONIC_TD_FRAG_COUNT, 0);
+               sonic_tda_put(dev, i, SONIC_TD_LINK,
+                       (lp->tda_laddr & 0xffff) +
+                       (i + 1) * SIZEOF_SONIC_TD * SONIC_BUS_SCALE(lp->dma_bitmode));
+               lp->tx_skb[i] = NULL;
        }
-       lp->tda[SONIC_NUM_TDS - 1].link =
-           (lp->tda_laddr & 0xffff) | SONIC_END_OF_LINKS;
+       /* fix last descriptor */
+       sonic_tda_put(dev, SONIC_NUM_TDS - 1, SONIC_TD_LINK,
+               (lp->tda_laddr & 0xffff));
 
        SONIC_WRITE(SONIC_UTDA, lp->tda_laddr >> 16);
        SONIC_WRITE(SONIC_CTDA, lp->tda_laddr & 0xffff);
-       lp->cur_tx = lp->dirty_tx = 0;
-
+       lp->cur_tx = lp->next_tx = 0;
+       lp->eol_tx = SONIC_NUM_TDS - 1;
+    
        /*
         * put our own address to CAM desc[0]
         */
-       lp->cda.cam_desc[0].cam_cap0 =
-           dev->dev_addr[1] << 8 | dev->dev_addr[0];
-       lp->cda.cam_desc[0].cam_cap1 =
-           dev->dev_addr[3] << 8 | dev->dev_addr[2];
-       lp->cda.cam_desc[0].cam_cap2 =
-           dev->dev_addr[5] << 8 | dev->dev_addr[4];
-       lp->cda.cam_enable = 1;
+       sonic_cda_put(dev, 0, SONIC_CD_CAP0, dev->dev_addr[1] << 8 | dev->dev_addr[0]);
+       sonic_cda_put(dev, 0, SONIC_CD_CAP1, dev->dev_addr[3] << 8 | dev->dev_addr[2]);
+       sonic_cda_put(dev, 0, SONIC_CD_CAP2, dev->dev_addr[5] << 8 | dev->dev_addr[4]);
+       sonic_set_cam_enable(dev, 1);
 
        for (i = 0; i < 16; i++)
-               lp->cda.cam_desc[i].cam_entry_pointer = i;
+               sonic_cda_put(dev, i, SONIC_CD_ENTRY_POINTER, i);
 
        /*
         * initialize CAM registers
@@ -588,8 +742,8 @@ static int sonic_init(struct net_device *dev)
                        break;
        }
        if (sonic_debug > 2) {
-               printk("sonic_init: CMD=%x, ISR=%x\n",
-                      SONIC_READ(SONIC_CMD), SONIC_READ(SONIC_ISR));
+               printk("sonic_init: CMD=%x, ISR=%x\n, i=%d",
+                      SONIC_READ(SONIC_CMD), SONIC_READ(SONIC_ISR), i);
        }
 
        /*
@@ -604,7 +758,7 @@ static int sonic_init(struct net_device *dev)
 
        cmd = SONIC_READ(SONIC_CMD);
        if ((cmd & SONIC_CR_RXEN) == 0 || (cmd & SONIC_CR_STP) == 0)
-               printk("sonic_init: failed, status=%x\n", cmd);
+               printk(KERN_ERR "sonic_init: failed, status=%x\n", cmd);
 
        if (sonic_debug > 2)
                printk("sonic_init: new status=%x\n",
index c4a6d58..cede969 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Helpfile for sonic.c
+ * Header file for sonic.c
  *
  * (C) Waldorf Electronics, Germany
  * Written by Andreas Busse
@@ -9,10 +9,16 @@
  * and pad structure members must be exchanged. Also, the structures
  * need to be changed accordingly to the bus size. 
  *
- * 981229 MSch:        did just that for the 68k Mac port (32 bit, big endian),
- *             see CONFIG_MACSONIC branch below.
+ * 981229 MSch:        did just that for the 68k Mac port (32 bit, big endian)
  *
+ * 990611 David Huggins-Daines <dhd@debian.org>: This machine abstraction
+ * does not cope with 16-bit bus sizes very well.  Therefore I have
+ * rewritten it with ugly macros and evil inlines.
+ *
+ * 050625 Finn Thain: introduced more 32-bit cards and dhd's support
+ *        for 16-bit cards (from the mac68k project).
  */
+
 #ifndef SONIC_H
 #define SONIC_H
 
@@ -83,6 +89,7 @@
 /*
  * Error counters
  */
+
 #define SONIC_CRCT              0x2c
 #define SONIC_FAET              0x2d
 #define SONIC_MPT               0x2e
 
 #define SONIC_INT_BR           0x4000
 #define SONIC_INT_HBL          0x2000
-#define SONIC_INT_LCD           0x1000
-#define SONIC_INT_PINT          0x0800
-#define SONIC_INT_PKTRX         0x0400
-#define SONIC_INT_TXDN          0x0200
-#define SONIC_INT_TXER          0x0100
-#define SONIC_INT_TC            0x0080
-#define SONIC_INT_RDE           0x0040
-#define SONIC_INT_RBE           0x0020
+#define SONIC_INT_LCD          0x1000
+#define SONIC_INT_PINT         0x0800
+#define SONIC_INT_PKTRX                0x0400
+#define SONIC_INT_TXDN         0x0200
+#define SONIC_INT_TXER         0x0100
+#define SONIC_INT_TC           0x0080
+#define SONIC_INT_RDE          0x0040
+#define SONIC_INT_RBE          0x0020
 #define SONIC_INT_RBAE         0x0010
 #define SONIC_INT_CRC          0x0008
 #define SONIC_INT_FAE          0x0004
  * The interrupts we allow.
  */
 
-#define SONIC_IMR_DEFAULT      (SONIC_INT_BR | \
-                               SONIC_INT_LCD | \
-                                SONIC_INT_PINT | \
+#define SONIC_IMR_DEFAULT     SONIC_INT_BR | \
+                                SONIC_INT_LCD | \
+                                SONIC_INT_RFO | \
                                 SONIC_INT_PKTRX | \
                                 SONIC_INT_TXDN | \
                                 SONIC_INT_TXER | \
                                 SONIC_INT_RDE | \
-                                SONIC_INT_RBE | \
                                 SONIC_INT_RBAE | \
                                 SONIC_INT_CRC | \
                                 SONIC_INT_FAE | \
                                 SONIC_INT_MP)
 
 
-#define        SONIC_END_OF_LINKS      0x0001
-
-
-#ifdef CONFIG_MACSONIC
-/*
- * Big endian like structures on 680x0 Macs
- */
-
-typedef struct {
-       u32 rx_bufadr_l;        /* receive buffer ptr */
-       u32 rx_bufadr_h;
-
-       u32 rx_bufsize_l;       /* no. of words in the receive buffer */
-       u32 rx_bufsize_h;
-} sonic_rr_t;
-
-/*
- * Sonic receive descriptor. Receive descriptors are
- * kept in a linked list of these structures.
- */
-
-typedef struct {
-       SREGS_PAD(pad0);
-       u16 rx_status;          /* status after reception of a packet */
-        SREGS_PAD(pad1);
-       u16 rx_pktlen;          /* length of the packet incl. CRC */
-
-       /*
-        * Pointers to the location in the receive buffer area (RBA)
-        * where the packet resides. A packet is always received into
-        * a contiguous piece of memory.
-        */
-        SREGS_PAD(pad2);
-       u16 rx_pktptr_l;
-        SREGS_PAD(pad3);
-       u16 rx_pktptr_h;
-
-        SREGS_PAD(pad4);
-       u16 rx_seqno;           /* sequence no. */
-
-        SREGS_PAD(pad5);
-       u16 link;               /* link to next RDD (end if EOL bit set) */
-
-       /*
-        * Owner of this descriptor, 0= driver, 1=sonic
-        */
-
-        SREGS_PAD(pad6);
-       u16 in_use;
-
-       caddr_t rda_next;       /* pointer to next RD */
-} sonic_rd_t;
-
-
-/*
- * Describes a Transmit Descriptor
- */
-typedef struct {
-       SREGS_PAD(pad0);
-       u16 tx_status;          /* status after transmission of a packet */
-        SREGS_PAD(pad1);
-       u16 tx_config;          /* transmit configuration for this packet */
-        SREGS_PAD(pad2);
-       u16 tx_pktsize;         /* size of the packet to be transmitted */
-        SREGS_PAD(pad3);
-       u16 tx_frag_count;      /* no. of fragments */
-
-        SREGS_PAD(pad4);
-       u16 tx_frag_ptr_l;
-        SREGS_PAD(pad5);
-       u16 tx_frag_ptr_h;
-        SREGS_PAD(pad6);
-       u16 tx_frag_size;
-
-        SREGS_PAD(pad7);
-       u16 link;               /* ptr to next descriptor */
-} sonic_td_t;
-
-
-/*
- * Describes an entry in the CAM Descriptor Area.
- */
-
-typedef struct {
-       SREGS_PAD(pad0);
-       u16 cam_entry_pointer;
-        SREGS_PAD(pad1);
-       u16 cam_cap0;
-        SREGS_PAD(pad2);
-       u16 cam_cap1;
-        SREGS_PAD(pad3);
-       u16 cam_cap2;
-} sonic_cd_t;
-
+#define SONIC_EOL       0x0001
 #define CAM_DESCRIPTORS 16
 
-
-typedef struct {
-       sonic_cd_t cam_desc[CAM_DESCRIPTORS];
-        SREGS_PAD(pad);
-       u16 cam_enable;
-} sonic_cda_t;
-
-#else                          /* original declarations, little endian 32 bit */
-
-/*
- * structure definitions
- */
-
-typedef struct {
-       u32 rx_bufadr_l;        /* receive buffer ptr */
-       u32 rx_bufadr_h;
-
-       u32 rx_bufsize_l;       /* no. of words in the receive buffer */
-       u32 rx_bufsize_h;
-} sonic_rr_t;
-
-/*
- * Sonic receive descriptor. Receive descriptors are
- * kept in a linked list of these structures.
- */
-
-typedef struct {
-       u16 rx_status;          /* status after reception of a packet */
-        SREGS_PAD(pad0);
-       u16 rx_pktlen;          /* length of the packet incl. CRC */
-        SREGS_PAD(pad1);
-
-       /*
-        * Pointers to the location in the receive buffer area (RBA)
-        * where the packet resides. A packet is always received into
-        * a contiguous piece of memory.
-        */
-       u16 rx_pktptr_l;
-        SREGS_PAD(pad2);
-       u16 rx_pktptr_h;
-        SREGS_PAD(pad3);
-
-       u16 rx_seqno;           /* sequence no. */
-        SREGS_PAD(pad4);
-
-       u16 link;               /* link to next RDD (end if EOL bit set) */
-        SREGS_PAD(pad5);
-
-       /*
-        * Owner of this descriptor, 0= driver, 1=sonic
-        */
-
-       u16 in_use;
-        SREGS_PAD(pad6);
-
-       caddr_t rda_next;       /* pointer to next RD */
-} sonic_rd_t;
-
-
-/*
- * Describes a Transmit Descriptor
- */
-typedef struct {
-       u16 tx_status;          /* status after transmission of a packet */
-        SREGS_PAD(pad0);
-       u16 tx_config;          /* transmit configuration for this packet */
-        SREGS_PAD(pad1);
-       u16 tx_pktsize;         /* size of the packet to be transmitted */
-        SREGS_PAD(pad2);
-       u16 tx_frag_count;      /* no. of fragments */
-        SREGS_PAD(pad3);
-
-       u16 tx_frag_ptr_l;
-        SREGS_PAD(pad4);
-       u16 tx_frag_ptr_h;
-        SREGS_PAD(pad5);
-       u16 tx_frag_size;
-        SREGS_PAD(pad6);
-
-       u16 link;               /* ptr to next descriptor */
-        SREGS_PAD(pad7);
-} sonic_td_t;
-
-
-/*
- * Describes an entry in the CAM Descriptor Area.
- */
-
-typedef struct {
-       u16 cam_entry_pointer;
-        SREGS_PAD(pad0);
-       u16 cam_cap0;
-        SREGS_PAD(pad1);
-       u16 cam_cap1;
-        SREGS_PAD(pad2);
-       u16 cam_cap2;
-        SREGS_PAD(pad3);
-} sonic_cd_t;
-
-#define CAM_DESCRIPTORS 16
-
-
-typedef struct {
-       sonic_cd_t cam_desc[CAM_DESCRIPTORS];
-       u16 cam_enable;
-        SREGS_PAD(pad);
-} sonic_cda_t;
-#endif                         /* endianness */
+/* Offsets in the various DMA buffers accessed by the SONIC */
+
+#define SONIC_BITMODE16 0
+#define SONIC_BITMODE32 1
+#define SONIC_BUS_SCALE(bitmode) ((bitmode) ? 4 : 2)
+/* Note!  These are all measured in bus-size units, so use SONIC_BUS_SCALE */
+#define SIZEOF_SONIC_RR 4
+#define SONIC_RR_BUFADR_L  0
+#define SONIC_RR_BUFADR_H  1
+#define SONIC_RR_BUFSIZE_L 2
+#define SONIC_RR_BUFSIZE_H 3
+
+#define SIZEOF_SONIC_RD 7
+#define SONIC_RD_STATUS   0
+#define SONIC_RD_PKTLEN   1
+#define SONIC_RD_PKTPTR_L 2
+#define SONIC_RD_PKTPTR_H 3
+#define SONIC_RD_SEQNO    4
+#define SONIC_RD_LINK     5
+#define SONIC_RD_IN_USE   6
+
+#define SIZEOF_SONIC_TD 8
+#define SONIC_TD_STATUS       0
+#define SONIC_TD_CONFIG       1
+#define SONIC_TD_PKTSIZE      2
+#define SONIC_TD_FRAG_COUNT   3
+#define SONIC_TD_FRAG_PTR_L   4
+#define SONIC_TD_FRAG_PTR_H   5
+#define SONIC_TD_FRAG_SIZE    6
+#define SONIC_TD_LINK         7
+
+#define SIZEOF_SONIC_CD 4
+#define SONIC_CD_ENTRY_POINTER 0
+#define SONIC_CD_CAP0          1
+#define SONIC_CD_CAP1          2
+#define SONIC_CD_CAP2          3
+
+#define SIZEOF_SONIC_CDA ((CAM_DESCRIPTORS * SIZEOF_SONIC_CD) + 1)
+#define SONIC_CDA_CAM_ENABLE   (CAM_DESCRIPTORS * SIZEOF_SONIC_CD)
 
 /*
  * Some tunables for the buffer areas. Power of 2 is required
@@ -426,44 +270,60 @@ typedef struct {
  *
  * MSch: use more buffer space for the slow m68k Macs!
  */
-#ifdef CONFIG_MACSONIC
-#define SONIC_NUM_RRS    32    /* number of receive resources */
-#define SONIC_NUM_RDS    SONIC_NUM_RRS /* number of receive descriptors */
-#define SONIC_NUM_TDS    32    /* number of transmit descriptors */
-#else
-#define SONIC_NUM_RRS    16    /* number of receive resources */
-#define SONIC_NUM_RDS    SONIC_NUM_RRS /* number of receive descriptors */
-#define SONIC_NUM_TDS    16    /* number of transmit descriptors */
-#endif
-#define SONIC_RBSIZE   1520    /* size of one resource buffer */
+#define SONIC_NUM_RRS   16            /* number of receive resources */
+#define SONIC_NUM_RDS   SONIC_NUM_RRS /* number of receive descriptors */
+#define SONIC_NUM_TDS   16            /* number of transmit descriptors */
 
-#define SONIC_RDS_MASK   (SONIC_NUM_RDS-1)
-#define SONIC_TDS_MASK   (SONIC_NUM_TDS-1)
+#define SONIC_RDS_MASK  (SONIC_NUM_RDS-1)
+#define SONIC_TDS_MASK  (SONIC_NUM_TDS-1)
 
+#define SONIC_RBSIZE   1520          /* size of one resource buffer */
+
+/* Again, measured in bus size units! */
+#define SIZEOF_SONIC_DESC (SIZEOF_SONIC_CDA    \
+       + (SIZEOF_SONIC_TD * SONIC_NUM_TDS)     \
+       + (SIZEOF_SONIC_RD * SONIC_NUM_RDS)     \
+       + (SIZEOF_SONIC_RR * SONIC_NUM_RRS))
 
 /* Information that need to be kept for each board. */
 struct sonic_local {
-       sonic_cda_t cda;        /* virtual CPU address of CDA */
-       sonic_td_t tda[SONIC_NUM_TDS];  /* transmit descriptor area */
-       sonic_rr_t rra[SONIC_NUM_RRS];  /* receive resource area */
-       sonic_rd_t rda[SONIC_NUM_RDS];  /* receive descriptor area */
-       struct sk_buff *tx_skb[SONIC_NUM_TDS];  /* skbuffs for packets to transmit */
-       unsigned int tx_laddr[SONIC_NUM_TDS];   /* logical DMA address fro skbuffs */
-       unsigned char *rba;     /* start of receive buffer areas */
-       unsigned int cda_laddr; /* logical DMA address of CDA */
-       unsigned int tda_laddr; /* logical DMA address of TDA */
-       unsigned int rra_laddr; /* logical DMA address of RRA */
-       unsigned int rda_laddr; /* logical DMA address of RDA */
-       unsigned int rba_laddr; /* logical DMA address of RBA */
-       unsigned int cur_rra;   /* current indexes to resource areas */
+       /* Bus size.  0 == 16 bits, 1 == 32 bits. */
+       int dma_bitmode;
+       /* Register offset within the longword (independent of endianness,
+          and varies from one type of Macintosh SONIC to another
+          (Aarrgh)) */
+       int reg_offset;
+       void *descriptors;
+       /* Crud.  These areas have to be within the same 64K.  Therefore
+       we allocate a desriptors page, and point these to places within it. */
+       void *cda;  /* CAM descriptor area */
+       void *tda;  /* Transmit descriptor area */
+       void *rra;  /* Receive resource area */
+       void *rda;  /* Receive descriptor area */
+       struct sk_buff* volatile rx_skb[SONIC_NUM_RRS]; /* packets to be received */
+       struct sk_buff* volatile tx_skb[SONIC_NUM_TDS]; /* packets to be transmitted */
+       unsigned int tx_len[SONIC_NUM_TDS]; /* lengths of tx DMA mappings */
+       /* Logical DMA addresses on MIPS, bus addresses on m68k
+        * (so "laddr" is a bit misleading) */
+       dma_addr_t descriptors_laddr;
+       u32 cda_laddr;              /* logical DMA address of CDA */
+       u32 tda_laddr;              /* logical DMA address of TDA */
+       u32 rra_laddr;              /* logical DMA address of RRA */
+       u32 rda_laddr;              /* logical DMA address of RDA */
+       dma_addr_t rx_laddr[SONIC_NUM_RRS]; /* logical DMA addresses of rx skbuffs */
+       dma_addr_t tx_laddr[SONIC_NUM_TDS]; /* logical DMA addresses of tx skbuffs */
+       unsigned int rra_end;
+       unsigned int cur_rwp;
        unsigned int cur_rx;
-       unsigned int cur_tx;
-       unsigned int dirty_tx;  /* last unacked transmit packet */
-       char tx_full;
+       unsigned int cur_tx;           /* first unacked transmit packet */
+       unsigned int eol_rx;
+       unsigned int eol_tx;           /* last unacked transmit packet */
+       unsigned int next_tx;          /* next free TD */
+       struct device *device;         /* generic device */
        struct net_device_stats stats;
 };
 
-#define TX_TIMEOUT 6
+#define TX_TIMEOUT (3 * HZ)
 
 /* Index to functions, as function prototypes. */
 
@@ -477,6 +337,114 @@ static void sonic_multicast_list(struct net_device *dev);
 static int sonic_init(struct net_device *dev);
 static void sonic_tx_timeout(struct net_device *dev);
 
+/* Internal inlines for reading/writing DMA buffers.  Note that bus
+   size and endianness matter here, whereas they don't for registers,
+   as far as we can tell. */
+/* OpenBSD calls this "SWO".  I'd like to think that sonic_buf_put()
+   is a much better name. */
+static inline void sonic_buf_put(void* base, int bitmode,
+                                int offset, __u16 val)
+{
+       if (bitmode)
+#ifdef __BIG_ENDIAN
+               ((__u16 *) base + (offset*2))[1] = val;
+#else
+               ((__u16 *) base + (offset*2))[0] = val;
+#endif
+       else
+               ((__u16 *) base)[offset] = val;
+}
+
+static inline __u16 sonic_buf_get(void* base, int bitmode,
+                                 int offset)
+{
+       if (bitmode)
+#ifdef __BIG_ENDIAN
+               return ((volatile __u16 *) base + (offset*2))[1];
+#else
+               return ((volatile __u16 *) base + (offset*2))[0];
+#endif
+       else
+               return ((volatile __u16 *) base)[offset];
+}
+
+/* Inlines that you should actually use for reading/writing DMA buffers */
+static inline void sonic_cda_put(struct net_device* dev, int entry,
+                                int offset, __u16 val)
+{
+       struct sonic_local* lp = (struct sonic_local *) dev->priv;
+       sonic_buf_put(lp->cda, lp->dma_bitmode,
+                     (entry * SIZEOF_SONIC_CD) + offset, val);
+}
+
+static inline __u16 sonic_cda_get(struct net_device* dev, int entry,
+                                 int offset)
+{
+       struct sonic_local* lp = (struct sonic_local *) dev->priv;
+       return sonic_buf_get(lp->cda, lp->dma_bitmode,
+                            (entry * SIZEOF_SONIC_CD) + offset);
+}
+
+static inline void sonic_set_cam_enable(struct net_device* dev, __u16 val)
+{
+       struct sonic_local* lp = (struct sonic_local *) dev->priv;
+       sonic_buf_put(lp->cda, lp->dma_bitmode, SONIC_CDA_CAM_ENABLE, val);
+}
+
+static inline __u16 sonic_get_cam_enable(struct net_device* dev)
+{
+       struct sonic_local* lp = (struct sonic_local *) dev->priv;
+       return sonic_buf_get(lp->cda, lp->dma_bitmode, SONIC_CDA_CAM_ENABLE);
+}
+
+static inline void sonic_tda_put(struct net_device* dev, int entry,
+                                int offset, __u16 val)
+{
+       struct sonic_local* lp = (struct sonic_local *) dev->priv;
+       sonic_buf_put(lp->tda, lp->dma_bitmode,
+                     (entry * SIZEOF_SONIC_TD) + offset, val);
+}
+
+static inline __u16 sonic_tda_get(struct net_device* dev, int entry,
+                                 int offset)
+{
+       struct sonic_local* lp = (struct sonic_local *) dev->priv;
+       return sonic_buf_get(lp->tda, lp->dma_bitmode,
+                            (entry * SIZEOF_SONIC_TD) + offset);
+}
+
+static inline void sonic_rda_put(struct net_device* dev, int entry,
+                                int offset, __u16 val)
+{
+       struct sonic_local* lp = (struct sonic_local *) dev->priv;
+       sonic_buf_put(lp->rda, lp->dma_bitmode,
+                     (entry * SIZEOF_SONIC_RD) + offset, val);
+}
+
+static inline __u16 sonic_rda_get(struct net_device* dev, int entry,
+                                 int offset)
+{
+       struct sonic_local* lp = (struct sonic_local *) dev->priv;
+       return sonic_buf_get(lp->rda, lp->dma_bitmode,
+                            (entry * SIZEOF_SONIC_RD) + offset);
+}
+
+static inline void sonic_rra_put(struct net_device* dev, int entry,
+                                int offset, __u16 val)
+{
+       struct sonic_local* lp = (struct sonic_local *) dev->priv;
+       sonic_buf_put(lp->rra, lp->dma_bitmode,
+                     (entry * SIZEOF_SONIC_RR) + offset, val);
+}
+
+static inline __u16 sonic_rra_get(struct net_device* dev, int entry,
+                                 int offset)
+{
+       struct sonic_local* lp = (struct sonic_local *) dev->priv;
+       return sonic_buf_get(lp->rra, lp->dma_bitmode,
+                            (entry * SIZEOF_SONIC_RR) + offset);
+}
+
 static const char *version =
     "sonic.c:v0.92 20.9.98 tsbogend@alpha.franken.de\n";
 
index 201a550..6d4ab1e 100644 (file)
@@ -66,8 +66,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.34"
-#define DRV_MODULE_RELDATE     "July 25, 2005"
+#define DRV_MODULE_VERSION     "3.37"
+#define DRV_MODULE_RELDATE     "August 25, 2005"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -7865,8 +7865,6 @@ static int tg3_test_loopback(struct tg3 *tp)
 
        err = -EIO;
 
-       tg3_abort_hw(tp, 1);
-
        tg3_reset_hw(tp);
 
        mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
@@ -8970,6 +8968,8 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
                tp->phy_id = hw_phy_id;
                if (hw_phy_id_masked == PHY_ID_BCM8002)
                        tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
+               else
+                       tp->tg3_flags2 &= ~TG3_FLG2_PHY_SERDES;
        } else {
                if (tp->phy_id != PHY_ID_INVALID) {
                        /* Do nothing, phy ID already set up in
@@ -10421,6 +10421,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
        tg3_init_coal(tp);
 
+       /* Now that we have fully setup the chip, save away a snapshot
+        * of the PCI config space.  We need to restore this after
+        * GRC_MISC_CFG core clock resets and some resume events.
+        */
+       pci_save_state(tp->pdev);
+
        err = register_netdev(dev);
        if (err) {
                printk(KERN_ERR PFX "Cannot register net device, "
@@ -10430,12 +10436,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
        pci_set_drvdata(pdev, dev);
 
-       /* Now that we have fully setup the chip, save away a snapshot
-        * of the PCI config space.  We need to restore this after
-        * GRC_MISC_CFG core clock resets and some resume events.
-        */
-       pci_save_state(tp->pdev);
-
        printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT Ethernet ",
               dev->name,
               tp->board_part_number,
index 23d0fa4..e4cfc80 100644 (file)
@@ -84,7 +84,7 @@ config 3C359
 
 config TMS380TR
        tristate "Generic TMS380 Token Ring ISA/PCI adapter support"
-       depends on TR && (PCI || ISA)
+       depends on TR && (PCI || ISA && ISA_DMA_API || MCA)
        select FW_LOADER
        ---help---
          This driver provides generic support for token ring adapters
@@ -158,7 +158,7 @@ config ABYSS
 
 config MADGEMC
        tristate "Madge Smart 16/4 Ringnode MicroChannel"
-       depends on TR && TMS380TR && MCA_LEGACY
+       depends on TR && TMS380TR && MCA
        help
          This tms380 module supports the Madge Smart 16/4 MC16 and MC32
          MicroChannel adapters.
index 87103c4..9345e68 100644 (file)
@@ -139,7 +139,7 @@ static int __devinit abyss_attach(struct pci_dev *pdev, const struct pci_device_
         */
        dev->base_addr += 0x10;
                
-       ret = tmsdev_init(dev, PCI_MAX_ADDRESS, pdev);
+       ret = tmsdev_init(dev, &pdev->dev);
        if (ret) {
                printk("%s: unable to get memory for dev->priv.\n", 
                       dev->name);
index 659cbdb..3a25d19 100644 (file)
@@ -20,7 +20,7 @@
 static const char version[] = "madgemc.c: v0.91 23/01/2000 by Adam Fritzler\n";
 
 #include <linux/module.h>
-#include <linux/mca-legacy.h>
+#include <linux/mca.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/pci.h>
@@ -38,9 +38,7 @@ static const char version[] = "madgemc.c: v0.91 23/01/2000 by Adam Fritzler\n";
 #define MADGEMC_IO_EXTENT 32
 #define MADGEMC_SIF_OFFSET 0x08
 
-struct madgemc_card {
-       struct net_device *dev;
-
+struct card_info {
        /*
         * These are read from the BIA ROM.
         */
@@ -57,16 +55,12 @@ struct madgemc_card {
        unsigned int arblevel:4;
        unsigned int ringspeed:2; /* 0 = 4mb, 1 = 16, 2 = Auto/none */
        unsigned int cabletype:1; /* 0 = RJ45, 1 = DB9 */
-
-       struct madgemc_card *next;
 };
-static struct madgemc_card *madgemc_card_list;
-
 
 static int madgemc_open(struct net_device *dev);
 static int madgemc_close(struct net_device *dev);
 static int madgemc_chipset_init(struct net_device *dev);
-static void madgemc_read_rom(struct madgemc_card *card);
+static void madgemc_read_rom(struct net_device *dev, struct card_info *card);
 static unsigned short madgemc_setnselout_pins(struct net_device *dev);
 static void madgemc_setcabletype(struct net_device *dev, int type);
 
@@ -151,261 +145,237 @@ static void madgemc_sifwritew(struct net_device *dev, unsigned short val, unsign
 
 
 
-static int __init madgemc_probe(void)
+static int __devinit madgemc_probe(struct device *device)
 {      
        static int versionprinted;
        struct net_device *dev;
        struct net_local *tp;
-       struct madgemc_card *card;
-       int i,slot = 0;
-       __u8 posreg[4];
-
-       if (!MCA_bus)
-               return -1;      
-       while (slot != MCA_NOTFOUND) {
-               /*
-                * Currently we only support the MC16/32 (MCA ID 002d)
-                */
-               slot = mca_find_unused_adapter(0x002d, slot);
-               if (slot == MCA_NOTFOUND)
-                       break;
-
-               /*
-                * If we get here, we have an adapter.
-                */
-               if (versionprinted++ == 0)
-                       printk("%s", version);
-
-               dev = alloc_trdev(sizeof(struct net_local));
-               if (dev == NULL) {
-                       printk("madgemc: unable to allocate dev space\n");
-                       if (madgemc_card_list)
-                               return 0;
-                       return -1;
-               }
+       struct card_info *card;
+       struct mca_device *mdev = to_mca_device(device);
+       int ret = 0, i = 0;
+
+       if (versionprinted++ == 0)
+               printk("%s", version);
+
+       if(mca_device_claimed(mdev))
+               return -EBUSY;
+       mca_device_set_claim(mdev, 1);
+
+       dev = alloc_trdev(sizeof(struct net_local));
+       if (!dev) {
+               printk("madgemc: unable to allocate dev space\n");
+               mca_device_set_claim(mdev, 0);
+               ret = -ENOMEM;
+               goto getout;
+       }
 
-               SET_MODULE_OWNER(dev);
-               dev->dma = 0;
+       SET_MODULE_OWNER(dev);
+       dev->dma = 0;
 
-               /*
-                * Fetch MCA config registers
-                */
-               for(i=0;i<4;i++)
-                       posreg[i] = mca_read_stored_pos(slot, i+2);
-               
-               card = kmalloc(sizeof(struct madgemc_card), GFP_KERNEL);
-               if (card==NULL) {
-                       printk("madgemc: unable to allocate card struct\n");
-                       free_netdev(dev);
-                       if (madgemc_card_list)
-                               return 0;
-                       return -1;
-               }
-               card->dev = dev;
-
-               /*
-                * Parse configuration information.  This all comes
-                * directly from the publicly available @002d.ADF.
-                * Get it from Madge or your local ADF library.
-                */
-
-               /*
-                * Base address 
-                */
-               dev->base_addr = 0x0a20 + 
-                       ((posreg[2] & MC16_POS2_ADDR2)?0x0400:0) +
-                       ((posreg[0] & MC16_POS0_ADDR1)?0x1000:0) +
-                       ((posreg[3] & MC16_POS3_ADDR3)?0x2000:0);
-
-               /*
-                * Interrupt line
-                */
-               switch(posreg[0] >> 6) { /* upper two bits */
+       card = kmalloc(sizeof(struct card_info), GFP_KERNEL);
+       if (card==NULL) {
+               printk("madgemc: unable to allocate card struct\n");
+               ret = -ENOMEM;
+               goto getout1;
+       }
+
+       /*
+        * Parse configuration information.  This all comes
+        * directly from the publicly available @002d.ADF.
+        * Get it from Madge or your local ADF library.
+        */
+
+       /*
+        * Base address 
+        */
+       dev->base_addr = 0x0a20 + 
+               ((mdev->pos[2] & MC16_POS2_ADDR2)?0x0400:0) +
+               ((mdev->pos[0] & MC16_POS0_ADDR1)?0x1000:0) +
+               ((mdev->pos[3] & MC16_POS3_ADDR3)?0x2000:0);
+
+       /*
+        * Interrupt line
+        */
+       switch(mdev->pos[0] >> 6) { /* upper two bits */
                case 0x1: dev->irq = 3; break;
                case 0x2: dev->irq = 9; break; /* IRQ 2 = IRQ 9 */
                case 0x3: dev->irq = 10; break;
                default: dev->irq = 0; break;
-               }
+       }
 
-               if (dev->irq == 0) {
-                       printk("%s: invalid IRQ\n", dev->name);
-                       goto getout1;
-               }
+       if (dev->irq == 0) {
+               printk("%s: invalid IRQ\n", dev->name);
+               ret = -EBUSY;
+               goto getout2;
+       }
 
-               if (!request_region(dev->base_addr, MADGEMC_IO_EXTENT, 
-                                  "madgemc")) {
-                       printk(KERN_INFO "madgemc: unable to setup Smart MC in slot %d because of I/O base conflict at 0x%04lx\n", slot, dev->base_addr);
-                       dev->base_addr += MADGEMC_SIF_OFFSET;
-                       goto getout1;
-               }
+       if (!request_region(dev->base_addr, MADGEMC_IO_EXTENT, 
+                          "madgemc")) {
+               printk(KERN_INFO "madgemc: unable to setup Smart MC in slot %d because of I/O base conflict at 0x%04lx\n", mdev->slot, dev->base_addr);
                dev->base_addr += MADGEMC_SIF_OFFSET;
+               ret = -EBUSY;
+               goto getout2;
+       }
+       dev->base_addr += MADGEMC_SIF_OFFSET;
+       
+       /*
+        * Arbitration Level
+        */
+       card->arblevel = ((mdev->pos[0] >> 1) & 0x7) + 8;
+
+       /*
+        * Burst mode and Fairness
+        */
+       card->burstmode = ((mdev->pos[2] >> 6) & 0x3);
+       card->fairness = ((mdev->pos[2] >> 4) & 0x1);
+
+       /*
+        * Ring Speed
+        */
+       if ((mdev->pos[1] >> 2)&0x1)
+               card->ringspeed = 2; /* not selected */
+       else if ((mdev->pos[2] >> 5) & 0x1)
+               card->ringspeed = 1; /* 16Mb */
+       else
+               card->ringspeed = 0; /* 4Mb */
+
+       /* 
+        * Cable type
+        */
+       if ((mdev->pos[1] >> 6)&0x1)
+               card->cabletype = 1; /* STP/DB9 */
+       else
+               card->cabletype = 0; /* UTP/RJ-45 */
+
+
+       /* 
+        * ROM Info. This requires us to actually twiddle
+        * bits on the card, so we must ensure above that 
+        * the base address is free of conflict (request_region above).
+        */
+       madgemc_read_rom(dev, card);
                
-               /*
-                * Arbitration Level
-                */
-               card->arblevel = ((posreg[0] >> 1) & 0x7) + 8;
-
-               /*
-                * Burst mode and Fairness
-                */
-               card->burstmode = ((posreg[2] >> 6) & 0x3);
-               card->fairness = ((posreg[2] >> 4) & 0x1);
-
-               /*
-                * Ring Speed
-                */
-               if ((posreg[1] >> 2)&0x1)
-                       card->ringspeed = 2; /* not selected */
-               else if ((posreg[2] >> 5) & 0x1)
-                       card->ringspeed = 1; /* 16Mb */
-               else
-                       card->ringspeed = 0; /* 4Mb */
-
-               /* 
-                * Cable type
-                */
-               if ((posreg[1] >> 6)&0x1)
-                       card->cabletype = 1; /* STP/DB9 */
-               else
-                       card->cabletype = 0; /* UTP/RJ-45 */
-
-
-               /* 
-                * ROM Info. This requires us to actually twiddle
-                * bits on the card, so we must ensure above that 
-                * the base address is free of conflict (request_region above).
-                */
-               madgemc_read_rom(card);
-               
-               if (card->manid != 0x4d) { /* something went wrong */
-                       printk(KERN_INFO "%s: Madge MC ROM read failed (unknown manufacturer ID %02x)\n", dev->name, card->manid);
-                       goto getout;
-               }
+       if (card->manid != 0x4d) { /* something went wrong */
+               printk(KERN_INFO "%s: Madge MC ROM read failed (unknown manufacturer ID %02x)\n", dev->name, card->manid);
+               goto getout3;
+       }
                
-               if ((card->cardtype != 0x08) && (card->cardtype != 0x0d)) {
-                       printk(KERN_INFO "%s: Madge MC ROM read failed (unknown card ID %02x)\n", dev->name, card->cardtype);
-                       goto getout;
-               }
+       if ((card->cardtype != 0x08) && (card->cardtype != 0x0d)) {
+               printk(KERN_INFO "%s: Madge MC ROM read failed (unknown card ID %02x)\n", dev->name, card->cardtype);
+               ret = -EIO;
+               goto getout3;
+       }
               
-               /* All cards except Rev 0 and 1 MC16's have 256kb of RAM */
-               if ((card->cardtype == 0x08) && (card->cardrev <= 0x01))
-                       card->ramsize = 128;
-               else
-                       card->ramsize = 256;
-
-               printk("%s: %s Rev %d at 0x%04lx IRQ %d\n", 
-                      dev->name, 
-                      (card->cardtype == 0x08)?MADGEMC16_CARDNAME:
-                      MADGEMC32_CARDNAME, card->cardrev, 
-                      dev->base_addr, dev->irq);
-
-               if (card->cardtype == 0x0d)
-                       printk("%s:     Warning: MC32 support is experimental and highly untested\n", dev->name);
-               
-               if (card->ringspeed==2) { /* Unknown */
-                       printk("%s:     Warning: Ring speed not set in POS -- Please run the reference disk and set it!\n", dev->name);
-                       card->ringspeed = 1; /* default to 16mb */
-               }
+       /* All cards except Rev 0 and 1 MC16's have 256kb of RAM */
+       if ((card->cardtype == 0x08) && (card->cardrev <= 0x01))
+               card->ramsize = 128;
+       else
+               card->ramsize = 256;
+
+       printk("%s: %s Rev %d at 0x%04lx IRQ %d\n", 
+              dev->name, 
+              (card->cardtype == 0x08)?MADGEMC16_CARDNAME:
+              MADGEMC32_CARDNAME, card->cardrev, 
+              dev->base_addr, dev->irq);
+
+       if (card->cardtype == 0x0d)
+               printk("%s:     Warning: MC32 support is experimental and highly untested\n", dev->name);
+       
+       if (card->ringspeed==2) { /* Unknown */
+               printk("%s:     Warning: Ring speed not set in POS -- Please run the reference disk and set it!\n", dev->name);
+               card->ringspeed = 1; /* default to 16mb */
+       }
                
-               printk("%s:     RAM Size: %dKB\n", dev->name, card->ramsize);
+       printk("%s:     RAM Size: %dKB\n", dev->name, card->ramsize);
 
-               printk("%s:     Ring Speed: %dMb/sec on %s\n", dev->name, 
-                      (card->ringspeed)?16:4, 
-                      card->cabletype?"STP/DB9":"UTP/RJ-45");
-               printk("%s:     Arbitration Level: %d\n", dev->name, 
-                      card->arblevel);
+       printk("%s:     Ring Speed: %dMb/sec on %s\n", dev->name, 
+              (card->ringspeed)?16:4, 
+              card->cabletype?"STP/DB9":"UTP/RJ-45");
+       printk("%s:     Arbitration Level: %d\n", dev->name, 
+              card->arblevel);
 
-               printk("%s:     Burst Mode: ", dev->name);
-               switch(card->burstmode) {
+       printk("%s:     Burst Mode: ", dev->name);
+       switch(card->burstmode) {
                case 0: printk("Cycle steal"); break;
                case 1: printk("Limited burst"); break;
                case 2: printk("Delayed release"); break;
                case 3: printk("Immediate release"); break;
-               }
-               printk(" (%s)\n", (card->fairness)?"Unfair":"Fair");
-
-
-               /* 
-                * Enable SIF before we assign the interrupt handler,
-                * just in case we get spurious interrupts that need
-                * handling.
-                */ 
-               outb(0, dev->base_addr + MC_CONTROL_REG0); /* sanity */
-               madgemc_setsifsel(dev, 1);
-               if (request_irq(dev->irq, madgemc_interrupt, SA_SHIRQ,
-                              "madgemc", dev)) 
-                       goto getout;
-               
-               madgemc_chipset_init(dev); /* enables interrupts! */
-               madgemc_setcabletype(dev, card->cabletype);
+       }
+       printk(" (%s)\n", (card->fairness)?"Unfair":"Fair");
 
-               /* Setup MCA structures */
-               mca_set_adapter_name(slot, (card->cardtype == 0x08)?MADGEMC16_CARDNAME:MADGEMC32_CARDNAME);
-               mca_set_adapter_procfn(slot, madgemc_mcaproc, dev);
-               mca_mark_as_used(slot);
 
-               printk("%s:     Ring Station Address: ", dev->name);
-               printk("%2.2x", dev->dev_addr[0]);
-               for (i = 1; i < 6; i++)
-                       printk(":%2.2x", dev->dev_addr[i]);
-               printk("\n");
-
-               /* XXX is ISA_MAX_ADDRESS correct here? */
-               if (tmsdev_init(dev, ISA_MAX_ADDRESS, NULL)) {
-                       printk("%s: unable to get memory for dev->priv.\n", 
-                              dev->name);
-                       release_region(dev->base_addr-MADGEMC_SIF_OFFSET, 
-                              MADGEMC_IO_EXTENT); 
-                       
-                       kfree(card);
-                       tmsdev_term(dev);
-                       free_netdev(dev);
-                       if (madgemc_card_list)
-                               return 0;
-                       return -1;
-               }
-               tp = netdev_priv(dev);
-
-               /* 
-                * The MC16 is physically a 32bit card.  However, Madge
-                * insists on calling it 16bit, so I'll assume here that
-                * they know what they're talking about.  Cut off DMA
-                * at 16mb.
-                */
-               tp->setnselout = madgemc_setnselout_pins;
-               tp->sifwriteb = madgemc_sifwriteb;
-               tp->sifreadb = madgemc_sifreadb;
-               tp->sifwritew = madgemc_sifwritew;
-               tp->sifreadw = madgemc_sifreadw;
-               tp->DataRate = (card->ringspeed)?SPEED_16:SPEED_4;
-
-               memcpy(tp->ProductID, "Madge MCA 16/4    ", PROD_ID_SIZE + 1);
-
-               dev->open = madgemc_open;
-               dev->stop = madgemc_close;
-
-               if (register_netdev(dev) == 0) {
-                       /* Enlist in the card list */
-                       card->next = madgemc_card_list;
-                       madgemc_card_list = card;
-                       slot++;
-                       continue; /* successful, try to find another */
-               }
-               
-               free_irq(dev->irq, dev);
-       getout:
-               release_region(dev->base_addr-MADGEMC_SIF_OFFSET, 
-                              MADGEMC_IO_EXTENT); 
-       getout1:
-               kfree(card);
-               free_netdev(dev);
-               slot++;
+       /* 
+        * Enable SIF before we assign the interrupt handler,
+        * just in case we get spurious interrupts that need
+        * handling.
+        */ 
+       outb(0, dev->base_addr + MC_CONTROL_REG0); /* sanity */
+       madgemc_setsifsel(dev, 1);
+       if (request_irq(dev->irq, madgemc_interrupt, SA_SHIRQ,
+                      "madgemc", dev)) {
+               ret = -EBUSY;
+               goto getout3;
        }
 
-       if (madgemc_card_list)
+       madgemc_chipset_init(dev); /* enables interrupts! */
+       madgemc_setcabletype(dev, card->cabletype);
+
+       /* Setup MCA structures */
+       mca_device_set_name(mdev, (card->cardtype == 0x08)?MADGEMC16_CARDNAME:MADGEMC32_CARDNAME);
+       mca_set_adapter_procfn(mdev->slot, madgemc_mcaproc, dev);
+
+       printk("%s:     Ring Station Address: ", dev->name);
+       printk("%2.2x", dev->dev_addr[0]);
+       for (i = 1; i < 6; i++)
+               printk(":%2.2x", dev->dev_addr[i]);
+       printk("\n");
+
+       if (tmsdev_init(dev, device)) {
+               printk("%s: unable to get memory for dev->priv.\n", 
+                      dev->name);
+               ret = -ENOMEM;
+               goto getout4;
+       }
+       tp = netdev_priv(dev);
+
+       /* 
+        * The MC16 is physically a 32bit card.  However, Madge
+        * insists on calling it 16bit, so I'll assume here that
+        * they know what they're talking about.  Cut off DMA
+        * at 16mb.
+        */
+       tp->setnselout = madgemc_setnselout_pins;
+       tp->sifwriteb = madgemc_sifwriteb;
+       tp->sifreadb = madgemc_sifreadb;
+       tp->sifwritew = madgemc_sifwritew;
+       tp->sifreadw = madgemc_sifreadw;
+       tp->DataRate = (card->ringspeed)?SPEED_16:SPEED_4;
+
+       memcpy(tp->ProductID, "Madge MCA 16/4    ", PROD_ID_SIZE + 1);
+
+       dev->open = madgemc_open;
+       dev->stop = madgemc_close;
+
+       tp->tmspriv = card;
+       dev_set_drvdata(device, dev);
+
+       if (register_netdev(dev) == 0)
                return 0;
-       return -1;
+
+       dev_set_drvdata(device, NULL);
+       ret = -ENOMEM;
+getout4:
+       free_irq(dev->irq, dev);
+getout3:
+       release_region(dev->base_addr-MADGEMC_SIF_OFFSET, 
+                      MADGEMC_IO_EXTENT); 
+getout2:
+       kfree(card);
+getout1:
+       free_netdev(dev);
+getout:
+       mca_device_set_claim(mdev, 0);
+       return ret;
 }
 
 /*
@@ -664,12 +634,12 @@ static void madgemc_chipset_close(struct net_device *dev)
  * is complete.
  *
  */
-static void madgemc_read_rom(struct madgemc_card *card)
+static void madgemc_read_rom(struct net_device *dev, struct card_info *card)
 {
        unsigned long ioaddr;
        unsigned char reg0, reg1, tmpreg0, i;
 
-       ioaddr = card->dev->base_addr;
+       ioaddr = dev->base_addr;
 
        reg0 = inb(ioaddr + MC_CONTROL_REG0);
        reg1 = inb(ioaddr + MC_CONTROL_REG1);
@@ -686,9 +656,9 @@ static void madgemc_read_rom(struct madgemc_card *card)
        outb(tmpreg0 | MC_CONTROL_REG0_PAGE, ioaddr + MC_CONTROL_REG0);
 
        /* Read BIA */
-       card->dev->addr_len = 6;
+       dev->addr_len = 6;
        for (i = 0; i < 6; i++)
-               card->dev->dev_addr[i] = inb(ioaddr + MC_ROM_BIA_START + i);
+               dev->dev_addr[i] = inb(ioaddr + MC_ROM_BIA_START + i);
        
        /* Restore original register values */
        outb(reg0, ioaddr + MC_CONTROL_REG0);
@@ -721,14 +691,10 @@ static int madgemc_close(struct net_device *dev)
 static int madgemc_mcaproc(char *buf, int slot, void *d) 
 {      
        struct net_device *dev = (struct net_device *)d;
-       struct madgemc_card *curcard = madgemc_card_list;
+       struct net_local *tp = dev->priv;
+       struct card_info *curcard = tp->tmspriv;
        int len = 0;
        
-       while (curcard) { /* search for card struct */
-               if (curcard->dev == dev)
-                       break;
-               curcard = curcard->next;
-       }
        len += sprintf(buf+len, "-------\n");
        if (curcard) {
                struct net_local *tp = netdev_priv(dev);
@@ -763,25 +729,56 @@ static int madgemc_mcaproc(char *buf, int slot, void *d)
        return len;
 }
 
-static void __exit madgemc_exit(void)
+static int __devexit madgemc_remove(struct device *device)
 {
-       struct net_device *dev;
-       struct madgemc_card *this_card;
-       
-       while (madgemc_card_list) {
-               dev = madgemc_card_list->dev;
-               unregister_netdev(dev);
-               release_region(dev->base_addr-MADGEMC_SIF_OFFSET, MADGEMC_IO_EXTENT);
-               free_irq(dev->irq, dev);
-               tmsdev_term(dev);
-               free_netdev(dev);
-               this_card = madgemc_card_list;
-               madgemc_card_list = this_card->next;
-               kfree(this_card);
-       }
+       struct net_device *dev = dev_get_drvdata(device);
+       struct net_local *tp;
+        struct card_info *card;
+
+       if (!dev)
+               BUG();
+
+       tp = dev->priv;
+       card = tp->tmspriv;
+       kfree(card);
+       tp->tmspriv = NULL;
+
+       unregister_netdev(dev);
+       release_region(dev->base_addr-MADGEMC_SIF_OFFSET, MADGEMC_IO_EXTENT);
+       free_irq(dev->irq, dev);
+       tmsdev_term(dev);
+       free_netdev(dev);
+       dev_set_drvdata(device, NULL);
+
+       return 0;
+}
+
+static short madgemc_adapter_ids[] __initdata = {
+       0x002d,
+       0x0000
+};
+
+static struct mca_driver madgemc_driver = {
+       .id_table = madgemc_adapter_ids,
+       .driver = {
+               .name = "madgemc",
+               .bus = &mca_bus_type,
+               .probe = madgemc_probe,
+               .remove = __devexit_p(madgemc_remove),
+       },
+};
+
+static int __init madgemc_init (void)
+{
+       return mca_register_driver (&madgemc_driver);
+}
+
+static void __exit madgemc_exit (void)
+{
+       mca_unregister_driver (&madgemc_driver);
 }
 
-module_init(madgemc_probe);
+module_init(madgemc_init);
 module_exit(madgemc_exit);
 
 MODULE_LICENSE("GPL");
index 40ad0fd..eb1423e 100644 (file)
@@ -62,8 +62,7 @@ static int dmalist[] __initdata = {
 };
 
 static char cardname[] = "Proteon 1392\0";
-
-struct net_device *proteon_probe(int unit);
+static u64 dma_mask = ISA_MAX_ADDRESS;
 static int proteon_open(struct net_device *dev);
 static void proteon_read_eeprom(struct net_device *dev);
 static unsigned short proteon_setnselout_pins(struct net_device *dev);
@@ -116,7 +115,7 @@ nodev:
        return -ENODEV;
 }
 
-static int __init setup_card(struct net_device *dev)
+static int __init setup_card(struct net_device *dev, struct device *pdev)
 {
        struct net_local *tp;
         static int versionprinted;
@@ -137,7 +136,7 @@ static int __init setup_card(struct net_device *dev)
                }
        }
        if (err)
-               goto out4;
+               goto out5;
 
        /* At this point we have found a valid card. */
 
@@ -145,14 +144,15 @@ static int __init setup_card(struct net_device *dev)
                printk(KERN_DEBUG "%s", version);
 
        err = -EIO;
-       if (tmsdev_init(dev, ISA_MAX_ADDRESS, NULL))
+       pdev->dma_mask = &dma_mask;
+       if (tmsdev_init(dev, pdev))
                goto out4;
 
        dev->base_addr &= ~3; 
                
        proteon_read_eeprom(dev);
 
-       printk(KERN_DEBUG "%s:    Ring Station Address: ", dev->name);
+       printk(KERN_DEBUG "proteon.c:    Ring Station Address: ");
        printk("%2.2x", dev->dev_addr[0]);
        for (j = 1; j < 6; j++)
                printk(":%2.2x", dev->dev_addr[j]);
@@ -185,7 +185,7 @@ static int __init setup_card(struct net_device *dev)
                
                 if(irqlist[j] == 0)
                 {
-                        printk(KERN_INFO "%s: AutoSelect no IRQ available\n", dev->name);
+                        printk(KERN_INFO "proteon.c: AutoSelect no IRQ available\n");
                        goto out3;
                }
        }
@@ -196,15 +196,15 @@ static int __init setup_card(struct net_device *dev)
                                break;
                if (irqlist[j] == 0)
                {
-                       printk(KERN_INFO "%s: Illegal IRQ %d specified\n",
-                               dev->name, dev->irq);
+                       printk(KERN_INFO "proteon.c: Illegal IRQ %d specified\n",
+                               dev->irq);
                        goto out3;
                }
                if (request_irq(dev->irq, tms380tr_interrupt, 0, 
                        cardname, dev))
                {
-                        printk(KERN_INFO "%s: Selected IRQ %d not available\n", 
-                               dev->name, dev->irq);
+                        printk(KERN_INFO "proteon.c: Selected IRQ %d not available\n",
+                               dev->irq);
                        goto out3;
                }
        }
@@ -220,7 +220,7 @@ static int __init setup_card(struct net_device *dev)
 
                if(dmalist[j] == 0)
                {
-                       printk(KERN_INFO "%s: AutoSelect no DMA available\n", dev->name);
+                       printk(KERN_INFO "proteon.c: AutoSelect no DMA available\n");
                        goto out2;
                }
        }
@@ -231,25 +231,25 @@ static int __init setup_card(struct net_device *dev)
                                break;
                if (dmalist[j] == 0)
                {
-                        printk(KERN_INFO "%s: Illegal DMA %d specified\n", 
-                               dev->name, dev->dma);
+                        printk(KERN_INFO "proteon.c: Illegal DMA %d specified\n",
+                               dev->dma);
                        goto out2;
                }
                if (request_dma(dev->dma, cardname))
                {
-                        printk(KERN_INFO "%s: Selected DMA %d not available\n", 
-                               dev->name, dev->dma);
+                        printk(KERN_INFO "proteon.c: Selected DMA %d not available\n",
+                               dev->dma);
                        goto out2;
                }
        }
 
-       printk(KERN_DEBUG "%s:    IO: %#4lx  IRQ: %d  DMA: %d\n",
-              dev->name, dev->base_addr, dev->irq, dev->dma);
-               
        err = register_netdev(dev);
        if (err)
                goto out;
 
+       printk(KERN_DEBUG "%s:    IO: %#4lx  IRQ: %d  DMA: %d\n",
+              dev->name, dev->base_addr, dev->irq, dev->dma);
+
        return 0;
 out:
        free_dma(dev->dma);
@@ -258,34 +258,11 @@ out2:
 out3:
        tmsdev_term(dev);
 out4:
-       release_region(dev->base_addr, PROTEON_IO_EXTENT); 
+       release_region(dev->base_addr, PROTEON_IO_EXTENT);
+out5:
        return err;
 }
 
-struct net_device * __init proteon_probe(int unit)
-{
-       struct net_device *dev = alloc_trdev(sizeof(struct net_local));
-       int err = 0;
-
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       if (unit >= 0) {
-               sprintf(dev->name, "tr%d", unit);
-               netdev_boot_setup_check(dev);
-       }
-
-       err = setup_card(dev);
-       if (err)
-               goto out;
-
-       return dev;
-
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-
 /*
  * Reads MAC address from adapter RAM, which should've read it from
  * the onboard ROM.  
@@ -352,8 +329,6 @@ static int proteon_open(struct net_device *dev)
        return tms380tr_open(dev);
 }
 
-#ifdef MODULE
-
 #define ISATR_MAX_ADAPTERS 3
 
 static int io[ISATR_MAX_ADAPTERS];
@@ -366,13 +341,23 @@ module_param_array(io, int, NULL, 0);
 module_param_array(irq, int, NULL, 0);
 module_param_array(dma, int, NULL, 0);
 
-static struct net_device *proteon_dev[ISATR_MAX_ADAPTERS];
+static struct platform_device *proteon_dev[ISATR_MAX_ADAPTERS];
+
+static struct device_driver proteon_driver = {
+       .name           = "proteon",
+       .bus            = &platform_bus_type,
+};
 
-int init_module(void)
+static int __init proteon_init(void)
 {
        struct net_device *dev;
+       struct platform_device *pdev;
        int i, num = 0, err = 0;
 
+       err = driver_register(&proteon_driver);
+       if (err)
+               return err;
+
        for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
                dev = alloc_trdev(sizeof(struct net_local));
                if (!dev)
@@ -381,11 +366,15 @@ int init_module(void)
                dev->base_addr = io[i];
                dev->irq = irq[i];
                dev->dma = dma[i];
-               err = setup_card(dev);
+               pdev = platform_device_register_simple("proteon",
+                       i, NULL, 0);
+               err = setup_card(dev, &pdev->dev);
                if (!err) {
-                       proteon_dev[i] = dev;
+                       proteon_dev[i] = pdev;
+                       dev_set_drvdata(&pdev->dev, dev);
                        ++num;
                } else {
+                       platform_device_unregister(pdev);
                        free_netdev(dev);
                }
        }
@@ -399,23 +388,28 @@ int init_module(void)
        return (0);
 }
 
-void cleanup_module(void)
+static void __exit proteon_cleanup(void)
 {
+       struct net_device *dev;
        int i;
 
        for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
-               struct net_device *dev = proteon_dev[i];
+               struct platform_device *pdev = proteon_dev[i];
                
-               if (!dev) 
+               if (!pdev)
                        continue;
-               
+               dev = dev_get_drvdata(&pdev->dev);
                unregister_netdev(dev);
                release_region(dev->base_addr, PROTEON_IO_EXTENT);
                free_irq(dev->irq, dev);
                free_dma(dev->dma);
                tmsdev_term(dev);
                free_netdev(dev);
+               dev_set_drvdata(&pdev->dev, NULL);
+               platform_device_unregister(pdev);
        }
+       driver_unregister(&proteon_driver);
 }
-#endif /* MODULE */
 
+module_init(proteon_init);
+module_exit(proteon_cleanup);
index f26796e..3c7c662 100644 (file)
@@ -68,8 +68,7 @@ static int dmalist[] __initdata = {
 };
 
 static char isa_cardname[] = "SK NET TR 4/16 ISA\0";
-
-struct net_device *sk_isa_probe(int unit);
+static u64 dma_mask = ISA_MAX_ADDRESS;
 static int sk_isa_open(struct net_device *dev);
 static void sk_isa_read_eeprom(struct net_device *dev);
 static unsigned short sk_isa_setnselout_pins(struct net_device *dev);
@@ -133,7 +132,7 @@ static int __init sk_isa_probe1(struct net_device *dev, int ioaddr)
        return 0;
 }
 
-static int __init setup_card(struct net_device *dev)
+static int __init setup_card(struct net_device *dev, struct device *pdev)
 {
        struct net_local *tp;
         static int versionprinted;
@@ -154,7 +153,7 @@ static int __init setup_card(struct net_device *dev)
                }
        }
        if (err)
-               goto out4;
+               goto out5;
 
        /* At this point we have found a valid card. */
 
@@ -162,14 +161,15 @@ static int __init setup_card(struct net_device *dev)
                printk(KERN_DEBUG "%s", version);
 
        err = -EIO;
-       if (tmsdev_init(dev, ISA_MAX_ADDRESS, NULL))
+       pdev->dma_mask = &dma_mask;
+       if (tmsdev_init(dev, pdev))
                goto out4;
 
        dev->base_addr &= ~3; 
                
        sk_isa_read_eeprom(dev);
 
-       printk(KERN_DEBUG "%s:    Ring Station Address: ", dev->name);
+       printk(KERN_DEBUG "skisa.c:    Ring Station Address: ");
        printk("%2.2x", dev->dev_addr[0]);
        for (j = 1; j < 6; j++)
                printk(":%2.2x", dev->dev_addr[j]);
@@ -202,7 +202,7 @@ static int __init setup_card(struct net_device *dev)
                
                 if(irqlist[j] == 0)
                 {
-                        printk(KERN_INFO "%s: AutoSelect no IRQ available\n", dev->name);
+                        printk(KERN_INFO "skisa.c: AutoSelect no IRQ available\n");
                        goto out3;
                }
        }
@@ -213,15 +213,15 @@ static int __init setup_card(struct net_device *dev)
                                break;
                if (irqlist[j] == 0)
                {
-                       printk(KERN_INFO "%s: Illegal IRQ %d specified\n",
-                               dev->name, dev->irq);
+                       printk(KERN_INFO "skisa.c: Illegal IRQ %d specified\n",
+                               dev->irq);
                        goto out3;
                }
                if (request_irq(dev->irq, tms380tr_interrupt, 0, 
                        isa_cardname, dev))
                {
-                        printk(KERN_INFO "%s: Selected IRQ %d not available\n", 
-                               dev->name, dev->irq);
+                        printk(KERN_INFO "skisa.c: Selected IRQ %d not available\n",
+                               dev->irq);
                        goto out3;
                }
        }
@@ -237,7 +237,7 @@ static int __init setup_card(struct net_device *dev)
 
                if(dmalist[j] == 0)
                {
-                       printk(KERN_INFO "%s: AutoSelect no DMA available\n", dev->name);
+                       printk(KERN_INFO "skisa.c: AutoSelect no DMA available\n");
                        goto out2;
                }
        }
@@ -248,25 +248,25 @@ static int __init setup_card(struct net_device *dev)
                                break;
                if (dmalist[j] == 0)
                {
-                        printk(KERN_INFO "%s: Illegal DMA %d specified\n", 
-                               dev->name, dev->dma);
+                        printk(KERN_INFO "skisa.c: Illegal DMA %d specified\n",
+                               dev->dma);
                        goto out2;
                }
                if (request_dma(dev->dma, isa_cardname))
                {
-                        printk(KERN_INFO "%s: Selected DMA %d not available\n", 
-                               dev->name, dev->dma);
+                        printk(KERN_INFO "skisa.c: Selected DMA %d not available\n",
+                               dev->dma);
                        goto out2;
                }
        }
 
-       printk(KERN_DEBUG "%s:    IO: %#4lx  IRQ: %d  DMA: %d\n",
-              dev->name, dev->base_addr, dev->irq, dev->dma);
-               
        err = register_netdev(dev);
        if (err)
                goto out;
 
+       printk(KERN_DEBUG "%s:    IO: %#4lx  IRQ: %d  DMA: %d\n",
+              dev->name, dev->base_addr, dev->irq, dev->dma);
+
        return 0;
 out:
        free_dma(dev->dma);
@@ -275,33 +275,11 @@ out2:
 out3:
        tmsdev_term(dev);
 out4:
-       release_region(dev->base_addr, SK_ISA_IO_EXTENT); 
+       release_region(dev->base_addr, SK_ISA_IO_EXTENT);
+out5:
        return err;
 }
 
-struct net_device * __init sk_isa_probe(int unit)
-{
-       struct net_device *dev = alloc_trdev(sizeof(struct net_local));
-       int err = 0;
-
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       if (unit >= 0) {
-               sprintf(dev->name, "tr%d", unit);
-               netdev_boot_setup_check(dev);
-       }
-
-       err = setup_card(dev);
-       if (err)
-               goto out;
-
-       return dev;
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-
 /*
  * Reads MAC address from adapter RAM, which should've read it from
  * the onboard ROM.  
@@ -361,8 +339,6 @@ static int sk_isa_open(struct net_device *dev)
        return tms380tr_open(dev);
 }
 
-#ifdef MODULE
-
 #define ISATR_MAX_ADAPTERS 3
 
 static int io[ISATR_MAX_ADAPTERS];
@@ -375,13 +351,23 @@ module_param_array(io, int, NULL, 0);
 module_param_array(irq, int, NULL, 0);
 module_param_array(dma, int, NULL, 0);
 
-static struct net_device *sk_isa_dev[ISATR_MAX_ADAPTERS];
+static struct platform_device *sk_isa_dev[ISATR_MAX_ADAPTERS];
 
-int init_module(void)
+static struct device_driver sk_isa_driver = {
+       .name           = "skisa",
+       .bus            = &platform_bus_type,
+};
+
+static int __init sk_isa_init(void)
 {
        struct net_device *dev;
+       struct platform_device *pdev;
        int i, num = 0, err = 0;
 
+       err = driver_register(&sk_isa_driver);
+       if (err)
+               return err;
+
        for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
                dev = alloc_trdev(sizeof(struct net_local));
                if (!dev)
@@ -390,12 +376,15 @@ int init_module(void)
                dev->base_addr = io[i];
                dev->irq = irq[i];
                dev->dma = dma[i];
-               err = setup_card(dev);
-
+               pdev = platform_device_register_simple("skisa",
+                       i, NULL, 0);
+               err = setup_card(dev, &pdev->dev);
                if (!err) {
-                       sk_isa_dev[i] = dev;
+                       sk_isa_dev[i] = pdev;
+                       dev_set_drvdata(&sk_isa_dev[i]->dev, dev);
                        ++num;
                } else {
+                       platform_device_unregister(pdev);
                        free_netdev(dev);
                }
        }
@@ -409,23 +398,28 @@ int init_module(void)
        return (0);
 }
 
-void cleanup_module(void)
+static void __exit sk_isa_cleanup(void)
 {
+       struct net_device *dev;
        int i;
 
        for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
-               struct net_device *dev = sk_isa_dev[i];
+               struct platform_device *pdev = sk_isa_dev[i];
 
-               if (!dev) 
+               if (!pdev)
                        continue;
-               
+               dev = dev_get_drvdata(&pdev->dev);
                unregister_netdev(dev);
                release_region(dev->base_addr, SK_ISA_IO_EXTENT);
                free_irq(dev->irq, dev);
                free_dma(dev->dma);
                tmsdev_term(dev);
                free_netdev(dev);
+               dev_set_drvdata(&pdev->dev, NULL);
+               platform_device_unregister(pdev);
        }
+       driver_unregister(&sk_isa_driver);
 }
-#endif /* MODULE */
 
+module_init(sk_isa_init);
+module_exit(sk_isa_cleanup);
index 5e0b0ce..2e39bf1 100644 (file)
@@ -62,6 +62,7 @@
  *                             normal operation.
  *     30-Dec-02       JF      Removed incorrect __init from 
  *                             tms380tr_init_card.
+ *     22-Jul-05       JF      Converted to dma-mapping.
  *                             
  *  To do:
  *    1. Multi/Broadcast packet handling (this may have fixed itself)
@@ -89,7 +90,7 @@ static const char version[] = "tms380tr.c: v1.10 30/12/2002 by Christoph Goos, A
 #include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -114,8 +115,6 @@ static const char version[] = "tms380tr.c: v1.10 30/12/2002 by Christoph Goos, A
 #endif
 static unsigned int tms380tr_debug = TMS380TR_DEBUG;
 
-static struct device tms_device;
-
 /* Index to functions, as function prototypes.
  * Alphabetical by function name.
  */
@@ -434,7 +433,7 @@ static void tms380tr_init_net_local(struct net_device *dev)
                        skb_put(tp->Rpl[i].Skb, tp->MaxPacketSize);
 
                        /* data unreachable for DMA ? then use local buffer */
-                       dmabuf = pci_map_single(tp->pdev, tp->Rpl[i].Skb->data, tp->MaxPacketSize, PCI_DMA_FROMDEVICE);
+                       dmabuf = dma_map_single(tp->pdev, tp->Rpl[i].Skb->data, tp->MaxPacketSize, DMA_FROM_DEVICE);
                        if(tp->dmalimit && (dmabuf + tp->MaxPacketSize > tp->dmalimit))
                        {
                                tp->Rpl[i].SkbStat = SKB_DATA_COPY;
@@ -638,10 +637,10 @@ static int tms380tr_hardware_send_packet(struct sk_buff *skb, struct net_device
        /* Is buffer reachable for Busmaster-DMA? */
 
        length  = skb->len;
-       dmabuf = pci_map_single(tp->pdev, skb->data, length, PCI_DMA_TODEVICE);
+       dmabuf = dma_map_single(tp->pdev, skb->data, length, DMA_TO_DEVICE);
        if(tp->dmalimit && (dmabuf + length > tp->dmalimit)) {
                /* Copy frame to local buffer */
-               pci_unmap_single(tp->pdev, dmabuf, length, PCI_DMA_TODEVICE);
+               dma_unmap_single(tp->pdev, dmabuf, length, DMA_TO_DEVICE);
                dmabuf  = 0;
                i       = tp->TplFree->TPLIndex;
                buf     = tp->LocalTxBuffers[i];
@@ -1284,9 +1283,7 @@ static int tms380tr_reset_adapter(struct net_device *dev)
        unsigned short count, c, count2;
        const struct firmware *fw_entry = NULL;
 
-       strncpy(tms_device.bus_id,dev->name, BUS_ID_SIZE);
-
-       if (request_firmware(&fw_entry, "tms380tr.bin", &tms_device) != 0) {
+       if (request_firmware(&fw_entry, "tms380tr.bin", tp->pdev) != 0) {
                printk(KERN_ALERT "%s: firmware %s is missing, cannot start.\n",
                        dev->name, "tms380tr.bin");
                return (-1);
@@ -2021,7 +2018,7 @@ static void tms380tr_cancel_tx_queue(struct net_local* tp)
 
                printk(KERN_INFO "Cancel tx (%08lXh).\n", (unsigned long)tpl);
                if (tpl->DMABuff)
-                       pci_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, PCI_DMA_TODEVICE);
+                       dma_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, DMA_TO_DEVICE);
                dev_kfree_skb_any(tpl->Skb);
        }
 
@@ -2090,7 +2087,7 @@ static void tms380tr_tx_status_irq(struct net_device *dev)
 
                tp->MacStat.tx_packets++;
                if (tpl->DMABuff)
-                       pci_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, PCI_DMA_TODEVICE);
+                       dma_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, DMA_TO_DEVICE);
                dev_kfree_skb_irq(tpl->Skb);
                tpl->BusyFlag = 0;      /* "free" TPL */
        }
@@ -2209,7 +2206,7 @@ static void tms380tr_rcv_status_irq(struct net_device *dev)
                                tp->MacStat.rx_errors++;
                }
                if (rpl->DMABuff)
-                       pci_unmap_single(tp->pdev, rpl->DMABuff, tp->MaxPacketSize, PCI_DMA_TODEVICE);
+                       dma_unmap_single(tp->pdev, rpl->DMABuff, tp->MaxPacketSize, DMA_TO_DEVICE);
                rpl->DMABuff = 0;
 
                /* Allocate new skb for rpl */
@@ -2227,7 +2224,7 @@ static void tms380tr_rcv_status_irq(struct net_device *dev)
                        skb_put(rpl->Skb, tp->MaxPacketSize);
 
                        /* Data unreachable for DMA ? then use local buffer */
-                       dmabuf = pci_map_single(tp->pdev, rpl->Skb->data, tp->MaxPacketSize, PCI_DMA_FROMDEVICE);
+                       dmabuf = dma_map_single(tp->pdev, rpl->Skb->data, tp->MaxPacketSize, DMA_FROM_DEVICE);
                        if(tp->dmalimit && (dmabuf + tp->MaxPacketSize > tp->dmalimit))
                        {
                                rpl->SkbStat = SKB_DATA_COPY;
@@ -2332,23 +2329,26 @@ void tmsdev_term(struct net_device *dev)
        struct net_local *tp;
 
        tp = netdev_priv(dev);
-       pci_unmap_single(tp->pdev, tp->dmabuffer, sizeof(struct net_local),
-               PCI_DMA_BIDIRECTIONAL);
+       dma_unmap_single(tp->pdev, tp->dmabuffer, sizeof(struct net_local),
+               DMA_BIDIRECTIONAL);
 }
 
-int tmsdev_init(struct net_device *dev, unsigned long dmalimit, 
-               struct pci_dev *pdev)
+int tmsdev_init(struct net_device *dev, struct device *pdev)
 {
        struct net_local *tms_local;
 
        memset(dev->priv, 0, sizeof(struct net_local));
        tms_local = netdev_priv(dev);
        init_waitqueue_head(&tms_local->wait_for_tok_int);
-       tms_local->dmalimit = dmalimit;
+       if (pdev->dma_mask)
+               tms_local->dmalimit = *pdev->dma_mask;
+       else
+               return -ENOMEM;
        tms_local->pdev = pdev;
-       tms_local->dmabuffer = pci_map_single(pdev, (void *)tms_local,
-           sizeof(struct net_local), PCI_DMA_BIDIRECTIONAL);
-       if (tms_local->dmabuffer + sizeof(struct net_local) > dmalimit)
+       tms_local->dmabuffer = dma_map_single(pdev, (void *)tms_local,
+           sizeof(struct net_local), DMA_BIDIRECTIONAL);
+       if (tms_local->dmabuffer + sizeof(struct net_local) > 
+                       tms_local->dmalimit)
        {
                printk(KERN_INFO "%s: Memory not accessible for DMA\n",
                        dev->name);
@@ -2370,8 +2370,6 @@ int tmsdev_init(struct net_device *dev, unsigned long dmalimit,
        return 0;
 }
 
-#ifdef MODULE
-
 EXPORT_SYMBOL(tms380tr_open);
 EXPORT_SYMBOL(tms380tr_close);
 EXPORT_SYMBOL(tms380tr_interrupt);
@@ -2379,6 +2377,8 @@ EXPORT_SYMBOL(tmsdev_init);
 EXPORT_SYMBOL(tmsdev_term);
 EXPORT_SYMBOL(tms380tr_wait);
 
+#ifdef MODULE
+
 static struct module *TMS380_module = NULL;
 
 int init_module(void)
index f2c5ba0..30452c6 100644 (file)
@@ -17,8 +17,7 @@
 int tms380tr_open(struct net_device *dev);
 int tms380tr_close(struct net_device *dev);
 irqreturn_t tms380tr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-int tmsdev_init(struct net_device *dev, unsigned long dmalimit,
-               struct pci_dev *pdev);
+int tmsdev_init(struct net_device *dev, struct device *pdev);
 void tmsdev_term(struct net_device *dev);
 void tms380tr_wait(unsigned long time);
 
@@ -719,7 +718,7 @@ struct s_TPL {      /* Transmit Parameter List (align on even word boundaries) */
        struct sk_buff *Skb;
        unsigned char TPLIndex;
        volatile unsigned char BusyFlag;/* Flag: TPL busy? */
-       dma_addr_t DMABuff;             /* DMA IO bus address from pci_map */
+       dma_addr_t DMABuff;             /* DMA IO bus address from dma_map */
 };
 
 /* ---------------------Receive Functions-------------------------------*
@@ -1060,7 +1059,7 @@ struct s_RPL {    /* Receive Parameter List */
        struct sk_buff *Skb;
        SKB_STAT SkbStat;
        int RPLIndex;
-       dma_addr_t DMABuff;             /* DMA IO bus address from pci_map */
+       dma_addr_t DMABuff;             /* DMA IO bus address from dma_map */
 };
 
 /* Information that need to be kept for each board. */
@@ -1091,7 +1090,7 @@ typedef struct net_local {
        RPL *RplTail;
        unsigned char LocalRxBuffers[RPL_NUM][DEFAULT_PACKET_SIZE];
 
-       struct pci_dev *pdev;
+       struct device *pdev;
        int DataRate;
        unsigned char ScbInUse;
        unsigned short CMDqueue;
index 2e18c0a..ab47c05 100644 (file)
@@ -100,7 +100,7 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic
        unsigned int pci_irq_line;
        unsigned long pci_ioaddr;
        struct card_info *cardinfo = &card_info_table[ent->driver_data];
-               
+
        if (versionprinted++ == 0)
                printk("%s", version);
 
@@ -143,7 +143,7 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic
                printk(":%2.2x", dev->dev_addr[i]);
        printk("\n");
                
-       ret = tmsdev_init(dev, PCI_MAX_ADDRESS, pdev);
+       ret = tmsdev_init(dev, &pdev->dev);
        if (ret) {
                printk("%s: unable to get memory for dev->priv.\n", dev->name);
                goto err_out_irq;
index e2cdaf8..8c9634a 100644 (file)
@@ -135,6 +135,18 @@ config DM9102
          <file:Documentation/networking/net-modules.txt>.  The module will
          be called dmfe.
 
+config ULI526X
+       tristate "ULi M526x controller support"
+       depends on NET_TULIP && PCI
+       select CRC32
+       ---help---
+         This driver is for ULi M5261/M5263 10/100M Ethernet Controller
+         (<http://www.uli.com.tw/>).
+
+         To compile this driver as a module, choose M here and read
+         <file:Documentation/networking/net-modules.txt>.  The module will
+         be called uli526x.
+         
 config PCMCIA_XIRCOM
        tristate "Xircom CardBus support (new driver)"
        depends on NET_TULIP && CARDBUS
index 8bb9b46..451090d 100644 (file)
@@ -9,6 +9,7 @@ obj-$(CONFIG_WINBOND_840)       += winbond-840.o
 obj-$(CONFIG_DE2104X)          += de2104x.o
 obj-$(CONFIG_TULIP)            += tulip.o
 obj-$(CONFIG_DE4X5)            += de4x5.o
+obj-$(CONFIG_ULI526X)          += uli526x.o
 
 # Declare multi-part drivers.
 
index e26c31f..f53396f 100644 (file)
@@ -81,25 +81,6 @@ int tulip_mdio_read(struct net_device *dev, int phy_id, int location)
                return retval & 0xffff;
        }
 
-       if(tp->chip_id == ULI526X && tp->revision >= 0x40) {
-               int value;
-               int i = 1000;
-               
-               value = ioread32(ioaddr + CSR9);
-               iowrite32(value & 0xFFEFFFFF, ioaddr + CSR9);
-               
-               value = (phy_id << 21) | (location << 16) | 0x08000000;
-               iowrite32(value, ioaddr + CSR10);
-               
-               while(--i > 0) {
-                       mdio_delay();
-                       if(ioread32(ioaddr + CSR10) & 0x10000000)
-                               break;
-               }
-               retval = ioread32(ioaddr + CSR10);
-               spin_unlock_irqrestore(&tp->mii_lock, flags);
-               return retval & 0xFFFF;
-       }
        /* Establish sync by sending at least 32 logic ones. */
        for (i = 32; i >= 0; i--) {
                iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
@@ -159,23 +140,6 @@ void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val)
                spin_unlock_irqrestore(&tp->mii_lock, flags);
                return;
        }
-       if (tp->chip_id == ULI526X && tp->revision >= 0x40) {
-               int value;
-               int i = 1000;
-               
-               value = ioread32(ioaddr + CSR9);
-               iowrite32(value & 0xFFEFFFFF, ioaddr + CSR9);
-               
-               value = (phy_id << 21) | (location << 16) | 0x04000000 | (val & 0xFFFF);
-               iowrite32(value, ioaddr + CSR10);
-               
-               while(--i > 0) {
-                       if (ioread32(ioaddr + CSR10) & 0x10000000)
-                               break;
-               }
-               spin_unlock_irqrestore(&tp->mii_lock, flags);
-               return;
-       }
                
        /* Establish sync by sending 32 logic ones. */
        for (i = 32; i >= 0; i--) {
index 6915682..e058a9f 100644 (file)
@@ -39,7 +39,6 @@ void tulip_timer(unsigned long data)
        case MX98713:
        case COMPEX9881:
        case DM910X:
-       case ULI526X:
        default: {
                struct medialeaf *mleaf;
                unsigned char *p;
index 20346d8..05d2d96 100644 (file)
@@ -88,7 +88,6 @@ enum chips {
        I21145,
        DM910X,
        CONEXANT,
-       ULI526X
 };
 
 
@@ -482,11 +481,8 @@ static inline void tulip_stop_rxtx(struct tulip_private *tp)
 
 static inline void tulip_restart_rxtx(struct tulip_private *tp)
 {
-       if(!(tp->chip_id == ULI526X && 
-               (tp->revision == 0x40 || tp->revision == 0x50))) {
-               tulip_stop_rxtx(tp);
-               udelay(5);
-       }
+       tulip_stop_rxtx(tp);
+       udelay(5);
        tulip_start_rxtx(tp);
 }
 
index d45d8f5..05da5be 100644 (file)
@@ -199,9 +199,6 @@ struct tulip_chip_table tulip_tbl[] = {
   { "Conexant LANfinity", 256, 0x0001ebef,
        HAS_MII | HAS_ACPI, tulip_timer },
 
-   /* ULi526X */
-   { "ULi M5261/M5263", 128, 0x0001ebef,
-        HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI, tulip_timer },
 };
 
 
@@ -239,8 +236,6 @@ static struct pci_device_id tulip_pci_tbl[] = {
        { 0x1737, 0xAB09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
        { 0x1737, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
        { 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
-       { 0x10b9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X },      /* ALi 1563 integrated ethernet */
-       { 0x10b9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X },      /* ALi 1563 integrated ethernet */
        { 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */
        { 0x14ea, 0xab08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Planex FNW-3602-TX */
        { } /* terminate list */
@@ -522,7 +517,7 @@ static void tulip_tx_timeout(struct net_device *dev)
                                   dev->name);
        } else if (tp->chip_id == DC21140 || tp->chip_id == DC21142
                           || tp->chip_id == MX98713 || tp->chip_id == COMPEX9881
-                          || tp->chip_id == DM910X || tp->chip_id == ULI526X) {
+                          || tp->chip_id == DM910X) {
                printk(KERN_WARNING "%s: 21140 transmit timed out, status %8.8x, "
                           "SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n",
                           dev->name, ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12),
@@ -1103,18 +1098,16 @@ static void set_rx_mode(struct net_device *dev)
                        entry = tp->cur_tx++ % TX_RING_SIZE;
 
                        if (entry != 0) {
-                               /* Avoid a chip errata by prefixing a dummy entry. Don't do
-                                  this on the ULI526X as it triggers a different problem */
-                               if (!(tp->chip_id == ULI526X && (tp->revision == 0x40 || tp->revision == 0x50))) {
-                                       tp->tx_buffers[entry].skb = NULL;
-                                       tp->tx_buffers[entry].mapping = 0;
-                                       tp->tx_ring[entry].length =
-                                               (entry == TX_RING_SIZE-1) ? cpu_to_le32(DESC_RING_WRAP) : 0;
-                                       tp->tx_ring[entry].buffer1 = 0;
-                                       /* Must set DescOwned later to avoid race with chip */
-                                       dummy = entry;
-                                       entry = tp->cur_tx++ % TX_RING_SIZE;
-                               }
+                               /* Avoid a chip errata by prefixing a dummy entry. */
+                               tp->tx_buffers[entry].skb = NULL;
+                               tp->tx_buffers[entry].mapping = 0;
+                               tp->tx_ring[entry].length =
+                                       (entry == TX_RING_SIZE-1) ? cpu_to_le32(DESC_RING_WRAP) : 0;
+                               tp->tx_ring[entry].buffer1 = 0;
+                               /* Must set DescOwned later to avoid race with chip */
+                               dummy = entry;
+                               entry = tp->cur_tx++ % TX_RING_SIZE;
+
                        }
 
                        tp->tx_buffers[entry].skb = NULL;
@@ -1235,10 +1228,6 @@ static int tulip_uli_dm_quirk(struct pci_dev *pdev)
 {
        if (pdev->vendor == 0x1282 && pdev->device == 0x9102)
                return 1;
-       if (pdev->vendor == 0x10b9 && pdev->device == 0x5261)
-               return 1;
-       if (pdev->vendor == 0x10b9 && pdev->device == 0x5263)
-               return 1;
        return 0;
 }
 
@@ -1680,7 +1669,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
        switch (chip_idx) {
        case DC21140:
        case DM910X:
-       case ULI526X:
        default:
                if (tp->mtable)
                        iowrite32(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
new file mode 100644 (file)
index 0000000..5ae22b7
--- /dev/null
@@ -0,0 +1,1749 @@
+/*
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License
+    as published by the Free Software Foundation; either version 2
+    of the License, or (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    
+*/
+
+#define DRV_NAME       "uli526x"
+#define DRV_VERSION    "0.9.3"
+#define DRV_RELDATE    "2005-7-29"
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+
+#include <asm/processor.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/uaccess.h>
+
+
+/* Board/System/Debug information/definition ---------------- */
+#define PCI_ULI5261_ID  0x526110B9     /* ULi M5261 ID*/
+#define PCI_ULI5263_ID  0x526310B9     /* ULi M5263 ID*/
+
+#define ULI526X_IO_SIZE 0x100
+#define TX_DESC_CNT     0x20            /* Allocated Tx descriptors */
+#define RX_DESC_CNT     0x30            /* Allocated Rx descriptors */
+#define TX_FREE_DESC_CNT (TX_DESC_CNT - 2)     /* Max TX packet count */
+#define TX_WAKE_DESC_CNT (TX_DESC_CNT - 3)     /* TX wakeup count */
+#define DESC_ALL_CNT    (TX_DESC_CNT + RX_DESC_CNT)
+#define TX_BUF_ALLOC    0x600
+#define RX_ALLOC_SIZE   0x620
+#define ULI526X_RESET    1
+#define CR0_DEFAULT     0
+#define CR6_DEFAULT     0x22200000
+#define CR7_DEFAULT     0x180c1
+#define CR15_DEFAULT    0x06            /* TxJabber RxWatchdog */
+#define TDES0_ERR_MASK  0x4302          /* TXJT, LC, EC, FUE */
+#define MAX_PACKET_SIZE 1514
+#define ULI5261_MAX_MULTICAST 14
+#define RX_COPY_SIZE   100
+#define MAX_CHECK_PACKET 0x8000
+
+#define ULI526X_10MHF      0
+#define ULI526X_100MHF     1
+#define ULI526X_10MFD      4
+#define ULI526X_100MFD     5
+#define ULI526X_AUTO       8
+
+#define ULI526X_TXTH_72        0x400000        /* TX TH 72 byte */
+#define ULI526X_TXTH_96        0x404000        /* TX TH 96 byte */
+#define ULI526X_TXTH_128       0x0000          /* TX TH 128 byte */
+#define ULI526X_TXTH_256       0x4000          /* TX TH 256 byte */
+#define ULI526X_TXTH_512       0x8000          /* TX TH 512 byte */
+#define ULI526X_TXTH_1K        0xC000          /* TX TH 1K  byte */
+
+#define ULI526X_TIMER_WUT  (jiffies + HZ * 1)/* timer wakeup time : 1 second */
+#define ULI526X_TX_TIMEOUT ((16*HZ)/2) /* tx packet time-out time 8 s" */
+#define ULI526X_TX_KICK        (4*HZ/2)        /* tx packet Kick-out time 2 s" */
+
+#define ULI526X_DBUG(dbug_now, msg, value) if (uli526x_debug || (dbug_now)) printk(KERN_ERR DRV_NAME ": %s %lx\n", (msg), (long) (value))
+
+#define SHOW_MEDIA_TYPE(mode) printk(KERN_ERR DRV_NAME ": Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half");
+
+
+/* CR9 definition: SROM/MII */
+#define CR9_SROM_READ   0x4800
+#define CR9_SRCS        0x1
+#define CR9_SRCLK       0x2
+#define CR9_CRDOUT      0x8
+#define SROM_DATA_0     0x0
+#define SROM_DATA_1     0x4
+#define PHY_DATA_1      0x20000
+#define PHY_DATA_0      0x00000
+#define MDCLKH          0x10000
+
+#define PHY_POWER_DOWN 0x800
+
+#define SROM_V41_CODE   0x14
+
+#define SROM_CLK_WRITE(data, ioaddr)                                   \
+               outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);               \
+               udelay(5);                                              \
+               outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK,ioaddr);     \
+               udelay(5);                                              \
+               outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);               \
+               udelay(5);
+
+/* Structure/enum declaration ------------------------------- */
+struct tx_desc {
+        u32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */
+        char *tx_buf_ptr;               /* Data for us */
+        struct tx_desc *next_tx_desc;
+} __attribute__(( aligned(32) ));
+
+struct rx_desc {
+       u32 rdes0, rdes1, rdes2, rdes3; /* Data for the card */
+       struct sk_buff *rx_skb_ptr;     /* Data for us */
+       struct rx_desc *next_rx_desc;
+} __attribute__(( aligned(32) ));
+
+struct uli526x_board_info {
+       u32 chip_id;                    /* Chip vendor/Device ID */
+       struct net_device *next_dev;    /* next device */
+       struct pci_dev *pdev;           /* PCI device */
+       spinlock_t lock;
+
+       long ioaddr;                    /* I/O base address */
+       u32 cr0_data;
+       u32 cr5_data;
+       u32 cr6_data;
+       u32 cr7_data;
+       u32 cr15_data;
+
+       /* pointer for memory physical address */
+       dma_addr_t buf_pool_dma_ptr;    /* Tx buffer pool memory */
+       dma_addr_t buf_pool_dma_start;  /* Tx buffer pool align dword */
+       dma_addr_t desc_pool_dma_ptr;   /* descriptor pool memory */
+       dma_addr_t first_tx_desc_dma;
+       dma_addr_t first_rx_desc_dma;
+
+       /* descriptor pointer */
+       unsigned char *buf_pool_ptr;    /* Tx buffer pool memory */
+       unsigned char *buf_pool_start;  /* Tx buffer pool align dword */
+       unsigned char *desc_pool_ptr;   /* descriptor pool memory */
+       struct tx_desc *first_tx_desc;
+       struct tx_desc *tx_insert_ptr;
+       struct tx_desc *tx_remove_ptr;
+       struct rx_desc *first_rx_desc;
+       struct rx_desc *rx_insert_ptr;
+       struct rx_desc *rx_ready_ptr;   /* packet come pointer */
+       unsigned long tx_packet_cnt;    /* transmitted packet count */
+       unsigned long rx_avail_cnt;     /* available rx descriptor count */
+       unsigned long interval_rx_cnt;  /* rx packet count a callback time */
+
+       u16 dbug_cnt;
+       u16 NIC_capability;             /* NIC media capability */
+       u16 PHY_reg4;                   /* Saved Phyxcer register 4 value */
+
+       u8 media_mode;                  /* user specify media mode */
+       u8 op_mode;                     /* real work media mode */
+       u8 phy_addr;
+       u8 link_failed;                 /* Ever link failed */
+       u8 wait_reset;                  /* Hardware failed, need to reset */
+       struct timer_list timer;
+
+       /* System defined statistic counter */
+       struct net_device_stats stats;
+
+       /* Driver defined statistic counter */
+       unsigned long tx_fifo_underrun;
+       unsigned long tx_loss_carrier;
+       unsigned long tx_no_carrier;
+       unsigned long tx_late_collision;
+       unsigned long tx_excessive_collision;
+       unsigned long tx_jabber_timeout;
+       unsigned long reset_count;
+       unsigned long reset_cr8;
+       unsigned long reset_fatal;
+       unsigned long reset_TXtimeout;
+
+       /* NIC SROM data */
+       unsigned char srom[128];
+       u8 init;        
+};
+
+enum uli526x_offsets {
+       DCR0 = 0x00, DCR1 = 0x08, DCR2 = 0x10, DCR3 = 0x18, DCR4 = 0x20,
+       DCR5 = 0x28, DCR6 = 0x30, DCR7 = 0x38, DCR8 = 0x40, DCR9 = 0x48,
+       DCR10 = 0x50, DCR11 = 0x58, DCR12 = 0x60, DCR13 = 0x68, DCR14 = 0x70,
+       DCR15 = 0x78
+};
+
+enum uli526x_CR6_bits {
+       CR6_RXSC = 0x2, CR6_PBF = 0x8, CR6_PM = 0x40, CR6_PAM = 0x80,
+       CR6_FDM = 0x200, CR6_TXSC = 0x2000, CR6_STI = 0x100000,
+       CR6_SFT = 0x200000, CR6_RXA = 0x40000000, CR6_NO_PURGE = 0x20000000
+};
+
+/* Global variable declaration ----------------------------- */
+static int __devinitdata printed_version;
+static char version[] __devinitdata =
+       KERN_INFO DRV_NAME ": ULi M5261/M5263 net driver, version "
+       DRV_VERSION " (" DRV_RELDATE ")\n";
+
+static int uli526x_debug;
+static unsigned char uli526x_media_mode = ULI526X_AUTO;
+static u32 uli526x_cr6_user_set;
+
+/* For module input parameter */
+static int debug;
+static u32 cr6set;
+static unsigned char mode = 8;
+
+/* function declaration ------------------------------------- */
+static int uli526x_open(struct net_device *);
+static int uli526x_start_xmit(struct sk_buff *, struct net_device *);
+static int uli526x_stop(struct net_device *);
+static struct net_device_stats * uli526x_get_stats(struct net_device *);
+static void uli526x_set_filter_mode(struct net_device *);
+static struct ethtool_ops netdev_ethtool_ops;
+static u16 read_srom_word(long, int);
+static irqreturn_t uli526x_interrupt(int, void *, struct pt_regs *);
+static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long);
+static void allocate_rx_buffer(struct uli526x_board_info *);
+static void update_cr6(u32, unsigned long);
+static void send_filter_frame(struct net_device *, int);
+static u16 phy_read(unsigned long, u8, u8, u32);
+static u16 phy_readby_cr10(unsigned long, u8, u8);
+static void phy_write(unsigned long, u8, u8, u16, u32);
+static void phy_writeby_cr10(unsigned long, u8, u8, u16);
+static void phy_write_1bit(unsigned long, u32, u32);
+static u16 phy_read_1bit(unsigned long, u32);
+static u8 uli526x_sense_speed(struct uli526x_board_info *);
+static void uli526x_process_mode(struct uli526x_board_info *);
+static void uli526x_timer(unsigned long);
+static void uli526x_rx_packet(struct net_device *, struct uli526x_board_info *);
+static void uli526x_free_tx_pkt(struct net_device *, struct uli526x_board_info *);
+static void uli526x_reuse_skb(struct uli526x_board_info *, struct sk_buff *);
+static void uli526x_dynamic_reset(struct net_device *);
+static void uli526x_free_rxbuffer(struct uli526x_board_info *);
+static void uli526x_init(struct net_device *);
+static void uli526x_set_phyxcer(struct uli526x_board_info *);
+
+/* ULI526X network board routine ---------------------------- */
+
+/*
+ *     Search ULI526X board, allocate space and register it
+ */
+
+static int __devinit uli526x_init_one (struct pci_dev *pdev,
+                                   const struct pci_device_id *ent)
+{
+       struct uli526x_board_info *db;  /* board information structure */
+       struct net_device *dev;
+       int i, err;
+       
+       ULI526X_DBUG(0, "uli526x_init_one()", 0);
+
+       if (!printed_version++)
+               printk(version);
+
+       /* Init network device */
+       dev = alloc_etherdev(sizeof(*db));
+       if (dev == NULL)
+               return -ENOMEM;
+       SET_MODULE_OWNER(dev);
+       SET_NETDEV_DEV(dev, &pdev->dev);
+
+       if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+               printk(KERN_WARNING DRV_NAME ": 32-bit PCI DMA not available.\n");
+               err = -ENODEV;
+               goto err_out_free;
+       }
+
+       /* Enable Master/IO access, Disable memory access */
+       err = pci_enable_device(pdev);
+       if (err)
+               goto err_out_free;
+
+       if (!pci_resource_start(pdev, 0)) {
+               printk(KERN_ERR DRV_NAME ": I/O base is zero\n");
+               err = -ENODEV;
+               goto err_out_disable;
+       }
+
+       if (pci_resource_len(pdev, 0) < (ULI526X_IO_SIZE) ) {
+               printk(KERN_ERR DRV_NAME ": Allocated I/O size too small\n");
+               err = -ENODEV;
+               goto err_out_disable;
+       }
+
+       if (pci_request_regions(pdev, DRV_NAME)) {
+               printk(KERN_ERR DRV_NAME ": Failed to request PCI regions\n");
+               err = -ENODEV;
+               goto err_out_disable;
+       }
+
+       /* Init system & device */
+       db = netdev_priv(dev);
+
+       /* Allocate Tx/Rx descriptor memory */
+       db->desc_pool_ptr = pci_alloc_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, &db->desc_pool_dma_ptr);
+       if(db->desc_pool_ptr == NULL)
+       {
+               err = -ENOMEM;
+               goto err_out_nomem;
+       }
+       db->buf_pool_ptr = pci_alloc_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4, &db->buf_pool_dma_ptr);
+       if(db->buf_pool_ptr == NULL)
+       {
+               err = -ENOMEM;
+               goto err_out_nomem;
+       }
+       
+       db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr;
+       db->first_tx_desc_dma = db->desc_pool_dma_ptr;
+       db->buf_pool_start = db->buf_pool_ptr;
+       db->buf_pool_dma_start = db->buf_pool_dma_ptr;
+
+       db->chip_id = ent->driver_data;
+       db->ioaddr = pci_resource_start(pdev, 0);
+       
+       db->pdev = pdev;
+       db->init = 1;
+       
+       dev->base_addr = db->ioaddr;
+       dev->irq = pdev->irq;
+       pci_set_drvdata(pdev, dev);
+       
+       /* Register some necessary functions */
+       dev->open = &uli526x_open;
+       dev->hard_start_xmit = &uli526x_start_xmit;
+       dev->stop = &uli526x_stop;
+       dev->get_stats = &uli526x_get_stats;
+       dev->set_multicast_list = &uli526x_set_filter_mode;
+       dev->ethtool_ops = &netdev_ethtool_ops;
+       spin_lock_init(&db->lock);
+
+               
+       /* read 64 word srom data */
+       for (i = 0; i < 64; i++)
+               ((u16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr, i));
+
+       /* Set Node address */
+       if(((u16 *) db->srom)[0] == 0xffff || ((u16 *) db->srom)[0] == 0)               /* SROM absent, so read MAC address from ID Table */
+       {
+               outl(0x10000, db->ioaddr + DCR0);       //Diagnosis mode
+               outl(0x1c0, db->ioaddr + DCR13);        //Reset dianostic pointer port
+               outl(0, db->ioaddr + DCR14);            //Clear reset port
+               outl(0x10, db->ioaddr + DCR14);         //Reset ID Table pointer
+               outl(0, db->ioaddr + DCR14);            //Clear reset port
+               outl(0, db->ioaddr + DCR13);            //Clear CR13
+               outl(0x1b0, db->ioaddr + DCR13);        //Select ID Table access port
+               //Read MAC address from CR14
+               for (i = 0; i < 6; i++)
+                       dev->dev_addr[i] = inl(db->ioaddr + DCR14);
+               //Read end
+               outl(0, db->ioaddr + DCR13);    //Clear CR13
+               outl(0, db->ioaddr + DCR0);             //Clear CR0
+               udelay(10);
+       }
+       else            /*Exist SROM*/
+       {
+               for (i = 0; i < 6; i++)
+                       dev->dev_addr[i] = db->srom[20 + i];
+       }
+       err = register_netdev (dev);
+       if (err)
+               goto err_out_res;
+
+       printk(KERN_INFO "%s: ULi M%04lx at pci%s,",dev->name,ent->driver_data >> 16,pci_name(pdev));
+       
+       for (i = 0; i < 6; i++)
+               printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
+       printk(", irq %d.\n", dev->irq);
+
+       pci_set_master(pdev);
+
+       return 0;
+
+err_out_res:
+       pci_release_regions(pdev);
+err_out_nomem:
+       if(db->desc_pool_ptr)
+               pci_free_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20,
+                       db->desc_pool_ptr, db->desc_pool_dma_ptr);
+                       
+       if(db->buf_pool_ptr != NULL)
+               pci_free_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
+                       db->buf_pool_ptr, db->buf_pool_dma_ptr);
+err_out_disable:
+       pci_disable_device(pdev);
+err_out_free:
+       pci_set_drvdata(pdev, NULL);
+       free_netdev(dev);
+
+       return err;
+}
+
+
+static void __devexit uli526x_remove_one (struct pci_dev *pdev)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       struct uli526x_board_info *db = netdev_priv(dev);
+
+       ULI526X_DBUG(0, "uli526x_remove_one()", 0);
+
+       pci_free_consistent(db->pdev, sizeof(struct tx_desc) *
+                               DESC_ALL_CNT + 0x20, db->desc_pool_ptr,
+                               db->desc_pool_dma_ptr);
+       pci_free_consistent(db->pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
+                               db->buf_pool_ptr, db->buf_pool_dma_ptr);
+       unregister_netdev(dev);
+       pci_release_regions(pdev);
+       free_netdev(dev);       /* free board information */
+       pci_set_drvdata(pdev, NULL);
+       pci_disable_device(pdev);
+       ULI526X_DBUG(0, "uli526x_remove_one() exit", 0);
+}
+
+
+/*
+ *     Open the interface.
+ *     The interface is opened whenever "ifconfig" activates it.
+ */
+
+static int uli526x_open(struct net_device *dev)
+{
+       int ret;
+       struct uli526x_board_info *db = netdev_priv(dev);
+       
+       ULI526X_DBUG(0, "uli526x_open", 0);
+
+       ret = request_irq(dev->irq, &uli526x_interrupt, SA_SHIRQ, dev->name, dev);
+       if (ret)
+               return ret;
+
+       /* system variable init */
+       db->cr6_data = CR6_DEFAULT | uli526x_cr6_user_set;
+       db->tx_packet_cnt = 0;
+       db->rx_avail_cnt = 0;
+       db->link_failed = 1;
+       netif_carrier_off(dev);
+       db->wait_reset = 0;
+
+       db->NIC_capability = 0xf;       /* All capability*/
+       db->PHY_reg4 = 0x1e0;
+
+       /* CR6 operation mode decision */
+       db->cr6_data |= ULI526X_TXTH_256;
+       db->cr0_data = CR0_DEFAULT;
+       
+       /* Initialize ULI526X board */
+       uli526x_init(dev);
+
+       /* Active System Interface */
+       netif_wake_queue(dev);
+
+       /* set and active a timer process */
+       init_timer(&db->timer);
+       db->timer.expires = ULI526X_TIMER_WUT + HZ * 2;
+       db->timer.data = (unsigned long)dev;
+       db->timer.function = &uli526x_timer;
+       add_timer(&db->timer);
+
+       return 0;
+}
+
+
+/*     Initialize ULI526X board
+ *     Reset ULI526X board
+ *     Initialize TX/Rx descriptor chain structure
+ *     Send the set-up frame
+ *     Enable Tx/Rx machine
+ */
+
+static void uli526x_init(struct net_device *dev)
+{
+       struct uli526x_board_info *db = netdev_priv(dev);
+       unsigned long ioaddr = db->ioaddr;
+       u8      phy_tmp;
+       u16     phy_value;
+       u16 phy_reg_reset;
+
+       ULI526X_DBUG(0, "uli526x_init()", 0);
+
+       /* Reset M526x MAC controller */
+       outl(ULI526X_RESET, ioaddr + DCR0);     /* RESET MAC */
+       udelay(100);
+       outl(db->cr0_data, ioaddr + DCR0);
+       udelay(5);
+
+       /* Phy addr : In some boards,M5261/M5263 phy address != 1 */
+       db->phy_addr = 1;
+       for(phy_tmp=0;phy_tmp<32;phy_tmp++)
+       {
+               phy_value=phy_read(db->ioaddr,phy_tmp,3,db->chip_id);//peer add
+               if(phy_value != 0xffff&&phy_value!=0)
+               {
+                       db->phy_addr = phy_tmp;
+                       break;
+               }
+       }
+       if(phy_tmp == 32)
+               printk(KERN_WARNING "Can not find the phy address!!!");
+       /* Parser SROM and media mode */
+       db->media_mode = uli526x_media_mode;
+
+       /* Phyxcer capability setting */
+       phy_reg_reset = phy_read(db->ioaddr, db->phy_addr, 0, db->chip_id);
+       phy_reg_reset = (phy_reg_reset | 0x8000);
+       phy_write(db->ioaddr, db->phy_addr, 0, phy_reg_reset, db->chip_id);
+       udelay(500);
+
+       /* Process Phyxcer Media Mode */
+       uli526x_set_phyxcer(db);
+
+       /* Media Mode Process */
+       if ( !(db->media_mode & ULI526X_AUTO) )
+               db->op_mode = db->media_mode;   /* Force Mode */
+
+       /* Initialize Transmit/Receive decriptor and CR3/4 */
+       uli526x_descriptor_init(db, ioaddr);
+
+       /* Init CR6 to program M526X operation */
+       update_cr6(db->cr6_data, ioaddr);
+
+       /* Send setup frame */
+       send_filter_frame(dev, dev->mc_count);  /* M5261/M5263 */
+
+       /* Init CR7, interrupt active bit */
+       db->cr7_data = CR7_DEFAULT;
+       outl(db->cr7_data, ioaddr + DCR7);
+
+       /* Init CR15, Tx jabber and Rx watchdog timer */
+       outl(db->cr15_data, ioaddr + DCR15);
+
+       /* Enable ULI526X Tx/Rx function */
+       db->cr6_data |= CR6_RXSC | CR6_TXSC;
+       update_cr6(db->cr6_data, ioaddr);
+}
+
+
+/*
+ *     Hardware start transmission.
+ *     Send a packet to media from the upper layer.
+ */
+
+static int uli526x_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct uli526x_board_info *db = netdev_priv(dev);
+       struct tx_desc *txptr;
+       unsigned long flags;
+
+       ULI526X_DBUG(0, "uli526x_start_xmit", 0);
+
+       /* Resource flag check */
+       netif_stop_queue(dev);
+
+       /* Too large packet check */
+       if (skb->len > MAX_PACKET_SIZE) {
+               printk(KERN_ERR DRV_NAME ": big packet = %d\n", (u16)skb->len);
+               dev_kfree_skb(skb);
+               return 0;
+       }
+
+       spin_lock_irqsave(&db->lock, flags);
+
+       /* No Tx resource check, it never happen nromally */
+       if (db->tx_packet_cnt >= TX_FREE_DESC_CNT) {
+               spin_unlock_irqrestore(&db->lock, flags);
+               printk(KERN_ERR DRV_NAME ": No Tx resource %ld\n", db->tx_packet_cnt);
+               return 1;
+       }
+
+       /* Disable NIC interrupt */
+       outl(0, dev->base_addr + DCR7);
+
+       /* transmit this packet */
+       txptr = db->tx_insert_ptr;
+       memcpy(txptr->tx_buf_ptr, skb->data, skb->len);
+       txptr->tdes1 = cpu_to_le32(0xe1000000 | skb->len);
+
+       /* Point to next transmit free descriptor */
+       db->tx_insert_ptr = txptr->next_tx_desc;
+
+       /* Transmit Packet Process */
+       if ( (db->tx_packet_cnt < TX_DESC_CNT) ) {
+               txptr->tdes0 = cpu_to_le32(0x80000000); /* Set owner bit */
+               db->tx_packet_cnt++;                    /* Ready to send */
+               outl(0x1, dev->base_addr + DCR1);       /* Issue Tx polling */
+               dev->trans_start = jiffies;             /* saved time stamp */
+       }
+
+       /* Tx resource check */
+       if ( db->tx_packet_cnt < TX_FREE_DESC_CNT )
+               netif_wake_queue(dev);
+
+       /* Restore CR7 to enable interrupt */
+       spin_unlock_irqrestore(&db->lock, flags);
+       outl(db->cr7_data, dev->base_addr + DCR7);
+       
+       /* free this SKB */
+       dev_kfree_skb(skb);
+
+       return 0;
+}
+
+
+/*
+ *     Stop the interface.
+ *     The interface is stopped when it is brought.
+ */
+
+static int uli526x_stop(struct net_device *dev)
+{
+       struct uli526x_board_info *db = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+
+       ULI526X_DBUG(0, "uli526x_stop", 0);
+
+       /* disable system */
+       netif_stop_queue(dev);
+
+       /* deleted timer */
+       del_timer_sync(&db->timer);
+
+       /* Reset & stop ULI526X board */
+       outl(ULI526X_RESET, ioaddr + DCR0);
+       udelay(5);
+       phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id);
+
+       /* free interrupt */
+       free_irq(dev->irq, dev);
+
+       /* free allocated rx buffer */
+       uli526x_free_rxbuffer(db);
+
+#if 0
+       /* show statistic counter */
+       printk(DRV_NAME ": FU:%lx EC:%lx LC:%lx NC:%lx LOC:%lx TXJT:%lx RESET:%lx RCR8:%lx FAL:%lx TT:%lx\n",
+               db->tx_fifo_underrun, db->tx_excessive_collision,
+               db->tx_late_collision, db->tx_no_carrier, db->tx_loss_carrier,
+               db->tx_jabber_timeout, db->reset_count, db->reset_cr8,
+               db->reset_fatal, db->reset_TXtimeout);
+#endif
+
+       return 0;
+}
+
+
+/*
+ *     M5261/M5263 insterrupt handler
+ *     receive the packet to upper layer, free the transmitted packet
+ */
+
+static irqreturn_t uli526x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct net_device *dev = dev_id;
+       struct uli526x_board_info *db = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       unsigned long flags;
+
+       if (!dev) {
+               ULI526X_DBUG(1, "uli526x_interrupt() without DEVICE arg", 0);
+               return IRQ_NONE;
+       }
+
+       spin_lock_irqsave(&db->lock, flags);
+       outl(0, ioaddr + DCR7);
+
+       /* Got ULI526X status */
+       db->cr5_data = inl(ioaddr + DCR5);
+       outl(db->cr5_data, ioaddr + DCR5);
+       if ( !(db->cr5_data & 0x180c1) ) {
+               spin_unlock_irqrestore(&db->lock, flags);
+               outl(db->cr7_data, ioaddr + DCR7);
+               return IRQ_HANDLED;
+       }
+
+       /* Check system status */
+       if (db->cr5_data & 0x2000) {
+               /* system bus error happen */
+               ULI526X_DBUG(1, "System bus error happen. CR5=", db->cr5_data);
+               db->reset_fatal++;
+               db->wait_reset = 1;     /* Need to RESET */
+               spin_unlock_irqrestore(&db->lock, flags);
+               return IRQ_HANDLED;
+       }
+
+        /* Received the coming packet */
+       if ( (db->cr5_data & 0x40) && db->rx_avail_cnt )
+               uli526x_rx_packet(dev, db);
+
+       /* reallocate rx descriptor buffer */
+       if (db->rx_avail_cnt<RX_DESC_CNT)
+               allocate_rx_buffer(db);
+
+       /* Free the transmitted descriptor */
+       if ( db->cr5_data & 0x01)
+               uli526x_free_tx_pkt(dev, db);
+
+       /* Restore CR7 to enable interrupt mask */
+       outl(db->cr7_data, ioaddr + DCR7);
+
+       spin_unlock_irqrestore(&db->lock, flags);
+       return IRQ_HANDLED;
+}
+
+
+/*
+ *     Free TX resource after TX complete
+ */
+
+static void uli526x_free_tx_pkt(struct net_device *dev, struct uli526x_board_info * db)
+{
+       struct tx_desc *txptr;
+       u32 tdes0;
+
+       txptr = db->tx_remove_ptr;
+       while(db->tx_packet_cnt) {
+               tdes0 = le32_to_cpu(txptr->tdes0);
+               /* printk(DRV_NAME ": tdes0=%x\n", tdes0); */
+               if (tdes0 & 0x80000000)
+                       break;
+
+               /* A packet sent completed */
+               db->tx_packet_cnt--;
+               db->stats.tx_packets++;
+
+               /* Transmit statistic counter */
+               if ( tdes0 != 0x7fffffff ) {
+                       /* printk(DRV_NAME ": tdes0=%x\n", tdes0); */
+                       db->stats.collisions += (tdes0 >> 3) & 0xf;
+                       db->stats.tx_bytes += le32_to_cpu(txptr->tdes1) & 0x7ff;
+                       if (tdes0 & TDES0_ERR_MASK) {
+                               db->stats.tx_errors++;
+                               if (tdes0 & 0x0002) {   /* UnderRun */
+                                       db->tx_fifo_underrun++;
+                                       if ( !(db->cr6_data & CR6_SFT) ) {
+                                               db->cr6_data = db->cr6_data | CR6_SFT;
+                                               update_cr6(db->cr6_data, db->ioaddr);
+                                       }
+                               }
+                               if (tdes0 & 0x0100)
+                                       db->tx_excessive_collision++;
+                               if (tdes0 & 0x0200)
+                                       db->tx_late_collision++;
+                               if (tdes0 & 0x0400)
+                                       db->tx_no_carrier++;
+                               if (tdes0 & 0x0800)
+                                       db->tx_loss_carrier++;
+                               if (tdes0 & 0x4000)
+                                       db->tx_jabber_timeout++;
+                       }
+               }
+
+               txptr = txptr->next_tx_desc;
+       }/* End of while */
+
+       /* Update TX remove pointer to next */
+       db->tx_remove_ptr = txptr;
+
+       /* Resource available check */
+       if ( db->tx_packet_cnt < TX_WAKE_DESC_CNT )
+               netif_wake_queue(dev);  /* Active upper layer, send again */
+}
+
+
+/*
+ *     Receive the come packet and pass to upper layer
+ */
+
+static void uli526x_rx_packet(struct net_device *dev, struct uli526x_board_info * db)
+{
+       struct rx_desc *rxptr;
+       struct sk_buff *skb;
+       int rxlen;
+       u32 rdes0;
+       
+       rxptr = db->rx_ready_ptr;
+
+       while(db->rx_avail_cnt) {
+               rdes0 = le32_to_cpu(rxptr->rdes0);
+               if (rdes0 & 0x80000000) /* packet owner check */
+               {
+                       break;
+               }
+
+               db->rx_avail_cnt--;
+               db->interval_rx_cnt++;
+
+               pci_unmap_single(db->pdev, le32_to_cpu(rxptr->rdes2), RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE);
+               if ( (rdes0 & 0x300) != 0x300) {
+                       /* A packet without First/Last flag */
+                       /* reuse this SKB */
+                       ULI526X_DBUG(0, "Reuse SK buffer, rdes0", rdes0);
+                       uli526x_reuse_skb(db, rxptr->rx_skb_ptr);
+               } else {
+                       /* A packet with First/Last flag */
+                       rxlen = ( (rdes0 >> 16) & 0x3fff) - 4;
+
+                       /* error summary bit check */
+                       if (rdes0 & 0x8000) {
+                               /* This is a error packet */
+                               //printk(DRV_NAME ": rdes0: %lx\n", rdes0);
+                               db->stats.rx_errors++;
+                               if (rdes0 & 1)
+                                       db->stats.rx_fifo_errors++;
+                               if (rdes0 & 2)
+                                       db->stats.rx_crc_errors++;
+                               if (rdes0 & 0x80)
+                                       db->stats.rx_length_errors++;
+                       }
+
+                       if ( !(rdes0 & 0x8000) ||
+                               ((db->cr6_data & CR6_PM) && (rxlen>6)) ) {
+                               skb = rxptr->rx_skb_ptr;
+               
+                               /* Good packet, send to upper layer */
+                               /* Shorst packet used new SKB */
+                               if ( (rxlen < RX_COPY_SIZE) &&
+                                       ( (skb = dev_alloc_skb(rxlen + 2) )
+                                       != NULL) ) {
+                                       /* size less than COPY_SIZE, allocate a rxlen SKB */
+                                       skb->dev = dev;
+                                       skb_reserve(skb, 2); /* 16byte align */
+                                       memcpy(skb_put(skb, rxlen), rxptr->rx_skb_ptr->tail, rxlen);
+                                       uli526x_reuse_skb(db, rxptr->rx_skb_ptr);
+                               } else {
+                                       skb->dev = dev;
+                                       skb_put(skb, rxlen);
+                               }
+                               skb->protocol = eth_type_trans(skb, dev);
+                               netif_rx(skb);
+                               dev->last_rx = jiffies;
+                               db->stats.rx_packets++;
+                               db->stats.rx_bytes += rxlen;
+                               
+                       } else {
+                               /* Reuse SKB buffer when the packet is error */
+                               ULI526X_DBUG(0, "Reuse SK buffer, rdes0", rdes0);
+                               uli526x_reuse_skb(db, rxptr->rx_skb_ptr);
+                       }
+               }
+
+               rxptr = rxptr->next_rx_desc;
+       }
+
+       db->rx_ready_ptr = rxptr;
+}
+
+
+/*
+ *     Get statistics from driver.
+ */
+
+static struct net_device_stats * uli526x_get_stats(struct net_device *dev)
+{
+       struct uli526x_board_info *db = netdev_priv(dev);
+
+       ULI526X_DBUG(0, "uli526x_get_stats", 0);
+       return &db->stats;
+}
+
+
+/*
+ * Set ULI526X multicast address
+ */
+
+static void uli526x_set_filter_mode(struct net_device * dev)
+{
+       struct uli526x_board_info *db = dev->priv;
+       unsigned long flags;
+
+       ULI526X_DBUG(0, "uli526x_set_filter_mode()", 0);
+       spin_lock_irqsave(&db->lock, flags);
+
+       if (dev->flags & IFF_PROMISC) {
+               ULI526X_DBUG(0, "Enable PROM Mode", 0);
+               db->cr6_data |= CR6_PM | CR6_PBF;
+               update_cr6(db->cr6_data, db->ioaddr);
+               spin_unlock_irqrestore(&db->lock, flags);
+               return;
+       }
+
+       if (dev->flags & IFF_ALLMULTI || dev->mc_count > ULI5261_MAX_MULTICAST) {
+               ULI526X_DBUG(0, "Pass all multicast address", dev->mc_count);
+               db->cr6_data &= ~(CR6_PM | CR6_PBF);
+               db->cr6_data |= CR6_PAM;
+               spin_unlock_irqrestore(&db->lock, flags);
+               return;
+       }
+
+       ULI526X_DBUG(0, "Set multicast address", dev->mc_count);
+       send_filter_frame(dev, dev->mc_count);  /* M5261/M5263 */
+       spin_unlock_irqrestore(&db->lock, flags);
+}
+
+static void
+ULi_ethtool_gset(struct uli526x_board_info *db, struct ethtool_cmd *ecmd)
+{
+       ecmd->supported = (SUPPORTED_10baseT_Half |
+                          SUPPORTED_10baseT_Full |
+                          SUPPORTED_100baseT_Half |
+                          SUPPORTED_100baseT_Full |
+                          SUPPORTED_Autoneg |
+                          SUPPORTED_MII);
+               
+       ecmd->advertising = (ADVERTISED_10baseT_Half |
+                          ADVERTISED_10baseT_Full |
+                          ADVERTISED_100baseT_Half |
+                          ADVERTISED_100baseT_Full |
+                          ADVERTISED_Autoneg |
+                          ADVERTISED_MII);
+
+
+       ecmd->port = PORT_MII;
+       ecmd->phy_address = db->phy_addr;
+
+       ecmd->transceiver = XCVR_EXTERNAL;
+               
+       ecmd->speed = 10;
+       ecmd->duplex = DUPLEX_HALF;
+       
+       if(db->op_mode==ULI526X_100MHF || db->op_mode==ULI526X_100MFD)
+       {
+               ecmd->speed = 100;               
+       }
+       if(db->op_mode==ULI526X_10MFD || db->op_mode==ULI526X_100MFD)
+       {
+               ecmd->duplex = DUPLEX_FULL;
+       }
+       if(db->link_failed)
+       {
+               ecmd->speed = -1;
+               ecmd->duplex = -1;      
+       }
+       
+       if (db->media_mode & ULI526X_AUTO)
+       {       
+               ecmd->autoneg = AUTONEG_ENABLE;
+       }
+}
+
+static void netdev_get_drvinfo(struct net_device *dev,
+                              struct ethtool_drvinfo *info)
+{
+       struct uli526x_board_info *np = netdev_priv(dev);
+
+       strcpy(info->driver, DRV_NAME);
+       strcpy(info->version, DRV_VERSION);
+       if (np->pdev)
+               strcpy(info->bus_info, pci_name(np->pdev));
+       else
+               sprintf(info->bus_info, "EISA 0x%lx %d",
+                       dev->base_addr, dev->irq);
+}
+
+static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) {
+       struct uli526x_board_info *np = netdev_priv(dev);
+       
+       ULi_ethtool_gset(np, cmd);
+       
+       return 0;
+}
+
+static u32 netdev_get_link(struct net_device *dev) {
+       struct uli526x_board_info *np = netdev_priv(dev);
+               
+       if(np->link_failed)
+               return 0;
+       else
+               return 1;
+}
+
+static void uli526x_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+       wol->supported = WAKE_PHY | WAKE_MAGIC;
+       wol->wolopts = 0;
+}
+
+static struct ethtool_ops netdev_ethtool_ops = {
+       .get_drvinfo            = netdev_get_drvinfo,
+       .get_settings           = netdev_get_settings,
+       .get_link               = netdev_get_link,
+       .get_wol                = uli526x_get_wol,
+};
+
+/*
+ *     A periodic timer routine
+ *     Dynamic media sense, allocate Rx buffer...
+ */
+
+static void uli526x_timer(unsigned long data)
+{
+       u32 tmp_cr8;
+       unsigned char tmp_cr12=0;
+       struct net_device *dev = (struct net_device *) data;
+       struct uli526x_board_info *db = netdev_priv(dev);
+       unsigned long flags;
+       u8 TmpSpeed=10;
+       
+       //ULI526X_DBUG(0, "uli526x_timer()", 0);
+       spin_lock_irqsave(&db->lock, flags);
+
+       
+       /* Dynamic reset ULI526X : system error or transmit time-out */
+       tmp_cr8 = inl(db->ioaddr + DCR8);
+       if ( (db->interval_rx_cnt==0) && (tmp_cr8) ) {
+               db->reset_cr8++;
+               db->wait_reset = 1;
+       }
+       db->interval_rx_cnt = 0;
+
+       /* TX polling kick monitor */
+       if ( db->tx_packet_cnt &&
+            time_after(jiffies, dev->trans_start + ULI526X_TX_KICK) ) {
+               outl(0x1, dev->base_addr + DCR1);   // Tx polling again 
+
+               // TX Timeout 
+               if ( time_after(jiffies, dev->trans_start + ULI526X_TX_TIMEOUT) ) {
+                       db->reset_TXtimeout++;
+                       db->wait_reset = 1;
+                       printk( "%s: Tx timeout - resetting\n",
+                              dev->name);
+               }
+       }
+
+       if (db->wait_reset) {
+               ULI526X_DBUG(0, "Dynamic Reset device", db->tx_packet_cnt);
+               db->reset_count++;
+               uli526x_dynamic_reset(dev);
+               db->timer.expires = ULI526X_TIMER_WUT;
+               add_timer(&db->timer);
+               spin_unlock_irqrestore(&db->lock, flags);
+               return;
+       }
+
+       /* Link status check, Dynamic media type change */
+       if((phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id) & 0x01e0)!=0)
+               tmp_cr12 = 3;
+
+       if ( !(tmp_cr12 & 0x3) && !db->link_failed ) {
+               /* Link Failed */
+               ULI526X_DBUG(0, "Link Failed", tmp_cr12);
+               netif_carrier_off(dev);
+               printk(KERN_INFO "uli526x: %s NIC Link is Down\n",dev->name);
+               db->link_failed = 1;
+
+               /* For Force 10/100M Half/Full mode: Enable Auto-Nego mode */
+               /* AUTO don't need */
+               if ( !(db->media_mode & 0x8) )
+                       phy_write(db->ioaddr, db->phy_addr, 0, 0x1000, db->chip_id);
+
+               /* AUTO mode, if INT phyxcer link failed, select EXT device */
+               if (db->media_mode & ULI526X_AUTO) {
+                       db->cr6_data&=~0x00000200;      /* bit9=0, HD mode */
+                       update_cr6(db->cr6_data, db->ioaddr);
+               }
+       } else
+               if ((tmp_cr12 & 0x3) && db->link_failed) {
+                       ULI526X_DBUG(0, "Link link OK", tmp_cr12);
+                       db->link_failed = 0;
+
+                       /* Auto Sense Speed */
+                       if ( (db->media_mode & ULI526X_AUTO) &&
+                               uli526x_sense_speed(db) )
+                               db->link_failed = 1;
+                       uli526x_process_mode(db);
+                       
+                       if(db->link_failed==0)
+                       {
+                               if(db->op_mode==ULI526X_100MHF || db->op_mode==ULI526X_100MFD)
+                               {
+                                       TmpSpeed = 100;
+                               }
+                               if(db->op_mode==ULI526X_10MFD || db->op_mode==ULI526X_100MFD)
+                               {
+                                       printk(KERN_INFO "uli526x: %s NIC Link is Up %d Mbps Full duplex\n",dev->name,TmpSpeed);
+                               }
+                               else
+                               {
+                                       printk(KERN_INFO "uli526x: %s NIC Link is Up %d Mbps Half duplex\n",dev->name,TmpSpeed);
+                               }
+                               netif_carrier_on(dev);
+                       }
+                       /* SHOW_MEDIA_TYPE(db->op_mode); */
+               }
+               else if(!(tmp_cr12 & 0x3) && db->link_failed)
+               {
+                       if(db->init==1)
+                       {
+                               printk(KERN_INFO "uli526x: %s NIC Link is Down\n",dev->name);
+                               netif_carrier_off(dev);
+                       }
+               }
+               db->init=0;
+
+       /* Timer active again */
+       db->timer.expires = ULI526X_TIMER_WUT;
+       add_timer(&db->timer);
+       spin_unlock_irqrestore(&db->lock, flags);
+}
+
+
+/*
+ *     Dynamic reset the ULI526X board
+ *     Stop ULI526X board
+ *     Free Tx/Rx allocated memory
+ *     Reset ULI526X board
+ *     Re-initialize ULI526X board
+ */
+
+static void uli526x_dynamic_reset(struct net_device *dev)
+{
+       struct uli526x_board_info *db = netdev_priv(dev);
+
+       ULI526X_DBUG(0, "uli526x_dynamic_reset()", 0);
+
+       /* Sopt MAC controller */
+       db->cr6_data &= ~(CR6_RXSC | CR6_TXSC); /* Disable Tx/Rx */
+       update_cr6(db->cr6_data, dev->base_addr);
+       outl(0, dev->base_addr + DCR7);         /* Disable Interrupt */
+       outl(inl(dev->base_addr + DCR5), dev->base_addr + DCR5);
+
+       /* Disable upper layer interface */
+       netif_stop_queue(dev);
+
+       /* Free Rx Allocate buffer */
+       uli526x_free_rxbuffer(db);
+
+       /* system variable init */
+       db->tx_packet_cnt = 0;
+       db->rx_avail_cnt = 0;
+       db->link_failed = 1;
+       db->init=1;
+       db->wait_reset = 0;
+
+       /* Re-initialize ULI526X board */
+       uli526x_init(dev);
+
+       /* Restart upper layer interface */
+       netif_wake_queue(dev);
+}
+
+
+/*
+ *     free all allocated rx buffer
+ */
+
+static void uli526x_free_rxbuffer(struct uli526x_board_info * db)
+{
+       ULI526X_DBUG(0, "uli526x_free_rxbuffer()", 0);
+
+       /* free allocated rx buffer */
+       while (db->rx_avail_cnt) {
+               dev_kfree_skb(db->rx_ready_ptr->rx_skb_ptr);
+               db->rx_ready_ptr = db->rx_ready_ptr->next_rx_desc;
+               db->rx_avail_cnt--;
+       }
+}
+
+
+/*
+ *     Reuse the SK buffer
+ */
+
+static void uli526x_reuse_skb(struct uli526x_board_info *db, struct sk_buff * skb)
+{
+       struct rx_desc *rxptr = db->rx_insert_ptr;
+
+       if (!(rxptr->rdes0 & cpu_to_le32(0x80000000))) {
+               rxptr->rx_skb_ptr = skb;
+               rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
+               wmb();
+               rxptr->rdes0 = cpu_to_le32(0x80000000);
+               db->rx_avail_cnt++;
+               db->rx_insert_ptr = rxptr->next_rx_desc;
+       } else
+               ULI526X_DBUG(0, "SK Buffer reuse method error", db->rx_avail_cnt);
+}
+
+
+/*
+ *     Initialize transmit/Receive descriptor
+ *     Using Chain structure, and allocate Tx/Rx buffer
+ */
+
+static void uli526x_descriptor_init(struct uli526x_board_info *db, unsigned long ioaddr)
+{
+       struct tx_desc *tmp_tx;
+       struct rx_desc *tmp_rx;
+       unsigned char *tmp_buf;
+       dma_addr_t tmp_tx_dma, tmp_rx_dma;
+       dma_addr_t tmp_buf_dma;
+       int i;
+
+       ULI526X_DBUG(0, "uli526x_descriptor_init()", 0);
+
+       /* tx descriptor start pointer */
+       db->tx_insert_ptr = db->first_tx_desc;
+       db->tx_remove_ptr = db->first_tx_desc;
+       outl(db->first_tx_desc_dma, ioaddr + DCR4);     /* TX DESC address */
+
+       /* rx descriptor start pointer */
+       db->first_rx_desc = (void *)db->first_tx_desc + sizeof(struct tx_desc) * TX_DESC_CNT;
+       db->first_rx_desc_dma =  db->first_tx_desc_dma + sizeof(struct tx_desc) * TX_DESC_CNT;
+       db->rx_insert_ptr = db->first_rx_desc;
+       db->rx_ready_ptr = db->first_rx_desc;
+       outl(db->first_rx_desc_dma, ioaddr + DCR3);     /* RX DESC address */
+
+       /* Init Transmit chain */
+       tmp_buf = db->buf_pool_start;
+       tmp_buf_dma = db->buf_pool_dma_start;
+       tmp_tx_dma = db->first_tx_desc_dma;
+       for (tmp_tx = db->first_tx_desc, i = 0; i < TX_DESC_CNT; i++, tmp_tx++) {
+               tmp_tx->tx_buf_ptr = tmp_buf;
+               tmp_tx->tdes0 = cpu_to_le32(0);
+               tmp_tx->tdes1 = cpu_to_le32(0x81000000);        /* IC, chain */
+               tmp_tx->tdes2 = cpu_to_le32(tmp_buf_dma);
+               tmp_tx_dma += sizeof(struct tx_desc);
+               tmp_tx->tdes3 = cpu_to_le32(tmp_tx_dma);
+               tmp_tx->next_tx_desc = tmp_tx + 1;
+               tmp_buf = tmp_buf + TX_BUF_ALLOC;
+               tmp_buf_dma = tmp_buf_dma + TX_BUF_ALLOC;
+       }
+       (--tmp_tx)->tdes3 = cpu_to_le32(db->first_tx_desc_dma);
+       tmp_tx->next_tx_desc = db->first_tx_desc;
+
+        /* Init Receive descriptor chain */
+       tmp_rx_dma=db->first_rx_desc_dma;
+       for (tmp_rx = db->first_rx_desc, i = 0; i < RX_DESC_CNT; i++, tmp_rx++) {
+               tmp_rx->rdes0 = cpu_to_le32(0);
+               tmp_rx->rdes1 = cpu_to_le32(0x01000600);
+               tmp_rx_dma += sizeof(struct rx_desc);
+               tmp_rx->rdes3 = cpu_to_le32(tmp_rx_dma);
+               tmp_rx->next_rx_desc = tmp_rx + 1;
+       }
+       (--tmp_rx)->rdes3 = cpu_to_le32(db->first_rx_desc_dma);
+       tmp_rx->next_rx_desc = db->first_rx_desc;
+
+       /* pre-allocate Rx buffer */
+       allocate_rx_buffer(db);
+}
+
+
+/*
+ *     Update CR6 value
+ *     Firstly stop ULI526X, then written value and start
+ */
+
+static void update_cr6(u32 cr6_data, unsigned long ioaddr)
+{
+
+       outl(cr6_data, ioaddr + DCR6);
+       udelay(5);
+}
+
+
+/*
+ *     Send a setup frame for M5261/M5263
+ *     This setup frame initialize ULI526X address filter mode
+ */
+
+static void send_filter_frame(struct net_device *dev, int mc_cnt)
+{
+       struct uli526x_board_info *db = netdev_priv(dev);
+       struct dev_mc_list *mcptr;
+       struct tx_desc *txptr;
+       u16 * addrptr;
+       u32 * suptr;
+       int i;
+
+       ULI526X_DBUG(0, "send_filter_frame()", 0);
+
+       txptr = db->tx_insert_ptr;
+       suptr = (u32 *) txptr->tx_buf_ptr;
+
+       /* Node address */
+       addrptr = (u16 *) dev->dev_addr;
+       *suptr++ = addrptr[0];
+       *suptr++ = addrptr[1];
+       *suptr++ = addrptr[2];
+
+       /* broadcast address */
+       *suptr++ = 0xffff;
+       *suptr++ = 0xffff;
+       *suptr++ = 0xffff;
+
+       /* fit the multicast address */
+       for (mcptr = dev->mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
+               addrptr = (u16 *) mcptr->dmi_addr;
+               *suptr++ = addrptr[0];
+               *suptr++ = addrptr[1];
+               *suptr++ = addrptr[2];
+       }
+
+       for (; i<14; i++) {
+               *suptr++ = 0xffff;
+               *suptr++ = 0xffff;
+               *suptr++ = 0xffff;
+       }
+
+       /* prepare the setup frame */
+       db->tx_insert_ptr = txptr->next_tx_desc;
+       txptr->tdes1 = cpu_to_le32(0x890000c0);
+
+       /* Resource Check and Send the setup packet */
+       if (db->tx_packet_cnt < TX_DESC_CNT) {
+               /* Resource Empty */
+               db->tx_packet_cnt++;
+               txptr->tdes0 = cpu_to_le32(0x80000000);
+               update_cr6(db->cr6_data | 0x2000, dev->base_addr);
+               outl(0x1, dev->base_addr + DCR1);       /* Issue Tx polling */
+               update_cr6(db->cr6_data, dev->base_addr);
+               dev->trans_start = jiffies;
+       } else
+               printk(KERN_ERR DRV_NAME ": No Tx resource - Send_filter_frame!\n");
+}
+
+
+/*
+ *     Allocate rx buffer,
+ *     As possible as allocate maxiumn Rx buffer
+ */
+
+static void allocate_rx_buffer(struct uli526x_board_info *db)
+{
+       struct rx_desc *rxptr;
+       struct sk_buff *skb;
+
+       rxptr = db->rx_insert_ptr;
+
+       while(db->rx_avail_cnt < RX_DESC_CNT) {
+               if ( ( skb = dev_alloc_skb(RX_ALLOC_SIZE) ) == NULL )
+                       break;
+               rxptr->rx_skb_ptr = skb; /* FIXME (?) */
+               rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
+               wmb();
+               rxptr->rdes0 = cpu_to_le32(0x80000000);
+               rxptr = rxptr->next_rx_desc;
+               db->rx_avail_cnt++;
+       }
+
+       db->rx_insert_ptr = rxptr;
+}
+
+
+/*
+ *     Read one word data from the serial ROM
+ */
+
+static u16 read_srom_word(long ioaddr, int offset)
+{
+       int i;
+       u16 srom_data = 0;
+       long cr9_ioaddr = ioaddr + DCR9;
+
+       outl(CR9_SROM_READ, cr9_ioaddr);
+       outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+
+       /* Send the Read Command 110b */
+       SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
+       SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
+       SROM_CLK_WRITE(SROM_DATA_0, cr9_ioaddr);
+
+       /* Send the offset */
+       for (i = 5; i >= 0; i--) {
+               srom_data = (offset & (1 << i)) ? SROM_DATA_1 : SROM_DATA_0;
+               SROM_CLK_WRITE(srom_data, cr9_ioaddr);
+       }
+
+       outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+
+       for (i = 16; i > 0; i--) {
+               outl(CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, cr9_ioaddr);
+               udelay(5);
+               srom_data = (srom_data << 1) | ((inl(cr9_ioaddr) & CR9_CRDOUT) ? 1 : 0);
+               outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+               udelay(5);
+       }
+
+       outl(CR9_SROM_READ, cr9_ioaddr);
+       return srom_data;
+}
+
+
+/*
+ *     Auto sense the media mode
+ */
+
+static u8 uli526x_sense_speed(struct uli526x_board_info * db)
+{
+       u8 ErrFlag = 0;
+       u16 phy_mode;
+
+       phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
+       phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
+
+       if ( (phy_mode & 0x24) == 0x24 ) {
+               
+               phy_mode = ((phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id) & 0x01e0)<<7);
+               if(phy_mode&0x8000)
+                       phy_mode = 0x8000;
+               else if(phy_mode&0x4000)
+                       phy_mode = 0x4000;
+               else if(phy_mode&0x2000)
+                       phy_mode = 0x2000;
+               else
+                       phy_mode = 0x1000;
+               
+               /* printk(DRV_NAME ": Phy_mode %x ",phy_mode); */
+               switch (phy_mode) {
+               case 0x1000: db->op_mode = ULI526X_10MHF; break;
+               case 0x2000: db->op_mode = ULI526X_10MFD; break;
+               case 0x4000: db->op_mode = ULI526X_100MHF; break;
+               case 0x8000: db->op_mode = ULI526X_100MFD; break;
+               default: db->op_mode = ULI526X_10MHF; ErrFlag = 1; break;
+               }
+       } else {
+               db->op_mode = ULI526X_10MHF;
+               ULI526X_DBUG(0, "Link Failed :", phy_mode);
+               ErrFlag = 1;
+       }
+
+       return ErrFlag;
+}
+
+
+/*
+ *     Set 10/100 phyxcer capability
+ *     AUTO mode : phyxcer register4 is NIC capability
+ *     Force mode: phyxcer register4 is the force media
+ */
+
+static void uli526x_set_phyxcer(struct uli526x_board_info *db)
+{
+       u16 phy_reg;
+       
+       /* Phyxcer capability setting */
+       phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x01e0;
+
+       if (db->media_mode & ULI526X_AUTO) {
+               /* AUTO Mode */
+               phy_reg |= db->PHY_reg4;
+       } else {
+               /* Force Mode */
+               switch(db->media_mode) {
+               case ULI526X_10MHF: phy_reg |= 0x20; break;
+               case ULI526X_10MFD: phy_reg |= 0x40; break;
+               case ULI526X_100MHF: phy_reg |= 0x80; break;
+               case ULI526X_100MFD: phy_reg |= 0x100; break;
+               }
+               
+       }
+
+       /* Write new capability to Phyxcer Reg4 */
+       if ( !(phy_reg & 0x01e0)) {
+               phy_reg|=db->PHY_reg4;
+               db->media_mode|=ULI526X_AUTO;
+       }
+       phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);
+
+       /* Restart Auto-Negotiation */
+       phy_write(db->ioaddr, db->phy_addr, 0, 0x1200, db->chip_id);
+       udelay(50);
+}
+
+
+/*
+ *     Process op-mode
+       AUTO mode : PHY controller in Auto-negotiation Mode
+ *     Force mode: PHY controller in force mode with HUB
+ *                     N-way force capability with SWITCH
+ */
+
+static void uli526x_process_mode(struct uli526x_board_info *db)
+{
+       u16 phy_reg;
+
+       /* Full Duplex Mode Check */
+       if (db->op_mode & 0x4)
+               db->cr6_data |= CR6_FDM;        /* Set Full Duplex Bit */
+       else
+               db->cr6_data &= ~CR6_FDM;       /* Clear Full Duplex Bit */
+
+       update_cr6(db->cr6_data, db->ioaddr);
+
+       /* 10/100M phyxcer force mode need */
+       if ( !(db->media_mode & 0x8)) {
+               /* Forece Mode */
+               phy_reg = phy_read(db->ioaddr, db->phy_addr, 6, db->chip_id);
+               if ( !(phy_reg & 0x1) ) {
+                       /* parter without N-Way capability */
+                       phy_reg = 0x0;
+                       switch(db->op_mode) {
+                       case ULI526X_10MHF: phy_reg = 0x0; break;
+                       case ULI526X_10MFD: phy_reg = 0x100; break;
+                       case ULI526X_100MHF: phy_reg = 0x2000; break;
+                       case ULI526X_100MFD: phy_reg = 0x2100; break;
+                       }
+                       phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id);
+                               phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id);
+               }
+       }
+}
+
+
+/*
+ *     Write a word to Phy register
+ */
+
+static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data, u32 chip_id)
+{
+       u16 i;
+       unsigned long ioaddr;
+
+       if(chip_id == PCI_ULI5263_ID)
+       {
+               phy_writeby_cr10(iobase, phy_addr, offset, phy_data);
+               return;
+       }
+       /* M5261/M5263 Chip */
+       ioaddr = iobase + DCR9;
+
+       /* Send 33 synchronization clock to Phy controller */
+       for (i = 0; i < 35; i++)
+               phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+       /* Send start command(01) to Phy */
+       phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+       phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+       /* Send write command(01) to Phy */
+       phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+       phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+       /* Send Phy address */
+       for (i = 0x10; i > 0; i = i >> 1)
+               phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+       /* Send register address */
+       for (i = 0x10; i > 0; i = i >> 1)
+               phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+       /* written trasnition */
+       phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+       phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+
+       /* Write a word data to PHY controller */
+       for ( i = 0x8000; i > 0; i >>= 1)
+               phy_write_1bit(ioaddr, phy_data & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+       
+}
+
+
+/*
+ *     Read a word data from phy register
+ */
+
+static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id)
+{
+       int i;
+       u16 phy_data;
+       unsigned long ioaddr;
+
+       if(chip_id == PCI_ULI5263_ID)
+               return phy_readby_cr10(iobase, phy_addr, offset);
+       /* M5261/M5263 Chip */
+       ioaddr = iobase + DCR9;
+       
+       /* Send 33 synchronization clock to Phy controller */
+       for (i = 0; i < 35; i++)
+               phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+       /* Send start command(01) to Phy */
+       phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+       phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+       /* Send read command(10) to Phy */
+       phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+       phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+
+       /* Send Phy address */
+       for (i = 0x10; i > 0; i = i >> 1)
+               phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+       /* Send register address */
+       for (i = 0x10; i > 0; i = i >> 1)
+               phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+       /* Skip transition state */
+       phy_read_1bit(ioaddr, chip_id);
+
+       /* read 16bit data */
+       for (phy_data = 0, i = 0; i < 16; i++) {
+               phy_data <<= 1;
+               phy_data |= phy_read_1bit(ioaddr, chip_id);
+       }
+
+       return phy_data;
+}
+
+static u16 phy_readby_cr10(unsigned long iobase, u8 phy_addr, u8 offset)
+{
+       unsigned long ioaddr,cr10_value;
+       
+       ioaddr = iobase + DCR10;
+       cr10_value = phy_addr;
+       cr10_value = (cr10_value<<5) + offset;
+       cr10_value = (cr10_value<<16) + 0x08000000;
+       outl(cr10_value,ioaddr);
+       udelay(1);
+       while(1)
+       {
+               cr10_value = inl(ioaddr);
+               if(cr10_value&0x10000000)
+                       break;
+       }
+       return (cr10_value&0x0ffff);
+}
+
+static void phy_writeby_cr10(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data)
+{
+       unsigned long ioaddr,cr10_value;
+       
+       ioaddr = iobase + DCR10;
+       cr10_value = phy_addr;
+       cr10_value = (cr10_value<<5) + offset;
+       cr10_value = (cr10_value<<16) + 0x04000000 + phy_data;
+       outl(cr10_value,ioaddr);
+       udelay(1);
+}
+/*
+ *     Write one bit data to Phy Controller
+ */
+
+static void phy_write_1bit(unsigned long ioaddr, u32 phy_data, u32 chip_id)
+{
+       outl(phy_data , ioaddr);                        /* MII Clock Low */
+       udelay(1);
+       outl(phy_data  | MDCLKH, ioaddr);       /* MII Clock High */
+       udelay(1);
+       outl(phy_data , ioaddr);                        /* MII Clock Low */
+       udelay(1);
+}
+
+
+/*
+ *     Read one bit phy data from PHY controller
+ */
+
+static u16 phy_read_1bit(unsigned long ioaddr, u32 chip_id)
+{
+       u16 phy_data;
+       
+       outl(0x50000 , ioaddr);
+       udelay(1);
+       phy_data = ( inl(ioaddr) >> 19 ) & 0x1;
+       outl(0x40000 , ioaddr);
+       udelay(1);
+
+       return phy_data;
+}
+
+
+static struct pci_device_id uli526x_pci_tbl[] = {
+       { 0x10B9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ULI5261_ID },
+       { 0x10B9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ULI5263_ID },
+       { 0, }
+};
+MODULE_DEVICE_TABLE(pci, uli526x_pci_tbl);
+
+
+static struct pci_driver uli526x_driver = {
+       .name           = "uli526x",
+       .id_table       = uli526x_pci_tbl,
+       .probe          = uli526x_init_one,
+       .remove         = __devexit_p(uli526x_remove_one),
+};
+
+MODULE_AUTHOR("Peer Chen, peer.chen@uli.com.tw");
+MODULE_DESCRIPTION("ULi M5261/M5263 fast ethernet driver");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(debug, "i");
+MODULE_PARM(mode, "i");
+MODULE_PARM(cr6set, "i");
+MODULE_PARM_DESC(debug, "ULi M5261/M5263 enable debugging (0-1)");
+MODULE_PARM_DESC(mode, "ULi M5261/M5263: Bit 0: 10/100Mbps, bit 2: duplex, bit 8: HomePNA");
+
+/*     Description:
+ *     when user used insmod to add module, system invoked init_module()
+ *     to register the services.
+ */
+
+static int __init uli526x_init_module(void)
+{
+       int rc;
+
+       printk(version);
+       printed_version = 1;
+
+       ULI526X_DBUG(0, "init_module() ", debug);
+
+       if (debug)
+               uli526x_debug = debug;  /* set debug flag */
+       if (cr6set)
+               uli526x_cr6_user_set = cr6set;
+
+       switch(mode) {
+       case ULI526X_10MHF:
+       case ULI526X_100MHF:
+       case ULI526X_10MFD:
+       case ULI526X_100MFD:
+               uli526x_media_mode = mode;
+               break;
+       default:uli526x_media_mode = ULI526X_AUTO;
+               break;
+       }
+
+       rc = pci_module_init(&uli526x_driver);
+       if (rc < 0)
+               return rc;
+
+       return 0;
+}
+
+
+/*
+ *     Description:
+ *     when user used rmmod to delete module, system invoked clean_module()
+ *     to un-register all registered services.
+ */
+
+static void __exit uli526x_cleanup_module(void)
+{
+       ULI526X_DBUG(0, "uli526x_clean_module() ", debug);
+       pci_unregister_driver(&uli526x_driver);
+}
+
+module_init(uli526x_init_module);
+module_exit(uli526x_cleanup_module);
index 6e74af6..9e56fc3 100644 (file)
@@ -56,7 +56,7 @@
 #include <linux/sched.h>       /* for jiffies, HZ, etc. */
 #include <linux/cycx_drv.h>    /* API definitions */
 #include <linux/cycx_cfm.h>    /* CYCX firmware module definitions */
-#include <linux/delay.h>       /* udelay */
+#include <linux/delay.h>       /* udelay, msleep_interruptible */
 #include <asm/io.h>            /* read[wl], write[wl], ioremap, iounmap */
 
 #define        MOD_VERSION     0
@@ -74,7 +74,6 @@ static int reset_cyc2x(void __iomem *addr);
 static int detect_cyc2x(void __iomem *addr);
 
 /* Miscellaneous functions */
-static void delay_cycx(int sec);
 static int get_option_index(long *optlist, long optval);
 static u16 checksum(u8 *buf, u32 len);
 
@@ -259,7 +258,7 @@ static int memory_exists(void __iomem *addr)
                        if (readw(addr + 0x10) == TEST_PATTERN)
                                return 1;
 
-               delay_cycx(1);
+               msleep_interruptible(1 * 1000);
        }
 
        return 0;
@@ -316,7 +315,7 @@ static void cycx_reset_boot(void __iomem *addr, u8 *code, u32 len)
 
        /* 80186 was in hold, go */
        writeb(0, addr + START_CPU);
-       delay_cycx(1);
+       msleep_interruptible(1 * 1000);
 }
 
 /* Load data.bin file through boot (reset) interface. */
@@ -462,13 +461,13 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
                cycx_reset_boot(hw->dpmbase, reset_image, img_hdr->reset_size);
                /* reset is waiting for boot */
                writew(GEN_POWER_ON, pt_cycld);
-               delay_cycx(1);
+               msleep_interruptible(1 * 1000);
 
                for (j = 0 ; j < 3 ; j++)
                        if (!readw(pt_cycld))
                                goto reset_loaded;
                        else
-                               delay_cycx(1);
+                               msleep_interruptible(1 * 1000);
        }
 
        printk(KERN_ERR "%s: reset not started.\n", modname);
@@ -495,7 +494,7 @@ reset_loaded:
 
        /* Arthur Ganzert's tip: wait a while after the firmware loading...
           seg abr 26 17:17:12 EST 1999 - acme */
-       delay_cycx(7);
+       msleep_interruptible(7 * 1000);
        printk(KERN_INFO "%s: firmware loaded!\n", modname);
 
        /* enable interrupts */
@@ -547,20 +546,13 @@ static int get_option_index(long *optlist, long optval)
 static int reset_cyc2x(void __iomem *addr)
 {
        writeb(0, addr + RST_ENABLE);
-       delay_cycx(2);
+       msleep_interruptible(2 * 1000);
        writeb(0, addr + RST_DISABLE);
-       delay_cycx(2);
+       msleep_interruptible(2 * 1000);
 
        return memory_exists(addr);
 }
 
-/* Delay */
-static void delay_cycx(int sec)
-{
-       set_current_state(TASK_INTERRUPTIBLE);
-       schedule_timeout(sec * HZ);
-}
-
 /* Calculate 16-bit CRC using CCITT polynomial. */
 static u16 checksum(u8 *buf, u32 len)
 {
index 1d3231c..ec3f75a 100644 (file)
@@ -270,7 +270,7 @@ config PCMCIA_HERMES
 
 config AIRO_CS
        tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards"
-       depends on NET_RADIO && PCMCIA
+       depends on NET_RADIO && PCMCIA && (BROKEN || !M32R)
        ---help---
          This is the standard Linux driver to support Cisco/Aironet PCMCIA
          802.11 wireless cards.  This driver is the same as the Aironet
index aabcdc2..9c2d07c 100644 (file)
@@ -4322,36 +4322,36 @@ static const struct iw_priv_args orinoco_privtab[] = {
  */
 
 static const iw_handler        orinoco_handler[] = {
-       [SIOCSIWCOMMIT-SIOCIWFIRST] (iw_handler) orinoco_ioctl_commit,
-       [SIOCGIWNAME  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getname,
-       [SIOCSIWFREQ  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfreq,
-       [SIOCGIWFREQ  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfreq,
-       [SIOCSIWMODE  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setmode,
-       [SIOCGIWMODE  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getmode,
-       [SIOCSIWSENS  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setsens,
-       [SIOCGIWSENS  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getsens,
-       [SIOCGIWRANGE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwrange,
-       [SIOCSIWSPY   -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setspy,
-       [SIOCGIWSPY   -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getspy,
-       [SIOCSIWAP    -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setwap,
-       [SIOCGIWAP    -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getwap,
-       [SIOCSIWSCAN  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setscan,
-       [SIOCGIWSCAN  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getscan,
-       [SIOCSIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setessid,
-       [SIOCGIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getessid,
-       [SIOCSIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setnick,
-       [SIOCGIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getnick,
-       [SIOCSIWRATE  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrate,
-       [SIOCGIWRATE  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrate,
-       [SIOCSIWRTS   -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrts,
-       [SIOCGIWRTS   -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrts,
-       [SIOCSIWFRAG  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfrag,
-       [SIOCGIWFRAG  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfrag,
-       [SIOCGIWRETRY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getretry,
-       [SIOCSIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_setiwencode,
-       [SIOCGIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwencode,
-       [SIOCSIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setpower,
-       [SIOCGIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getpower,
+       [SIOCSIWCOMMIT-SIOCIWFIRST] (iw_handler) orinoco_ioctl_commit,
+       [SIOCGIWNAME  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getname,
+       [SIOCSIWFREQ  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfreq,
+       [SIOCGIWFREQ  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfreq,
+       [SIOCSIWMODE  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setmode,
+       [SIOCGIWMODE  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getmode,
+       [SIOCSIWSENS  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setsens,
+       [SIOCGIWSENS  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getsens,
+       [SIOCGIWRANGE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwrange,
+       [SIOCSIWSPY   -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setspy,
+       [SIOCGIWSPY   -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getspy,
+       [SIOCSIWAP    -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setwap,
+       [SIOCGIWAP    -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getwap,
+       [SIOCSIWSCAN  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setscan,
+       [SIOCGIWSCAN  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getscan,
+       [SIOCSIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setessid,
+       [SIOCGIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getessid,
+       [SIOCSIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setnick,
+       [SIOCGIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getnick,
+       [SIOCSIWRATE  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrate,
+       [SIOCGIWRATE  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrate,
+       [SIOCSIWRTS   -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrts,
+       [SIOCGIWRTS   -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrts,
+       [SIOCSIWFRAG  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfrag,
+       [SIOCGIWFRAG  -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfrag,
+       [SIOCGIWRETRY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getretry,
+       [SIOCSIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_setiwencode,
+       [SIOCGIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwencode,
+       [SIOCSIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setpower,
+       [SIOCGIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getpower,
 };
 
 
@@ -4359,15 +4359,15 @@ static const iw_handler orinoco_handler[] = {
   Added typecasting since we no longer use iwreq_data -- Moustafa
  */
 static const iw_handler        orinoco_private_handler[] = {
-       [0] (iw_handler) orinoco_ioctl_reset,
-       [1] (iw_handler) orinoco_ioctl_reset,
-       [2] (iw_handler) orinoco_ioctl_setport3,
-       [3] (iw_handler) orinoco_ioctl_getport3,
-       [4] (iw_handler) orinoco_ioctl_setpreamble,
-       [5] (iw_handler) orinoco_ioctl_getpreamble,
-       [6] (iw_handler) orinoco_ioctl_setibssport,
-       [7] (iw_handler) orinoco_ioctl_getibssport,
-       [9] (iw_handler) orinoco_ioctl_getrid,
+       [0] (iw_handler) orinoco_ioctl_reset,
+       [1] (iw_handler) orinoco_ioctl_reset,
+       [2] (iw_handler) orinoco_ioctl_setport3,
+       [3] (iw_handler) orinoco_ioctl_getport3,
+       [4] (iw_handler) orinoco_ioctl_setpreamble,
+       [5] (iw_handler) orinoco_ioctl_getpreamble,
+       [6] (iw_handler) orinoco_ioctl_setibssport,
+       [7] (iw_handler) orinoco_ioctl_getibssport,
+       [9] (iw_handler) orinoco_ioctl_getrid,
 };
 
 static const struct iw_handler_def orinoco_handler_def = {
index 16a2e6a..725a141 100644 (file)
@@ -34,7 +34,7 @@ config PARPORT
 
 config PARPORT_PC
        tristate "PC-style hardware"
-       depends on PARPORT && (!SPARC64 || PCI) && !SPARC32
+       depends on PARPORT && (!SPARC64 || PCI) && !SPARC32 && !M32R
        ---help---
          You should say Y here if you have a PC-style parallel port. All
          IBM PC compatible computers and some Alphas have PC-style
index 00498e2..d3dad0a 100644 (file)
 #include <linux/pci.h>
 #include <linux/parport.h>
 #include <linux/parport_pc.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/list.h>
 #include <linux/8250_pci.h>
 
-#include <asm/serial.h>
-
 enum parport_pc_pci_cards {
        titan_110l = 0,
        titan_210l,
@@ -168,182 +163,147 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
 
-struct pci_board_no_ids {
-       int flags;
-       int num_ports;
-       int base_baud;
-       int uart_offset;
-       int reg_shift;
-       int (*init_fn)(struct pci_dev *dev, struct pci_board_no_ids *board,
-                       int enable);
-       int first_uart_offset;
-};
-
-static int __devinit siig10x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
-{
-       return pci_siig10x_fn(dev, enable);
-}
-
-static int __devinit siig20x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
-{
-       return pci_siig20x_fn(dev, enable);
-}
-
-static int __devinit netmos_serial_init(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
-{
-       board->num_ports = dev->subsystem_device & 0xf;
-       return 0;
-}
-
-static struct pci_board_no_ids pci_boards[] __devinitdata = {
-       /*
-        * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
-        * Offset to get to next UART's registers,
-        * Register shift to use for memory-mapped I/O,
-        * Initialization function, first UART offset
-        */
-
-// Cards not tested are marked n/t
-// If you have one of these cards and it works for you, please tell me..
-
-/* titan_110l */       { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 1, 921600 },
-/* titan_210l */       { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
-/* netmos_9xx5_combo */        { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init },
-/* netmos_9855 */      { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init },
-/* avlab_1s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s2p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s2p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s2p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_2s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
-/* avlab_2s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
-/* avlab_2s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
-/* siig_1s1p_10x */    { SPCI_FL_BASE2, 1, 460800, 0, 0, siig10x_init_fn },
-/* siig_2s1p_10x */    { SPCI_FL_BASE2, 1, 921600, 0, 0, siig10x_init_fn },
-/* siig_2p1s_20x */    { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
-/* siig_1s1p_20x */    { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
-/* siig_2s1p_20x */    { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
+/*
+ * This table describes the serial "geometry" of these boards.  Any
+ * quirks for these can be found in drivers/serial/8250_pci.c
+ *
+ * Cards not tested are marked n/t
+ * If you have one of these cards and it works for you, please tell me..
+ */
+static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
+       [titan_110l] = {
+               .flags          = FL_BASE1 | FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [titan_210l] = {
+               .flags          = FL_BASE1 | FL_BASE_BARS,
+               .num_ports      = 2,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [netmos_9xx5_combo] = {
+               .flags          = FL_BASE0 | FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [netmos_9855] = {
+               .flags          = FL_BASE2 | FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [avlab_1s1p] = { /* n/t */
+               .flags          = FL_BASE0 | FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [avlab_1s1p_650] = { /* nt */
+               .flags          = FL_BASE0 | FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [avlab_1s1p_850] = { /* nt */
+               .flags          = FL_BASE0 | FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [avlab_1s2p] = { /* n/t */
+               .flags          = FL_BASE0 | FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [avlab_1s2p_650] = { /* nt */
+               .flags          = FL_BASE0 | FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [avlab_1s2p_850] = { /* nt */
+               .flags          = FL_BASE0 | FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [avlab_2s1p] = { /* n/t */
+               .flags          = FL_BASE0 | FL_BASE_BARS,
+               .num_ports      = 2,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [avlab_2s1p_650] = { /* nt */
+               .flags          = FL_BASE0 | FL_BASE_BARS,
+               .num_ports      = 2,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [avlab_2s1p_850] = { /* nt */
+               .flags          = FL_BASE0 | FL_BASE_BARS,
+               .num_ports      = 2,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [siig_1s1p_10x] = {
+               .flags          = FL_BASE2,
+               .num_ports      = 1,
+               .base_baud      = 460800,
+               .uart_offset    = 8,
+       },
+       [siig_2s1p_10x] = {
+               .flags          = FL_BASE2,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [siig_2p1s_20x] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [siig_1s1p_20x] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [siig_2s1p_20x] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
 };
 
 struct parport_serial_private {
-       int num_ser;
-       int line[20];
-       struct pci_board_no_ids ser;
+       struct serial_private   *serial;
        int num_par;
        struct parport *port[PARPORT_MAX];
        struct parport_pc_pci par;
 };
 
-static int __devinit get_pci_port (struct pci_dev *dev,
-                                  struct pci_board_no_ids *board,
-                                  struct serial_struct *req,
-                                  int idx)
-{
-       unsigned long port;
-       int base_idx;
-       int max_port;
-       int offset;
-
-       base_idx = SPCI_FL_GET_BASE(board->flags);
-       if (board->flags & SPCI_FL_BASE_TABLE)
-               base_idx += idx;
-
-       if (board->flags & SPCI_FL_REGION_SZ_CAP) {
-               max_port = pci_resource_len(dev, base_idx) / 8;
-               if (idx >= max_port)
-                       return 1;
-       }
-                       
-       offset = board->first_uart_offset;
-
-       /* Timedia/SUNIX uses a mixture of BARs and offsets */
-       /* Ugh, this is ugly as all hell --- TYT */
-       if(dev->vendor == PCI_VENDOR_ID_TIMEDIA )  /* 0x1409 */
-               switch(idx) {
-                       case 0: base_idx=0;
-                               break;
-                       case 1: base_idx=0; offset=8;
-                               break;
-                       case 2: base_idx=1; 
-                               break;
-                       case 3: base_idx=1; offset=8;
-                               break;
-                       case 4: /* BAR 2*/
-                       case 5: /* BAR 3 */
-                       case 6: /* BAR 4*/
-                       case 7: base_idx=idx-2; /* BAR 5*/
-               }
-  
-       port =  pci_resource_start(dev, base_idx) + offset;
-
-       if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
-               port += idx * (board->uart_offset ? board->uart_offset : 8);
-
-       if (pci_resource_flags (dev, base_idx) & IORESOURCE_IO) {
-               int high_bits_offset = ((sizeof(long)-sizeof(int))*8);
-               req->port = port;
-               if (high_bits_offset)
-                       req->port_high = port >> high_bits_offset;
-               else
-                       req->port_high = 0;
-               return 0;
-       }
-       req->io_type = SERIAL_IO_MEM;
-       req->iomem_base = ioremap(port, board->uart_offset);
-       req->iomem_reg_shift = board->reg_shift;
-       req->port = 0;
-       return req->iomem_base ? 0 : 1;
-}
-
 /* Register the serial port(s) of a PCI card. */
 static int __devinit serial_register (struct pci_dev *dev,
                                      const struct pci_device_id *id)
 {
-       struct pci_board_no_ids *board;
        struct parport_serial_private *priv = pci_get_drvdata (dev);
-       struct serial_struct serial_req;
-       int base_baud;
-       int k;
-       int success = 0;
-
-       priv->ser = pci_boards[id->driver_data];
-       board = &priv->ser;
-       if (board->init_fn && ((board->init_fn) (dev, board, 1) != 0))
-               return 1;
-
-       base_baud = board->base_baud;
-       if (!base_baud)
-               base_baud = BASE_BAUD;
-       memset (&serial_req, 0, sizeof (serial_req));
-
-       for (k = 0; k < board->num_ports; k++) {
-               int line;
+       struct pciserial_board *board;
+       struct serial_private *serial;
 
-               if (priv->num_ser == ARRAY_SIZE (priv->line)) {
-                       printk (KERN_WARNING
-                               "parport_serial: %s: only %u serial lines "
-                               "supported (%d reported)\n", pci_name (dev),
-                               ARRAY_SIZE (priv->line), board->num_ports);
-                       break;
-               }
+       board = &pci_parport_serial_boards[id->driver_data];
+       serial = pciserial_init_ports(dev, board);
 
-               serial_req.irq = dev->irq;
-               if (get_pci_port (dev, board, &serial_req, k))
-                       break;
-               serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
-               serial_req.baud_base = base_baud;
-               line = register_serial (&serial_req);
-               if (line < 0) {
-                       printk (KERN_DEBUG
-                               "parport_serial: register_serial failed\n");
-                       continue;
-               }
-               priv->line[priv->num_ser++] = line;
-               success = 1;
-       }
+       if (IS_ERR(serial))
+               return PTR_ERR(serial);
 
-       return success ? 0 : 1;
+       priv->serial = serial;
+       return 0;
 }
 
 /* Register the parallel port(s) of a PCI card. */
@@ -411,7 +371,7 @@ static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
        priv = kmalloc (sizeof *priv, GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
-       priv->num_ser = priv->num_par = 0;
+       memset(priv, 0, sizeof(struct parport_serial_private));
        pci_set_drvdata (dev, priv);
 
        err = pci_enable_device (dev);
@@ -444,15 +404,12 @@ static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
        struct parport_serial_private *priv = pci_get_drvdata (dev);
        int i;
 
+       pci_set_drvdata(dev, NULL);
+
        // Serial ports
-       for (i = 0; i < priv->num_ser; i++) {
-               unregister_serial (priv->line[i]);
+       if (priv->serial)
+               pciserial_remove_ports(priv->serial);
 
-               if (priv->ser.init_fn)
-                       (priv->ser.init_fn) (dev, &priv->ser, 0);
-       }
-       pci_set_drvdata (dev, NULL);
-       
        // Parallel ports
        for (i = 0; i < priv->num_par; i++)
                parport_pc_unregister_port (priv->port[i]);
@@ -461,11 +418,47 @@ static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
        return;
 }
 
+static int parport_serial_pci_suspend(struct pci_dev *dev, pm_message_t state)
+{
+       struct parport_serial_private *priv = pci_get_drvdata(dev);
+
+       if (priv->serial)
+               pciserial_suspend_ports(priv->serial);
+
+       /* FIXME: What about parport? */
+
+       pci_save_state(dev);
+       pci_set_power_state(dev, pci_choose_state(dev, state));
+       return 0;
+}
+
+static int parport_serial_pci_resume(struct pci_dev *dev)
+{
+       struct parport_serial_private *priv = pci_get_drvdata(dev);
+
+       pci_set_power_state(dev, PCI_D0);
+       pci_restore_state(dev);
+
+       /*
+        * The device may have been disabled.  Re-enable it.
+        */
+       pci_enable_device(dev);
+
+       if (priv->serial)
+               pciserial_resume_ports(priv->serial);
+
+       /* FIXME: What about parport? */
+
+       return 0;
+}
+
 static struct pci_driver parport_serial_pci_driver = {
        .name           = "parport_serial",
        .id_table       = parport_serial_pci_tbl,
        .probe          = parport_serial_pci_probe,
        .remove         = __devexit_p(parport_serial_pci_remove),
+       .suspend        = parport_serial_pci_suspend,
+       .resume         = parport_serial_pci_resume,
 };
 
 
index fedae89..fb9a112 100644 (file)
@@ -60,7 +60,9 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
                        continue;
 
                /* Ok, try it out.. */
-               ret = allocate_resource(r, res, size, min, -1, align,
+               ret = allocate_resource(r, res, size,
+                                       r->start ? : min,
+                                       -1, align,
                                        alignf, alignf_data);
                if (ret == 0)
                        break;
index 46b294a..2b92b9e 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
  *
  */
 #ifndef _PCIEHP_H
index df4915d..cafc7ea 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
  *
  */
 
index 0dbcf04..0e09476 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
  *
  */
 
index 1cda30b..7a0e27f 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>,<dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com>
  *
  */
 
index 723b12c..33b539b 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
  *
  */
 
index 966775f..05f20fb 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
  *
  */
 
index 57f4e6d..305b47e 100644 (file)
@@ -20,7 +20,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <dely.l.sy@intel.com>
+ * Send feedback to <kristen.c.accardi@intel.com>
  *
  */
 
index 79a0aa6..3622965 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
  *
  */
 
index 87c90e8..b10603b 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
  *
  */
 
index 67b6a33..fe4d653 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>,<dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com>
  *
  */
 #ifndef _SHPCHP_H
index a70a5c5..6f7d8a2 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
  *
  */
 
index 490a955..783b5ab 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
  *
  */
 
index 38c5d90..8d98410 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>,<dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com>
  *
  */
 
index 90113e9..d867099 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
  *
  */
 
index 88aeb97..057b192 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
  *
  */
 
index 7957cdc..d37b316 100644 (file)
@@ -20,7 +20,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <dely.l.sy@intel.com>
+ * Send feedback to <kristen.c.accardi@intel.com>
  *
  */
 
index 37fa77a..ba6c549 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>,<dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com>
  *
  */
 
index 29ccea5..21bda74 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
  *
  */
 
index 88f4d9f..5f75ef7 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
  *
  */
 
index 6bc8668..cddaaa5 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
  *
  */
 
index b5ab9aa..2b85aa3 100644 (file)
@@ -453,7 +453,7 @@ static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
        }
 }
 
-static void disable_msi_mode(struct pci_dev *dev, int pos, int type)
+void disable_msi_mode(struct pci_dev *dev, int pos, int type)
 {
        u16 control;
 
@@ -699,6 +699,9 @@ int pci_enable_msi(struct pci_dev* dev)
        if (!pci_msi_enable || !dev)
                return status;
 
+       if (dev->no_msi)
+               return status;
+
        temp = dev->irq;
 
        if ((status = msi_init()) < 0)
index d94d7af..d00168b 100644 (file)
@@ -47,6 +47,12 @@ extern int pci_msi_quirk;
 #define pci_msi_quirk 0
 #endif
 
+#ifdef CONFIG_PCI_MSI
+void disable_msi_mode(struct pci_dev *dev, int pos, int type);
+#else
+static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { }
+#endif
+
 extern int pcie_mch_quirk;
 extern struct device_attribute pci_dev_attrs[];
 extern struct class_device_attribute class_device_attr_cpuaffinity;
index 8d0968b..bb36bb6 100644 (file)
@@ -373,6 +373,25 @@ static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,    PCI_DEVICE_ID_VIA_82C686_4,     quirk_vt82c686_acpi );
 
+/*
+ * VIA VT8235 ISA Bridge: Two IO regions pointed to by words at
+ *     0x88 (128 bytes of power management registers)
+ *     0xd0 (16 bytes of SMB registers)
+ */
+static void __devinit quirk_vt8235_acpi(struct pci_dev *dev)
+{
+       u16 pm, smb;
+
+       pci_read_config_word(dev, 0x88, &pm);
+       pm &= PCI_BASE_ADDRESS_IO_MASK;
+       quirk_io_region(dev, pm, 128, PCI_BRIDGE_RESOURCES);
+
+       pci_read_config_word(dev, 0xd0, &smb);
+       smb &= PCI_BASE_ADDRESS_IO_MASK;
+       quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 1);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,    PCI_DEVICE_ID_VIA_8235, quirk_vt8235_acpi);
+
 
 #ifdef CONFIG_X86_IO_APIC 
 
@@ -1272,6 +1291,27 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,     PCI_DEVICE_ID_INTEL_E7520_MCH,  quir
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7320_MCH,  quirk_pcie_mch );
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7525_MCH,  quirk_pcie_mch );
 
+
+/*
+ * It's possible for the MSI to get corrupted if shpc and acpi
+ * are used together on certain PXH-based systems.
+ */
+static void __devinit quirk_pcie_pxh(struct pci_dev *dev)
+{
+       disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI),
+                                       PCI_CAP_ID_MSI);
+       dev->no_msi = 1;
+
+       printk(KERN_WARNING "PCI: PXH quirk detected, "
+               "disabling MSI for SHPC device\n");
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_PXHD_0,     quirk_pcie_pxh);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_PXHD_1,     quirk_pcie_pxh);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_PXH_0,      quirk_pcie_pxh);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_PXH_1,      quirk_pcie_pxh);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_PXHV,       quirk_pcie_pxh);
+
+
 static void __devinit quirk_netmos(struct pci_dev *dev)
 {
        unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4;
index a2eebc6..6d864c5 100644 (file)
@@ -40,7 +40,7 @@
  * FIXME: IO should be max 256 bytes.  However, since we may
  * have a P2P bridge below a cardbus bridge, we need 4K.
  */
-#define CARDBUS_IO_SIZE                (4096)
+#define CARDBUS_IO_SIZE                (256)
 #define CARDBUS_MEM_SIZE       (32*1024*1024)
 
 static void __devinit
index 1ca21d2..5598b47 100644 (file)
@@ -33,6 +33,11 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
        u32 new, check, mask;
        int reg;
 
+       /* Ignore resources for unimplemented BARs and unused resource slots
+          for 64 bit BARs. */
+       if (!res->flags)
+               return;
+
        pcibios_resource_to_bus(dev, &region, res);
 
        pr_debug("  got res [%lx:%lx] bus [%lx:%lx] flags %lx for "
@@ -48,7 +53,9 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
        if (resno < 6) {
                reg = PCI_BASE_ADDRESS_0 + 4 * resno;
        } else if (resno == PCI_ROM_RESOURCE) {
-               new |= res->flags & IORESOURCE_ROM_ENABLE;
+               if (!(res->flags & IORESOURCE_ROM_ENABLE))
+                       return;
+               new |= PCI_ROM_ADDRESS_ENABLE;
                reg = dev->rom_base_reg;
        } else {
                /* Hmm, non-standard resource. */
@@ -67,7 +74,7 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
 
        if ((new & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
            (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) {
-               new = 0; /* currently everyone zeros the high address */
+               new = region.start >> 16 >> 16;
                pci_write_config_dword(dev, reg + 4, new);
                pci_read_config_dword(dev, reg + 4, &check);
                if (check != new) {
index d63f22a..43da2e9 100644 (file)
@@ -589,8 +589,8 @@ static void pcmcia_delayed_add_pseudo_device(void *data)
 static inline void pcmcia_add_pseudo_device(struct pcmcia_socket *s)
 {
        if (!s->pcmcia_state.device_add_pending) {
-               schedule_work(&s->device_add);
                s->pcmcia_state.device_add_pending = 1;
+               schedule_work(&s->device_add);
        }
        return;
 }
index 6f9fdb2..599b116 100644 (file)
@@ -41,6 +41,7 @@ module_param(io_speed, int, 0444);
 
 
 #ifdef CONFIG_PCMCIA_PROBE
+#include <asm/irq.h>
 /* mask of IRQs already reserved by other cards, we should avoid using them */
 static u8 pcmcia_used_irq[NR_IRQS];
 #endif
index 744e469..62fd705 100644 (file)
@@ -605,9 +605,8 @@ static int yenta_search_res(struct yenta_socket *socket, struct resource *res,
 
 static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end)
 {
-       struct pci_bus *bus;
        struct resource *root, *res;
-       u32 start, end;
+       struct pci_bus_region region;
        unsigned mask;
 
        res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr;
@@ -620,15 +619,13 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
        if (type & IORESOURCE_IO)
                mask = ~3;
 
-       bus = socket->dev->subordinate;
-       res->name = bus->name;
+       res->name = socket->dev->subordinate->name;
        res->flags = type;
 
-       start = config_readl(socket, addr_start) & mask;
-       end = config_readl(socket, addr_end) | ~mask;
-       if (start && end > start && !override_bios) {
-               res->start = start;
-               res->end = end;
+       region.start = config_readl(socket, addr_start) & mask;
+       region.end = config_readl(socket, addr_end) | ~mask;
+       if (region.start && region.end > region.start && !override_bios) {
+               pcibios_bus_to_resource(socket->dev, res, &region);
                root = pci_find_parent_resource(socket->dev, res);
                if (root && (request_resource(root, res) == 0))
                        return;
@@ -642,6 +639,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
                    (yenta_search_res(socket, res, BRIDGE_IO_MIN))) {
                        config_writel(socket, addr_start, res->start);
                        config_writel(socket, addr_end, res->end);
+                       return;
                }
        } else {
                if (type & IORESOURCE_PREFETCH) {
@@ -650,6 +648,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
                            (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
                                config_writel(socket, addr_start, res->start);
                                config_writel(socket, addr_end, res->end);
+                               return;
                        }
                        /* Approximating prefetchable by non-prefetchable */
                        res->flags = IORESOURCE_MEM;
@@ -659,6 +658,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
                    (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
                        config_writel(socket, addr_start, res->start);
                        config_writel(socket, addr_end, res->end);
+                       return;
                }
        }
 
@@ -1107,8 +1107,6 @@ static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state)
                pci_read_config_dword(dev, 17*4, &socket->saved_state[1]);
                pci_disable_device(dev);
 
-               free_irq(dev->irq, socket);
-
                /*
                 * Some laptops (IBM T22) do not like us putting the Cardbus
                 * bridge into D3.  At a guess, some other laptop will
@@ -1134,13 +1132,6 @@ static int yenta_dev_resume (struct pci_dev *dev)
                pci_enable_device(dev);
                pci_set_master(dev);
 
-               if (socket->cb_irq)
-                       if (request_irq(socket->cb_irq, yenta_interrupt,
-                                       SA_SHIRQ, "yenta", socket)) {
-                               printk(KERN_WARNING "Yenta: request_irq() failed on resume!\n");
-                               socket->cb_irq = 0;
-                       }
-
                if (socket->type && socket->type->restore_state)
                        socket->type->restore_state(socket);
        }
index add12f7..6e5229e 100644 (file)
@@ -312,6 +312,8 @@ found:
        if (drv->link.driver.probe) {
                if (drv->link.driver.probe(&dev->dev)) {
                        dev->dev.driver = NULL;
+                       dev->card_link = NULL;
+                       up_write(&dev->dev.bus->subsys.rwsem);
                        return NULL;
                }
        }
index d36258d..381f339 100644 (file)
@@ -112,7 +112,7 @@ qdio_min(int a,int b)
 
 /***************** SCRUBBER HELPER ROUTINES **********************/
 
-static inline volatile __u64 
+static inline __u64 
 qdio_get_micros(void)
 {
         return (get_clock() >> 10); /* time>>12 is microseconds */
@@ -230,7 +230,7 @@ qdio_siga_input(struct qdio_q *q)
 }
 
 /* locked by the locks in qdio_activate and qdio_cleanup */
-static __u32 * volatile 
+static __u32 volatile *
 qdio_get_indicator(void)
 {
        int i;
index 82a1d97..0a3bb5a 100644 (file)
 #define z90crypt_RELEASE 3     // 2 = PCIXCC, 3 = rewrite for coding standards
 #define z90crypt_VARIANT 2     // 2 = added PCIXCC MCL3 and CEX2C support
 
-/**
- * If we are not using the sparse checker, __user has no use.
- */
-#ifdef __CHECKER__
-# define __user                __attribute__((noderef, address_space(1)))
-#else
-# define __user
-#endif
-
 /**
  * struct ica_rsa_modexpo
  *
index 8f4d299..79c74f3 100644 (file)
@@ -8120,20 +8120,22 @@ static struct notifier_block qeth_ip6_notifier = {
 #endif
 
 static int
-qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
+__qeth_reboot_event_card(struct device *dev, void *data)
 {
-
-       struct device *entry;
        struct qeth_card *card;
 
-       down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
-              list_for_each_entry(entry, &qeth_ccwgroup_driver.driver.devices,
-                                  driver_list) {
-                      card = (struct qeth_card *) entry->driver_data;
-                      qeth_clear_ip_list(card, 0, 0);
-                      qeth_qdio_clear_card(card, 0);
-              }
-       up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
+       card = (struct qeth_card *) dev->driver_data;
+       qeth_clear_ip_list(card, 0, 0);
+       qeth_qdio_clear_card(card, 0);
+       return 0;
+}
+
+static int
+qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+
+       driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
+                              __qeth_reboot_event_card);
        return NOTIFY_DONE;
 }
 
index 0471919..f2ccfea 100644 (file)
@@ -27,23 +27,33 @@ const char *VERSION_QETH_PROC_C = "$Revision: 1.13 $";
 #define QETH_PROCFILE_NAME "qeth"
 static struct proc_dir_entry *qeth_procfile;
 
+static int
+qeth_procfile_seq_match(struct device *dev, void *data)
+{
+       return 1;
+}
+
 static void *
 qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)
 {
-       struct list_head *next_card = NULL;
-       int i = 0;
+       struct device *dev;
+       loff_t nr;
 
        down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
 
-       if (*offset == 0)
+       nr = *offset;
+       if (nr == 0)
                return SEQ_START_TOKEN;
 
-       /* get card at pos *offset */
-       list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices)
-               if (++i == *offset)
-                       return next_card;
+       dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL,
+                                NULL, qeth_procfile_seq_match);
 
-       return NULL;
+       /* get card at pos *offset */
+       nr = *offset;
+       while (nr-- > 1 && dev)
+               dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev,
+                                        NULL, qeth_procfile_seq_match);
+       return (void *) dev;
 }
 
 static void
@@ -55,23 +65,21 @@ qeth_procfile_seq_stop(struct seq_file *s, void* it)
 static void *
 qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
 {
-       struct list_head *next_card = NULL;
-       struct list_head *current_card;
+       struct device *prev, *next;
 
        if (it == SEQ_START_TOKEN) {
-               next_card = qeth_ccwgroup_driver.driver.devices.next;
-               if (next_card->next == next_card) /* list empty */
-                       return NULL;
-               (*offset)++;
-       } else {
-               current_card = (struct list_head *)it;
-               if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
-                       return NULL; /* end of list reached */
-               next_card = current_card->next;
-               (*offset)++;
+               next = driver_find_device(&qeth_ccwgroup_driver.driver,
+                                         NULL, NULL, qeth_procfile_seq_match);
+               if (next)
+                       (*offset)++;
+               return (void *) next;
        }
-
-       return next_card;
+       prev = (struct device *) it;
+       next = driver_find_device(&qeth_ccwgroup_driver.driver,
+                                 prev, NULL, qeth_procfile_seq_match);
+       if (next)
+               (*offset)++;
+       return (void *) next;
 }
 
 static inline const char *
@@ -126,7 +134,7 @@ qeth_procfile_seq_show(struct seq_file *s, void *it)
                              "-------------- ---- ------ ---------- ---- "
                              "---- ----- -----\n");
        } else {
-               device = list_entry(it, struct device, driver_list);
+               device = (struct device *) it;
                card = device->driver_data;
                seq_printf(s, "%s/%s/%s x%02X   %-10s %-14s %-4i ",
                                CARD_RDEV_ID(card),
@@ -180,17 +188,20 @@ static struct proc_dir_entry *qeth_perf_procfile;
 static void *
 qeth_perf_procfile_seq_start(struct seq_file *s, loff_t *offset)
 {
-       struct list_head *next_card = NULL;
-       int i = 0;
+       struct device *dev = NULL;
+       int nr;
 
        down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
        /* get card at pos *offset */
-       list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){
-               if (i == *offset)
-                       return next_card;
-               i++;
-       }
-       return NULL;
+       dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
+                                qeth_procfile_seq_match);
+
+       /* get card at pos *offset */
+       nr = *offset;
+       while (nr-- > 1 && dev)
+               dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev,
+                                        NULL, qeth_procfile_seq_match);
+       return (void *) dev;
 }
 
 static void
@@ -202,12 +213,14 @@ qeth_perf_procfile_seq_stop(struct seq_file *s, void* it)
 static void *
 qeth_perf_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
 {
-       struct list_head *current_card = (struct list_head *)it;
+       struct device *prev, *next;
 
-       if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
-               return NULL; /* end of list reached */
-       (*offset)++;
-       return current_card->next;
+       prev = (struct device *) it;
+       next = driver_find_device(&qeth_ccwgroup_driver.driver, prev,
+                                 NULL, qeth_procfile_seq_match);
+       if (next)
+               (*offset)++;
+       return (void *) next;
 }
 
 static int
@@ -216,7 +229,7 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
        struct device *device;
        struct qeth_card *card;
 
-       device = list_entry(it, struct device, driver_list);
+       device = (struct device *) it;
        card = device->driver_data;
        seq_printf(s, "For card with devnos %s/%s/%s (%s):\n",
                        CARD_RDEV_ID(card),
@@ -318,8 +331,8 @@ static struct proc_dir_entry *qeth_ipato_procfile;
 static void *
 qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset)
 {
-       struct list_head *next_card = NULL;
-       int i = 0;
+       struct device *dev;
+       loff_t nr;
 
        down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
        /* TODO: finish this */
@@ -328,13 +341,16 @@ qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset)
         * output driver settings then;
         * else output setting for respective card
         */
+
+       dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
+                                qeth_procfile_seq_match);
+
        /* get card at pos *offset */
-       list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){
-               if (i == *offset)
-                       return next_card;
-               i++;
-       }
-       return NULL;
+       nr = *offset;
+       while (nr-- > 1 && dev)
+               dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev,
+                                        NULL, qeth_procfile_seq_match);
+       return (void *) dev;
 }
 
 static void
@@ -346,18 +362,14 @@ qeth_ipato_procfile_seq_stop(struct seq_file *s, void* it)
 static void *
 qeth_ipato_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
 {
-       struct list_head *current_card = (struct list_head *)it;
+       struct device *prev, *next;
 
-       /* TODO: finish this */
-       /*
-        * maybe SEQ_SATRT_TOKEN can be returned for offset 0
-        * output driver settings then;
-        * else output setting for respective card
-        */
-       if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
-               return NULL; /* end of list reached */
-       (*offset)++;
-       return current_card->next;
+       prev = (struct device *) it;
+       next = driver_find_device(&qeth_ccwgroup_driver.driver, prev,
+                                 NULL, qeth_procfile_seq_match);
+       if (next)
+               (*offset)++;
+       return (void *) next;
 }
 
 static int
@@ -372,7 +384,7 @@ qeth_ipato_procfile_seq_show(struct seq_file *s, void *it)
         * output driver settings then;
         * else output setting for respective card
         */
-       device = list_entry(it, struct device, driver_list);
+       device = (struct device *) it;
        card = device->driver_data;
 
        return 0;
index e17b4d5..bfe3ba7 100644 (file)
@@ -1299,13 +1299,10 @@ struct zfcp_port *
 zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
                  u32 d_id)
 {
-       struct zfcp_port *port, *tmp_port;
+       struct zfcp_port *port;
        int check_wwpn;
-       scsi_id_t scsi_id;
-       int found;
 
        check_wwpn = !(status & ZFCP_STATUS_PORT_NO_WWPN);
-
        /*
         * check that there is no port with this WWPN already in list
         */
@@ -1368,7 +1365,7 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
        } else {
                snprintf(port->sysfs_device.bus_id,
                         BUS_ID_SIZE, "0x%016llx", wwpn);
-       port->sysfs_device.parent = &adapter->ccw_device->dev;
+               port->sysfs_device.parent = &adapter->ccw_device->dev;
        }
        port->sysfs_device.release = zfcp_sysfs_port_release;
        dev_set_drvdata(&port->sysfs_device, port);
@@ -1388,24 +1385,8 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
 
        zfcp_port_get(port);
 
-       scsi_id = 1;
-       found = 0;
        write_lock_irq(&zfcp_data.config_lock);
-       list_for_each_entry(tmp_port, &adapter->port_list_head, list) {
-               if (atomic_test_mask(ZFCP_STATUS_PORT_NO_SCSI_ID,
-                                    &tmp_port->status))
-                       continue;
-               if (tmp_port->scsi_id != scsi_id) {
-                       found = 1;
-                       break;
-               }
-               scsi_id++;
-       }
-       port->scsi_id = scsi_id;
-       if (found)
-               list_add_tail(&port->list, &tmp_port->list);
-       else
-               list_add_tail(&port->list, &adapter->port_list_head);
+       list_add_tail(&port->list, &adapter->port_list_head);
        atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
        atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status);
        if (d_id == ZFCP_DID_DIRECTORY_SERVICE)
@@ -1427,6 +1408,9 @@ zfcp_port_dequeue(struct zfcp_port *port)
        list_del(&port->list);
        port->adapter->ports--;
        write_unlock_irq(&zfcp_data.config_lock);
+       if (port->rport)
+               fc_remote_port_delete(port->rport);
+       port->rport = NULL;
        zfcp_adapter_put(port->adapter);
        zfcp_sysfs_port_remove_files(&port->sysfs_device,
                                     atomic_read(&port->status));
index 0fc4638..b30abab 100644 (file)
@@ -202,9 +202,19 @@ static int
 zfcp_ccw_set_offline(struct ccw_device *ccw_device)
 {
        struct zfcp_adapter *adapter;
+       struct zfcp_port *port;
+       struct fc_rport *rport;
 
        down(&zfcp_data.config_sema);
        adapter = dev_get_drvdata(&ccw_device->dev);
+       /* might be racy, but we cannot take config_lock due to the fact that
+          fc_remote_port_delete might sleep */
+       list_for_each_entry(port, &adapter->port_list_head, list)
+               if (port->rport) {
+                       rport = port->rport;
+                       port->rport = NULL;
+                       fc_remote_port_delete(rport);
+               }
        zfcp_erp_adapter_shutdown(adapter, 0);
        zfcp_erp_wait(adapter);
        zfcp_adapter_scsi_unregister(adapter);
index 4103b5b..455e902 100644 (file)
@@ -906,6 +906,7 @@ struct zfcp_adapter {
  */
 struct zfcp_port {
        struct device          sysfs_device;   /* sysfs device */
+       struct fc_rport        *rport;         /* rport of fc transport class */
        struct list_head       list;           /* list of remote ports */
        atomic_t               refcount;       /* reference count */
        wait_queue_head_t      remove_wq;      /* can be used to wait for
@@ -916,7 +917,6 @@ struct zfcp_port {
                                                  list */
        u32                    units;          /* # of logical units in list */
        atomic_t               status;         /* status of this remote port */
-       scsi_id_t              scsi_id;        /* own SCSI ID */
        wwn_t                  wwnn;           /* WWNN if known */
        wwn_t                  wwpn;           /* WWPN */
        fc_id_t                d_id;           /* D_ID */
index 0cf31f7..cb4f612 100644 (file)
@@ -3360,13 +3360,32 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
                if ((result == ZFCP_ERP_SUCCEEDED)
                    && (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY,
                                          &unit->status))
-                   && (!unit->device))
-                       scsi_add_device(unit->port->adapter->scsi_host, 0,
-                                       unit->port->scsi_id, unit->scsi_lun);
+                   && !unit->device
+                   && port->rport)
+                       scsi_add_device(port->adapter->scsi_host, 0,
+                                       port->rport->scsi_target_id,
+                                       unit->scsi_lun);
                zfcp_unit_put(unit);
                break;
        case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
        case ZFCP_ERP_ACTION_REOPEN_PORT:
+               if ((result == ZFCP_ERP_SUCCEEDED)
+                   && !atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN,
+                                        &port->status)
+                   && !port->rport) {
+                       struct fc_rport_identifiers ids;
+                       ids.node_name = port->wwnn;
+                       ids.port_name = port->wwpn;
+                       ids.port_id = port->d_id;
+                       ids.roles = FC_RPORT_ROLE_FCP_TARGET;
+                       port->rport =
+                               fc_remote_port_add(adapter->scsi_host, 0, &ids);
+                       if (!port->rport)
+                               ZFCP_LOG_NORMAL("failed registration of rport"
+                                               "(adapter %s, wwpn=0x%016Lx)\n",
+                                               zfcp_get_busid_by_port(port),
+                                               port->wwpn);
+               }
                zfcp_port_put(port);
                break;
        case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
index 42df7e5..cd98a2d 100644 (file)
@@ -143,6 +143,8 @@ extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *,
                                   struct scsi_cmnd *, struct timer_list *);
 extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *,
                                  struct timer_list *);
+extern void zfcp_set_fc_host_attrs(struct zfcp_adapter *);
+extern void zfcp_set_fc_rport_attrs(struct zfcp_port *);
 extern struct scsi_transport_template *zfcp_transport_template;
 extern struct fc_function_template zfcp_transport_functions;
 
index 0d9f20e..c007b64 100644 (file)
@@ -2062,6 +2062,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
                zfcp_erp_adapter_shutdown(adapter, 0);
                return -EIO;
        }
+       zfcp_set_fc_host_attrs(adapter);
        return 0;
 }
 
index b61d309..31a7606 100644 (file)
@@ -389,7 +389,7 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id,
        struct zfcp_unit *unit, *retval = NULL;
 
        list_for_each_entry(port, &adapter->port_list_head, list) {
-               if (id != port->scsi_id)
+               if (!port->rport || (id != port->rport->scsi_target_id))
                        continue;
                list_for_each_entry(unit, &port->unit_list_head, list) {
                        if (lun == unit->scsi_lun) {
@@ -408,7 +408,7 @@ zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id)
        struct zfcp_port *port;
 
        list_for_each_entry(port, &adapter->port_list_head, list) {
-               if (id == port->scsi_id)
+               if (port->rport && (id == port->rport->scsi_target_id))
                        return port;
        }
        return (struct zfcp_port *) NULL;
@@ -634,7 +634,6 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
 {
        int retval;
        struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;
-       struct Scsi_Host *scsi_host = scpnt->device->host;
 
        if (!unit) {
                ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n");
@@ -729,7 +728,6 @@ zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt)
 {
        int retval = 0;
        struct zfcp_unit *unit;
-       struct Scsi_Host *scsi_host = scpnt->device->host;
 
        unit = (struct zfcp_unit *) scpnt->device->hostdata;
        ZFCP_LOG_NORMAL("bus reset because of problems with "
@@ -753,7 +751,6 @@ zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
 {
        int retval = 0;
        struct zfcp_unit *unit;
-       struct Scsi_Host *scsi_host = scpnt->device->host;
 
        unit = (struct zfcp_unit *) scpnt->device->hostdata;
        ZFCP_LOG_NORMAL("host reset because of problems with "
@@ -833,6 +830,7 @@ zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
        shost = adapter->scsi_host;
        if (!shost)
                return;
+       fc_remove_host(shost);
        scsi_remove_host(shost);
        scsi_host_put(shost);
        adapter->scsi_host = NULL;
@@ -906,6 +904,18 @@ zfcp_get_node_name(struct scsi_target *starget)
        read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 }
 
+void
+zfcp_set_fc_host_attrs(struct zfcp_adapter *adapter)
+{
+       struct Scsi_Host *shost = adapter->scsi_host;
+
+       fc_host_node_name(shost) = adapter->wwnn;
+       fc_host_port_name(shost) = adapter->wwpn;
+       strncpy(fc_host_serial_number(shost), adapter->serial_number,
+                min(FC_SERIAL_NUMBER_SIZE, 32));
+       fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
+}
+
 struct fc_function_template zfcp_transport_functions = {
        .get_starget_port_id = zfcp_get_port_id,
        .get_starget_port_name = zfcp_get_port_name,
@@ -913,6 +923,11 @@ struct fc_function_template zfcp_transport_functions = {
        .show_starget_port_id = 1,
        .show_starget_port_name = 1,
        .show_starget_node_name = 1,
+       .show_rport_supported_classes = 1,
+       .show_host_node_name = 1,
+       .show_host_port_name = 1,
+       .show_host_supported_classes = 1,
+       .show_host_serial_number = 1,
 };
 
 /**
index 7a84c7d..c55e82d 100644 (file)
@@ -67,7 +67,6 @@ static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_port_##_name##_show, NULL);
 ZFCP_DEFINE_PORT_ATTR(status, "0x%08x\n", atomic_read(&port->status));
 ZFCP_DEFINE_PORT_ATTR(wwnn, "0x%016llx\n", port->wwnn);
 ZFCP_DEFINE_PORT_ATTR(d_id, "0x%06x\n", port->d_id);
-ZFCP_DEFINE_PORT_ATTR(scsi_id, "0x%x\n", port->scsi_id);
 ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask
                      (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status));
 ZFCP_DEFINE_PORT_ATTR(access_denied, "%d\n", atomic_test_mask
@@ -263,7 +262,6 @@ static struct attribute_group zfcp_port_common_attr_group = {
 static struct attribute *zfcp_port_no_ns_attrs[] = {
        &dev_attr_unit_add.attr,
        &dev_attr_unit_remove.attr,
-       &dev_attr_scsi_id.attr,
        NULL
 };
 
index b8a2c73..d44205d 100644 (file)
@@ -7,6 +7,7 @@
 #define __KERNEL_SYSCALLS__
 
 #include <linux/kernel.h>
+#include <linux/kthread.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -459,10 +460,6 @@ static struct task_struct *kenvctrld_task;
 
 static int kenvctrld(void *__unused)
 {
-       daemonize("kenvctrld");
-       allow_signal(SIGKILL);
-       kenvctrld_task = current;
-
        printk(KERN_INFO "bbc_envctrl: kenvctrld starting...\n");
        last_warning_jiffies = jiffies - WARN_INTERVAL;
        for (;;) {
@@ -470,7 +467,7 @@ static int kenvctrld(void *__unused)
                struct bbc_fan_control *fp;
 
                msleep_interruptible(POLL_INTERVAL);
-               if (signal_pending(current))
+               if (kthread_should_stop())
                        break;
 
                for (tp = all_bbc_temps; tp; tp = tp->next) {
@@ -577,7 +574,6 @@ int bbc_envctrl_init(void)
        int temp_index = 0;
        int fan_index = 0;
        int devidx = 0;
-       int err = 0;
 
        while ((echild = bbc_i2c_getdev(devidx++)) != NULL) {
                if (!strcmp(echild->prom_name, "temperature"))
@@ -585,9 +581,13 @@ int bbc_envctrl_init(void)
                if (!strcmp(echild->prom_name, "fan-control"))
                        attach_one_fan(echild, fan_index++);
        }
-       if (temp_index != 0 && fan_index != 0)
-               err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES);
-       return err;
+       if (temp_index != 0 && fan_index != 0) {
+               kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld");
+               if (IS_ERR(kenvctrld_task))
+                       return PTR_ERR(kenvctrld_task);
+       }
+
+       return 0;
 }
 
 static void destroy_one_temp(struct bbc_cpu_temperature *tp)
@@ -607,26 +607,7 @@ void bbc_envctrl_cleanup(void)
        struct bbc_cpu_temperature *tp;
        struct bbc_fan_control *fp;
 
-       if (kenvctrld_task != NULL) {
-               force_sig(SIGKILL, kenvctrld_task);
-               for (;;) {
-                       struct task_struct *p;
-                       int found = 0;
-
-                       read_lock(&tasklist_lock);
-                       for_each_process(p) {
-                               if (p == kenvctrld_task) {
-                                       found = 1;
-                                       break;
-                               }
-                       }
-                       read_unlock(&tasklist_lock);
-                       if (!found)
-                               break;
-                       msleep(1000);
-               }
-               kenvctrld_task = NULL;
-       }
+       kthread_stop(kenvctrld_task);
 
        tp = all_bbc_temps;
        while (tp != NULL) {
index 9a8c572..d765cc1 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/sched.h>
+#include <linux/kthread.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
@@ -1010,16 +1011,13 @@ static int kenvctrld(void *__unused)
 
        poll_interval = 5000; /* TODO env_mon_interval */
 
-       daemonize("kenvctrld");
-       allow_signal(SIGKILL);
-
-       kenvctrld_task = current;
-
        printk(KERN_INFO "envctrl: %s starting...\n", current->comm);
        for (;;) {
-               if(msleep_interruptible(poll_interval))
-                       break;
+               msleep_interruptible(poll_interval);
 
+               if (kthread_should_stop())
+                       break;
+               
                for (whichcpu = 0; whichcpu < ENVCTRL_MAX_CPU; ++whichcpu) {
                        if (0 < envctrl_read_cpu_info(whichcpu, cputemp,
                                                      ENVCTRL_CPUTEMP_MON,
@@ -1041,7 +1039,6 @@ static int kenvctrld(void *__unused)
 
 static int __init envctrl_init(void)
 {
-#ifdef CONFIG_PCI
        struct linux_ebus *ebus = NULL;
        struct linux_ebus_device *edev = NULL;
        struct linux_ebus_child *edev_child = NULL;
@@ -1118,9 +1115,11 @@ done:
                        i2c_childlist[i].addr, (0 == i) ? ("\n") : (" "));
        }
 
-       err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES);
-       if (err < 0)
+       kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld");
+       if (IS_ERR(kenvctrld_task)) {
+               err = PTR_ERR(kenvctrld_task);
                goto out_deregister;
+       }
 
        return 0;
 
@@ -1133,37 +1132,13 @@ out_iounmap:
                        kfree(i2c_childlist[i].tables);
        }
        return err;
-#else
-       return -ENODEV;
-#endif
 }
 
 static void __exit envctrl_cleanup(void)
 {
        int i;
 
-       if (NULL != kenvctrld_task) {
-               force_sig(SIGKILL, kenvctrld_task);
-               for (;;) {
-                       struct task_struct *p;
-                       int found = 0;
-
-                       read_lock(&tasklist_lock);
-                       for_each_process(p) {
-                               if (p == kenvctrld_task) {
-                                       found = 1;
-                                       break;
-                               }
-                       }
-                       read_unlock(&tasklist_lock);
-
-                       if (!found)
-                               break;
-
-                       msleep(1000);
-               }
-               kenvctrld_task = NULL;
-       }
+       kthread_stop(kenvctrld_task);
 
        iounmap(i2c);
        misc_deregister(&envctrl_dev);
index e56a43a..a7782e7 100644 (file)
@@ -129,8 +129,6 @@ struct vfc_dev {
        struct vfc_regs *phys_regs;
        unsigned int control_reg;
        struct semaphore device_lock_sem;
-       struct timer_list poll_timer;
-       wait_queue_head_t poll_wait;
        int instance;
        int busy;
        unsigned long which_io;
index 86ce541..7a10369 100644 (file)
@@ -137,7 +137,6 @@ int init_vfc_devstruct(struct vfc_dev *dev, int instance)
        dev->instance=instance;
        init_MUTEX(&dev->device_lock_sem);
        dev->control_reg=0;
-       init_waitqueue_head(&dev->poll_wait);
        dev->busy=0;
        return 0;
 }
index 1faf1e7..739cad9 100644 (file)
@@ -79,25 +79,10 @@ int vfc_pcf8584_init(struct vfc_dev *dev)
        return 0;
 }
 
-void vfc_i2c_delay_wakeup(struct vfc_dev *dev) 
-{
-       /* Used to profile code and eliminate too many delays */
-       VFC_I2C_DEBUG_PRINTK(("vfc%d: Delaying\n", dev->instance));
-       wake_up(&dev->poll_wait);
-}
-
 void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs) 
 {
-       DEFINE_WAIT(wait);
-       init_timer(&dev->poll_timer);
-       dev->poll_timer.expires = jiffies + usecs_to_jiffies(usecs);
-       dev->poll_timer.data=(unsigned long)dev;
-       dev->poll_timer.function=(void *)(unsigned long)vfc_i2c_delay_wakeup;
-       add_timer(&dev->poll_timer);
-       prepare_to_wait(&dev->poll_wait, &wait, TASK_UNINTERRUPTIBLE);
-       schedule();
-       del_timer(&dev->poll_timer);
-       finish_wait(&dev->poll_wait, &wait);
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       schedule_timeout(usecs_to_jiffies(usecs));
 }
 
 void inline vfc_i2c_delay(struct vfc_dev *dev) 
index 96df148..12c208f 100644 (file)
@@ -424,7 +424,7 @@ config SCSI_IN2000
 source "drivers/scsi/megaraid/Kconfig.megaraid"
 
 config SCSI_SATA
-       bool "Serial ATA (SATA) support"
+       tristate "Serial ATA (SATA) support"
        depends on SCSI
        help
          This driver family supports Serial ATA host controllers
@@ -1696,7 +1696,7 @@ config TT_DMA_EMUL
 
 config MAC_SCSI
        bool "Macintosh NCR5380 SCSI"
-       depends on MAC && SCSI
+       depends on MAC && SCSI=y
        help
          This is the NCR 5380 SCSI controller included on most of the 68030
          based Macintoshes.  If you have one of these say Y and read the
@@ -1717,7 +1717,7 @@ config SCSI_MAC_ESP
 
 config MVME147_SCSI
        bool "WD33C93 SCSI driver for MVME147"
-       depends on MVME147 && SCSI
+       depends on MVME147 && SCSI=y
        help
          Support for the on-board SCSI controller on the Motorola MVME147
          single-board computer.
@@ -1758,7 +1758,7 @@ config SUN3_SCSI
 
 config SUN3X_ESP
        bool "Sun3x ESP SCSI"
-       depends on SUN3X && SCSI
+       depends on SUN3X && SCSI=y
        help
          The ESP was an on-board SCSI controller used on Sun 3/80
          machines.  Say Y here to compile in support for it.
index 3a11a53..4ab0786 100644 (file)
 #define AAC_MAX_LUN            (8)
 
 #define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff)
-/*
- *  max_sectors is an unsigned short, otherwise limit is 0x100000000 / 512
- * Linux has starvation problems if we permit larger than 4MB I/O ...
- */
-#define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)8192)
+#define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)512)
 
 /*
  * These macros convert from physical channels to virtual channels
index c1a4f97..562da90 100644 (file)
@@ -374,7 +374,8 @@ static int aac_slave_configure(struct scsi_device *sdev)
        else
                scsi_adjust_queue_depth(sdev, 0, 1);
 
-       if (host->max_sectors < AAC_MAX_32BIT_SGBCOUNT)
+       if (!(((struct aac_dev *)host->hostdata)->adapter_info.options
+         & AAC_OPT_NEW_COMM))
                blk_queue_max_segment_size(sdev->request_queue, 65536);
 
        return 0;
index c562369..841f4e2 100644 (file)
@@ -269,6 +269,8 @@ static struct pci_device_id ahci_pci_tbl[] = {
          board_ahci }, /* ESB2 */
        { PCI_VENDOR_ID_INTEL, 0x2683, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
          board_ahci }, /* ESB2 */
+       { PCI_VENDOR_ID_INTEL, 0x27c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ICH7-M DH */
        { }     /* terminate list */
 };
 
@@ -584,12 +586,16 @@ static void ahci_intr_error(struct ata_port *ap, u32 irq_stat)
 
 static void ahci_eng_timeout(struct ata_port *ap)
 {
-       void *mmio = ap->host_set->mmio_base;
+       struct ata_host_set *host_set = ap->host_set;
+       void *mmio = host_set->mmio_base;
        void *port_mmio = ahci_port_base(mmio, ap->port_no);
        struct ata_queued_cmd *qc;
+       unsigned long flags;
 
        DPRINTK("ENTER\n");
 
+       spin_lock_irqsave(&host_set->lock, flags);
+
        ahci_intr_error(ap, readl(port_mmio + PORT_IRQ_STAT));
 
        qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -607,6 +613,7 @@ static void ahci_eng_timeout(struct ata_port *ap)
                ata_qc_complete(qc, ATA_ERR);
        }
 
+       spin_unlock_irqrestore(&host_set->lock, flags);
 }
 
 static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
@@ -696,9 +703,6 @@ static int ahci_qc_issue(struct ata_queued_cmd *qc)
        struct ata_port *ap = qc->ap;
        void *port_mmio = (void *) ap->ioaddr.cmd_addr;
 
-       writel(1, port_mmio + PORT_SCR_ACT);
-       readl(port_mmio + PORT_SCR_ACT);        /* flush */
-
        writel(1, port_mmio + PORT_CMD_ISSUE);
        readl(port_mmio + PORT_CMD_ISSUE);      /* flush */
 
@@ -1105,6 +1109,7 @@ MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("AHCI SATA low-level driver");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
 
 module_init(ahci_init);
 module_exit(ahci_exit);
index 116d0f5..687f19e 100644 (file)
@@ -1264,14 +1264,12 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
        }
        switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) {
        case AHC_DEV_Q_BASIC:
-               scsi_adjust_queue_depth(sdev,
-                                       MSG_SIMPLE_TASK,
-                                       dev->openings + dev->active);
+               scsi_set_tag_type(sdev, MSG_SIMPLE_TAG);
+               scsi_activate_tcq(sdev, dev->openings + dev->active);
                break;
        case AHC_DEV_Q_TAGGED:
-               scsi_adjust_queue_depth(sdev,
-                                       MSG_ORDERED_TASK,
-                                       dev->openings + dev->active);
+               scsi_set_tag_type(sdev, MSG_ORDERED_TAG);
+               scsi_activate_tcq(sdev, dev->openings + dev->active);
                break;
        default:
                /*
@@ -1280,9 +1278,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
                 * serially on the controller/device.  This should
                 * remove some latency.
                 */
-               scsi_adjust_queue_depth(sdev,
-                                       /*NON-TAGGED*/0,
-                                       /*queue depth*/2);
+               scsi_deactivate_tcq(sdev, 2);
                break;
        }
 }
@@ -1635,9 +1631,9 @@ ahc_send_async(struct ahc_softc *ahc, char channel,
                spi_period(starget) = tinfo->curr.period;
                spi_width(starget) = tinfo->curr.width;
                spi_offset(starget) = tinfo->curr.offset;
-               spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ;
-               spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ;
-               spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ;
+               spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ ? 1 : 0;
+               spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ ? 1 : 0;
+               spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ ? 1 : 0;
                spi_display_xfer_agreement(starget);
                break;
        }
@@ -2429,12 +2425,14 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt)
        unsigned int ppr_options = tinfo->goal.ppr_options
                & ~MSG_EXT_PPR_DT_REQ;
        unsigned int period = tinfo->goal.period;
+       unsigned int width = tinfo->goal.width;
        unsigned long flags;
        struct ahc_syncrate *syncrate;
 
        if (dt) {
-               period = 9;     /* 12.5ns is the only period valid for DT */
                ppr_options |= MSG_EXT_PPR_DT_REQ;
+               if (!width)
+                       ahc_linux_set_width(starget, 1);
        } else if (period == 9)
                period = 10;    /* if resetting DT, period must be >= 25ns */
 
index c346394..f936b69 100644 (file)
@@ -369,7 +369,7 @@ output_code()
 
                fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x",
                        cur_instr == STAILQ_FIRST(&seq_program) ? "" : ",\n",
-#if BYTE_ORDER == LITTLE_ENDIAN
+#ifdef __LITTLE_ENDIAN
                        cur_instr->format.bytes[0],
                        cur_instr->format.bytes[1],
                        cur_instr->format.bytes[2],
@@ -613,7 +613,7 @@ output_listing(char *ifilename)
                                line++;
                }
                fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr,
-#if BYTE_ORDER == LITTLE_ENDIAN
+#ifdef __LITTLE_ENDIAN
                        cur_instr->format.bytes[0],
                        cur_instr->format.bytes[1],
                        cur_instr->format.bytes[2],
index 3e80f07..e64f802 100644 (file)
  * $FreeBSD$
  */
 
+#include <asm/byteorder.h>
+
 struct ins_format1 {
-#if BYTE_ORDER == LITTLE_ENDIAN
+#ifdef __LITTLE_ENDIAN
        uint32_t        immediate       : 8,
                        source          : 9,
                        destination     : 9,
@@ -61,7 +63,7 @@ struct ins_format1 {
 };
 
 struct ins_format2 {
-#if BYTE_ORDER == LITTLE_ENDIAN
+#ifdef __LITTLE_ENDIAN
        uint32_t        shift_control   : 8,
                        source          : 9,
                        destination     : 9,
@@ -79,7 +81,7 @@ struct ins_format2 {
 };
 
 struct ins_format3 {
-#if BYTE_ORDER == LITTLE_ENDIAN
+#ifdef __LITTLE_ENDIAN
        uint32_t        immediate       : 8,
                        source          : 9,
                        address         : 10,
index 54b3286..13f2304 100644 (file)
@@ -3,7 +3,7 @@
 #
 config SCSI_ACORNSCSI_3
        tristate "Acorn SCSI card (aka30) support"
-       depends on ARCH_ACORN && SCSI
+       depends on ARCH_ACORN && SCSI && BROKEN
        help
          This enables support for the Acorn SCSI card (aka30). If you have an
          Acorn system with one of these, say Y. If unsure, say N.
index a2cfade..0369561 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "ata_piix"
-#define DRV_VERSION    "1.03"
+#define DRV_VERSION    "1.04"
 
 enum {
        PIIX_IOCFG              = 0x54, /* IDE I/O configuration register */
@@ -629,13 +629,13 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        port_info[1] = NULL;
 
        if (port_info[0]->host_flags & PIIX_FLAG_AHCI) {
-               u8 tmp;
-               pci_read_config_byte(pdev, PIIX_SCC, &tmp);
-               if (tmp == PIIX_AHCI_DEVICE) {
-                       int rc = piix_disable_ahci(pdev);
-                       if (rc)
-                           return rc;
-               }
+               u8 tmp;
+               pci_read_config_byte(pdev, PIIX_SCC, &tmp);
+               if (tmp == PIIX_AHCI_DEVICE) {
+                       int rc = piix_disable_ahci(pdev);
+                       if (rc)
+                               return rc;
+               }
        }
 
        if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) {
index 929170d..600ba12 100644 (file)
  * cross a page boundy.
  */
 #define SEGMENTX_LEN   (sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY)
-#define VIRTX_LEN      (sizeof(void *) * DC395x_MAX_SG_LISTENTRY)
+
 
 struct SGentry {
        u32 address;            /* bus! address */
@@ -235,7 +235,6 @@ struct ScsiReqBlk {
        u8 sg_count;                    /* No of HW sg entries for this request */
        u8 sg_index;                    /* Index of HW sg entry for this request */
        u32 total_xfer_length;          /* Total number of bytes remaining to be transfered */
-       void **virt_map;
        unsigned char *virt_addr;       /* Virtual address of current transfer position */
 
        /*
@@ -1022,14 +1021,14 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
                        reqlen, cmd->request_buffer, cmd->use_sg,
                        srb->sg_count);
 
+               srb->virt_addr = page_address(sl->page);
                for (i = 0; i < srb->sg_count; i++) {
-                       u32 seglen = (u32)sg_dma_len(sl + i);
-                       sgp[i].address = (u32)sg_dma_address(sl + i);
+                       u32 busaddr = (u32)sg_dma_address(&sl[i]);
+                       u32 seglen = (u32)sl[i].length;
+                       sgp[i].address = busaddr;
                        sgp[i].length = seglen;
                        srb->total_xfer_length += seglen;
-                       srb->virt_map[i] = kmap(sl[i].page);
                }
-               srb->virt_addr = srb->virt_map[0];
                sgp += srb->sg_count - 1;
 
                /*
@@ -1976,7 +1975,6 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
        int segment = cmd->use_sg;
        u32 xferred = srb->total_xfer_length - left; /* bytes transfered */
        struct SGentry *psge = srb->segment_x + srb->sg_index;
-       void **virt = srb->virt_map;
 
        dprintkdbg(DBG_0,
                "sg_update_list: Transfered %i of %i bytes, %i remain\n",
@@ -2016,16 +2014,16 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
 
        /* We have to walk the scatterlist to find it */
        sg = (struct scatterlist *)cmd->request_buffer;
-       idx = 0;
        while (segment--) {
                unsigned long mask =
                    ~((unsigned long)sg->length - 1) & PAGE_MASK;
                if ((sg_dma_address(sg) & mask) == (psge->address & mask)) {
-                       srb->virt_addr = virt[idx] + (psge->address & ~PAGE_MASK);
+                       srb->virt_addr = (page_address(sg->page)
+                                          + psge->address -
+                                          (psge->address & PAGE_MASK));
                        return;
                }
                ++sg;
-               ++idx;
        }
 
        dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n");
@@ -2151,7 +2149,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
                                DC395x_read32(acb, TRM_S1040_DMA_CXCNT));
                }
                /*
-                * calculate all the residue data that not yet transfered
+                * calculate all the residue data that not yet tranfered
                 * SCSI transfer counter + left in SCSI FIFO data
                 *
                 * .....TRM_S1040_SCSI_COUNTER (24bits)
@@ -3269,7 +3267,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
        struct scsi_cmnd *cmd = srb->cmd;
        enum dma_data_direction dir = cmd->sc_data_direction;
        if (cmd->use_sg && dir != PCI_DMA_NONE) {
-               int i;
                /* unmap DC395x SG list */
                dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n",
                        srb->sg_bus_addr, SEGMENTX_LEN);
@@ -3279,8 +3276,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
                dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n",
                        cmd->use_sg, cmd->request_buffer);
                /* unmap the sg segments */
-               for (i = 0; i < srb->sg_count; i++)
-                       kunmap(virt_to_page(srb->virt_map[i]));
                pci_unmap_sg(acb->dev,
                             (struct scatterlist *)cmd->request_buffer,
                             cmd->use_sg, dir);
@@ -3327,7 +3322,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
 
        if (cmd->use_sg) {
                struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
-               ptr = (struct ScsiInqData *)(srb->virt_map[0] + sg->offset);
+               ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset);
        } else {
                ptr = (struct ScsiInqData *)(cmd->request_buffer);
        }
@@ -4262,9 +4257,8 @@ static void adapter_sg_tables_free(struct AdapterCtlBlk *acb)
        const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN;
 
        for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page)
-               kfree(acb->srb_array[i].segment_x);
-
-       vfree(acb->srb_array[0].virt_map);
+               if (acb->srb_array[i].segment_x)
+                       kfree(acb->srb_array[i].segment_x);
 }
 
 
@@ -4280,12 +4274,9 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
        int srb_idx = 0;
        unsigned i = 0;
        struct SGentry *ptr;
-       void **virt_array;
 
-       for (i = 0; i < DC395x_MAX_SRB_CNT; i++) {
+       for (i = 0; i < DC395x_MAX_SRB_CNT; i++)
                acb->srb_array[i].segment_x = NULL;
-               acb->srb_array[i].virt_map = NULL;
-       }
 
        dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages);
        while (pages--) {
@@ -4306,19 +4297,6 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
                    ptr + (i * DC395x_MAX_SG_LISTENTRY);
        else
                dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n");
-
-       virt_array = vmalloc((DC395x_MAX_SRB_CNT + 1) * DC395x_MAX_SG_LISTENTRY * sizeof(void*));
-
-       if (!virt_array) {
-               adapter_sg_tables_free(acb);
-               return 1;
-       }
-
-       for (i = 0; i < DC395x_MAX_SRB_CNT + 1; i++) {
-               acb->srb_array[i].virt_map = virt_array;
-               virt_array += DC395x_MAX_SG_LISTENTRY;
-       }
-
        return 0;
 }
 
index e237052..7235f94 100644 (file)
@@ -907,9 +907,13 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
                raptorFlag = TRUE;
        }
 
-
+       if (pci_request_regions(pDev, "dpt_i2o")) {
+               PERROR("dpti: adpt_config_hba: pci request region failed\n");
+               return -EINVAL;
+       }
        base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size);
        if (!base_addr_virt) {
+               pci_release_regions(pDev);
                PERROR("dpti: adpt_config_hba: io remap failed\n");
                return -EINVAL;
        }
@@ -919,6 +923,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
                if (!msg_addr_virt) {
                        PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n");
                        iounmap(base_addr_virt);
+                       pci_release_regions(pDev);
                        return -EINVAL;
                }
        } else {
@@ -932,6 +937,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
                        iounmap(msg_addr_virt);
                }
                iounmap(base_addr_virt);
+               pci_release_regions(pDev);
                return -ENOMEM;
        }
        memset(pHba, 0, sizeof(adpt_hba));
@@ -1027,6 +1033,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba)
        up(&adpt_configuration_lock);
 
        iounmap(pHba->base_addr_virt);
+       pci_release_regions(pHba->pDev);
        if(pHba->msg_addr_virt != pHba->base_addr_virt){
                iounmap(pHba->msg_addr_virt);
        }
index 2ae5154..7d8e4c4 100644 (file)
@@ -35,7 +35,7 @@
 enum srp_types {
        SRP_LOGIN_REQ_TYPE = 0x00,
        SRP_LOGIN_RSP_TYPE = 0xC0,
-       SRP_LOGIN_REJ_TYPE = 0x80,
+       SRP_LOGIN_REJ_TYPE = 0xC2,
        SRP_I_LOGOUT_TYPE = 0x03,
        SRP_T_LOGOUT_TYPE = 0x80,
        SRP_TSK_MGMT_TYPE = 0x01,
index 6dfcb4f..4cdd891 100644 (file)
 /* 6.10.00  - Remove 1G Addressing Limitations                               */
 /* 6.11.xx  - Get VersionInfo buffer off the stack !              DDTS 60401 */
 /* 6.11.xx  - Make Logical Drive Info structure safe for DMA      DDTS 60639 */
-/* 7.10.xx  - Add highmem_io flag in SCSI Templete for 2.4 kernels           */
+/* 7.10.18  - Add highmem_io flag in SCSI Templete for 2.4 kernels           */
 /*          - Fix path/name for scsi_hosts.h include for 2.6 kernels         */
 /*          - Fix sort order of 7k                                           */
 /*          - Remove 3 unused "inline" functions                             */
+/* 7.12.xx  - Use STATIC functions whereever possible                        */
+/*          - Clean up deprecated MODULE_PARM calls                          */
 /*****************************************************************************/
 
 /*
@@ -207,8 +209,8 @@ module_param(ips, charp, 0);
 /*
  * DRIVER_VER
  */
-#define IPS_VERSION_HIGH        "7.10"
-#define IPS_VERSION_LOW         ".18 "
+#define IPS_VERSION_HIGH        "7.12"
+#define IPS_VERSION_LOW         ".02 "
 
 #if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__)
 #warning "This driver has only been tested on the x86/ia64/x86_64 platforms"
index 480e06f..505e967 100644 (file)
       #define scsi_set_pci_device(sh,dev) (0)
    #endif
 
-   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-   
-      #ifndef irqreturn_t
-         typedef void irqreturn_t;
-      #endif 
-      
+   #ifndef IRQ_NONE
+      typedef void irqreturn_t;
       #define IRQ_NONE
       #define IRQ_HANDLED
       #define IRQ_RETVAL(x)
+   #endif
+   
+   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
       #define IPS_REGISTER_HOSTS(SHT)      scsi_register_module(MODULE_SCSI_HA,SHT)
       #define IPS_UNREGISTER_HOSTS(SHT)    scsi_unregister_module(MODULE_SCSI_HA,SHT)
       #define IPS_ADD_HOST(shost,device)
    #ifndef min
       #define min(x,y) ((x) < (y) ? x : y)
    #endif
+   
+   #ifndef __iomem       /* For clean compiles in earlier kernels without __iomem annotations */
+      #define __iomem
+   #endif
 
    #define pci_dma_hi32(a)         ((a >> 16) >> 16)
    #define pci_dma_lo32(a)         (a & 0xffffffff)
@@ -1206,13 +1209,13 @@ typedef struct {
 
 #define IPS_VER_MAJOR 7
 #define IPS_VER_MAJOR_STRING "7"
-#define IPS_VER_MINOR 10
-#define IPS_VER_MINOR_STRING "10"
-#define IPS_VER_BUILD 18
-#define IPS_VER_BUILD_STRING "18"
-#define IPS_VER_STRING "7.10.18"
+#define IPS_VER_MINOR 12
+#define IPS_VER_MINOR_STRING "12"
+#define IPS_VER_BUILD 02
+#define IPS_VER_BUILD_STRING "02"
+#define IPS_VER_STRING "7.12.02"
 #define IPS_RELEASE_ID 0x00020000
-#define IPS_BUILD_IDENT 731
+#define IPS_BUILD_IDENT 761
 #define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2002. All Rights Reserved."
 #define IPS_ADAPTECCOPYRIGHT_STRING "(c) Copyright Adaptec, Inc. 2002 to 2004. All Rights Reserved."
 #define IPS_DELLCOPYRIGHT_STRING "(c) Copyright Dell 2004. All Rights Reserved."
@@ -1223,12 +1226,12 @@ typedef struct {
 #define IPS_VER_SERVERAID2 "2.88.13"
 #define IPS_VER_NAVAJO "2.88.13"
 #define IPS_VER_SERVERAID3 "6.10.24"
-#define IPS_VER_SERVERAID4H "7.10.11"
-#define IPS_VER_SERVERAID4MLx "7.10.18"
-#define IPS_VER_SARASOTA "7.10.18"
-#define IPS_VER_MARCO "7.10.18"
-#define IPS_VER_SEBRING "7.10.18"
-#define IPS_VER_KEYWEST "7.10.18"
+#define IPS_VER_SERVERAID4H "7.12.02"
+#define IPS_VER_SERVERAID4MLx "7.12.02"
+#define IPS_VER_SARASOTA "7.12.02"
+#define IPS_VER_MARCO "7.12.02"
+#define IPS_VER_SEBRING "7.12.02"
+#define IPS_VER_KEYWEST "7.12.02"
 
 /* Compatability IDs for various adapters */
 #define IPS_COMPAT_UNKNOWN ""
index 73b1f72..f15a07f 100644 (file)
@@ -1304,12 +1304,12 @@ static inline u8 ata_dev_knobble(struct ata_port *ap)
 /**
  *     ata_dev_config - Run device specific handlers and check for
  *                      SATA->PATA bridges
- *     @ap: Bus 
+ *     @ap: Bus
  *     @i:  Device
  *
  *     LOCKING:
  */
+
 void ata_dev_config(struct ata_port *ap, unsigned int i)
 {
        /* limit bridge transfers to udma5, 200 sectors */
@@ -2268,19 +2268,6 @@ void ata_qc_prep(struct ata_queued_cmd *qc)
  *     spin_lock_irqsave(host_set lock)
  */
 
-
-
-/**
- *     ata_sg_init_one - Prepare a one-entry scatter-gather list.
- *     @qc:  Queued command
- *     @buf:  transfer buffer
- *     @buflen:  length of buf
- *
- *     Builds a single-entry scatter-gather list to initiate a
- *     transfer utilizing the specified buffer.
- *
- *     LOCKING:
- */
 void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
 {
        struct scatterlist *sg;
@@ -2312,18 +2299,6 @@ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
  *     spin_lock_irqsave(host_set lock)
  */
 
-
-/**
- *     ata_sg_init - Assign a scatter gather list to a queued command
- *     @qc:  Queued command
- *     @sg:  Scatter-gather list
- *     @n_elem:  length of sg list
- *
- *     Attaches a scatter-gather list to a queued command.
- *
- *     LOCKING:
- */
-
 void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
                 unsigned int n_elem)
 {
@@ -2401,6 +2376,27 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
        return 0;
 }
 
+/**
+ *     ata_poll_qc_complete - turn irq back on and finish qc
+ *     @qc: Command to complete
+ *     @drv_stat: ATA status register content
+ *
+ *     LOCKING:
+ *     None.  (grabs host lock)
+ */
+
+void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+{
+       struct ata_port *ap = qc->ap;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       ap->flags &= ~ATA_FLAG_NOINTR;
+       ata_irq_on(ap);
+       ata_qc_complete(qc, drv_stat);
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+}
+
 /**
  *     ata_pio_poll -
  *     @ap:
@@ -2463,11 +2459,10 @@ static void ata_pio_complete (struct ata_port *ap)
        u8 drv_stat;
 
        /*
-        * This is purely hueristic.  This is a fast path.
-        * Sometimes when we enter, BSY will be cleared in
-        * a chk-status or two.  If not, the drive is probably seeking
-        * or something.  Snooze for a couple msecs, then
-        * chk-status again.  If still busy, fall back to
+        * This is purely heuristic.  This is a fast path.  Sometimes when
+        * we enter, BSY will be cleared in a chk-status or two.  If not,
+        * the drive is probably seeking or something.  Snooze for a couple
+        * msecs, then chk-status again.  If still busy, fall back to
         * PIO_ST_POLL state.
         */
        drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
@@ -2492,9 +2487,7 @@ static void ata_pio_complete (struct ata_port *ap)
 
        ap->pio_task_state = PIO_ST_IDLE;
 
-       ata_irq_on(ap);
-
-       ata_qc_complete(qc, drv_stat);
+       ata_poll_qc_complete(qc, drv_stat);
 }
 
 
@@ -2519,6 +2512,20 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
 #endif /* __BIG_ENDIAN */
 }
 
+/**
+ *     ata_mmio_data_xfer - Transfer data by MMIO
+ *     @ap: port to read/write
+ *     @buf: data buffer
+ *     @buflen: buffer length
+ *     @do_write: read/write
+ *
+ *     Transfer data from/to the device data register by MMIO.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ *
+ */
+
 static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
                               unsigned int buflen, int write_data)
 {
@@ -2527,6 +2534,7 @@ static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
        u16 *buf16 = (u16 *) buf;
        void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
 
+       /* Transfer multiple of 2 bytes */
        if (write_data) {
                for (i = 0; i < words; i++)
                        writew(le16_to_cpu(buf16[i]), mmio);
@@ -2534,19 +2542,76 @@ static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
                for (i = 0; i < words; i++)
                        buf16[i] = cpu_to_le16(readw(mmio));
        }
+
+       /* Transfer trailing 1 byte, if any. */
+       if (unlikely(buflen & 0x01)) {
+               u16 align_buf[1] = { 0 };
+               unsigned char *trailing_buf = buf + buflen - 1;
+
+               if (write_data) {
+                       memcpy(align_buf, trailing_buf, 1);
+                       writew(le16_to_cpu(align_buf[0]), mmio);
+               } else {
+                       align_buf[0] = cpu_to_le16(readw(mmio));
+                       memcpy(trailing_buf, align_buf, 1);
+               }
+       }
 }
 
+/**
+ *     ata_pio_data_xfer - Transfer data by PIO
+ *     @ap: port to read/write
+ *     @buf: data buffer
+ *     @buflen: buffer length
+ *     @do_write: read/write
+ *
+ *     Transfer data from/to the device data register by PIO.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ *
+ */
+
 static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
                              unsigned int buflen, int write_data)
 {
-       unsigned int dwords = buflen >> 1;
+       unsigned int words = buflen >> 1;
 
+       /* Transfer multiple of 2 bytes */
        if (write_data)
-               outsw(ap->ioaddr.data_addr, buf, dwords);
+               outsw(ap->ioaddr.data_addr, buf, words);
        else
-               insw(ap->ioaddr.data_addr, buf, dwords);
+               insw(ap->ioaddr.data_addr, buf, words);
+
+       /* Transfer trailing 1 byte, if any. */
+       if (unlikely(buflen & 0x01)) {
+               u16 align_buf[1] = { 0 };
+               unsigned char *trailing_buf = buf + buflen - 1;
+
+               if (write_data) {
+                       memcpy(align_buf, trailing_buf, 1);
+                       outw(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
+               } else {
+                       align_buf[0] = cpu_to_le16(inw(ap->ioaddr.data_addr));
+                       memcpy(trailing_buf, align_buf, 1);
+               }
+       }
 }
 
+/**
+ *     ata_data_xfer - Transfer data from/to the data register.
+ *     @ap: port to read/write
+ *     @buf: data buffer
+ *     @buflen: buffer length
+ *     @do_write: read/write
+ *
+ *     Transfer data from/to the device data register.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ *
+ */
+
 static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
                          unsigned int buflen, int do_write)
 {
@@ -2556,6 +2621,16 @@ static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
                ata_pio_data_xfer(ap, buf, buflen, do_write);
 }
 
+/**
+ *     ata_pio_sector - Transfer ATA_SECT_SIZE (512 bytes) of data.
+ *     @qc: Command on going
+ *
+ *     Transfer ATA_SECT_SIZE of data from/to the ATA device.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+
 static void ata_pio_sector(struct ata_queued_cmd *qc)
 {
        int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
@@ -2594,6 +2669,18 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
        kunmap(page);
 }
 
+/**
+ *     __atapi_pio_bytes - Transfer data from/to the ATAPI device.
+ *     @qc: Command on going
+ *     @bytes: number of bytes
+ *
+ *     Transfer Transfer data from/to the ATAPI device.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ *
+ */
+
 static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
 {
        int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
@@ -2603,10 +2690,33 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
        unsigned char *buf;
        unsigned int offset, count;
 
-       if (qc->curbytes == qc->nbytes - bytes)
+       if (qc->curbytes + bytes >= qc->nbytes)
                ap->pio_task_state = PIO_ST_LAST;
 
 next_sg:
+       if (unlikely(qc->cursg >= qc->n_elem)) {
+               /* 
+                * The end of qc->sg is reached and the device expects
+                * more data to transfer. In order not to overrun qc->sg
+                * and fulfill length specified in the byte count register,
+                *    - for read case, discard trailing data from the device
+                *    - for write case, padding zero data to the device
+                */
+               u16 pad_buf[1] = { 0 };
+               unsigned int words = bytes >> 1;
+               unsigned int i;
+
+               if (words) /* warning if bytes > 1 */
+                       printk(KERN_WARNING "ata%u: %u bytes trailing data\n", 
+                              ap->id, bytes);
+
+               for (i = 0; i < words; i++)
+                       ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write);
+
+               ap->pio_task_state = PIO_ST_LAST;
+               return;
+       }
+
        sg = &qc->sg[qc->cursg];
 
        page = sg->page;
@@ -2640,11 +2750,21 @@ next_sg:
 
        kunmap(page);
 
-       if (bytes) {
+       if (bytes)
                goto next_sg;
-       }
 }
 
+/**
+ *     atapi_pio_bytes - Transfer data from/to the ATAPI device.
+ *     @qc: Command on going
+ *
+ *     Transfer Transfer data from/to the ATAPI device.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ *
+ */
+
 static void atapi_pio_bytes(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
@@ -2717,9 +2837,7 @@ static void ata_pio_block(struct ata_port *ap)
                if ((status & ATA_DRQ) == 0) {
                        ap->pio_task_state = PIO_ST_IDLE;
 
-                       ata_irq_on(ap);
-
-                       ata_qc_complete(qc, status);
+                       ata_poll_qc_complete(qc, status);
                        return;
                }
 
@@ -2749,9 +2867,7 @@ static void ata_pio_error(struct ata_port *ap)
 
        ap->pio_task_state = PIO_ST_IDLE;
 
-       ata_irq_on(ap);
-
-       ata_qc_complete(qc, drv_stat | ATA_ERR);
+       ata_poll_qc_complete(qc, drv_stat | ATA_ERR);
 }
 
 static void ata_pio_task(void *_data)
@@ -2857,8 +2973,10 @@ static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
 static void ata_qc_timeout(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
+       struct ata_host_set *host_set = ap->host_set;
        struct ata_device *dev = qc->dev;
        u8 host_stat = 0, drv_stat;
+       unsigned long flags;
 
        DPRINTK("ENTER\n");
 
@@ -2869,7 +2987,9 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
                if (!(cmd->eh_eflags & SCSI_EH_CANCEL_CMD)) {
 
                        /* finish completing original command */
+                       spin_lock_irqsave(&host_set->lock, flags);
                        __ata_qc_complete(qc);
+                       spin_unlock_irqrestore(&host_set->lock, flags);
 
                        atapi_request_sense(ap, dev, cmd);
 
@@ -2880,6 +3000,8 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
                }
        }
 
+       spin_lock_irqsave(&host_set->lock, flags);
+
        /* hack alert!  We cannot use the supplied completion
         * function from inside the ->eh_strategy_handler() thread.
         * libata is the only user of ->eh_strategy_handler() in
@@ -2895,7 +3017,7 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
                host_stat = ap->ops->bmdma_status(ap);
 
                /* before we do anything else, clear DMA-Start bit */
-               ap->ops->bmdma_stop(ap);
+               ap->ops->bmdma_stop(qc);
 
                /* fall through */
 
@@ -2913,6 +3035,9 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
                ata_qc_complete(qc, drv_stat);
                break;
        }
+
+       spin_unlock_irqrestore(&host_set->lock, flags);
+
 out:
        DPRINTK("EXIT\n");
 }
@@ -3086,9 +3211,14 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
        if (likely(qc->flags & ATA_QCFLAG_DMAMAP))
                ata_sg_clean(qc);
 
+       /* atapi: mark qc as inactive to prevent the interrupt handler
+        * from completing the command twice later, before the error handler
+        * is called. (when rc != 0 and atapi request sense is needed)
+        */
+       qc->flags &= ~ATA_QCFLAG_ACTIVE;
+
        /* call completion callback */
        rc = qc->complete_fn(qc, drv_stat);
-       qc->flags &= ~ATA_QCFLAG_ACTIVE;
 
        /* if callback indicates not to complete command (non-zero),
         * return immediately
@@ -3218,11 +3348,13 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc)
                break;
 
        case ATA_PROT_ATAPI_NODATA:
+               ap->flags |= ATA_FLAG_NOINTR;
                ata_tf_to_host_nolock(ap, &qc->tf);
                queue_work(ata_wq, &ap->packet_task);
                break;
 
        case ATA_PROT_ATAPI_DMA:
+               ap->flags |= ATA_FLAG_NOINTR;
                ap->ops->tf_load(ap, &qc->tf);   /* load tf registers */
                ap->ops->bmdma_setup(qc);           /* set up bmdma */
                queue_work(ata_wq, &ap->packet_task);
@@ -3267,7 +3399,7 @@ static void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
 }
 
 /**
- *     ata_bmdma_start - Start a PCI IDE BMDMA transaction
+ *     ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction
  *     @qc: Info associated with this ATA transaction.
  *
  *     LOCKING:
@@ -3438,7 +3570,7 @@ u8 ata_bmdma_status(struct ata_port *ap)
 
 /**
  *     ata_bmdma_stop - Stop PCI IDE BMDMA transfer
- *     @ap: Port associated with this ATA transaction.
+ *     @qc: Command we are ending DMA for
  *
  *     Clears the ATA_DMA_START flag in the dma control register
  *
@@ -3448,8 +3580,9 @@ u8 ata_bmdma_status(struct ata_port *ap)
  *     spin_lock_irqsave(host_set lock)
  */
 
-void ata_bmdma_stop(struct ata_port *ap)
+void ata_bmdma_stop(struct ata_queued_cmd *qc)
 {
+       struct ata_port *ap = qc->ap;
        if (ap->flags & ATA_FLAG_MMIO) {
                void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 
@@ -3501,7 +3634,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
                        goto idle_irq;
 
                /* before we do anything else, clear DMA-Start bit */
-               ap->ops->bmdma_stop(ap);
+               ap->ops->bmdma_stop(qc);
 
                /* fall through */
 
@@ -3576,7 +3709,8 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
                struct ata_port *ap;
 
                ap = host_set->ports[i];
-               if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+               if (ap &&
+                   !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
                        struct ata_queued_cmd *qc;
 
                        qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -3628,19 +3762,27 @@ static void atapi_packet_task(void *_data)
        /* send SCSI cdb */
        DPRINTK("send cdb\n");
        assert(ap->cdb_len >= 12);
-       ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
 
-       /* if we are DMA'ing, irq handler takes over from here */
-       if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
-               ap->ops->bmdma_start(qc);           /* initiate bmdma */
+       if (qc->tf.protocol == ATA_PROT_ATAPI_DMA ||
+           qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
+               unsigned long flags;
 
-       /* non-data commands are also handled via irq */
-       else if (qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
-               /* do nothing */
-       }
+               /* Once we're done issuing command and kicking bmdma,
+                * irq handler takes over.  To not lose irq, we need
+                * to clear NOINTR flag before sending cdb, but
+                * interrupt handler shouldn't be invoked before we're
+                * finished.  Hence, the following locking.
+                */
+               spin_lock_irqsave(&ap->host_set->lock, flags);
+               ap->flags &= ~ATA_FLAG_NOINTR;
+               ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
+               if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
+                       ap->ops->bmdma_start(qc);       /* initiate bmdma */
+               spin_unlock_irqrestore(&ap->host_set->lock, flags);
+       } else {
+               ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
 
-       /* PIO commands are handled by polling */
-       else {
+               /* PIO commands are handled by polling */
                ap->pio_task_state = PIO_ST;
                queue_work(ata_wq, &ap->pio_task);
        }
@@ -3648,7 +3790,7 @@ static void atapi_packet_task(void *_data)
        return;
 
 err_out:
-       ata_qc_complete(qc, ATA_ERR);
+       ata_poll_qc_complete(qc, ATA_ERR);
 }
 
 
index 794fb55..4074e78 100644 (file)
@@ -385,11 +385,66 @@ int ata_scsi_error(struct Scsi_Host *host)
         * appropriate place
         */
        host->host_failed--;
+       INIT_LIST_HEAD(&host->eh_cmd_q);
 
        DPRINTK("EXIT\n");
        return 0;
 }
 
+/**
+ *     ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
+ *     @qc: Storage for translated ATA taskfile
+ *     @scsicmd: SCSI command to translate
+ *
+ *     Sets up an ATA taskfile to issue STANDBY (to stop) or READ VERIFY
+ *     (to start). Perhaps these commands should be preceded by
+ *     CHECK POWER MODE to see what power mode the device is already in.
+ *     [See SAT revision 5 at www.t10.org]
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Zero on success, non-zero on error.
+ */
+
+static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
+                                            u8 *scsicmd)
+{
+       struct ata_taskfile *tf = &qc->tf;
+
+       tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
+       tf->protocol = ATA_PROT_NODATA;
+       if (scsicmd[1] & 0x1) {
+               ;       /* ignore IMMED bit, violates sat-r05 */
+       }
+       if (scsicmd[4] & 0x2)
+               return 1;       /* LOEJ bit set not supported */
+       if (((scsicmd[4] >> 4) & 0xf) != 0)
+               return 1;       /* power conditions not supported */
+       if (scsicmd[4] & 0x1) {
+               tf->nsect = 1;  /* 1 sector, lba=0 */
+               tf->lbah = 0x0;
+               tf->lbam = 0x0;
+               tf->lbal = 0x0;
+               tf->device |= ATA_LBA;
+               tf->command = ATA_CMD_VERIFY;   /* READ VERIFY */
+       } else {
+               tf->nsect = 0;  /* time period value (0 implies now) */
+               tf->command = ATA_CMD_STANDBY;
+               /* Consider: ATA STANDBY IMMEDIATE command */
+       }
+       /*
+        * Standby and Idle condition timers could be implemented but that
+        * would require libata to implement the Power condition mode page
+        * and allow the user to change it. Changing mode pages requires
+        * MODE SELECT to be implemented.
+        */
+
+       return 0;
+}
+
+
 /**
  *     ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command
  *     @qc: Storage for translated ATA taskfile
@@ -575,11 +630,19 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
                tf->lbah = scsicmd[3];
 
                VPRINTK("ten-byte command\n");
+               if (qc->nsect == 0) /* we don't support length==0 cmds */
+                       return 1;
                return 0;
        }
 
        if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
                qc->nsect = tf->nsect = scsicmd[4];
+               if (!qc->nsect) {
+                       qc->nsect = 256;
+                       if (lba48)
+                               tf->hob_nsect = 1;
+               }
+
                tf->lbal = scsicmd[3];
                tf->lbam = scsicmd[2];
                tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */
@@ -619,6 +682,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
                tf->lbah = scsicmd[7];
 
                VPRINTK("sixteen-byte command\n");
+               if (qc->nsect == 0) /* we don't support length==0 cmds */
+                       return 1;
                return 0;
        }
 
@@ -1434,6 +1499,8 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
        case VERIFY:
        case VERIFY_16:
                return ata_scsi_verify_xlat;
+       case START_STOP:
+               return ata_scsi_start_stop_xlat;
        }
 
        return NULL;
index d90430b..620d217 100644 (file)
@@ -26,7 +26,7 @@
 #define __LIBATA_H__
 
 #define DRV_NAME       "libata"
-#define DRV_VERSION    "1.11"  /* must be exactly four chars */
+#define DRV_VERSION    "1.12"  /* must be exactly four chars */
 
 struct ata_scsi_args {
        u16                     *id;
@@ -72,7 +72,7 @@ extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
 extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
                            void (*done)(struct scsi_cmnd *),
                            u8 asc, u8 ascq);
-extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, 
+extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
                         unsigned int (*actor) (struct ata_scsi_args *args,
                                            u8 *rbuf, unsigned int buflen));
 
index b0403cc..41a3421 100644 (file)
  *  If you do not delete the provisions above, a recipient may use your
  *  version of this file under either the OSL or the GPL.
  *
+ *  0.08
+ *     - Added support for MCP51 and MCP55.
+ *
+ *  0.07
+ *     - Added support for RAID class code.
+ *
  *  0.06
  *     - Added generic SATA support by using a pci_device_id that filters on
  *       the IDE storage class code.
@@ -48,7 +54,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME                       "sata_nv"
-#define DRV_VERSION                    "0.6"
+#define DRV_VERSION                    "0.8"
 
 #define NV_PORTS                       2
 #define NV_PIO_MASK                    0x1f
@@ -116,7 +122,9 @@ enum nv_host_type
        GENERIC,
        NFORCE2,
        NFORCE3,
-       CK804
+       CK804,
+       MCP51,
+       MCP55
 };
 
 static struct pci_device_id nv_pci_tbl[] = {
@@ -134,9 +142,18 @@ static struct pci_device_id nv_pci_tbl[] = {
                PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP51 },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP51 },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP55 },
        { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
                PCI_ANY_ID, PCI_ANY_ID,
                PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
+       { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
+               PCI_ANY_ID, PCI_ANY_ID,
+               PCI_CLASS_STORAGE_RAID<<8, 0xffff00, GENERIC },
        { 0, } /* terminate list */
 };
 
@@ -274,7 +291,8 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance,
                struct ata_port *ap;
 
                ap = host_set->ports[i];
-               if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+               if (ap &&
+                   !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
                        struct ata_queued_cmd *qc;
 
                        qc = ata_qc_from_tag(ap, ap->active_tag);
index 5c1d441..b8dc49f 100644 (file)
@@ -40,7 +40,7 @@
 #include "sata_promise.h"
 
 #define DRV_NAME       "sata_promise"
-#define DRV_VERSION    "1.01"
+#define DRV_VERSION    "1.02"
 
 
 enum {
@@ -181,6 +181,10 @@ static struct pci_device_id pdc_ata_pci_tbl[] = {
          board_20319 },
        { PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
          board_20319 },
+       { PCI_VENDOR_ID_PROMISE, 0x3519, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_20319 },
+       { PCI_VENDOR_ID_PROMISE, 0x3d17, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_20319 },
        { PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
          board_20319 },
 
@@ -321,11 +325,15 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
 
 static void pdc_eng_timeout(struct ata_port *ap)
 {
+       struct ata_host_set *host_set = ap->host_set;
        u8 drv_stat;
        struct ata_queued_cmd *qc;
+       unsigned long flags;
 
        DPRINTK("ENTER\n");
 
+       spin_lock_irqsave(&host_set->lock, flags);
+
        qc = ata_qc_from_tag(ap, ap->active_tag);
        if (!qc) {
                printk(KERN_ERR "ata%u: BUG: timeout without command\n",
@@ -359,6 +367,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
        }
 
 out:
+       spin_unlock_irqrestore(&host_set->lock, flags);
        DPRINTK("EXIT\n");
 }
 
@@ -441,7 +450,8 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
                VPRINTK("port %u\n", i);
                ap = host_set->ports[i];
                tmp = mask & (1 << (i + 1));
-               if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+               if (tmp && ap &&
+                   !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
                        struct ata_queued_cmd *qc;
 
                        qc = ata_qc_from_tag(ap, ap->active_tag);
index 1383e8a..93fd06f 100644 (file)
@@ -117,7 +117,7 @@ static void qs_phy_reset(struct ata_port *ap);
 static void qs_qc_prep(struct ata_queued_cmd *qc);
 static int qs_qc_issue(struct ata_queued_cmd *qc);
 static int qs_check_atapi_dma(struct ata_queued_cmd *qc);
-static void qs_bmdma_stop(struct ata_port *ap);
+static void qs_bmdma_stop(struct ata_queued_cmd *qc);
 static u8 qs_bmdma_status(struct ata_port *ap);
 static void qs_irq_clear(struct ata_port *ap);
 static void qs_eng_timeout(struct ata_port *ap);
@@ -198,7 +198,7 @@ static int qs_check_atapi_dma(struct ata_queued_cmd *qc)
        return 1;       /* ATAPI DMA not supported */
 }
 
-static void qs_bmdma_stop(struct ata_port *ap)
+static void qs_bmdma_stop(struct ata_queued_cmd *qc)
 {
        /* nothing */
 }
@@ -386,7 +386,8 @@ static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set)
                        DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n",
                                        sff1, sff0, port_no, sHST, sDST);
                        handled = 1;
-                       if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+                       if (ap && !(ap->flags &
+                                   (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) {
                                struct ata_queued_cmd *qc;
                                struct qs_port_priv *pp = ap->private_data;
                                if (!pp || pp->state != qs_state_pkt)
@@ -417,7 +418,8 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set)
        for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
                struct ata_port *ap;
                ap = host_set->ports[port_no];
-               if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+               if (ap &&
+                   !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
                        struct ata_queued_cmd *qc;
                        struct qs_port_priv *pp = ap->private_data;
                        if (!pp || pp->state != qs_state_mmio)
@@ -431,7 +433,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set)
                                        continue;
                                DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
                                        ap->id, qc->tf.protocol, status);
-               
+
                                /* complete taskfile transaction */
                                pp->state = qs_state_idle;
                                ata_qc_complete(qc, status);
index 49ed557..9d24d6c 100644 (file)
  *  If you do not delete the provisions above, a recipient may use your
  *  version of this file under either the OSL or the GPL.
  *
+ *  Documentation for SiI 3112:
+ *  http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2
+ *
+ *  Other errata and documentation available under NDA.
+ *
  */
 
 #include <linux/kernel.h>
 #define DRV_VERSION    "0.9"
 
 enum {
+       SIL_FLAG_MOD15WRITE     = (1 << 30),
+
        sil_3112                = 0,
-       sil_3114                = 1,
+       sil_3112_m15w           = 1,
+       sil_3114                = 2,
 
        SIL_FIFO_R0             = 0x40,
        SIL_FIFO_W0             = 0x41,
@@ -76,13 +84,13 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static void sil_post_set_mode (struct ata_port *ap);
 
 static struct pci_device_id sil_pci_tbl[] = {
-       { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-       { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+       { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+       { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
        { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
        { 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
-       { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-       { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-       { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+       { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+       { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+       { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
        { }     /* terminate list */
 };
 
@@ -174,6 +182,16 @@ static struct ata_port_info sil_port_info[] = {
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = 0x3f,                 /* udma0-5 */
                .port_ops       = &sil_ops,
+       }, /* sil_3112_15w - keep it sync'd w/ sil_3112 */
+       {
+               .sht            = &sil_sht,
+               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                                 ATA_FLAG_SRST | ATA_FLAG_MMIO |
+                                 SIL_FLAG_MOD15WRITE,
+               .pio_mask       = 0x1f,                 /* pio0-4 */
+               .mwdma_mask     = 0x07,                 /* mwdma0-2 */
+               .udma_mask      = 0x3f,                 /* udma0-5 */
+               .port_ops       = &sil_ops,
        }, /* sil_3114 */
        {
                .sht            = &sil_sht,
@@ -323,15 +341,15 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
        while ((len > 0) && (s[len - 1] == ' '))
                len--;
 
-       for (n = 0; sil_blacklist[n].product; n++) 
+       for (n = 0; sil_blacklist[n].product; n++)
                if (!memcmp(sil_blacklist[n].product, s,
                            strlen(sil_blacklist[n].product))) {
                        quirks = sil_blacklist[n].quirk;
                        break;
                }
-       
+
        /* limit requests to 15 sectors */
-       if (quirks & SIL_QUIRK_MOD15WRITE) {
+       if ((ap->flags & SIL_FLAG_MOD15WRITE) && (quirks & SIL_QUIRK_MOD15WRITE)) {
                printk(KERN_INFO "ata%u(%u): applying Seagate errata fix\n",
                       ap->id, dev->devno);
                ap->host->max_sectors = 15;
index e418b89..b250ae0 100644 (file)
@@ -234,7 +234,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        pci_read_config_dword(pdev, SIS_GENCTL, &genctl);
        if ((genctl & GENCTL_IOMAPPED_SCR) == 0)
                probe_ent->host_flags |= SIS_FLAG_CFGSCR;
-       
+
        /* if hardware thinks SCRs are in IO space, but there are
         * no IO resources assigned, change to PCI cfg space.
         */
index 858e071..6fd2ce1 100644 (file)
@@ -195,18 +195,18 @@ static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
        /* start host DMA transaction */
        dmactl = readb(mmio + ATA_DMA_CMD);
        writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
-       /* There is a race condition in certain SATA controllers that can 
-          be seen when the r/w command is given to the controller before the 
+       /* There is a race condition in certain SATA controllers that can
+          be seen when the r/w command is given to the controller before the
           host DMA is started. On a Read command, the controller would initiate
           the command to the drive even before it sees the DMA start. When there
-          are very fast drives connected to the controller, or when the data request 
+          are very fast drives connected to the controller, or when the data request
           hits in the drive cache, there is the possibility that the drive returns a part
           or all of the requested data to the controller before the DMA start is issued.
           In this case, the controller would become confused as to what to do with the data.
           In the worst case when all the data is returned back to the controller, the
           controller could hang. In other cases it could return partial data returning
           in data corruption. This problem has been seen in PPC systems and can also appear
-          on an system with very fast disks, where the SATA controller is sitting behind a 
+          on an system with very fast disks, where the SATA controller is sitting behind a
           number of bridges, and hence there is significant latency between the r/w command
           and the start command. */
        /* issue r/w command if the access is to ATA*/
@@ -214,7 +214,7 @@ static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
                ap->ops->exec_command(ap, &qc->tf);
 }
 
-                                                                             
+
 static u8 k2_stat_check_status(struct ata_port *ap)
 {
                return readl((void *) ap->ioaddr.status_addr);
index 140cea0..a20d428 100644 (file)
@@ -94,7 +94,7 @@ enum {
        PDC_DIMM1_CONTROL_OFFSET      = 0x84,
        PDC_SDRAM_CONTROL_OFFSET      = 0x88,
        PDC_I2C_WRITE                 = 0x00000000,
-       PDC_I2C_READ                  = 0x00000040,     
+       PDC_I2C_READ                  = 0x00000040,
        PDC_I2C_START                 = 0x00000080,
        PDC_I2C_MASK_INT              = 0x00000020,
        PDC_I2C_COMPLETE              = 0x00010000,
@@ -105,16 +105,16 @@ enum {
        PDC_DIMM_SPD_COLUMN_NUM       = 4,
        PDC_DIMM_SPD_MODULE_ROW       = 5,
        PDC_DIMM_SPD_TYPE             = 11,
-       PDC_DIMM_SPD_FRESH_RATE       = 12,         
-       PDC_DIMM_SPD_BANK_NUM         = 17,     
+       PDC_DIMM_SPD_FRESH_RATE       = 12,
+       PDC_DIMM_SPD_BANK_NUM         = 17,
        PDC_DIMM_SPD_CAS_LATENCY      = 18,
-       PDC_DIMM_SPD_ATTRIBUTE        = 21,    
+       PDC_DIMM_SPD_ATTRIBUTE        = 21,
        PDC_DIMM_SPD_ROW_PRE_CHARGE   = 27,
-       PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,      
+       PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,
        PDC_DIMM_SPD_RAS_CAS_DELAY    = 29,
        PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30,
        PDC_DIMM_SPD_SYSTEM_FREQ      = 126,
-       PDC_CTL_STATUS                = 0x08,   
+       PDC_CTL_STATUS                = 0x08,
        PDC_DIMM_WINDOW_CTLR          = 0x0C,
        PDC_TIME_CONTROL              = 0x3C,
        PDC_TIME_PERIOD               = 0x40,
@@ -157,15 +157,15 @@ static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static void pdc20621_host_stop(struct ata_host_set *host_set);
 static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
 static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
-static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, 
+static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe,
                                      u32 device, u32 subaddr, u32 *pdata);
 static int pdc20621_prog_dimm0(struct ata_probe_ent *pe);
 static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe);
 #ifdef ATA_VERBOSE_DEBUG
-static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, 
+static void pdc20621_get_from_dimm(struct ata_probe_ent *pe,
                                   void *psource, u32 offset, u32 size);
 #endif
-static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, 
+static void pdc20621_put_to_dimm(struct ata_probe_ent *pe,
                                 void *psource, u32 offset, u32 size);
 static void pdc20621_irq_clear(struct ata_port *ap);
 static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
@@ -468,7 +468,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
        for (i = 0; i < last; i++) {
                buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i]));
                buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i]));
-               total_len += sg[i].length;
+               total_len += sg_dma_len(&sg[i]);
        }
        buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT);
        sgt_len = idx * 4;
@@ -825,7 +825,8 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re
                        ap = host_set->ports[port_no];
                tmp = mask & (1 << i);
                VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp);
-               if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+               if (tmp && ap &&
+                   !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
                        struct ata_queued_cmd *qc;
 
                        qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -847,10 +848,14 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re
 static void pdc_eng_timeout(struct ata_port *ap)
 {
        u8 drv_stat;
+       struct ata_host_set *host_set = ap->host_set;
        struct ata_queued_cmd *qc;
+       unsigned long flags;
 
        DPRINTK("ENTER\n");
 
+       spin_lock_irqsave(&host_set->lock, flags);
+
        qc = ata_qc_from_tag(ap, ap->active_tag);
        if (!qc) {
                printk(KERN_ERR "ata%u: BUG: timeout without command\n",
@@ -884,6 +889,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
        }
 
 out:
+       spin_unlock_irqrestore(&host_set->lock, flags);
        DPRINTK("EXIT\n");
 }
 
@@ -922,7 +928,7 @@ static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base)
 
 
 #ifdef ATA_VERBOSE_DEBUG
-static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource, 
+static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
                                   u32 offset, u32 size)
 {
        u32 window_size;
@@ -936,9 +942,9 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
        /* hard-code chip #0 */
        mmio += PDC_CHIP0_OFS;
 
-       page_mask = 0x00;       
-       window_size = 0x2000 * 4; /* 32K byte uchar size */  
-       idx = (u16) (offset / window_size); 
+       page_mask = 0x00;
+       window_size = 0x2000 * 4; /* 32K byte uchar size */
+       idx = (u16) (offset / window_size);
 
        writel(0x01, mmio + PDC_GENERAL_CTLR);
        readl(mmio + PDC_GENERAL_CTLR);
@@ -947,19 +953,19 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
 
        offset -= (idx * window_size);
        idx++;
-       dist = ((long) (window_size - (offset + size))) >= 0 ? size : 
+       dist = ((long) (window_size - (offset + size))) >= 0 ? size :
                (long) (window_size - offset);
-       memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4), 
+       memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4),
                      dist);
 
-       psource += dist;    
+       psource += dist;
        size -= dist;
        for (; (long) size >= (long) window_size ;) {
                writel(0x01, mmio + PDC_GENERAL_CTLR);
                readl(mmio + PDC_GENERAL_CTLR);
                writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
                readl(mmio + PDC_DIMM_WINDOW_CTLR);
-               memcpy_fromio((char *) psource, (char *) (dimm_mmio), 
+               memcpy_fromio((char *) psource, (char *) (dimm_mmio),
                              window_size / 4);
                psource += window_size;
                size -= window_size;
@@ -971,14 +977,14 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
                readl(mmio + PDC_GENERAL_CTLR);
                writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
                readl(mmio + PDC_DIMM_WINDOW_CTLR);
-               memcpy_fromio((char *) psource, (char *) (dimm_mmio), 
+               memcpy_fromio((char *) psource, (char *) (dimm_mmio),
                              size / 4);
        }
 }
 #endif
 
 
-static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, 
+static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
                                 u32 offset, u32 size)
 {
        u32 window_size;
@@ -989,16 +995,16 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
        struct pdc_host_priv *hpriv = pe->private_data;
        void *dimm_mmio = hpriv->dimm_mmio;
 
-       /* hard-code chip #0 */   
+       /* hard-code chip #0 */
        mmio += PDC_CHIP0_OFS;
 
-       page_mask = 0x00;       
-       window_size = 0x2000 * 4;       /* 32K byte uchar size */  
+       page_mask = 0x00;
+       window_size = 0x2000 * 4;       /* 32K byte uchar size */
        idx = (u16) (offset / window_size);
 
        writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
        readl(mmio + PDC_DIMM_WINDOW_CTLR);
-       offset -= (idx * window_size); 
+       offset -= (idx * window_size);
        idx++;
        dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size :
                (long) (window_size - offset);
@@ -1006,12 +1012,12 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
        writel(0x01, mmio + PDC_GENERAL_CTLR);
        readl(mmio + PDC_GENERAL_CTLR);
 
-       psource += dist;    
+       psource += dist;
        size -= dist;
        for (; (long) size >= (long) window_size ;) {
                writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
                readl(mmio + PDC_DIMM_WINDOW_CTLR);
-               memcpy_toio((char *) (dimm_mmio), (char *) psource, 
+               memcpy_toio((char *) (dimm_mmio), (char *) psource,
                            window_size / 4);
                writel(0x01, mmio + PDC_GENERAL_CTLR);
                readl(mmio + PDC_GENERAL_CTLR);
@@ -1019,7 +1025,7 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
                size -= window_size;
                idx ++;
        }
-    
+
        if (size) {
                writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
                readl(mmio + PDC_DIMM_WINDOW_CTLR);
@@ -1030,12 +1036,12 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
 }
 
 
-static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device, 
+static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
                                      u32 subaddr, u32 *pdata)
 {
        void *mmio = pe->mmio_base;
        u32 i2creg  = 0;
-       u32 status;     
+       u32 status;
        u32 count =0;
 
        /* hard-code chip #0 */
@@ -1049,7 +1055,7 @@ static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
        readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
 
        /* Write Control to perform read operation, mask int */
-       writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT, 
+       writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT,
               mmio + PDC_I2C_CONTROL_OFFSET);
 
        for (count = 0; count <= 1000; count ++) {
@@ -1062,26 +1068,26 @@ static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
        }
 
        *pdata = (status >> 8) & 0x000000ff;
-       return 1;           
+       return 1;
 }
 
 
 static int pdc20621_detect_dimm(struct ata_probe_ent *pe)
 {
        u32 data=0 ;
-       if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 
+       if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
                             PDC_DIMM_SPD_SYSTEM_FREQ, &data)) {
                if (data == 100)
                        return 100;
        } else
                return 0;
-       
+
        if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) {
-               if(data <= 0x75) 
+               if(data <= 0x75)
                        return 133;
        } else
                return 0;
-       
+
        return 0;
 }
 
@@ -1091,15 +1097,15 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
        u32 spd0[50];
        u32 data = 0;
        int size, i;
-       u8 bdimmsize; 
+       u8 bdimmsize;
        void *mmio = pe->mmio_base;
        static const struct {
                unsigned int reg;
                unsigned int ofs;
        } pdc_i2c_read_data [] = {
-               { PDC_DIMM_SPD_TYPE, 11 },              
+               { PDC_DIMM_SPD_TYPE, 11 },
                { PDC_DIMM_SPD_FRESH_RATE, 12 },
-               { PDC_DIMM_SPD_COLUMN_NUM, 4 }, 
+               { PDC_DIMM_SPD_COLUMN_NUM, 4 },
                { PDC_DIMM_SPD_ATTRIBUTE, 21 },
                { PDC_DIMM_SPD_ROW_NUM, 3 },
                { PDC_DIMM_SPD_BANK_NUM, 17 },
@@ -1108,7 +1114,7 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
                { PDC_DIMM_SPD_ROW_ACTIVE_DELAY, 28 },
                { PDC_DIMM_SPD_RAS_CAS_DELAY, 29 },
                { PDC_DIMM_SPD_ACTIVE_PRECHARGE, 30 },
-               { PDC_DIMM_SPD_CAS_LATENCY, 18 },       
+               { PDC_DIMM_SPD_CAS_LATENCY, 18 },
        };
 
        /* hard-code chip #0 */
@@ -1116,17 +1122,17 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
 
        for(i=0; i<ARRAY_SIZE(pdc_i2c_read_data); i++)
                pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
-                                 pdc_i2c_read_data[i].reg, 
+                                 pdc_i2c_read_data[i].reg,
                                  &spd0[pdc_i2c_read_data[i].ofs]);
-  
+
        data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4);
-       data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) | 
+       data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) |
                ((((spd0[27] + 9) / 10) - 1) << 8) ;
-       data |= (((((spd0[29] > spd0[28]) 
-                   ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10; 
+       data |= (((((spd0[29] > spd0[28])
+                   ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10;
        data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12;
-   
-       if (spd0[18] & 0x08) 
+
+       if (spd0[18] & 0x08)
                data |= ((0x03) << 14);
        else if (spd0[18] & 0x04)
                data |= ((0x02) << 14);
@@ -1135,7 +1141,7 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
        else
                data |= (0 << 14);
 
-       /* 
+       /*
           Calculate the size of bDIMMSize (power of 2) and
           merge the DIMM size by program start/end address.
        */
@@ -1145,9 +1151,9 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
        data |= (((size / 16) - 1) << 16);
        data |= (0 << 23);
        data |= 8;
-       writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET); 
+       writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET);
        readl(mmio + PDC_DIMM0_CONTROL_OFFSET);
-       return size;                          
+       return size;
 }
 
 
@@ -1167,12 +1173,12 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
          Refresh Enable (bit 17)
        */
 
-       data = 0x022259F1;   
+       data = 0x022259F1;
        writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
        readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
 
        /* Turn on for ECC */
-       pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 
+       pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
                          PDC_DIMM_SPD_TYPE, &spd0);
        if (spd0 == 0x02) {
                data |= (0x01 << 16);
@@ -1186,22 +1192,22 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
        data |= (1<<19);
        writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
 
-       error = 1;                     
+       error = 1;
        for (i = 1; i <= 10; i++) {   /* polling ~5 secs */
                data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
                if (!(data & (1<<19))) {
                        error = 0;
-                       break;     
+                       break;
                }
                msleep(i*100);
        }
        return error;
 }
-       
+
 
 static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
 {
-       int speed, size, length; 
+       int speed, size, length;
        u32 addr,spd0,pci_status;
        u32 tmp=0;
        u32 time_period=0;
@@ -1228,7 +1234,7 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
        /* Wait 3 seconds */
        msleep(3000);
 
-       /* 
+       /*
           When timer is enabled, counter is decreased every internal
           clock cycle.
        */
@@ -1236,24 +1242,24 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
        tcount = readl(mmio + PDC_TIME_COUNTER);
        VPRINTK("Time Counter Register (0x44): 0x%x\n", tcount);
 
-       /* 
+       /*
           If SX4 is on PCI-X bus, after 3 seconds, the timer counter
           register should be >= (0xffffffff - 3x10^8).
        */
        if(tcount >= PCI_X_TCOUNT) {
                ticks = (time_period - tcount);
                VPRINTK("Num counters 0x%x (%d)\n", ticks, ticks);
-       
+
                clock = (ticks / 300000);
                VPRINTK("10 * Internal clk = 0x%x (%d)\n", clock, clock);
-               
+
                clock = (clock * 33);
                VPRINTK("10 * Internal clk * 33 = 0x%x (%d)\n", clock, clock);
 
                /* PLL F Param (bit 22:16) */
                fparam = (1400000 / clock) - 2;
                VPRINTK("PLL F Param: 0x%x (%d)\n", fparam, fparam);
-               
+
                /* OD param = 0x2 (bit 31:30), R param = 0x5 (bit 29:25) */
                pci_status = (0x8a001824 | (fparam << 16));
        } else
@@ -1264,21 +1270,21 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
        writel(pci_status, mmio + PDC_CTL_STATUS);
        readl(mmio + PDC_CTL_STATUS);
 
-       /* 
+       /*
           Read SPD of DIMM by I2C interface,
           and program the DIMM Module Controller.
        */
        if (!(speed = pdc20621_detect_dimm(pe))) {
-               printk(KERN_ERR "Detect Local DIMM Fail\n");  
+               printk(KERN_ERR "Detect Local DIMM Fail\n");
                return 1;       /* DIMM error */
        }
        VPRINTK("Local DIMM Speed = %d\n", speed);
 
-       /* Programming DIMM0 Module Control Register (index_CID0:80h) */ 
+       /* Programming DIMM0 Module Control Register (index_CID0:80h) */
        size = pdc20621_prog_dimm0(pe);
        VPRINTK("Local DIMM Size = %dMB\n",size);
 
-       /* Programming DIMM Module Global Control Register (index_CID0:88h) */ 
+       /* Programming DIMM Module Global Control Register (index_CID0:88h) */
        if (pdc20621_prog_dimm_global(pe)) {
                printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n");
                return 1;
@@ -1297,30 +1303,30 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
 
                pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x10040, 40);
                pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
-               printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], 
+               printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
                       test_parttern2[1], &(test_parttern2[2]));
-               pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040, 
+               pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040,
                                       40);
-               printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], 
+               printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
                       test_parttern2[1], &(test_parttern2[2]));
 
                pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x40, 40);
                pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
-               printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], 
+               printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
                       test_parttern2[1], &(test_parttern2[2]));
        }
 #endif
 
        /* ECC initiliazation. */
 
-       pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 
+       pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
                          PDC_DIMM_SPD_TYPE, &spd0);
        if (spd0 == 0x02) {
                VPRINTK("Start ECC initialization\n");
                addr = 0;
                length = size * 1024 * 1024;
                while (addr < length) {
-                       pdc20621_put_to_dimm(pe, (void *) &tmp, addr, 
+                       pdc20621_put_to_dimm(pe, (void *) &tmp, addr,
                                             sizeof(u32));
                        addr += sizeof(u32);
                }
index a71fb54..eb202a7 100644 (file)
@@ -214,7 +214,7 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                rc = -ENOMEM;
                goto err_out_regions;
        }
-       
+
        switch (board_idx) {
        case uli_5287:
                probe_ent->port[0].scr_addr = ULI5287_BASE;
index f43183c..feff109 100644 (file)
@@ -347,7 +347,7 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                probe_ent = vt6420_init_probe_ent(pdev);
        else
                probe_ent = vt6421_init_probe_ent(pdev);
-       
+
        if (!probe_ent) {
                printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
                       pci_name(pdev));
index c5e09dc..6f25621 100644 (file)
@@ -173,7 +173,8 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance,
                        struct ata_port *ap;
 
                        ap = host_set->ports[i];
-                       if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+                       if (ap && !(ap->flags &
+                                   (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) {
                                struct ata_queued_cmd *qc;
 
                                qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -342,7 +343,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
 
        pci_set_master(pdev);
 
-       /* 
+       /*
         * Config offset 0x98 is "Extended Control and Status Register 0"
         * Default value is (1 << 28).  All bits except bit 28 are reserved in
         * DPA mode.  If bit 28 is set, LED 0 reflects all ports' activity.
index 2d3c4ac..48edd67 100644 (file)
@@ -336,9 +336,23 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
        unsigned long flags;
        const int size = sizeof(struct scsi_target)
                + shost->transportt->target_size;
-       struct scsi_target *starget = kmalloc(size, GFP_ATOMIC);
+       struct scsi_target *starget;
        struct scsi_target *found_target;
 
+       /*
+        * Obtain the real parent from the transport. The transport
+        * is allowed to fail (no error) if there is nothing at that
+        * target id.
+        */
+       if (shost->transportt->target_parent) {
+               spin_lock_irqsave(shost->host_lock, flags);
+               parent = shost->transportt->target_parent(shost, channel, id);
+               spin_unlock_irqrestore(shost->host_lock, flags);
+               if (!parent)
+                       return NULL;
+       }
+
+       starget = kmalloc(size, GFP_KERNEL);
        if (!starget) {
                printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
                return NULL;
index 35d1c1e..e6412fc 100644 (file)
@@ -1022,6 +1022,23 @@ static int fc_rport_match(struct attribute_container *cont,
        return &i->rport_attr_cont.ac == cont;
 }
 
+
+/*
+ * Must be called with shost->host_lock held
+ */
+static struct device *fc_target_parent(struct Scsi_Host *shost,
+                                       int channel, uint id)
+{
+       struct fc_rport *rport;
+
+       list_for_each_entry(rport, &fc_host_rports(shost), peers)
+               if ((rport->channel == channel) &&
+                   (rport->scsi_target_id == id))
+                       return &rport->dev;
+
+       return NULL;
+}
+
 struct scsi_transport_template *
 fc_attach_transport(struct fc_function_template *ft)
 {
@@ -1057,6 +1074,8 @@ fc_attach_transport(struct fc_function_template *ft)
 
        /* Transport uses the shost workq for scsi scanning */
        i->t.create_work_queue = 1;
+
+       i->t.target_parent = fc_target_parent;
        
        /*
         * Setup SCSI Target Attributes.
index 51292f2..e822ca0 100644 (file)
@@ -2971,23 +2971,22 @@ static void * dev_seq_start(struct seq_file *s, loff_t *pos)
 {
        struct sg_proc_deviter * it = kmalloc(sizeof(*it), GFP_KERNEL);
 
+       s->private = it;
        if (! it)
                return NULL;
+
        if (NULL == sg_dev_arr)
-               goto err1;
+               return NULL;
        it->index = *pos;
        it->max = sg_last_dev();
        if (it->index >= it->max)
-               goto err1;
+               return NULL;
        return it;
-err1:
-       kfree(it);
-       return NULL;
 }
 
 static void * dev_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-       struct sg_proc_deviter * it = (struct sg_proc_deviter *) v;
+       struct sg_proc_deviter * it = s->private;
 
        *pos = ++it->index;
        return (it->index < it->max) ? it : NULL;
@@ -2995,7 +2994,7 @@ static void * dev_seq_next(struct seq_file *s, void *v, loff_t *pos)
 
 static void dev_seq_stop(struct seq_file *s, void *v)
 {
-       kfree (v);
+       kfree(s->private);
 }
 
 static int sg_proc_open_dev(struct inode *inode, struct file *file)
index 0291a8f..0a7839d 100644 (file)
@@ -4149,12 +4149,10 @@ static int __init init_st(void)
                        do_create_driverfs_files();
                        return 0;
                }
-               if (st_sysfs_class)
-                       class_destroy(st_sysfs_class);
                unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
-
                                         ST_MAX_TAPE_ENTRIES);
        }
+       class_destroy(st_sysfs_class);
 
        printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", SCSI_TAPE_MAJOR);
        return 1;
@@ -4162,13 +4160,11 @@ static int __init init_st(void)
 
 static void __exit exit_st(void)
 {
-       if (st_sysfs_class)
-               class_destroy(st_sysfs_class);
-       st_sysfs_class = NULL;
        do_remove_driverfs_files();
        scsi_unregister_driver(&st_template.gendrv);
        unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
                                 ST_MAX_TAPE_ENTRIES);
+       class_destroy(st_sysfs_class);
        kfree(scsi_tapes);
        printk(KERN_INFO "st: Unloaded.\n");
 }
index 07f05e9..0e21f58 100644 (file)
 
 #undef SERIAL_DEBUG_PCI
 
-/*
- * Definitions for PCI support.
- */
-#define FL_BASE_MASK           0x0007
-#define FL_BASE0               0x0000
-#define FL_BASE1               0x0001
-#define FL_BASE2               0x0002
-#define FL_BASE3               0x0003
-#define FL_BASE4               0x0004
-#define FL_GET_BASE(x)         (x & FL_BASE_MASK)
-
-/* Use successive BARs (PCI base address registers),
-   else use offset into some specified BAR */
-#define FL_BASE_BARS           0x0008
-
-/* do not assign an irq */
-#define FL_NOIRQ               0x0080
-
-/* Use the Base address register size to cap number of ports */
-#define FL_REGION_SZ_CAP       0x0100
-
-struct pci_board {
-       unsigned int flags;
-       unsigned int num_ports;
-       unsigned int base_baud;
-       unsigned int uart_offset;
-       unsigned int reg_shift;
-       unsigned int first_offset;
-};
-
 /*
  * init function returns:
  *  > 0 - number of ports
@@ -75,14 +45,15 @@ struct pci_serial_quirk {
        u32     subvendor;
        u32     subdevice;
        int     (*init)(struct pci_dev *dev);
-       int     (*setup)(struct pci_dev *dev, struct pci_board *board,
-                        struct uart_port *port, int idx);
+       int     (*setup)(struct serial_private *, struct pciserial_board *,
+                        struct uart_port *, int);
        void    (*exit)(struct pci_dev *dev);
 };
 
 #define PCI_NUM_BAR_RESOURCES  6
 
 struct serial_private {
+       struct pci_dev          *dev;
        unsigned int            nr;
        void __iomem            *remapped_bar[PCI_NUM_BAR_RESOURCES];
        struct pci_serial_quirk *quirk;
@@ -101,17 +72,18 @@ static void moan_device(const char *str, struct pci_dev *dev)
 }
 
 static int
-setup_port(struct pci_dev *dev, struct uart_port *port,
+setup_port(struct serial_private *priv, struct uart_port *port,
           int bar, int offset, int regshift)
 {
-       struct serial_private *priv = pci_get_drvdata(dev);
+       struct pci_dev *dev = priv->dev;
        unsigned long base, len;
 
        if (bar >= PCI_NUM_BAR_RESOURCES)
                return -EINVAL;
 
+       base = pci_resource_start(dev, bar);
+
        if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) {
-               base = pci_resource_start(dev, bar);
                len =  pci_resource_len(dev, bar);
 
                if (!priv->remapped_bar[bar])
@@ -120,13 +92,16 @@ setup_port(struct pci_dev *dev, struct uart_port *port,
                        return -ENOMEM;
 
                port->iotype = UPIO_MEM;
+               port->iobase = 0;
                port->mapbase = base + offset;
                port->membase = priv->remapped_bar[bar] + offset;
                port->regshift = regshift;
        } else {
-               base = pci_resource_start(dev, bar) + offset;
                port->iotype = UPIO_PORT;
-               port->iobase = base;
+               port->iobase = base + offset;
+               port->mapbase = 0;
+               port->membase = NULL;
+               port->regshift = 0;
        }
        return 0;
 }
@@ -136,7 +111,7 @@ setup_port(struct pci_dev *dev, struct uart_port *port,
  * Not that ugly ;) -- HW
  */
 static int
-afavlab_setup(struct pci_dev *dev, struct pci_board *board,
+afavlab_setup(struct serial_private *priv, struct pciserial_board *board,
              struct uart_port *port, int idx)
 {
        unsigned int bar, offset = board->first_offset;
@@ -149,7 +124,7 @@ afavlab_setup(struct pci_dev *dev, struct pci_board *board,
                offset += (idx - 4) * board->uart_offset;
        }
 
-       return setup_port(dev, port, bar, offset, board->reg_shift);
+       return setup_port(priv, port, bar, offset, board->reg_shift);
 }
 
 /*
@@ -189,13 +164,13 @@ static int __devinit pci_hp_diva_init(struct pci_dev *dev)
  * some serial ports are supposed to be hidden on certain models.
  */
 static int
-pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board,
+pci_hp_diva_setup(struct serial_private *priv, struct pciserial_board *board,
              struct uart_port *port, int idx)
 {
        unsigned int offset = board->first_offset;
        unsigned int bar = FL_GET_BASE(board->flags);
 
-       switch (dev->subsystem_device) {
+       switch (priv->dev->subsystem_device) {
        case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
                if (idx == 3)
                        idx++;
@@ -212,7 +187,7 @@ pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board,
 
        offset += idx * board->uart_offset;
 
-       return setup_port(dev, port, bar, offset, board->reg_shift);
+       return setup_port(priv, port, bar, offset, board->reg_shift);
 }
 
 /*
@@ -307,7 +282,7 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev)
 
 /* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
 static int
-sbs_setup(struct pci_dev *dev, struct pci_board *board,
+sbs_setup(struct serial_private *priv, struct pciserial_board *board,
                struct uart_port *port, int idx)
 {
        unsigned int bar, offset = board->first_offset;
@@ -323,7 +298,7 @@ sbs_setup(struct pci_dev *dev, struct pci_board *board,
        } else /* we have only 8 ports on PMC-OCTALPRO */
                return 1;
 
-       return setup_port(dev, port, bar, offset, board->reg_shift);
+       return setup_port(priv, port, bar, offset, board->reg_shift);
 }
 
 /*
@@ -389,6 +364,9 @@ static void __devexit sbs_exit(struct pci_dev *dev)
  *     - 10x cards have control registers in IO and/or memory space;
  *     - 20x cards have control registers in standard PCI configuration space.
  *
+ * Note: all 10x cards have PCI device ids 0x10..
+ *       all 20x cards have PCI device ids 0x20..
+ *
  * There are also Quartet Serial cards which use Oxford Semiconductor
  * 16954 quad UART PCI chip clocked by 18.432 MHz quartz.
  *
@@ -445,24 +423,18 @@ static int pci_siig20x_init(struct pci_dev *dev)
        return 0;
 }
 
-int pci_siig10x_fn(struct pci_dev *dev, int enable)
+static int pci_siig_init(struct pci_dev *dev)
 {
-       int ret = 0;
-       if (enable)
-               ret = pci_siig10x_init(dev);
-       return ret;
-}
+       unsigned int type = dev->device & 0xff00;
 
-int pci_siig20x_fn(struct pci_dev *dev, int enable)
-{
-       int ret = 0;
-       if (enable)
-               ret = pci_siig20x_init(dev);
-       return ret;
-}
+       if (type == 0x1000)
+               return pci_siig10x_init(dev);
+       else if (type == 0x2000)
+               return pci_siig20x_init(dev);
 
-EXPORT_SYMBOL(pci_siig10x_fn);
-EXPORT_SYMBOL(pci_siig20x_fn);
+       moan_device("Unknown SIIG card", dev);
+       return -ENODEV;
+}
 
 /*
  * Timedia has an explosion of boards, and to avoid the PCI table from
@@ -523,7 +495,7 @@ static int __devinit pci_timedia_init(struct pci_dev *dev)
  * Ugh, this is ugly as all hell --- TYT
  */
 static int
-pci_timedia_setup(struct pci_dev *dev, struct pci_board *board,
+pci_timedia_setup(struct serial_private *priv, struct pciserial_board *board,
                  struct uart_port *port, int idx)
 {
        unsigned int bar = 0, offset = board->first_offset;
@@ -549,14 +521,15 @@ pci_timedia_setup(struct pci_dev *dev, struct pci_board *board,
                bar = idx - 2;
        }
 
-       return setup_port(dev, port, bar, offset, board->reg_shift);
+       return setup_port(priv, port, bar, offset, board->reg_shift);
 }
 
 /*
  * Some Titan cards are also a little weird
  */
 static int
-titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board,
+titan_400l_800l_setup(struct serial_private *priv,
+                     struct pciserial_board *board,
                      struct uart_port *port, int idx)
 {
        unsigned int bar, offset = board->first_offset;
@@ -573,7 +546,7 @@ titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board,
                offset = (idx - 2) * board->uart_offset;
        }
 
-       return setup_port(dev, port, bar, offset, board->reg_shift);
+       return setup_port(priv, port, bar, offset, board->reg_shift);
 }
 
 static int __devinit pci_xircom_init(struct pci_dev *dev)
@@ -593,7 +566,7 @@ static int __devinit pci_netmos_init(struct pci_dev *dev)
 }
 
 static int
-pci_default_setup(struct pci_dev *dev, struct pci_board *board,
+pci_default_setup(struct serial_private *priv, struct pciserial_board *board,
                  struct uart_port *port, int idx)
 {
        unsigned int bar, offset = board->first_offset, maxnr;
@@ -604,13 +577,13 @@ pci_default_setup(struct pci_dev *dev, struct pci_board *board,
        else
                offset += idx * board->uart_offset;
 
-       maxnr = (pci_resource_len(dev, bar) - board->first_offset) /
+       maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) /
                (8 << board->reg_shift);
 
        if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
                return 1;
                        
-       return setup_port(dev, port, bar, offset, board->reg_shift);
+       return setup_port(priv, port, bar, offset, board->reg_shift);
 }
 
 /* This should be in linux/pci_ids.h */
@@ -754,152 +727,15 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
                .setup          = sbs_setup,
                .exit           = __devexit_p(sbs_exit),
        },
-
        /*
         * SIIG cards.
-        *  It is not clear whether these could be collapsed.
         */
        {
                .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_1S_10x_550,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig10x_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_1S_10x_650,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig10x_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_1S_10x_850,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig10x_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_2S_10x_550,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig10x_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_2S_10x_650,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig10x_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_2S_10x_850,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig10x_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_4S_10x_550,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig10x_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_4S_10x_650,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig10x_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_4S_10x_850,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig10x_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_1S_20x_550,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig20x_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_1S_20x_650,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig20x_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_1S_20x_850,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig20x_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_2S_20x_550,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig20x_init,
-               .setup          = pci_default_setup,
-       },
-       {       .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_2S_20x_650,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig20x_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_2S_20x_850,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig20x_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_4S_20x_550,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig20x_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_4S_20x_650,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig20x_init,
-               .setup          = pci_default_setup,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_SIIG,
-               .device         = PCI_DEVICE_ID_SIIG_4S_20x_850,
+               .device         = PCI_ANY_ID,
                .subvendor      = PCI_ANY_ID,
                .subdevice      = PCI_ANY_ID,
-               .init           = pci_siig20x_init,
+               .init           = pci_siig_init,
                .setup          = pci_default_setup,
        },
        /*
@@ -990,7 +826,7 @@ static struct pci_serial_quirk *find_quirk(struct pci_dev *dev)
 }
 
 static _INLINE_ int
-get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx)
+get_pci_irq(struct pci_dev *dev, struct pciserial_board *board)
 {
        if (board->flags & FL_NOIRQ)
                return 0;
@@ -1115,7 +951,7 @@ enum pci_board_num_t {
  * see first lines of serial_in() and serial_out() in 8250.c
 */
 
-static struct pci_board pci_boards[] __devinitdata = {
+static struct pciserial_board pci_boards[] __devinitdata = {
        [pbn_default] = {
                .flags          = FL_BASE0,
                .num_ports      = 1,
@@ -1575,7 +1411,7 @@ static struct pci_board pci_boards[] __devinitdata = {
  * serial specs.  Returns 0 on success, 1 on failure.
  */
 static int __devinit
-serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board)
+serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
 {
        int num_iomem, num_port, first_port = -1, i;
        
@@ -1640,7 +1476,8 @@ serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board)
 }
 
 static inline int
-serial_pci_matches(struct pci_board *board, struct pci_board *guessed)
+serial_pci_matches(struct pciserial_board *board,
+                  struct pciserial_board *guessed)
 {
        return
            board->num_ports == guessed->num_ports &&
@@ -1650,58 +1487,14 @@ serial_pci_matches(struct pci_board *board, struct pci_board *guessed)
            board->first_offset == guessed->first_offset;
 }
 
-/*
- * Probe one serial board.  Unfortunately, there is no rhyme nor reason
- * to the arrangement of serial ports on a PCI card.
- */
-static int __devinit
-pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
+struct serial_private *
+pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board)
 {
+       struct uart_port serial_port;
        struct serial_private *priv;
-       struct pci_board *board, tmp;
        struct pci_serial_quirk *quirk;
        int rc, nr_ports, i;
 
-       if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
-               printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n",
-                       ent->driver_data);
-               return -EINVAL;
-       }
-
-       board = &pci_boards[ent->driver_data];
-
-       rc = pci_enable_device(dev);
-       if (rc)
-               return rc;
-
-       if (ent->driver_data == pbn_default) {
-               /*
-                * Use a copy of the pci_board entry for this;
-                * avoid changing entries in the table.
-                */
-               memcpy(&tmp, board, sizeof(struct pci_board));
-               board = &tmp;
-
-               /*
-                * We matched one of our class entries.  Try to
-                * determine the parameters of this board.
-                */
-               rc = serial_pci_guess_board(dev, board);
-               if (rc)
-                       goto disable;
-       } else {
-               /*
-                * We matched an explicit entry.  If we are able to
-                * detect this boards settings with our heuristic,
-                * then we no longer need this entry.
-                */
-               memcpy(&tmp, &pci_boards[pbn_default], sizeof(struct pci_board));
-               rc = serial_pci_guess_board(dev, &tmp);
-               if (rc == 0 && serial_pci_matches(board, &tmp))
-                       moan_device("Redundant entry in serial pci_table.",
-                                   dev);
-       }
-
        nr_ports = board->num_ports;
 
        /*
@@ -1718,8 +1511,10 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
         */
        if (quirk->init) {
                rc = quirk->init(dev);
-               if (rc < 0)
-                       goto disable;
+               if (rc < 0) {
+                       priv = ERR_PTR(rc);
+                       goto err_out;
+               }
                if (rc)
                        nr_ports = rc;
        }
@@ -1728,27 +1523,26 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
                       sizeof(unsigned int) * nr_ports,
                       GFP_KERNEL);
        if (!priv) {
-               rc = -ENOMEM;
-               goto deinit;
+               priv = ERR_PTR(-ENOMEM);
+               goto err_deinit;
        }
 
        memset(priv, 0, sizeof(struct serial_private) +
                        sizeof(unsigned int) * nr_ports);
 
+       priv->dev = dev;
        priv->quirk = quirk;
-       pci_set_drvdata(dev, priv);
+
+       memset(&serial_port, 0, sizeof(struct uart_port));
+       serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+       serial_port.uartclk = board->base_baud * 16;
+       serial_port.irq = get_pci_irq(dev, board);
+       serial_port.dev = &dev->dev;
 
        for (i = 0; i < nr_ports; i++) {
-               struct uart_port serial_port;
-               memset(&serial_port, 0, sizeof(struct uart_port));
-
-               serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF |
-                                   UPF_SHARE_IRQ;
-               serial_port.uartclk = board->base_baud * 16;
-               serial_port.irq = get_pci_irq(dev, board, i);
-               serial_port.dev = &dev->dev;
-               if (quirk->setup(dev, board, &serial_port, i))
+               if (quirk->setup(priv, board, &serial_port, i))
                        break;
+
 #ifdef SERIAL_DEBUG_PCI
                printk("Setup PCI port: port %x, irq %d, type %d\n",
                       serial_port.iobase, serial_port.irq, serial_port.iotype);
@@ -1763,24 +1557,21 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
 
        priv->nr = i;
 
-       return 0;
+       return priv;
 
- deinit:
err_deinit:
        if (quirk->exit)
                quirk->exit(dev);
- disable:
-       pci_disable_device(dev);
-       return rc;
+ err_out:
+       return priv;
 }
+EXPORT_SYMBOL_GPL(pciserial_init_ports);
 
-static void __devexit pciserial_remove_one(struct pci_dev *dev)
+void pciserial_remove_ports(struct serial_private *priv)
 {
-       struct serial_private *priv = pci_get_drvdata(dev);
        struct pci_serial_quirk *quirk;
        int i;
 
-       pci_set_drvdata(dev, NULL);
-
        for (i = 0; i < priv->nr; i++)
                serial8250_unregister_port(priv->line[i]);
 
@@ -1793,25 +1584,123 @@ static void __devexit pciserial_remove_one(struct pci_dev *dev)
        /*
         * Find the exit quirks.
         */
-       quirk = find_quirk(dev);
+       quirk = find_quirk(priv->dev);
        if (quirk->exit)
-               quirk->exit(dev);
+               quirk->exit(priv->dev);
+
+       kfree(priv);
+}
+EXPORT_SYMBOL_GPL(pciserial_remove_ports);
+
+void pciserial_suspend_ports(struct serial_private *priv)
+{
+       int i;
+
+       for (i = 0; i < priv->nr; i++)
+               if (priv->line[i] >= 0)
+                       serial8250_suspend_port(priv->line[i]);
+}
+EXPORT_SYMBOL_GPL(pciserial_suspend_ports);
+
+void pciserial_resume_ports(struct serial_private *priv)
+{
+       int i;
+
+       /*
+        * Ensure that the board is correctly configured.
+        */
+       if (priv->quirk->init)
+               priv->quirk->init(priv->dev);
+
+       for (i = 0; i < priv->nr; i++)
+               if (priv->line[i] >= 0)
+                       serial8250_resume_port(priv->line[i]);
+}
+EXPORT_SYMBOL_GPL(pciserial_resume_ports);
+
+/*
+ * Probe one serial board.  Unfortunately, there is no rhyme nor reason
+ * to the arrangement of serial ports on a PCI card.
+ */
+static int __devinit
+pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+       struct serial_private *priv;
+       struct pciserial_board *board, tmp;
+       int rc;
+
+       if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
+               printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n",
+                       ent->driver_data);
+               return -EINVAL;
+       }
+
+       board = &pci_boards[ent->driver_data];
+
+       rc = pci_enable_device(dev);
+       if (rc)
+               return rc;
+
+       if (ent->driver_data == pbn_default) {
+               /*
+                * Use a copy of the pci_board entry for this;
+                * avoid changing entries in the table.
+                */
+               memcpy(&tmp, board, sizeof(struct pciserial_board));
+               board = &tmp;
+
+               /*
+                * We matched one of our class entries.  Try to
+                * determine the parameters of this board.
+                */
+               rc = serial_pci_guess_board(dev, board);
+               if (rc)
+                       goto disable;
+       } else {
+               /*
+                * We matched an explicit entry.  If we are able to
+                * detect this boards settings with our heuristic,
+                * then we no longer need this entry.
+                */
+               memcpy(&tmp, &pci_boards[pbn_default],
+                      sizeof(struct pciserial_board));
+               rc = serial_pci_guess_board(dev, &tmp);
+               if (rc == 0 && serial_pci_matches(board, &tmp))
+                       moan_device("Redundant entry in serial pci_table.",
+                                   dev);
+       }
 
+       priv = pciserial_init_ports(dev, board);
+       if (!IS_ERR(priv)) {
+               pci_set_drvdata(dev, priv);
+               return 0;
+       }
+
+       rc = PTR_ERR(priv);
+
+ disable:
        pci_disable_device(dev);
+       return rc;
+}
 
-       kfree(priv);
+static void __devexit pciserial_remove_one(struct pci_dev *dev)
+{
+       struct serial_private *priv = pci_get_drvdata(dev);
+
+       pci_set_drvdata(dev, NULL);
+
+       pciserial_remove_ports(priv);
+
+       pci_disable_device(dev);
 }
 
 static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state)
 {
        struct serial_private *priv = pci_get_drvdata(dev);
 
-       if (priv) {
-               int i;
+       if (priv)
+               pciserial_suspend_ports(priv);
 
-               for (i = 0; i < priv->nr; i++)
-                       serial8250_suspend_port(priv->line[i]);
-       }
        pci_save_state(dev);
        pci_set_power_state(dev, pci_choose_state(dev, state));
        return 0;
@@ -1825,21 +1714,12 @@ static int pciserial_resume_one(struct pci_dev *dev)
        pci_restore_state(dev);
 
        if (priv) {
-               int i;
-
                /*
                 * The device may have been disabled.  Re-enable it.
                 */
                pci_enable_device(dev);
 
-               /*
-                * Ensure that the board is correctly configured.
-                */
-               if (priv->quirk->init)
-                       priv->quirk->init(dev);
-
-               for (i = 0; i < priv->nr; i++)
-                       serial8250_resume_port(priv->line[i]);
+               pciserial_resume_ports(priv);
        }
        return 0;
 }
index 97034d3..d579761 100644 (file)
@@ -211,7 +211,7 @@ comment "Non-8250 serial port support"
 
 config SERIAL_AMBA_PL010
        tristate "ARM AMBA PL010 serial port support"
-       depends on ARM_AMBA
+       depends on ARM_AMBA && (BROKEN || !ARCH_VERSATILE)
        select SERIAL_CORE
        help
          This selects the ARM(R) AMBA(R) PrimeCell PL010 UART.  If you have
@@ -819,7 +819,7 @@ config SERIAL_M32R_SIO_CONSOLE
 
 config SERIAL_M32R_PLDSIO
        bool "M32R SIO I/F on a PLD"
-       depends on SERIAL_M32R_SIO=y
+       depends on SERIAL_M32R_SIO=y && (PLAT_OPSPUT || PALT_USRV || PLAT_M32700UT)
        default n
        help
          Say Y here if you want to use the M32R serial controller
index 5f6187b..73c8a08 100644 (file)
 #define TX_NUM_FIFO    4
 #define TX_BUF_SIZE    32
 
+#define SCC_WAIT_CLOSING 100
+
 struct uart_cpm_port {
        struct uart_port        port;
-       u16                     rx_nrfifos;     
+       u16                     rx_nrfifos;
        u16                     rx_fifosize;
-       u16                     tx_nrfifos;     
+       u16                     tx_nrfifos;
        u16                     tx_fifosize;
-       smc_t                   *smcp;  
+       smc_t                   *smcp;
        smc_uart_t              *smcup;
        scc_t                   *sccp;
        scc_uart_t              *sccup;
@@ -67,6 +69,8 @@ struct uart_cpm_port {
        int                      bits;
        /* Keep track of 'odd' SMC2 wirings */
        int                     is_portb;
+       /* wait on close if needed */
+       int                     wait_closing;
 };
 
 extern int cpm_uart_port_map[UART_NR];
index 29db677..d639ac9 100644 (file)
@@ -9,9 +9,10 @@
  *
  *  Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
  *              Pantelis Antoniou (panto@intracom.gr) (CPM1)
- * 
+ *
  *  Copyright (C) 2004 Freescale Semiconductor, Inc.
  *            (C) 2004 Intracom, S.A.
+ *            (C) 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -70,8 +71,22 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo);
 
 /**************************************************************/
 
+static inline unsigned long cpu2cpm_addr(void *addr)
+{
+       if ((unsigned long)addr >= CPM_ADDR)
+               return (unsigned long)addr;
+       return virt_to_bus(addr);
+}
+
+static inline void *cpm2cpu_addr(unsigned long addr)
+{
+       if (addr >= CPM_ADDR)
+               return (void *)addr;
+       return bus_to_virt(addr);
+}
+
 /*
- * Check, if transmit buffers are processed            
+ * Check, if transmit buffers are processed
 */
 static unsigned int cpm_uart_tx_empty(struct uart_port *port)
 {
@@ -143,15 +158,18 @@ static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start)
        }
 
        if (cpm_uart_tx_pump(port) != 0) {
-               if (IS_SMC(pinfo))
+               if (IS_SMC(pinfo)) {
                        smcp->smc_smcm |= SMCM_TX;
-               else
+                       smcp->smc_smcmr |= SMCMR_TEN;
+               } else {
                        sccp->scc_sccm |= UART_SCCM_TX;
+                       pinfo->sccp->scc_gsmrl |= SCC_GSMRL_ENT;
+               }
        }
 }
 
 /*
- * Stop receiver 
+ * Stop receiver
  */
 static void cpm_uart_stop_rx(struct uart_port *port)
 {
@@ -176,7 +194,7 @@ static void cpm_uart_enable_ms(struct uart_port *port)
 }
 
 /*
- * Generate a break. 
+ * Generate a break.
  */
 static void cpm_uart_break_ctl(struct uart_port *port, int break_state)
 {
@@ -231,7 +249,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
                /* get number of characters, and check spce in flip-buffer */
                i = bdp->cbd_datlen;
 
-               /* If we have not enough room in tty flip buffer, then we try 
+               /* If we have not enough room in tty flip buffer, then we try
                 * later, which will be the next rx-interrupt or a timeout
                 */
                if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) {
@@ -243,7 +261,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
                }
 
                /* get pointer */
-               cp = (unsigned char *)bus_to_virt(bdp->cbd_bufaddr);
+               cp = cpm2cpu_addr(bdp->cbd_bufaddr);
 
                /* loop through the buffer */
                while (i-- > 0) {
@@ -265,13 +283,14 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
                }               /* End while (i--) */
 
                /* This BD is ready to be used again. Clear status. get next */
-               bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
+               bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID);
                bdp->cbd_sc |= BD_SC_EMPTY;
 
                if (bdp->cbd_sc & BD_SC_WRAP)
                        bdp = pinfo->rx_bd_base;
                else
                        bdp++;
+
        } /* End for (;;) */
 
        /* Write back buffer pointer */
@@ -336,22 +355,22 @@ static irqreturn_t cpm_uart_int(int irq, void *data, struct pt_regs *regs)
 
        if (IS_SMC(pinfo)) {
                events = smcp->smc_smce;
+               smcp->smc_smce = events;
                if (events & SMCM_BRKE)
                        uart_handle_break(port);
                if (events & SMCM_RX)
                        cpm_uart_int_rx(port, regs);
                if (events & SMCM_TX)
                        cpm_uart_int_tx(port, regs);
-               smcp->smc_smce = events;
        } else {
                events = sccp->scc_scce;
+               sccp->scc_scce = events;
                if (events & UART_SCCM_BRKE)
                        uart_handle_break(port);
                if (events & UART_SCCM_RX)
                        cpm_uart_int_rx(port, regs);
                if (events & UART_SCCM_TX)
                        cpm_uart_int_tx(port, regs);
-               sccp->scc_scce = events;
        }
        return (events) ? IRQ_HANDLED : IRQ_NONE;
 }
@@ -360,6 +379,7 @@ static int cpm_uart_startup(struct uart_port *port)
 {
        int retval;
        struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+       int line = pinfo - cpm_uart_ports;
 
        pr_debug("CPM uart[%d]:startup\n", port->line);
 
@@ -376,9 +396,19 @@ static int cpm_uart_startup(struct uart_port *port)
                pinfo->sccp->scc_sccm |= UART_SCCM_RX;
        }
 
+       if (!(pinfo->flags & FLAG_CONSOLE))
+               cpm_line_cr_cmd(line,CPM_CR_INIT_TRX);
        return 0;
 }
 
+inline void cpm_uart_wait_until_send(struct uart_cpm_port *pinfo)
+{
+       unsigned long target_jiffies = jiffies + pinfo->wait_closing;
+
+       while (!time_after(jiffies, target_jiffies))
+               schedule();
+}
+
 /*
  * Shutdown the uart
  */
@@ -394,6 +424,12 @@ static void cpm_uart_shutdown(struct uart_port *port)
 
        /* If the port is not the console, disable Rx and Tx. */
        if (!(pinfo->flags & FLAG_CONSOLE)) {
+               /* Wait for all the BDs marked sent */
+               while(!cpm_uart_tx_empty(port))
+                       schedule_timeout(2);
+               if(pinfo->wait_closing)
+                       cpm_uart_wait_until_send(pinfo);
+
                /* Stop uarts */
                if (IS_SMC(pinfo)) {
                        volatile smc_t *smcp = pinfo->smcp;
@@ -502,7 +538,7 @@ static void cpm_uart_set_termios(struct uart_port *port,
         */
        if ((termios->c_cflag & CREAD) == 0)
                port->read_status_mask &= ~BD_SC_EMPTY;
-       
+
        spin_lock_irqsave(&port->lock, flags);
 
        /* Start bit has not been added (so don't, because we would just
@@ -569,7 +605,8 @@ static int cpm_uart_tx_pump(struct uart_port *port)
                /* Pick next descriptor and fill from buffer */
                bdp = pinfo->tx_cur;
 
-               p = bus_to_virt(bdp->cbd_bufaddr);
+               p = cpm2cpu_addr(bdp->cbd_bufaddr);
+
                *p++ = xmit->buf[xmit->tail];
                bdp->cbd_datlen = 1;
                bdp->cbd_sc |= BD_SC_READY;
@@ -595,7 +632,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
 
        while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
                count = 0;
-               p = bus_to_virt(bdp->cbd_bufaddr);
+               p = cpm2cpu_addr(bdp->cbd_bufaddr);
                while (count < pinfo->tx_fifosize) {
                        *p++ = xmit->buf[xmit->tail];
                        xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -606,6 +643,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
                }
                bdp->cbd_datlen = count;
                bdp->cbd_sc |= BD_SC_READY;
+               __asm__("eieio");
                /* Get next BD. */
                if (bdp->cbd_sc & BD_SC_WRAP)
                        bdp = pinfo->tx_bd_base;
@@ -643,12 +681,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
        mem_addr = pinfo->mem_addr;
        bdp = pinfo->rx_cur = pinfo->rx_bd_base;
        for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) {
-               bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+               bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
                bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
                mem_addr += pinfo->rx_fifosize;
        }
-       
-       bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+
+       bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
        bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
 
        /* Set the physical address of the host memory
@@ -658,12 +696,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
        mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize);
        bdp = pinfo->tx_cur = pinfo->tx_bd_base;
        for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) {
-               bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+               bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
                bdp->cbd_sc = BD_SC_INTRPT;
                mem_addr += pinfo->tx_fifosize;
        }
-       
-       bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+
+       bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
        bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT;
 }
 
@@ -763,6 +801,8 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
        /* Using idle charater time requires some additional tuning.  */
        up->smc_mrblr = pinfo->rx_fifosize;
        up->smc_maxidl = pinfo->rx_fifosize;
+       up->smc_brklen = 0;
+       up->smc_brkec = 0;
        up->smc_brkcr = 1;
 
        cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);
@@ -796,7 +836,7 @@ static int cpm_uart_request_port(struct uart_port *port)
        /*
         * Setup any port IO, connect any baud rate generators,
         * etc.  This is expected to be handled by board
-        * dependant code 
+        * dependant code
         */
        if (pinfo->set_lineif)
                pinfo->set_lineif(pinfo);
@@ -815,6 +855,10 @@ static int cpm_uart_request_port(struct uart_port *port)
                return ret;
 
        cpm_uart_initbd(pinfo);
+       if (IS_SMC(pinfo))
+               cpm_uart_init_smc(pinfo);
+       else
+               cpm_uart_init_scc(pinfo);
 
        return 0;
 }
@@ -869,7 +913,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
                .flags = FLAG_SMC,
                .tx_nrfifos = TX_NUM_FIFO,
                .tx_fifosize = TX_BUF_SIZE,
-               .rx_nrfifos = RX_NUM_FIFO, 
+               .rx_nrfifos = RX_NUM_FIFO,
                .rx_fifosize = RX_BUF_SIZE,
                .set_lineif = smc1_lineif,
        },
@@ -883,7 +927,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
                .flags = FLAG_SMC,
                .tx_nrfifos = TX_NUM_FIFO,
                .tx_fifosize = TX_BUF_SIZE,
-               .rx_nrfifos = RX_NUM_FIFO, 
+               .rx_nrfifos = RX_NUM_FIFO,
                .rx_fifosize = RX_BUF_SIZE,
                .set_lineif = smc2_lineif,
 #ifdef CONFIG_SERIAL_CPM_ALT_SMC2
@@ -899,9 +943,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
                },
                .tx_nrfifos = TX_NUM_FIFO,
                .tx_fifosize = TX_BUF_SIZE,
-               .rx_nrfifos = RX_NUM_FIFO, 
+               .rx_nrfifos = RX_NUM_FIFO,
                .rx_fifosize = RX_BUF_SIZE,
                .set_lineif = scc1_lineif,
+               .wait_closing = SCC_WAIT_CLOSING,
        },
        [UART_SCC2] = {
                .port = {
@@ -912,9 +957,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
                },
                .tx_nrfifos = TX_NUM_FIFO,
                .tx_fifosize = TX_BUF_SIZE,
-               .rx_nrfifos = RX_NUM_FIFO, 
+               .rx_nrfifos = RX_NUM_FIFO,
                .rx_fifosize = RX_BUF_SIZE,
                .set_lineif = scc2_lineif,
+               .wait_closing = SCC_WAIT_CLOSING,
        },
        [UART_SCC3] = {
                .port = {
@@ -925,9 +971,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
                },
                .tx_nrfifos = TX_NUM_FIFO,
                .tx_fifosize = TX_BUF_SIZE,
-               .rx_nrfifos = RX_NUM_FIFO, 
+               .rx_nrfifos = RX_NUM_FIFO,
                .rx_fifosize = RX_BUF_SIZE,
                .set_lineif = scc3_lineif,
+               .wait_closing = SCC_WAIT_CLOSING,
        },
        [UART_SCC4] = {
                .port = {
@@ -938,9 +985,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
                },
                .tx_nrfifos = TX_NUM_FIFO,
                .tx_fifosize = TX_BUF_SIZE,
-               .rx_nrfifos = RX_NUM_FIFO, 
+               .rx_nrfifos = RX_NUM_FIFO,
                .rx_fifosize = RX_BUF_SIZE,
                .set_lineif = scc4_lineif,
+               .wait_closing = SCC_WAIT_CLOSING,
        },
 };
 
@@ -983,11 +1031,8 @@ static void cpm_uart_console_write(struct console *co, const char *s,
                 * If the buffer address is in the CPM DPRAM, don't
                 * convert it.
                 */
-               if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR)
-                       cp = (unsigned char *) (bdp->cbd_bufaddr);
-               else
-                       cp = bus_to_virt(bdp->cbd_bufaddr);
-               
+               cp = cpm2cpu_addr(bdp->cbd_bufaddr);
+
                *cp = *s;
 
                bdp->cbd_datlen = 1;
@@ -1003,10 +1048,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
                        while ((bdp->cbd_sc & BD_SC_READY) != 0)
                                ;
 
-                       if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR)
-                               cp = (unsigned char *) (bdp->cbd_bufaddr);
-                       else
-                               cp = bus_to_virt(bdp->cbd_bufaddr);
+                       cp = cpm2cpu_addr(bdp->cbd_bufaddr);
 
                        *cp = 13;
                        bdp->cbd_datlen = 1;
@@ -1045,7 +1087,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
        port =
            (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
        pinfo = (struct uart_cpm_port *)port;
-       
+
        pinfo->flags |= FLAG_CONSOLE;
 
        if (options) {
@@ -1062,7 +1104,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
        /*
         * Setup any port IO, connect any baud rate generators,
         * etc.  This is expected to be handled by board
-        * dependant code 
+        * dependant code
         */
        if (pinfo->set_lineif)
                pinfo->set_lineif(pinfo);
@@ -1092,14 +1134,14 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
        return 0;
 }
 
-extern struct uart_driver cpm_reg;
+static struct uart_driver cpm_reg;
 static struct console cpm_scc_uart_console = {
-       .name           "ttyCPM",
-       .write          cpm_uart_console_write,
-       .device         uart_console_device,
-       .setup          cpm_uart_console_setup,
-       .flags          CON_PRINTBUFFER,
-       .index          -1,
+       .name           "ttyCPM",
+       .write          cpm_uart_console_write,
+       .device         uart_console_device,
+       .setup          cpm_uart_console_setup,
+       .flags          CON_PRINTBUFFER,
+       .index          -1,
        .data           = &cpm_reg,
 };
 
index 8efbd6d..4b0786e 100644 (file)
@@ -5,7 +5,7 @@
  *
  *  Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
  *              Pantelis Antoniou (panto@intracom.gr) (CPM1)
- * 
+ *
  *  Copyright (C) 2004 Freescale Semiconductor, Inc.
  *            (C) 2004 Intracom, S.A.
  *
@@ -82,6 +82,17 @@ void cpm_line_cr_cmd(int line, int cmd)
 void smc1_lineif(struct uart_cpm_port *pinfo)
 {
        volatile cpm8xx_t *cp = cpmp;
+
+       (void)cp;       /* fix warning */
+#if defined (CONFIG_MPC885ADS)
+       /* Enable SMC1 transceivers */
+       {
+               cp->cp_pepar |= 0x000000c0;
+               cp->cp_pedir &= ~0x000000c0;
+               cp->cp_peso &= ~0x00000040;
+               cp->cp_peso |= 0x00000080;
+       }
+#elif defined (CONFIG_MPC86XADS)
        unsigned int iobits = 0x000000c0;
 
        if (!pinfo->is_portb) {
@@ -93,41 +104,33 @@ void smc1_lineif(struct uart_cpm_port *pinfo)
                ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
                ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
        }
-
-#ifdef CONFIG_MPC885ADS
-       /* Enable SMC1 transceivers */
-       {
-               volatile uint __iomem *bcsr1 = ioremap(BCSR1, 4);
-               uint tmp;
-
-               tmp = in_be32(bcsr1);
-               tmp &= ~BCSR1_RS232EN_1;
-               out_be32(bcsr1, tmp);
-               iounmap(bcsr1);
-       }
 #endif
-
        pinfo->brg = 1;
 }
 
 void smc2_lineif(struct uart_cpm_port *pinfo)
 {
-#ifdef CONFIG_MPC885ADS
        volatile cpm8xx_t *cp = cpmp;
-       volatile uint __iomem *bcsr1;
-       uint tmp;
 
+       (void)cp;       /* fix warning */
+#if defined (CONFIG_MPC885ADS)
        cp->cp_pepar |= 0x00000c00;
        cp->cp_pedir &= ~0x00000c00;
        cp->cp_peso &= ~0x00000400;
        cp->cp_peso |= 0x00000800;
+#elif defined (CONFIG_MPC86XADS)
+       unsigned int iobits = 0x00000c00;
+
+       if (!pinfo->is_portb) {
+               cp->cp_pbpar |= iobits;
+               cp->cp_pbdir &= ~iobits;
+               cp->cp_pbodr &= ~iobits;
+       } else {
+               ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits;
+               ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
+               ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
+       }
 
-       /* Enable SMC2 transceivers */
-       bcsr1 = ioremap(BCSR1, 4);
-       tmp = in_be32(bcsr1);
-       tmp &= ~BCSR1_RS232EN_2;
-       out_be32(bcsr1, tmp);
-       iounmap(bcsr1);
 #endif
 
        pinfo->brg = 2;
@@ -158,7 +161,7 @@ void scc4_lineif(struct uart_cpm_port *pinfo)
 }
 
 /*
- * Allocate DP-Ram and memory buffers. We need to allocate a transmit and 
+ * Allocate DP-Ram and memory buffers. We need to allocate a transmit and
  * receive buffer descriptors from dual port ram, and a character
  * buffer area from host mem. If we are allocating for the console we need
  * to do it from bootmem
@@ -185,6 +188,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
        memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
            L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
        if (is_con) {
+               /* was hostalloc but changed cause it blows away the */
+               /* large tlb mapping when pinning the kernel area    */
                mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
                dma_addr = 0;
        } else
index 0301fea..9b50560 100644 (file)
@@ -1123,7 +1123,7 @@ static int __init m32r_sio_console_setup(struct console *co, char *options)
        return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
-extern struct uart_driver m32r_sio_reg;
+static struct uart_driver m32r_sio_reg;
 static struct console m32r_sio_console = {
        .name           = "ttyS",
        .write          = m32r_sio_console_write,
index 840815f..12d1f14 100644 (file)
@@ -1093,6 +1093,7 @@ int __init sn_serial_console_early_setup(void)
                return -1;
 
        sal_console_port.sc_ops = &poll_ops;
+       spin_lock_init(&sal_console_port.sc_port.lock);
        early_sn_setup();       /* Find SAL entry points */
        register_console(&sal_console_early);
 
index 50cb018..b01efb6 100644 (file)
@@ -527,7 +527,7 @@ show_periodic (struct class_device *class_dev, char *buf)
                                                p.qh->period,
                                                le32_to_cpup (&p.qh->hw_info2)
                                                        /* uframe masks */
-                                                       & 0xffff,
+                                                       & (QH_CMASK | QH_SMASK),
                                                p.qh);
                                size -= temp;
                                next += temp;
index 4f97a4a..20df01a 100644 (file)
@@ -222,7 +222,7 @@ __acquires(ehci->lock)
                struct ehci_qh  *qh = (struct ehci_qh *) urb->hcpriv;
 
                /* S-mask in a QH means it's an interrupt urb */
-               if ((qh->hw_info2 & __constant_cpu_to_le32 (0x00ff)) != 0) {
+               if ((qh->hw_info2 & __constant_cpu_to_le32 (QH_SMASK)) != 0) {
 
                        /* ... update hc-wide periodic stats (for usbfs) */
                        ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
@@ -428,7 +428,8 @@ halt:
                        /* should be rare for periodic transfers,
                         * except maybe high bandwidth ...
                         */
-                       if (qh->period) {
+                       if ((__constant_cpu_to_le32 (QH_SMASK)
+                                       & qh->hw_info2) != 0) {
                                intr_deschedule (ehci, qh);
                                (void) qh_schedule (ehci, qh);
                        } else
index 9af4f64..b56f258 100644 (file)
@@ -301,7 +301,7 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
        dev_dbg (&qh->dev->dev,
                "link qh%d-%04x/%p start %d [%d/%d us]\n",
-               period, le32_to_cpup (&qh->hw_info2) & 0xffff,
+               period, le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK),
                qh, qh->start, qh->usecs, qh->c_usecs);
 
        /* high bandwidth, or otherwise every microframe */
@@ -385,7 +385,8 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
        dev_dbg (&qh->dev->dev,
                "unlink qh%d-%04x/%p start %d [%d/%d us]\n",
-               qh->period, le32_to_cpup (&qh->hw_info2) & 0xffff,
+               qh->period,
+               le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK),
                qh, qh->start, qh->usecs, qh->c_usecs);
 
        /* qh->qh_next still "live" to HC */
@@ -411,7 +412,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
         * active high speed queues may need bigger delays...
         */
        if (list_empty (&qh->qtd_list)
-                       || (__constant_cpu_to_le32 (0x0ff << 8)
+                       || (__constant_cpu_to_le32 (QH_CMASK)
                                        & qh->hw_info2) != 0)
                wait = 2;
        else
@@ -533,7 +534,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
        /* reuse the previous schedule slots, if we can */
        if (frame < qh->period) {
-               uframe = ffs (le32_to_cpup (&qh->hw_info2) & 0x00ff);
+               uframe = ffs (le32_to_cpup (&qh->hw_info2) & QH_SMASK);
                status = check_intr_schedule (ehci, frame, --uframe,
                                qh, &c_mask);
        } else {
@@ -569,10 +570,10 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
                qh->start = frame;
 
                /* reset S-frame and (maybe) C-frame masks */
-               qh->hw_info2 &= __constant_cpu_to_le32 (~0xffff);
+               qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK));
                qh->hw_info2 |= qh->period
                        ? cpu_to_le32 (1 << uframe)
-                       : __constant_cpu_to_le32 (0xff);
+                       : __constant_cpu_to_le32 (QH_SMASK);
                qh->hw_info2 |= c_mask;
        } else
                ehci_dbg (ehci, "reused qh %p schedule\n", qh);
index 4df4982..a754215 100644 (file)
@@ -385,6 +385,11 @@ struct ehci_qh {
        __le32                  hw_info1;        /* see EHCI 3.6.2 */
 #define        QH_HEAD         0x00008000
        __le32                  hw_info2;        /* see EHCI 3.6.2 */
+#define        QH_SMASK        0x000000ff
+#define        QH_CMASK        0x0000ff00
+#define        QH_HUBADDR      0x007f0000
+#define        QH_HUBPORT      0x3f800000
+#define        QH_MULT         0xc0000000
        __le32                  hw_current;      /* qtd list - see EHCI 3.6.4 */
        
        /* qtd overlay (hardware parts of a struct ehci_qtd) */
index 50b1970..76cb496 100644 (file)
@@ -229,9 +229,11 @@ static void preproc_atl_queue(struct isp116x *isp116x)
        struct isp116x_ep *ep;
        struct urb *urb;
        struct ptd *ptd;
-       u16 toggle = 0, dir = PTD_DIR_SETUP, len;
+       u16 len;
 
        for (ep = isp116x->atl_active; ep; ep = ep->active) {
+               u16 toggle = 0, dir = PTD_DIR_SETUP;
+
                BUG_ON(list_empty(&ep->hep->urb_list));
                urb = container_of(ep->hep->urb_list.next,
                                   struct urb, urb_list);
index 02412e3..3b266af 100644 (file)
@@ -342,9 +342,6 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
                goto exit;
        }
 
-       x = le16_to_cpu(*(__le16 *) &data[2]);
-       y = le16_to_cpu(*(__le16 *) &data[4]);
-
        input_regs(dev, regs);
 
        if (data[1] & 0x10) { /* in prox */
@@ -373,15 +370,17 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
                }
        }
 
-       if (data[1] & 0x80) {
+       if (data[1] & 0x90) {
+               x = le16_to_cpu(*(__le16 *) &data[2]);
+               y = le16_to_cpu(*(__le16 *) &data[4]);
                input_report_abs(dev, ABS_X, x);
                input_report_abs(dev, ABS_Y, y);
-       }
-       if (wacom->tool[0] != BTN_TOOL_MOUSE) {
-               input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6]));
-               input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
-               input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
-               input_report_key(dev, BTN_STYLUS2, data[1] & 0x04);
+               if (wacom->tool[0] != BTN_TOOL_MOUSE) {
+                       input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6]));
+                       input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
+                       input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
+                       input_report_key(dev, BTN_STYLUS2, data[1] & 0x04);
+               }
        }
 
        input_report_key(dev, wacom->tool[0], data[1] & 0x10);
@@ -568,7 +567,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
 
        /* Cintiq doesn't send data when RDY bit isn't set */
        if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
-               return;
+               goto exit;
 
        if (wacom->features->type >= INTUOS3) {
                input_report_abs(dev, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
index 777642e..deb9ddf 100644 (file)
@@ -9,9 +9,8 @@ config USB_MON
        help
          If you say Y here, a component which captures the USB traffic
          between peripheral-specific drivers and HC drivers will be built.
-         The USB_MON is similar in spirit and may be compatible with Dave
-         Harding's USBMon.
+         For more information, see <file:Documentation/usb/usbmon.txt>.
 
-         This is somewhat experimental at this time, but it should be safe,
-         as long as you aren't using modular USB and try to remove this
-         module.
+         This is somewhat experimental at this time, but it should be safe.
+
+         If unsure, say Y.
index f18d10c..b0015b8 100644 (file)
@@ -4,4 +4,5 @@
 
 usbmon-objs    := mon_main.o mon_stat.o mon_text.o
 
+# This does not use CONFIG_USB_MON because we want this to use a tristate.
 obj-$(CONFIG_USB)      += usbmon.o
index aa9d008..508a210 100644 (file)
@@ -2,6 +2,8 @@
  * The USB Monitor, inspired by Dave Harding's USBMon.
  *
  * mon_main.c: Main file, module initiation and exit, registrations, etc.
+ *
+ * Copyright (C) 2005 Pete Zaitcev (zaitcev@redhat.com)
  */
 
 #include <linux/kernel.h>
@@ -311,7 +313,7 @@ static int __init mon_init(void)
 
        mondir = debugfs_create_dir("usbmon", NULL);
        if (IS_ERR(mondir)) {
-               printk(KERN_NOTICE TAG ": debugs is not available\n");
+               printk(KERN_NOTICE TAG ": debugfs is not available\n");
                return -ENODEV;
        }
        if (mondir == NULL) {
index ed35c18..9b06784 100644 (file)
@@ -1,5 +1,7 @@
 /*
  * The USB Monitor, inspired by Dave Harding's USBMon.
+ *
+ * Copyright (C) 2005 Pete Zaitcev (zaitcev@redhat.com)
  */
 
 #ifndef __USB_MON_H
index 576f3b8..4528a00 100644 (file)
@@ -1922,7 +1922,7 @@ static int genelink_rx_fixup (struct usbnet *dev, struct sk_buff *skb)
 
                        // copy the packet data to the new skb
                        memcpy(skb_put(gl_skb, size), packet->packet_data, size);
-                       skb_return (dev, skb);
+                       skb_return (dev, gl_skb);
                }
 
                // advance to the next packet
index 29cd801..e32a80b 100644 (file)
@@ -346,8 +346,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
                        if (datalen<14)
                                goto resubmit;
                        if ((seq & IEEE802_11_SCTL_FRAG) == 0) {
-                               frag = kmalloc(sizeof(struct zd1201_frag*),
-                                   GFP_ATOMIC);
+                               frag = kmalloc(sizeof(*frag), GFP_ATOMIC);
                                if (!frag)
                                        goto resubmit;
                                skb = dev_alloc_skb(IEEE802_11_DATA_LEN +14+2);
index cbff983..5fe182d 100644 (file)
@@ -6,7 +6,7 @@ menu "Console display driver support"
 
 config VGA_CONSOLE
        bool "VGA text console" if EMBEDDED || !X86
-       depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC32 && !SPARC64 && !M68K && !PARISC
+       depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC32 && !SPARC64 && !M68K && !PARISC && !ARCH_VERSATILE
        default y
        help
          Saying Y here will allow you to use Linux in text mode through a
index d2e19f6..4ff853f 100644 (file)
@@ -628,7 +628,7 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
 int
 fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
 {
-       int err;
+       int err, flags = info->flags;
 
        if (var->activate & FB_ACTIVATE_INV_MODE) {
                struct fb_videomode mode1, mode2;
@@ -682,7 +682,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
                            !list_empty(&info->modelist))
                                err = fb_add_videomode(&mode, &info->modelist);
 
-                       if (!err && info->flags & FBINFO_MISC_USEREVENT) {
+                       if (!err && (flags & FBINFO_MISC_USEREVENT)) {
                                struct fb_event event;
 
                                info->flags &= ~FBINFO_MISC_USEREVENT;
index ed1d4d1..1147b89 100644 (file)
@@ -414,6 +414,13 @@ static ssize_t show_pan(struct class_device *class_device, char *buf)
                        fb_info->var.xoffset);
 }
 
+static ssize_t show_name(struct class_device *class_device, char *buf)
+{
+       struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+
+       return snprintf(buf, PAGE_SIZE, "%s\n", fb_info->fix.id);
+}
+
 static struct class_device_attribute class_device_attrs[] = {
        __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
        __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
@@ -424,6 +431,7 @@ static struct class_device_attribute class_device_attrs[] = {
        __ATTR(modes, S_IRUGO|S_IWUSR, show_modes, store_modes),
        __ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan),
        __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual),
+       __ATTR(name, S_IRUGO, show_name, NULL),
 };
 
 int fb_init_class_device(struct fb_info *fb_info)
index 298bc9c..a112a17 100644 (file)
@@ -583,23 +583,6 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
                return -ENODEV;
        }
 
-       /* Map the fb and MMIO regions */
-       dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache
-               (dinfo->aperture.physical, dinfo->aperture.size);
-       if (!dinfo->aperture.virtual) {
-               ERR_MSG("Cannot remap FB region.\n");
-               cleanup(dinfo);
-               return -ENODEV;
-       }
-       dinfo->mmio_base =
-               (u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys,
-                                              INTEL_REG_SIZE);
-       if (!dinfo->mmio_base) {
-               ERR_MSG("Cannot remap MMIO region.\n");
-               cleanup(dinfo);
-               return -ENODEV;
-       }
-
        /* Get the chipset info. */
        dinfo->pci_chipset = pdev->device;
 
@@ -630,9 +613,15 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
                dinfo->accel = 0;
        }
 
+       if (MB(voffset) < stolen_size)
+               offset = (stolen_size >> 12);
+       else
+               offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE;
+
        /* Framebuffer parameters - Use all the stolen memory if >= vram */
-       if (ROUND_UP_TO_PAGE(stolen_size) >= MB(vram)) {
+       if (ROUND_UP_TO_PAGE(stolen_size) >= ((offset << 12) +  MB(vram))) {
                dinfo->fb.size = ROUND_UP_TO_PAGE(stolen_size);
+               dinfo->fb.offset = 0;
                dinfo->fbmem_gart = 0;
        } else {
                dinfo->fb.size =  MB(vram);
@@ -663,11 +652,6 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
                return -ENODEV;
        }
 
-       if (MB(voffset) < stolen_size)
-               offset = (stolen_size >> 12);
-       else
-               offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE;
-
        /* set the mem offsets - set them after the already used pages */
        if (dinfo->accel) {
                dinfo->ring.offset = offset + gtt_info.current_memory;
@@ -682,6 +666,26 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
                        + (dinfo->cursor.size >> 12);
        }
 
+       /* Map the fb and MMIO regions */
+       /* ioremap only up to the end of used aperture */
+       dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache
+               (dinfo->aperture.physical, (dinfo->fb.offset << 12)
+                + dinfo->fb.size);
+       if (!dinfo->aperture.virtual) {
+               ERR_MSG("Cannot remap FB region.\n");
+               cleanup(dinfo);
+               return -ENODEV;
+       }
+
+       dinfo->mmio_base =
+               (u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys,
+                                              INTEL_REG_SIZE);
+       if (!dinfo->mmio_base) {
+               ERR_MSG("Cannot remap MMIO region.\n");
+               cleanup(dinfo);
+               return -ENODEV;
+       }
+
        /* Allocate memories (which aren't stolen) */
        if (dinfo->accel) {
                if (!(dinfo->gtt_ring_mem =
index fbf659b..3edc9f4 100644 (file)
@@ -246,6 +246,11 @@ static const struct fb_videomode modedb[] = {
        /* 480x300 @ 72 Hz, 48.0 kHz hsync */
        NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3,
        0, FB_VMODE_DOUBLE
+    }, {
+       /* 1920x1200 @ 60 Hz, 74.5 Khz hsync */
+       NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3,
+       FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+       FB_VMODE_NONINTERLACED
     },
 };
 
index b2e6b24..52b1685 100644 (file)
@@ -1324,6 +1324,13 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
 
                fb_videomode_to_var(&nvidiafb_default_var, &modedb);
                nvidiafb_default_var.bits_per_pixel = 8;
+       } else if (par->fpWidth && par->fpHeight) {
+               char buf[16];
+
+               memset(buf, 0, 16);
+               snprintf(buf, 15, "%dx%d", par->fpWidth, par->fpHeight);
+               fb_find_mode(&nvidiafb_default_var, info, buf, specs->modedb,
+                            specs->modedb_len, &modedb, 8);
        }
 
        if (mode_option)
index 16e37a5..3011281 100644 (file)
@@ -717,6 +717,9 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
        DPRINTK("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2);
        DPRINTK("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
 
+       /* enable LCD controller clock */
+       pxa_set_cken(CKEN16_LCD, 1);
+
        /* Sequence from 11.7.10 */
        LCCR3 = fbi->reg_lccr3;
        LCCR2 = fbi->reg_lccr2;
@@ -750,6 +753,9 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
 
        schedule_timeout(20 * HZ / 1000);
        remove_wait_queue(&fbi->ctrlr_wait, &wait);
+
+       /* disable LCD controller clock */
+       pxa_set_cken(CKEN16_LCD, 0);
 }
 
 /*
@@ -1299,8 +1305,6 @@ int __init pxafb_probe(struct device *dev)
                ret = -ENOMEM;
                goto failed;
        }
-       /* enable LCD controller clock */
-       pxa_set_cken(CKEN16_LCD, 1);
 
        ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT, "LCD", fbi);
        if (ret) {
index c463870..a78b9bd 100644 (file)
@@ -80,7 +80,7 @@
 #include <video/radeon.h>
 #include <linux/radeonfb.h>
 
-#define DEBUG  1
+#define DEBUG  0
 
 #if DEBUG
 #define RTRACE         printk
index 2d29db7..beeec7b 100644 (file)
@@ -598,7 +598,7 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  *    requests for the LCD controller.  If we hit this, it means we're
  *    doing nothing but LCD DMA.
  */
-static unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
+static inline unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
 {
        /*
         * Period = pixclock * bits_per_byte * bytes_per_transfer
index da8004e..698ca92 100644 (file)
@@ -454,13 +454,16 @@ static struct accel_switch accel_image = {
 static void tridentfb_fillrect(struct fb_info * info, const struct fb_fillrect *fr)
 {
        int bpp = info->var.bits_per_pixel;
-       int col;
+       int col = 0;
        
        switch (bpp) {
                default:
-               case 8: col = fr->color;
+               case 8: col |= fr->color;
+                       col |= col << 8;
+                       col |= col << 16;
                        break;
                case 16: col = ((u32 *)(info->pseudo_palette))[fr->color];
+                       
                         break;
                case 32: col = ((u32 *)(info->pseudo_palette))[fr->color];
                         break;
@@ -882,8 +885,9 @@ static int tridentfb_set_par(struct fb_info *info)
 
        write3X4(GraphEngReg, 0x80);    //enable GE for text acceleration
 
-//     if (info->var.accel_flags & FB_ACCELF_TEXT)
-//FIXME                acc->init_accel(info->var.xres,bpp);
+#ifdef CONFIG_FB_TRIDENT_ACCEL 
+       acc->init_accel(info->var.xres,bpp);
+#endif
        
        switch (bpp) {
                case 8:  tmp = 0x00; break;
@@ -900,7 +904,7 @@ static int tridentfb_set_par(struct fb_info *info)
        write3X4(DRAMControl, tmp);     //both IO,linear enable
 
        write3X4(InterfaceSel, read3X4(InterfaceSel) | 0x40);
-       write3X4(Performance,0x20);
+       write3X4(Performance,0x92);
        write3X4(PCIReg,0x07);          //MMIO & PCI read and write burst enable
 
        /* convert from picoseconds to MHz */
@@ -981,12 +985,14 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,
                t_outb(green>>10,0x3C9);
                t_outb(blue>>10,0x3C9);
 
-       } else
-       if (bpp == 16)                  /* RGB 565 */
-                       ((u32*)info->pseudo_palette)[regno] = (red & 0xF800) |
-                       ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
-       else
-       if (bpp == 32)          /* ARGB 8888 */
+       } else if (bpp == 16) { /* RGB 565 */
+               u32 col;
+
+               col = (red & 0xF800) | ((green & 0xFC00) >> 5) |
+                       ((blue & 0xF800) >> 11);
+               col |= col << 16;       
+               ((u32 *)(info->pseudo_palette))[regno] = col;
+       } else if (bpp == 32)           /* ARGB 8888 */
                ((u32*)info->pseudo_palette)[regno] =
                        ((transp & 0xFF00) <<16)        |
                        ((red & 0xFF00) << 8)           |
index 8a9c428..0bbf029 100644 (file)
@@ -593,7 +593,7 @@ void w1_search(struct w1_master *dev, w1_slave_found_callback cb)
                 * Return 0 - device(s) present, 1 - no devices present.
                 */
                if (w1_reset_bus(dev)) {
-                       dev_info(&dev->dev, "No devices present on the wire.\n");
+                       dev_dbg(&dev->dev, "No devices present on the wire.\n");
                        break;
                }
 
index 5d0c4be..e54be70 100644 (file)
@@ -363,12 +363,15 @@ config INOTIFY
        bool "Inotify file change notification support"
        default y
        ---help---
-         Say Y here to enable inotify support and the /dev/inotify character
-         device.  Inotify is a file change notification system and a
+         Say Y here to enable inotify support and the associated system
+         calls.  Inotify is a file change notification system and a
          replacement for dnotify.  Inotify fixes numerous shortcomings in
          dnotify and introduces several new features.  It allows monitoring
-         of both files and directories via a single open fd.  Multiple file
-         events are supported.
+         of both files and directories via a single open fd.  Other features
+         include multiple file events, one-shot support, and unmount
+         notification.
+
+         For more information, see Documentation/filesystems/inotify.txt
 
          If unsure, say Y.
 
index 63f5df9..fd52843 100644 (file)
@@ -97,7 +97,7 @@ extern int adfs_dir_update(struct super_block *sb, struct object_info *obj);
 extern struct inode_operations adfs_file_inode_operations;
 extern struct file_operations adfs_file_operations;
 
-extern inline __u32 signed_asl(__u32 val, signed int shift)
+static inline __u32 signed_asl(__u32 val, signed int shift)
 {
        if (shift >= 0)
                val <<= shift;
@@ -112,7 +112,7 @@ extern inline __u32 signed_asl(__u32 val, signed int shift)
  *
  * The root directory ID should always be looked up in the map [3.4]
  */
-extern inline int
+static inline int
 __adfs_block_map(struct super_block *sb, unsigned int object_id,
                 unsigned int block)
 {
index bfc28ab..31ee065 100644 (file)
@@ -30,7 +30,7 @@ static struct dentry *afs_mntpt_lookup(struct inode *dir,
                                       struct dentry *dentry,
                                       struct nameidata *nd);
 static int afs_mntpt_open(struct inode *inode, struct file *file);
-static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd);
+static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd);
 
 struct file_operations afs_mntpt_file_operations = {
        .open           = afs_mntpt_open,
@@ -233,7 +233,7 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
 /*
  * follow a link from a mountpoint directory, thus causing it to be mounted
  */
-static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct vfsmount *newmnt;
        struct dentry *old_dentry;
@@ -249,7 +249,7 @@ static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd)
        newmnt = afs_mntpt_do_automount(dentry);
        if (IS_ERR(newmnt)) {
                path_release(nd);
-               return PTR_ERR(newmnt);
+               return (void *)newmnt;
        }
 
        old_dentry = nd->dentry;
@@ -267,7 +267,7 @@ static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd)
        }
 
        kleave(" = %d", err);
-       return err;
+       return ERR_PTR(err);
 } /* end afs_mntpt_follow_link() */
 
 /*****************************************************************************/
index f028396..52e8772 100644 (file)
 
 #include "autofs_i.h"
 
-static int autofs_follow_link(struct dentry *dentry, struct nameidata *nd)
+/* Nothing to release.. */
+static void *autofs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data;
        nd_set_link(nd, s);
-       return 0;
+       return NULL;
 }
 
 struct inode_operations autofs_symlink_inode_operations = {
index c265a66..2ea2c98 100644 (file)
 
 #include "autofs_i.h"
 
-static int autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct autofs_info *ino = autofs4_dentry_ino(dentry);
        nd_set_link(nd, (char *)ino->u.symlink);
-       return 0;
+       return NULL;
 }
 
 struct inode_operations autofs4_symlink_inode_operations = {
index de5bb28..e0a6025 100644 (file)
@@ -41,8 +41,8 @@ static struct inode *befs_alloc_inode(struct super_block *sb);
 static void befs_destroy_inode(struct inode *inode);
 static int befs_init_inodecache(void);
 static void befs_destroy_inodecache(void);
-static int befs_follow_link(struct dentry *, struct nameidata *);
-static void befs_put_link(struct dentry *, struct nameidata *);
+static void *befs_follow_link(struct dentry *, struct nameidata *);
+static void befs_put_link(struct dentry *, struct nameidata *, void *);
 static int befs_utf2nls(struct super_block *sb, const char *in, int in_len,
                        char **out, int *out_len);
 static int befs_nls2utf(struct super_block *sb, const char *in, int in_len,
@@ -461,7 +461,7 @@ befs_destroy_inodecache(void)
  * The data stream become link name. Unless the LONG_SYMLINK
  * flag is set.
  */
-static int
+static void *
 befs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
@@ -487,10 +487,10 @@ befs_follow_link(struct dentry *dentry, struct nameidata *nd)
        }
 
        nd_set_link(nd, link);
-       return 0;
+       return NULL;
 }
 
-static void befs_put_link(struct dentry *dentry, struct nameidata *nd)
+static void befs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
 {
        befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
        if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
index 249dd6b..1f2d464 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -248,17 +248,13 @@ inline void __bio_clone(struct bio *bio, struct bio *bio_src)
 {
        request_queue_t *q = bdev_get_queue(bio_src->bi_bdev);
 
-       memcpy(bio->bi_io_vec, bio_src->bi_io_vec, bio_src->bi_max_vecs * sizeof(struct bio_vec));
+       memcpy(bio->bi_io_vec, bio_src->bi_io_vec,
+               bio_src->bi_max_vecs * sizeof(struct bio_vec));
 
        bio->bi_sector = bio_src->bi_sector;
        bio->bi_bdev = bio_src->bi_bdev;
        bio->bi_flags |= 1 << BIO_CLONED;
        bio->bi_rw = bio_src->bi_rw;
-
-       /*
-        * notes -- maybe just leave bi_idx alone. assume identical mapping
-        * for the clone
-        */
        bio->bi_vcnt = bio_src->bi_vcnt;
        bio->bi_size = bio_src->bi_size;
        bio->bi_idx = bio_src->bi_idx;
index dab4774..3196d4c 100644 (file)
@@ -1,3 +1,9 @@
+Version 1.35
+------------
+Add writepage performance improvements.  Fix path name conversions
+for long filenames on mounts which were done with "mapchars" mount option
+specified.
+
 Version 1.34
 ------------
 Fix error mapping of the TOO_MANY_LINKS (hardlinks) case.
index 78af585..1fd21f6 100644 (file)
@@ -83,8 +83,8 @@ extern int cifs_dir_notify(struct file *, unsigned long arg);
 extern struct dentry_operations cifs_dentry_ops;
 
 /* Functions related to symlinks */
-extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
-extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd);
+extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
+extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *);
 extern int cifs_readlink(struct dentry *direntry, char __user *buffer, 
                         int buflen);
 extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
index 3c628bf..0db0b31 100644 (file)
@@ -2602,6 +2602,9 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
        if(name_len < PATH_MAX) {
                memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
                byte_count += name_len;
+               /* 14 byte parm len above enough for 2 byte null terminator */
+               pSMB->ResumeFileName[name_len] = 0;
+               pSMB->ResumeFileName[name_len+1] = 0;
        } else {
                rc = -EINVAL;
                goto FNext2_err_exit;
index 30ab70c..3497125 100644 (file)
@@ -643,7 +643,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
                         netfid, length,
                         pfLock->fl_start, numUnlock, numLock, lockType,
                         wait_flag);
-       if (rc == 0 && (pfLock->fl_flags & FL_POSIX))
+       if (pfLock->fl_flags & FL_POSIX)
                posix_lock_file_wait(file, pfLock);
        FreeXid(xid);
        return rc;
index bde0fab..ab925ef 100644 (file)
@@ -92,7 +92,7 @@ cifs_hl_exit:
        return rc;
 }
 
-int
+void *
 cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
 {
        struct inode *inode = direntry->d_inode;
@@ -148,7 +148,7 @@ out:
 out_no_free:
        FreeXid(xid);
        nd_set_link(nd, target_path);
-       return 0;
+       return NULL;    /* No cookie */
 }
 
 int
@@ -330,7 +330,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
        return rc;
 }
 
-void cifs_put_link(struct dentry *direntry, struct nameidata *nd)
+void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie)
 {
        char *p = nd_get_link(nd);
        if (!IS_ERR(p))
index 072b4ee..20ae415 100644 (file)
@@ -611,6 +611,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
                src_char = source[i];
                switch (src_char) {
                        case 0:
+                               target[j] = 0;
                                goto ctoUCS_out;
                        case ':':
                                target[j] = cpu_to_le16(UNI_COLON);
index 3aa8a7e..a15a2e1 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
+#include <linux/fsnotify.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
@@ -101,6 +102,7 @@ static inline void dentry_iput(struct dentry * dentry)
                list_del_init(&dentry->d_alias);
                spin_unlock(&dentry->d_lock);
                spin_unlock(&dcache_lock);
+               fsnotify_inoderemove(inode);
                if (dentry->d_op && dentry->d_op->d_iput)
                        dentry->d_op->d_iput(dentry, inode);
                else
@@ -1165,13 +1167,16 @@ out:
  
 void d_delete(struct dentry * dentry)
 {
+       int isdir = 0;
        /*
         * Are we the only user?
         */
        spin_lock(&dcache_lock);
        spin_lock(&dentry->d_lock);
+       isdir = S_ISDIR(dentry->d_inode->i_mode);
        if (atomic_read(&dentry->d_count) == 1) {
                dentry_iput(dentry);
+               fsnotify_nameremove(dentry, isdir);
                return;
        }
 
@@ -1180,6 +1185,8 @@ void d_delete(struct dentry * dentry)
 
        spin_unlock(&dentry->d_lock);
        spin_unlock(&dcache_lock);
+
+       fsnotify_nameremove(dentry, isdir);
 }
 
 static void __d_rehash(struct dentry * entry, struct hlist_head *list)
index 1ecfe1f..8b679b6 100644 (file)
@@ -2491,11 +2491,11 @@ static int devfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
        return 0;
 }                              /*  End Function devfs_mknod  */
 
-static int devfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *devfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct devfs_entry *p = get_devfs_entry_from_vfs_inode(dentry->d_inode);
        nd_set_link(nd, p ? p->u.symlink.linkname : ERR_PTR(-ENODEV));
-       return 0;
+       return NULL;
 }                              /*  End Function devfs_follow_link  */
 
 static struct inode_operations devfs_iops = {
index 9f7bac0..1e67d87 100644 (file)
 #include "xattr.h"
 #include <linux/namei.h>
 
-static int ext2_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *ext2_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct ext2_inode_info *ei = EXT2_I(dentry->d_inode);
        nd_set_link(nd, (char *)ei->i_data);
-       return 0;
+       return NULL;
 }
 
 struct inode_operations ext2_symlink_inode_operations = {
index 8c3e728..4f79122 100644 (file)
 #include <linux/namei.h>
 #include "xattr.h"
 
-static int ext3_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void * ext3_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct ext3_inode_info *ei = EXT3_I(dentry->d_inode);
        nd_set_link(nd, (char*)ei->i_data);
-       return 0;
+       return NULL;
 }
 
 struct inode_operations ext3_symlink_inode_operations = {
index ac677ab..d0401dc 100644 (file)
@@ -38,7 +38,7 @@
 #include "vxfs_inode.h"
 
 
-static int     vxfs_immed_follow_link(struct dentry *, struct nameidata *);
+static void *  vxfs_immed_follow_link(struct dentry *, struct nameidata *);
 
 static int     vxfs_immed_readpage(struct file *, struct page *);
 
@@ -72,12 +72,12 @@ struct address_space_operations vxfs_immed_aops = {
  * Returns:
  *   Zero on success, else a negative error code.
  */
-static int
+static void *
 vxfs_immed_follow_link(struct dentry *dp, struct nameidata *np)
 {
        struct vxfs_inode_info          *vip = VXFS_INO(dp->d_inode);
        nd_set_link(np, vip->vii_immed.vi_immed);
-       return 0;
+       return NULL;
 }
 
 /**
index 6ad1211..a096c5a 100644 (file)
@@ -480,6 +480,8 @@ void hfs_bnode_put(struct hfs_bnode *node)
                        return;
                }
                for (i = 0; i < tree->pages_per_bnode; i++) {
+                       if (!node->page[i])
+                               continue;
                        mark_page_accessed(node->page[i]);
 #if REF_PAGES
                        put_page(node->page[i]);
index cbc8510..5ea6b3d 100644 (file)
@@ -482,7 +482,8 @@ void hfs_file_truncate(struct inode *inode)
                page_cache_release(page);
                mark_inode_dirty(inode);
                return;
-       }
+       } else if (inode->i_size == HFS_I(inode)->phys_size)
+               return;
        size = inode->i_size + HFS_SB(sb)->alloc_blksz - 1;
        blk_cnt = size / HFS_SB(sb)->alloc_blksz;
        alloc_cnt = HFS_I(inode)->alloc_blocks;
index 267872e..8868d3b 100644 (file)
@@ -643,6 +643,8 @@ void hfs_bnode_put(struct hfs_bnode *node)
                        return;
                }
                for (i = 0; i < tree->pages_per_bnode; i++) {
+                       if (!node->page[i])
+                               continue;
                        mark_page_accessed(node->page[i]);
 #if REF_PAGES
                        put_page(node->page[i]);
index 376498c..e7235ca 100644 (file)
@@ -461,7 +461,9 @@ void hfsplus_file_truncate(struct inode *inode)
                page_cache_release(page);
                mark_inode_dirty(inode);
                return;
-       }
+       } else if (inode->i_size == HFSPLUS_I(inode).phys_size)
+               return;
+
        blk_cnt = (inode->i_size + HFSPLUS_SB(sb).alloc_blksz - 1) >> HFSPLUS_SB(sb).alloc_blksz_shift;
        alloc_cnt = HFSPLUS_I(inode).alloc_blocks;
        if (blk_cnt == alloc_cnt)
index ff150fe..5293091 100644 (file)
@@ -38,7 +38,7 @@ struct hppfs_inode_info {
 
 static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode)
 {
-       return(list_entry(inode, struct hppfs_inode_info, vfs_inode));
+       return container_of(inode, struct hppfs_inode_info, vfs_inode);
 }
 
 #define HPPFS_SUPER_MAGIC 0xb00000ee
@@ -662,42 +662,36 @@ static int hppfs_readlink(struct dentry *dentry, char *buffer, int buflen)
 {
        struct file *proc_file;
        struct dentry *proc_dentry;
-       int (*readlink)(struct dentry *, char *, int);
-       int err, n;
+       int ret;
 
        proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
        proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY);
-       err = PTR_ERR(proc_dentry);
-       if(IS_ERR(proc_dentry))
-               return(err);
+       if (IS_ERR(proc_file))
+               return PTR_ERR(proc_file);
 
-       readlink = proc_dentry->d_inode->i_op->readlink;
-       n = (*readlink)(proc_dentry, buffer, buflen);
+       ret = proc_dentry->d_inode->i_op->readlink(proc_dentry, buffer, buflen);
 
        fput(proc_file);
 
-       return(n);
+       return ret;
 }
 
-static int hppfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void* hppfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct file *proc_file;
        struct dentry *proc_dentry;
-       int (*follow_link)(struct dentry *, struct nameidata *);
-       int err, n;
+       void *ret;
 
        proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
        proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY);
-       err = PTR_ERR(proc_dentry);
-       if(IS_ERR(proc_dentry))
-               return(err);
+       if (IS_ERR(proc_file))
+               return proc_file;
 
-       follow_link = proc_dentry->d_inode->i_op->follow_link;
-       n = (*follow_link)(proc_dentry, nd);
+       ret = proc_dentry->d_inode->i_op->follow_link(proc_dentry, nd);
 
        fput(proc_file);
 
-       return(n);
+       return ret;
 }
 
 static struct inode_operations hppfs_dir_iops = {
index a8a714e..2e4e2a5 100644 (file)
@@ -90,6 +90,7 @@ struct inotify_device {
        unsigned int            queue_size;     /* size of the queue (bytes) */
        unsigned int            event_count;    /* number of pending events */
        unsigned int            max_events;     /* maximum number of events */
+       u32                     last_wd;        /* the last wd allocated */
 };
 
 /*
@@ -352,7 +353,7 @@ static int inotify_dev_get_wd(struct inotify_device *dev,
        do {
                if (unlikely(!idr_pre_get(&dev->idr, GFP_KERNEL)))
                        return -ENOSPC;
-               ret = idr_get_new(&dev->idr, watch, &watch->wd);
+               ret = idr_get_new_above(&dev->idr, watch, dev->last_wd+1, &watch->wd);
        } while (ret == -EAGAIN);
 
        return ret;
@@ -401,6 +402,7 @@ static struct inotify_watch *create_watch(struct inotify_device *dev,
                return ERR_PTR(ret);
        }
 
+       dev->last_wd = watch->wd;
        watch->mask = mask;
        atomic_set(&watch->count, 0);
        INIT_LIST_HEAD(&watch->d_list);
@@ -899,6 +901,7 @@ asmlinkage long sys_inotify_init(void)
        dev->queue_size = 0;
        dev->max_events = inotify_max_queued_events;
        dev->user = user;
+       dev->last_wd = 0;
        atomic_set(&dev->count, 0);
 
        get_inotify_dev(dev);
index 97e1f08..d1c1f2b 100644 (file)
@@ -62,6 +62,8 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
 
                        break;
                case IOPRIO_CLASS_IDLE:
+                       if (!capable(CAP_SYS_ADMIN))
+                               return -EPERM;
                        break;
                default:
                        return -EINVAL;
index 34a44e4..4917315 100644 (file)
@@ -129,8 +129,14 @@ static int zisofs_readpage(struct file *file, struct page *page)
        cend = le32_to_cpu(*(__le32 *)(bh->b_data + (blockendptr & bufmask)));
        brelse(bh);
 
+       if (cstart > cend)
+               goto eio;
+               
        csize = cend-cstart;
 
+       if (csize > deflateBound(1UL << zisofs_block_shift))
+               goto eio;
+
        /* Now page[] contains an array of pages, any of which can be NULL,
           and the locks on which we hold.  We should now read the data and
           release the pages.  If the pages are NULL the decompressed data
index 65ab6b0..82ef484 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/namei.h>
 #include "nodelist.h"
 
-static int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd);
+static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd);
 
 struct inode_operations jffs2_symlink_inode_operations =
 {      
@@ -27,9 +27,10 @@ struct inode_operations jffs2_symlink_inode_operations =
        .setattr =      jffs2_setattr
 };
 
-static int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode);
+       char *p = (char *)f->dents;
        
        /*
         * We don't acquire the f->sem mutex here since the only data we
@@ -45,19 +46,20 @@ static int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)
         * nd_set_link() call.
         */
        
-       if (!f->dents) {
+       if (!p) {
                printk(KERN_ERR "jffs2_follow_link(): can't find symlink taerget\n");
-               return -EIO;
+               p = ERR_PTR(-EIO);
+       } else {
+               D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->dents));
        }
-       D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->dents));
 
-       nd_set_link(nd, (char *)f->dents);
+       nd_set_link(nd, p);
        
        /*
         * We unlock the f->sem mutex but VFS will use the f->dents string. This is safe
         * since the only way that may cause f->dents to be changed is iput() operation.
         * But VFS will not use f->dents after iput() has been called.
         */
-       return 0;
+       return NULL;
 }
 
index 2137138..767c7ec 100644 (file)
@@ -128,6 +128,10 @@ void jfs_delete_inode(struct inode *inode)
 {
        jfs_info("In jfs_delete_inode, inode = 0x%p", inode);
 
+       if (is_bad_inode(inode) ||
+           (JFS_IP(inode)->fileset != cpu_to_le32(FILESYSTEM_I)))
+                       return;
+
        if (test_cflag(COMMIT_Freewmap, inode))
                jfs_free_zero_link(inode);
 
index 22815e8..d27bac6 100644 (file)
@@ -191,7 +191,7 @@ static int lbmIOWait(struct lbuf * bp, int flag);
 static bio_end_io_t lbmIODone;
 static void lbmStartIO(struct lbuf * bp);
 static void lmGCwrite(struct jfs_log * log, int cant_block);
-static int lmLogSync(struct jfs_log * log, int nosyncwait);
+static int lmLogSync(struct jfs_log * log, int hard_sync);
 
 
 
@@ -915,19 +915,17 @@ static void lmPostGC(struct lbuf * bp)
  *     if new sync address is available
  *     (normally the case if sync() is executed by back-ground
  *     process).
- *     if not, explicitly run jfs_blogsync() to initiate
- *     getting of new sync address.
  *     calculate new value of i_nextsync which determines when
  *     this code is called again.
  *
  * PARAMETERS: log     - log structure
- *             nosyncwait - 1 if called asynchronously
+ *             hard_sync - 1 to force all metadata to be written
  *
  * RETURN:     0
  *                     
  * serialization: LOG_LOCK() held on entry/exit
  */
-static int lmLogSync(struct jfs_log * log, int nosyncwait)
+static int lmLogSync(struct jfs_log * log, int hard_sync)
 {
        int logsize;
        int written;            /* written since last syncpt */
@@ -941,11 +939,18 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
        unsigned long flags;
 
        /* push dirty metapages out to disk */
-       list_for_each_entry(sbi, &log->sb_list, log_list) {
-               filemap_flush(sbi->ipbmap->i_mapping);
-               filemap_flush(sbi->ipimap->i_mapping);
-               filemap_flush(sbi->direct_inode->i_mapping);
-       }
+       if (hard_sync)
+               list_for_each_entry(sbi, &log->sb_list, log_list) {
+                       filemap_fdatawrite(sbi->ipbmap->i_mapping);
+                       filemap_fdatawrite(sbi->ipimap->i_mapping);
+                       filemap_fdatawrite(sbi->direct_inode->i_mapping);
+               }
+       else
+               list_for_each_entry(sbi, &log->sb_list, log_list) {
+                       filemap_flush(sbi->ipbmap->i_mapping);
+                       filemap_flush(sbi->ipimap->i_mapping);
+                       filemap_flush(sbi->direct_inode->i_mapping);
+               }
 
        /*
         *      forward syncpt
@@ -1021,10 +1026,6 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
                /* next syncpt trigger = written + more */
                log->nextsync = written + more;
 
-       /* return if lmLogSync() from outside of transaction, e.g., sync() */
-       if (nosyncwait)
-               return lsn;
-
        /* if number of bytes written from last sync point is more
         * than 1/4 of the log size, stop new transactions from
         * starting until all current transactions are completed
@@ -1049,11 +1050,12 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
  *
  * FUNCTION:   write log SYNCPT record for specified log
  *
- * PARAMETERS: log     - log structure
+ * PARAMETERS: log       - log structure
+ *             hard_sync - set to 1 to force metadata to be written
  */
-void jfs_syncpt(struct jfs_log *log)
+void jfs_syncpt(struct jfs_log *log, int hard_sync)
 {      LOG_LOCK(log);
-       lmLogSync(log, 1);
+       lmLogSync(log, hard_sync);
        LOG_UNLOCK(log);
 }
 
index 747114c..e4978b5 100644 (file)
@@ -510,6 +510,6 @@ extern int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize);
 extern int lmGroupCommit(struct jfs_log *, struct tblock *);
 extern int jfsIOWait(void *);
 extern void jfs_flush_journal(struct jfs_log * log, int wait);
-extern void jfs_syncpt(struct jfs_log *log);
+extern void jfs_syncpt(struct jfs_log *log, int hard_sync);
 
 #endif                         /* _H_JFS_LOGMGR */
index 121c981..c7a92f9 100644 (file)
@@ -552,6 +552,11 @@ void txEnd(tid_t tid)
                 * synchronize with logsync barrier
                 */
                if (test_bit(log_SYNCBARRIER, &log->flag)) {
+                       TXN_UNLOCK();
+
+                       /* write dirty metadata & forward log syncpt */
+                       jfs_syncpt(log, 1);
+
                        jfs_info("log barrier off: 0x%x", log->lsn);
 
                        /* enable new transactions start */
@@ -560,11 +565,6 @@ void txEnd(tid_t tid)
                        /* wakeup all waitors for logsync barrier */
                        TXN_WAKEUP(&log->syncwait);
 
-                       TXN_UNLOCK();
-
-                       /* forward log syncpt */
-                       jfs_syncpt(log);
-
                        goto wakeup;
                }
        }
@@ -657,7 +657,9 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
                                /* only anonymous txn.
                                 * Remove from anon_list
                                 */
+                               TXN_LOCK();
                                list_del_init(&jfs_ip->anon_inode_list);
+                               TXN_UNLOCK();
                        }
                        jfs_ip->atlhead = tlck->next;
                } else {
index ee32211..9ff8972 100644 (file)
@@ -114,6 +114,8 @@ static void jfs_destroy_inode(struct inode *inode)
 {
        struct jfs_inode_info *ji = JFS_IP(inode);
 
+       BUG_ON(!list_empty(&ji->anon_inode_list));
+
        spin_lock_irq(&ji->ag_lock);
        if (ji->active_ag != -1) {
                struct bmap *bmap = JFS_SBI(inode->i_sb)->bmap;
@@ -531,7 +533,7 @@ static int jfs_sync_fs(struct super_block *sb, int wait)
        /* log == NULL indicates read-only mount */
        if (log) {
                jfs_flush_journal(log, wait);
-               jfs_syncpt(log);
+               jfs_syncpt(log, 0);
        }
 
        return 0;
index 287d8d6..16477b3 100644 (file)
 #include "jfs_inode.h"
 #include "jfs_xattr.h"
 
-static int jfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *jfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        char *s = JFS_IP(dentry->d_inode)->i_inline;
        nd_set_link(nd, s);
-       return 0;
+       return NULL;
 }
 
 struct inode_operations jfs_symlink_inode_operations = {
index 02a824c..6ec1f0f 100644 (file)
@@ -501,6 +501,7 @@ struct path {
 static inline int __do_follow_link(struct path *path, struct nameidata *nd)
 {
        int error;
+       void *cookie;
        struct dentry *dentry = path->dentry;
 
        touch_atime(path->mnt, dentry);
@@ -508,13 +509,15 @@ static inline int __do_follow_link(struct path *path, struct nameidata *nd)
 
        if (path->mnt == nd->mnt)
                mntget(path->mnt);
-       error = dentry->d_inode->i_op->follow_link(dentry, nd);
-       if (!error) {
+       cookie = dentry->d_inode->i_op->follow_link(dentry, nd);
+       error = PTR_ERR(cookie);
+       if (!IS_ERR(cookie)) {
                char *s = nd_get_link(nd);
+               error = 0;
                if (s)
                        error = __vfs_follow_link(nd, s);
                if (dentry->d_inode->i_op->put_link)
-                       dentry->d_inode->i_op->put_link(dentry, nd);
+                       dentry->d_inode->i_op->put_link(dentry, nd, cookie);
        }
        dput(dentry);
        mntput(path->mnt);
@@ -1801,7 +1804,6 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
        }
        up(&dentry->d_inode->i_sem);
        if (!error) {
-               fsnotify_rmdir(dentry, dentry->d_inode, dir);
                d_delete(dentry);
        }
        dput(dentry);
@@ -1874,7 +1876,6 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
 
        /* We don't d_delete() NFS sillyrenamed files--they still exist. */
        if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) {
-               fsnotify_unlink(dentry, dir);
                d_delete(dentry);
        }
 
@@ -2218,7 +2219,8 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
        if (!error) {
                const char *new_name = old_dentry->d_name.name;
-               fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir);
+               fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir,
+                             new_dentry->d_inode, old_dentry->d_inode);
        }
        fsnotify_oldname_free(old_name);
 
@@ -2345,15 +2347,17 @@ out:
 int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen)
 {
        struct nameidata nd;
-       int res;
+       void *cookie;
+
        nd.depth = 0;
-       res = dentry->d_inode->i_op->follow_link(dentry, &nd);
-       if (!res) {
-               res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd));
+       cookie = dentry->d_inode->i_op->follow_link(dentry, &nd);
+       if (!IS_ERR(cookie)) {
+               int res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd));
                if (dentry->d_inode->i_op->put_link)
-                       dentry->d_inode->i_op->put_link(dentry, &nd);
+                       dentry->d_inode->i_op->put_link(dentry, &nd, cookie);
+               cookie = ERR_PTR(res);
        }
-       return res;
+       return PTR_ERR(cookie);
 }
 
 int vfs_follow_link(struct nameidata *nd, const char *link)
@@ -2396,23 +2400,20 @@ int page_readlink(struct dentry *dentry, char __user *buffer, int buflen)
        return res;
 }
 
-int page_follow_link_light(struct dentry *dentry, struct nameidata *nd)
+void *page_follow_link_light(struct dentry *dentry, struct nameidata *nd)
 {
-       struct page *page;
+       struct page *page = NULL;
        nd_set_link(nd, page_getlink(dentry, &page));
-       return 0;
+       return page;
 }
 
-void page_put_link(struct dentry *dentry, struct nameidata *nd)
+void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
 {
-       if (!IS_ERR(nd_get_link(nd))) {
-               struct page *page;
-               page = find_get_page(dentry->d_inode->i_mapping, 0);
-               if (!page)
-                       BUG();
+       struct page *page = cookie;
+
+       if (page) {
                kunmap(page);
                page_cache_release(page);
-               page_cache_release(page);
        }
 }
 
index 587eb0d..79bd8a4 100644 (file)
@@ -160,7 +160,7 @@ clone_mnt(struct vfsmount *old, struct dentry *root)
                mnt->mnt_root = dget(root);
                mnt->mnt_mountpoint = mnt->mnt_root;
                mnt->mnt_parent = mnt;
-               mnt->mnt_namespace = old->mnt_namespace;
+               mnt->mnt_namespace = current->namespace;
 
                /* stick the duplicate mount on the same expiry list
                 * as the original if that was on one */
index b38a57e..2df639f 100644 (file)
@@ -182,14 +182,16 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
                /* We requested READDIRPLUS, but the server doesn't grok it */
                if (error == -ENOTSUPP && desc->plus) {
                        NFS_SERVER(inode)->caps &= ~NFS_CAP_READDIRPLUS;
-                       NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS;
+                       clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode));
                        desc->plus = 0;
                        goto again;
                }
                goto error;
        }
        SetPageUptodate(page);
-       NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME;
+       spin_lock(&inode->i_lock);
+       NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
+       spin_unlock(&inode->i_lock);
        /* Ensure consistent page alignment of the data.
         * Note: assumes we have exclusive access to this mapping either
         *       through inode->i_sem or some other mechanism.
@@ -462,7 +464,9 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
                                                page,
                                                NFS_SERVER(inode)->dtsize,
                                                desc->plus);
-       NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME;
+       spin_lock(&inode->i_lock);
+       NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
+       spin_unlock(&inode->i_lock);
        desc->page = page;
        desc->ptr = kmap(page);         /* matching kunmap in nfs_do_filldir */
        if (desc->error >= 0) {
@@ -545,7 +549,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                        break;
                }
                if (res == -ETOOSMALL && desc->plus) {
-                       NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS;
+                       clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode));
                        nfs_zap_caches(inode);
                        desc->plus = 0;
                        desc->entry->eof = 0;
@@ -608,7 +612,7 @@ static inline int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
 {
        if (IS_ROOT(dentry))
                return 1;
-       if ((NFS_FLAGS(dir) & NFS_INO_INVALID_ATTR) != 0
+       if ((NFS_I(dir)->cache_validity & NFS_INO_INVALID_ATTR) != 0
                        || nfs_attribute_timeout(dir))
                return 0;
        return nfs_verify_change_attribute(dir, (unsigned long)dentry->d_fsdata);
@@ -935,6 +939,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
        error = nfs_revalidate_inode(NFS_SERVER(dir), dir);
        if (error < 0) {
                res = ERR_PTR(error);
+               unlock_kernel();
                goto out;
        }
 
@@ -1575,11 +1580,12 @@ out:
 
 int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res)
 {
-       struct nfs_access_entry *cache = &NFS_I(inode)->cache_access;
+       struct nfs_inode *nfsi = NFS_I(inode);
+       struct nfs_access_entry *cache = &nfsi->cache_access;
 
        if (cache->cred != cred
                        || time_after(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode))
-                       || (NFS_FLAGS(inode) & NFS_INO_INVALID_ACCESS))
+                       || (nfsi->cache_validity & NFS_INO_INVALID_ACCESS))
                return -ENOENT;
        memcpy(res, cache, sizeof(*res));
        return 0;
@@ -1587,14 +1593,18 @@ int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs
 
 void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
 {
-       struct nfs_access_entry *cache = &NFS_I(inode)->cache_access;
+       struct nfs_inode *nfsi = NFS_I(inode);
+       struct nfs_access_entry *cache = &nfsi->cache_access;
 
        if (cache->cred != set->cred) {
                if (cache->cred)
                        put_rpccred(cache->cred);
                cache->cred = get_rpccred(set->cred);
        }
-       NFS_FLAGS(inode) &= ~NFS_INO_INVALID_ACCESS;
+       /* FIXME: replace current access_cache BKL reliance with inode->i_lock */
+       spin_lock(&inode->i_lock);
+       nfsi->cache_validity &= ~NFS_INO_INVALID_ACCESS;
+       spin_unlock(&inode->i_lock);
        cache->jiffies = set->jiffies;
        cache->mask = set->mask;
 }
index 5621ba9..f6b9eda 100644 (file)
@@ -134,9 +134,10 @@ nfs_file_release(struct inode *inode, struct file *filp)
  */
 static int nfs_revalidate_file(struct inode *inode, struct file *filp)
 {
+       struct nfs_inode *nfsi = NFS_I(inode);
        int retval = 0;
 
-       if ((NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) || nfs_attribute_timeout(inode))
+       if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) || nfs_attribute_timeout(inode))
                retval = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
        nfs_revalidate_mapping(inode, filp->f_mapping);
        return 0;
@@ -164,7 +165,7 @@ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp)
                goto force_reval;
        if (nfsi->npages != 0)
                return 0;
-       if (!(NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode))
+       if (!(nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode))
                return 0;
 force_reval:
        return __nfs_revalidate_inode(server, inode);
index 4845911..541b418 100644 (file)
@@ -615,14 +615,18 @@ nfs_zap_caches(struct inode *inode)
        struct nfs_inode *nfsi = NFS_I(inode);
        int mode = inode->i_mode;
 
+       spin_lock(&inode->i_lock);
+
        NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
        NFS_ATTRTIMEO_UPDATE(inode) = jiffies;
 
        memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
        if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
-               nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
+               nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
        else
-               nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
+               nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
+
+       spin_unlock(&inode->i_lock);
 }
 
 static void nfs_zap_acl_cache(struct inode *inode)
@@ -632,7 +636,9 @@ static void nfs_zap_acl_cache(struct inode *inode)
        clear_acl_cache = NFS_PROTO(inode)->clear_acl_cache;
        if (clear_acl_cache != NULL)
                clear_acl_cache(inode);
-       NFS_I(inode)->flags &= ~NFS_INO_INVALID_ACL;
+       spin_lock(&inode->i_lock);
+       NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_ACL;
+       spin_unlock(&inode->i_lock);
 }
 
 /*
@@ -739,7 +745,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
                        inode->i_fop = &nfs_dir_operations;
                        if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS)
                            && fattr->size <= NFS_LIMIT_READDIRPLUS)
-                               NFS_FLAGS(inode) |= NFS_INO_ADVISE_RDPLUS;
+                               set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode));
                } else if (S_ISLNK(inode->i_mode))
                        inode->i_op = &nfs_symlink_inode_operations;
                else
@@ -814,55 +820,84 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
                nfs_wb_all(inode);
        }
        error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr);
-       if (error == 0) {
+       if (error == 0)
                nfs_refresh_inode(inode, &fattr);
+       nfs_end_data_update(inode);
+       unlock_kernel();
+       return error;
+}
+
+/**
+ * nfs_setattr_update_inode - Update inode metadata after a setattr call.
+ * @inode: pointer to struct inode
+ * @attr: pointer to struct iattr
+ *
+ * Note: we do this in the *proc.c in order to ensure that
+ *       it works for things like exclusive creates too.
+ */
+void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
+{
+       if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) {
                if ((attr->ia_valid & ATTR_MODE) != 0) {
-                       int mode;
-                       mode = inode->i_mode & ~S_IALLUGO;
-                       mode |= attr->ia_mode & S_IALLUGO;
+                       int mode = attr->ia_mode & S_IALLUGO;
+                       mode |= inode->i_mode & ~S_IALLUGO;
                        inode->i_mode = mode;
                }
                if ((attr->ia_valid & ATTR_UID) != 0)
                        inode->i_uid = attr->ia_uid;
                if ((attr->ia_valid & ATTR_GID) != 0)
                        inode->i_gid = attr->ia_gid;
-               if ((attr->ia_valid & ATTR_SIZE) != 0) {
-                       inode->i_size = attr->ia_size;
-                       vmtruncate(inode, attr->ia_size);
-               }
+               spin_lock(&inode->i_lock);
+               NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
+               spin_unlock(&inode->i_lock);
        }
-       if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
-               NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
-       nfs_end_data_update(inode);
-       unlock_kernel();
-       return error;
+       if ((attr->ia_valid & ATTR_SIZE) != 0) {
+               inode->i_size = attr->ia_size;
+               vmtruncate(inode, attr->ia_size);
+       }
+}
+
+static int nfs_wait_schedule(void *word)
+{
+       if (signal_pending(current))
+               return -ERESTARTSYS;
+       schedule();
+       return 0;
 }
 
 /*
  * Wait for the inode to get unlocked.
- * (Used for NFS_INO_LOCKED and NFS_INO_REVALIDATING).
  */
-static int
-nfs_wait_on_inode(struct inode *inode, int flag)
+static int nfs_wait_on_inode(struct inode *inode)
 {
        struct rpc_clnt *clnt = NFS_CLIENT(inode);
        struct nfs_inode *nfsi = NFS_I(inode);
-
+       sigset_t oldmask;
        int error;
-       if (!(NFS_FLAGS(inode) & flag))
-               return 0;
+
        atomic_inc(&inode->i_count);
-       error = nfs_wait_event(clnt, nfsi->nfs_i_wait,
-                               !(NFS_FLAGS(inode) & flag));
+       rpc_clnt_sigmask(clnt, &oldmask);
+       error = wait_on_bit_lock(&nfsi->flags, NFS_INO_REVALIDATING,
+                                       nfs_wait_schedule, TASK_INTERRUPTIBLE);
+       rpc_clnt_sigunmask(clnt, &oldmask);
        iput(inode);
+
        return error;
 }
 
+static void nfs_wake_up_inode(struct inode *inode)
+{
+       struct nfs_inode *nfsi = NFS_I(inode);
+
+       clear_bit(NFS_INO_REVALIDATING, &nfsi->flags);
+       smp_mb__after_clear_bit();
+       wake_up_bit(&nfsi->flags, NFS_INO_REVALIDATING);
+}
+
 int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
        struct inode *inode = dentry->d_inode;
-       struct nfs_inode *nfsi = NFS_I(inode);
-       int need_atime = nfsi->flags & NFS_INO_INVALID_ATIME;
+       int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME;
        int err;
 
        if (__IS_FLG(inode, MS_NOATIME))
@@ -1008,7 +1043,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
        struct nfs_fattr fattr;
        struct nfs_inode *nfsi = NFS_I(inode);
        unsigned long verifier;
-       unsigned int flags;
+       unsigned long cache_validity;
 
        dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n",
                inode->i_sb->s_id, (long long)NFS_FILEID(inode));
@@ -1019,18 +1054,19 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
        if (NFS_STALE(inode))
                goto out_nowait;
 
-       while (NFS_REVALIDATING(inode)) {
-               status = nfs_wait_on_inode(inode, NFS_INO_REVALIDATING);
-               if (status < 0)
-                       goto out_nowait;
-               if (NFS_ATTRTIMEO(inode) == 0)
-                       continue;
-               if (NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME))
-                       continue;
-               status = NFS_STALE(inode) ? -ESTALE : 0;
-               goto out_nowait;
+       status = nfs_wait_on_inode(inode);
+       if (status < 0)
+               goto out;
+       if (NFS_STALE(inode)) {
+               status = -ESTALE;
+               /* Do we trust the cached ESTALE? */
+               if (NFS_ATTRTIMEO(inode) != 0) {
+                       if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME)) {
+                               /* no */
+                       } else
+                               goto out;
+               }
        }
-       NFS_FLAGS(inode) |= NFS_INO_REVALIDATING;
 
        /* Protect against RPC races by saving the change attribute */
        verifier = nfs_save_change_attribute(inode);
@@ -1042,7 +1078,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
                if (status == -ESTALE) {
                        nfs_zap_caches(inode);
                        if (!S_ISDIR(inode->i_mode))
-                               NFS_FLAGS(inode) |= NFS_INO_STALE;
+                               set_bit(NFS_INO_STALE, &NFS_FLAGS(inode));
                }
                goto out;
        }
@@ -1054,25 +1090,30 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
                         (long long)NFS_FILEID(inode), status);
                goto out;
        }
-       flags = nfsi->flags;
-       nfsi->flags &= ~NFS_INO_REVAL_PAGECACHE;
+       spin_lock(&inode->i_lock);
+       cache_validity = nfsi->cache_validity;
+       nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
+
        /*
         * We may need to keep the attributes marked as invalid if
         * we raced with nfs_end_attr_update().
         */
        if (verifier == nfsi->cache_change_attribute)
-               nfsi->flags &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
-       /* Do the page cache invalidation */
+               nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
+       spin_unlock(&inode->i_lock);
+
        nfs_revalidate_mapping(inode, inode->i_mapping);
-       if (flags & NFS_INO_INVALID_ACL)
+
+       if (cache_validity & NFS_INO_INVALID_ACL)
                nfs_zap_acl_cache(inode);
+
        dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n",
                inode->i_sb->s_id,
                (long long)NFS_FILEID(inode));
 
-out:
-       NFS_FLAGS(inode) &= ~NFS_INO_REVALIDATING;
-       wake_up(&nfsi->nfs_i_wait);
+ out:
+       nfs_wake_up_inode(inode);
+
  out_nowait:
        unlock_kernel();
        return status;
@@ -1096,7 +1137,7 @@ int nfs_attribute_timeout(struct inode *inode)
  */
 int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 {
-       if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
+       if (!(NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
                        && !nfs_attribute_timeout(inode))
                return NFS_STALE(inode) ? -ESTALE : 0;
        return __nfs_revalidate_inode(server, inode);
@@ -1111,19 +1152,23 @@ void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
 {
        struct nfs_inode *nfsi = NFS_I(inode);
 
-       if (nfsi->flags & NFS_INO_INVALID_DATA) {
+       if (nfsi->cache_validity & NFS_INO_INVALID_DATA) {
                if (S_ISREG(inode->i_mode)) {
                        if (filemap_fdatawrite(mapping) == 0)
                                filemap_fdatawait(mapping);
                        nfs_wb_all(inode);
                }
                invalidate_inode_pages2(mapping);
-               nfsi->flags &= ~NFS_INO_INVALID_DATA;
+
+               spin_lock(&inode->i_lock);
+               nfsi->cache_validity &= ~NFS_INO_INVALID_DATA;
                if (S_ISDIR(inode->i_mode)) {
                        memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
                        /* This ensures we revalidate child dentries */
                        nfsi->cache_change_attribute++;
                }
+               spin_unlock(&inode->i_lock);
+
                dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n",
                                inode->i_sb->s_id,
                                (long long)NFS_FILEID(inode));
@@ -1153,10 +1198,12 @@ void nfs_end_data_update(struct inode *inode)
 
        if (!nfs_have_delegation(inode, FMODE_READ)) {
                /* Mark the attribute cache for revalidation */
-               nfsi->flags |= NFS_INO_INVALID_ATTR;
+               spin_lock(&inode->i_lock);
+               nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
                /* Directories and symlinks: invalidate page cache too */
                if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
-                       nfsi->flags |= NFS_INO_INVALID_DATA;
+                       nfsi->cache_validity |= NFS_INO_INVALID_DATA;
+               spin_unlock(&inode->i_lock);
        }
        nfsi->cache_change_attribute ++;
        atomic_dec(&nfsi->data_updates);
@@ -1181,6 +1228,8 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
        if (nfs_have_delegation(inode, FMODE_READ))
                return 0;
 
+       spin_lock(&inode->i_lock);
+
        /* Are we in the process of updating data on the server? */
        data_unstable = nfs_caches_unstable(inode);
 
@@ -1189,19 +1238,23 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
                                && nfsi->change_attr == fattr->pre_change_attr)
                        nfsi->change_attr = fattr->change_attr;
                if (nfsi->change_attr != fattr->change_attr) {
-                       nfsi->flags |= NFS_INO_INVALID_ATTR;
+                       nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
                        if (!data_unstable)
-                               nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
+                               nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
                }
        }
 
-       if ((fattr->valid & NFS_ATTR_FATTR) == 0)
+       if ((fattr->valid & NFS_ATTR_FATTR) == 0) {
+               spin_unlock(&inode->i_lock);
                return 0;
+       }
 
        /* Has the inode gone and changed behind our back? */
        if (nfsi->fileid != fattr->fileid
-                       || (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
+                       || (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) {
+               spin_unlock(&inode->i_lock);
                return -EIO;
+       }
 
        cur_size = i_size_read(inode);
        new_isize = nfs_size_to_loff_t(fattr->size);
@@ -1216,30 +1269,31 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
 
        /* Verify a few of the more important attributes */
        if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) {
-               nfsi->flags |= NFS_INO_INVALID_ATTR;
+               nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
                if (!data_unstable)
-                       nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
+                       nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
        }
        if (cur_size != new_isize) {
-               nfsi->flags |= NFS_INO_INVALID_ATTR;
+               nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
                if (nfsi->npages == 0)
-                       nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
+                       nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
        }
 
        /* Have any file permissions changed? */
        if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)
                        || inode->i_uid != fattr->uid
                        || inode->i_gid != fattr->gid)
-               nfsi->flags |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL;
+               nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL;
 
        /* Has the link count changed? */
        if (inode->i_nlink != fattr->nlink)
-               nfsi->flags |= NFS_INO_INVALID_ATTR;
+               nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
 
        if (!timespec_equal(&inode->i_atime, &fattr->atime))
-               nfsi->flags |= NFS_INO_INVALID_ATIME;
+               nfsi->cache_validity |= NFS_INO_INVALID_ATIME;
 
        nfsi->read_cache_jiffies = fattr->timestamp;
+       spin_unlock(&inode->i_lock);
        return 0;
 }
 
@@ -1278,11 +1332,15 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
                goto out_err;
        }
 
+       spin_lock(&inode->i_lock);
+
        /*
         * Make sure the inode's type hasn't changed.
         */
-       if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
+       if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) {
+               spin_unlock(&inode->i_lock);
                goto out_changed;
+       }
 
        /*
         * Update the read time so we don't revalidate too often.
@@ -1373,8 +1431,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
                                || S_ISLNK(inode->i_mode)))
                invalid &= ~NFS_INO_INVALID_DATA;
        if (!nfs_have_delegation(inode, FMODE_READ))
-               nfsi->flags |= invalid;
+               nfsi->cache_validity |= invalid;
 
+       spin_unlock(&inode->i_lock);
        return 0;
  out_changed:
        /*
@@ -1391,7 +1450,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
         */
        nfs_invalidate_inode(inode);
  out_err:
-       NFS_FLAGS(inode) |= NFS_INO_STALE;
+       set_bit(NFS_INO_STALE, &NFS_FLAGS(inode));
        return -ESTALE;
 }
 
@@ -1950,7 +2009,8 @@ static struct inode *nfs_alloc_inode(struct super_block *sb)
        nfsi = (struct nfs_inode *)kmem_cache_alloc(nfs_inode_cachep, SLAB_KERNEL);
        if (!nfsi)
                return NULL;
-       nfsi->flags = 0;
+       nfsi->flags = 0UL;
+       nfsi->cache_validity = 0UL;
 #ifdef CONFIG_NFS_V3_ACL
        nfsi->acl_access = ERR_PTR(-EAGAIN);
        nfsi->acl_default = ERR_PTR(-EAGAIN);
@@ -1982,7 +2042,6 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
                nfsi->ndirty = 0;
                nfsi->ncommit = 0;
                nfsi->npages = 0;
-               init_waitqueue_head(&nfsi->nfs_i_wait);
                nfs4_init_once(nfsi);
        }
 }
index 1b7a3ef..6a5bbc0 100644 (file)
@@ -308,7 +308,9 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
        nfs_begin_data_update(inode);
        status = rpc_call(server->client_acl, ACLPROC3_SETACL,
                          &args, &fattr, 0);
-       NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS;
+       spin_lock(&inode->i_lock);
+       NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS;
+       spin_unlock(&inode->i_lock);
        nfs_end_data_update(inode);
        dprintk("NFS reply setacl: %d\n", status);
 
index 7851569..2681485 100644 (file)
@@ -120,6 +120,8 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
        dprintk("NFS call  setattr\n");
        fattr->valid = 0;
        status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0);
+       if (status == 0)
+               nfs_setattr_update_inode(inode, sattr);
        dprintk("NFS reply setattr: %d\n", status);
        return status;
 }
@@ -370,6 +372,8 @@ again:
                 * not sure this buys us anything (and I'd have
                 * to revamp the NFSv3 XDR code) */
                status = nfs3_proc_setattr(dentry, &fattr, sattr);
+               if (status == 0)
+                       nfs_setattr_update_inode(dentry->d_inode, sattr);
                nfs_refresh_inode(dentry->d_inode, &fattr);
                dprintk("NFS reply setattr (post-create): %d\n", status);
        }
index 1b76f80..0c5a308 100644 (file)
@@ -753,6 +753,7 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
                 .rpc_argp       = &arg,
                 .rpc_resp       = &res,
         };
+       int status;
 
         fattr->valid = 0;
 
@@ -762,7 +763,8 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
        } else
                memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
 
-       return rpc_call_sync(server->client, &msg, 0);
+       status = rpc_call_sync(server->client, &msg, 0);
+       return status;
 }
 
 static int nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
@@ -1145,6 +1147,8 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 
        status = nfs4_do_setattr(NFS_SERVER(inode), fattr,
                        NFS_FH(inode), sattr, state);
+       if (status == 0)
+               nfs_setattr_update_inode(inode, sattr);
        if (state != NULL)
                nfs4_close_state(state, FMODE_WRITE);
        put_rpccred(cred);
@@ -1449,8 +1453,10 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                struct nfs_fattr fattr;
                status = nfs4_do_setattr(NFS_SERVER(dir), &fattr,
                                     NFS_FH(state->inode), sattr, state);
-               if (status == 0)
+               if (status == 0) {
+                       nfs_setattr_update_inode(state->inode, sattr);
                        goto out;
+               }
        } else if (flags != 0)
                goto out;
        nfs4_close_state(state, flags);
index cedf636..be23c3f 100644 (file)
@@ -114,6 +114,8 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
        dprintk("NFS call  setattr\n");
        fattr->valid = 0;
        status = rpc_call(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, 0);
+       if (status == 0)
+               nfs_setattr_update_inode(inode, sattr);
        dprintk("NFS reply setattr: %d\n", status);
        return status;
 }
index 6f866b8..6ceb1d4 100644 (file)
@@ -140,7 +140,9 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode,
                if (rdata->res.eof != 0 || result == 0)
                        break;
        } while (count);
-       NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME;
+       spin_lock(&inode->i_lock);
+       NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
+       spin_unlock(&inode->i_lock);
 
        if (count)
                memclear_highpage_flush(page, rdata->args.pgbase, count);
@@ -473,7 +475,9 @@ void nfs_readpage_result(struct rpc_task *task)
                }
                task->tk_status = -EIO;
        }
-       NFS_FLAGS(data->inode) |= NFS_INO_INVALID_ATIME;
+       spin_lock(&data->inode->i_lock);
+       NFS_I(data->inode)->cache_validity |= NFS_INO_INVALID_ATIME;
+       spin_unlock(&data->inode->i_lock);
        data->complete(data, status);
 }
 
index 35f1065..18dc95b 100644 (file)
 
 /* Symlink caching in the page cache is even more simplistic
  * and straight-forward than readdir caching.
- *
- * At the beginning of the page we store pointer to struct page in question,
- * simplifying nfs_put_link() (if inode got invalidated we can't find the page
- * to be freed via pagecache lookup).
- * The NUL-terminated string follows immediately thereafter.
  */
 
-struct nfs_symlink {
-       struct page *page;
-       char body[0];
-};
-
 static int nfs_symlink_filler(struct inode *inode, struct page *page)
 {
-       const unsigned int pgbase = offsetof(struct nfs_symlink, body);
-       const unsigned int pglen = PAGE_SIZE - pgbase;
        int error;
 
        lock_kernel();
-       error = NFS_PROTO(inode)->readlink(inode, page, pgbase, pglen);
+       error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE);
        unlock_kernel();
        if (error < 0)
                goto error;
@@ -60,11 +48,10 @@ error:
        return -EIO;
 }
 
-static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *inode = dentry->d_inode;
        struct page *page;
-       struct nfs_symlink *p;
        void *err = ERR_PTR(nfs_revalidate_inode(NFS_SERVER(inode), inode));
        if (err)
                goto read_failed;
@@ -78,28 +65,20 @@ static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
                err = ERR_PTR(-EIO);
                goto getlink_read_error;
        }
-       p = kmap(page);
-       p->page = page;
-       nd_set_link(nd, p->body);
-       return 0;
+       nd_set_link(nd, kmap(page));
+       return page;
 
 getlink_read_error:
        page_cache_release(page);
 read_failed:
        nd_set_link(nd, err);
-       return 0;
+       return NULL;
 }
 
-static void nfs_put_link(struct dentry *dentry, struct nameidata *nd)
+static void nfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
 {
-       char *s = nd_get_link(nd);
-       if (!IS_ERR(s)) {
-               struct nfs_symlink *p;
-               struct page *page;
-
-               p = container_of(s, struct nfs_symlink, body[0]);
-               page = p->page;
-
+       if (cookie) {
+               struct page *page = cookie;
                kunmap(page);
                page_cache_release(page);
        }
index 18c58c3..251e5a1 100644 (file)
@@ -239,6 +239,7 @@ nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt,
        if (xdr_decode_word(buf, base, &entries) ||
            entries > NFS_ACL_MAX_ENTRIES)
                return -EINVAL;
+       nfsacl_desc.desc.array_maxlen = entries;
        err = xdr_decode_array2(buf, base + 4, &nfsacl_desc.desc);
        if (err)
                return err;
index 07b9a06..1697539 100644 (file)
@@ -287,6 +287,7 @@ out:
        svc_exit_thread(rqstp);
 
        /* Release module */
+       unlock_kernel();
        module_put_and_exit(0);
 }
 
index 9709fac..9eecc99 100644 (file)
@@ -174,6 +174,9 @@ ToDo/Notes:
          fact that the vfs and ntfs inodes are one struct in memory to find
          the ntfs inode in memory if present.  Also, the ntfs inode has its
          own locking so it does not matter if the vfs inode is locked.
+       - Fix bug in mft record writing where we forgot to set the device in
+         the buffers when mapping them after the VM had discarded them.
+         Thanks to Martin MOKREJÅ  for the bug report.
 
 2.1.22 - Many bug and race fixes and error handling improvements.
 
index 3f43bfe..78adad7 100644 (file)
@@ -924,6 +924,7 @@ static int ntfs_write_mst_block(struct page *page,
                        LCN lcn;
                        unsigned int vcn_ofs;
 
+                       bh->b_bdev = vol->sb->s_bdev;
                        /* Obtain the vcn and offset of the current block. */
                        vcn = (VCN)block << bh_size_bits;
                        vcn_ofs = vcn & vol->cluster_size_mask;
index ac9ff39..317f7c6 100644 (file)
@@ -533,6 +533,7 @@ int ntfs_sync_mft_mirror(ntfs_volume *vol, const unsigned long mft_no,
                        LCN lcn;
                        unsigned int vcn_ofs;
 
+                       bh->b_bdev = vol->sb->s_bdev;
                        /* Obtain the vcn and offset of the current block. */
                        vcn = ((VCN)mft_no << vol->mft_record_size_bits) +
                                        (block_start - m_start);
@@ -725,6 +726,7 @@ int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync)
                        LCN lcn;
                        unsigned int vcn_ofs;
 
+                       bh->b_bdev = vol->sb->s_bdev;
                        /* Obtain the vcn and offset of the current block. */
                        vcn = ((VCN)ni->mft_no << vol->mft_record_size_bits) +
                                        (block_start - m_start);
index ace151f..491f2d9 100644 (file)
@@ -890,7 +890,7 @@ static struct file_operations proc_seccomp_operations = {
 };
 #endif /* CONFIG_SECCOMP */
 
-static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *inode = dentry->d_inode;
        int error = -EACCES;
@@ -907,7 +907,7 @@ static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
        error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt);
        nd->last_type = LAST_BIND;
 out:
-       return error;
+       return ERR_PTR(error);
 }
 
 static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt,
@@ -1692,11 +1692,11 @@ static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
        return vfs_readlink(dentry,buffer,buflen,tmp);
 }
 
-static int proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        char tmp[30];
        sprintf(tmp, "%d", current->tgid);
-       return vfs_follow_link(nd,tmp);
+       return ERR_PTR(vfs_follow_link(nd,tmp));
 }      
 
 static struct inode_operations proc_self_inode_operations = {
index 6c6315d..abe8920 100644 (file)
@@ -329,10 +329,10 @@ static void release_inode_number(unsigned int inum)
        spin_unlock(&proc_inum_lock);
 }
 
-static int proc_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        nd_set_link(nd, PDE(dentry->d_inode)->data);
-       return 0;
+       return NULL;
 }
 
 static struct inode_operations proc_link_inode_operations = {
index d9f614a..ff291c9 100644 (file)
@@ -1985,7 +1985,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
         * iput doesn't deadlock in reiserfs_delete_xattrs. The locking
         * code really needs to be reworked, but this will take care of it
         * for now. -jeffm */
-       if (REISERFS_I(dir)->i_acl_default) {
+       if (REISERFS_I(dir)->i_acl_default && !IS_ERR(REISERFS_I(dir)->i_acl_default)) {
                reiserfs_write_unlock_xattrs(dir->i_sb);
                iput(inode);
                reiserfs_write_lock_xattrs(dir->i_sb);
index a20bbc1..3549067 100644 (file)
@@ -593,6 +593,9 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode)
         */
        inode->i_uid = current->fsuid;
        inode->i_mode = mode;
+       /* Make inode invalid - just in case we are going to drop it before
+        * the initialization happens */
+       INODE_PKEY(inode)->k_objectid = 0;
 
        if (dir->i_mode & S_ISGID) {
                inode->i_gid = dir->i_gid;
index 8b069e0..0c64bc3 100644 (file)
@@ -34,7 +34,7 @@ int smb_symlink(struct inode *inode, struct dentry *dentry, const char *oldname)
        return smb_proc_symlink(server_from_dentry(dentry), dentry, oldname);
 }
 
-static int smb_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *smb_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        char *link = __getname();
        DEBUG1("followlink of %s/%s\n", DENTRY_PATH(dentry));
@@ -52,10 +52,10 @@ static int smb_follow_link(struct dentry *dentry, struct nameidata *nd)
                }
        }
        nd_set_link(nd, link);
-       return 0;
+       return NULL;
 }
 
-static void smb_put_link(struct dentry *dentry, struct nameidata *nd)
+static void smb_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
 {
        char *s = nd_get_link(nd);
        if (!IS_ERR(s))
index d727dc9..970a33f 100644 (file)
@@ -228,6 +228,10 @@ void sysfs_hash_and_remove(struct dentry * dir, const char * name)
        struct sysfs_dirent * sd;
        struct sysfs_dirent * parent_sd = dir->d_fsdata;
 
+       if (dir->d_inode == NULL)
+               /* no inode means this hasn't been made visible yet */
+               return;
+
        down(&dir->d_inode->i_sem);
        list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
                if (!sd->s_element)
index fae57c8..de402fa 100644 (file)
@@ -151,17 +151,17 @@ static int sysfs_getlink(struct dentry *dentry, char * path)
 
 }
 
-static int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        int error = -ENOMEM;
        unsigned long page = get_zeroed_page(GFP_KERNEL);
        if (page)
                error = sysfs_getlink(dentry, (char *) page); 
        nd_set_link(nd, error ? ERR_PTR(error) : (char *)page);
-       return 0;
+       return NULL;
 }
 
-static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd)
+static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
 {
        char *page = nd_get_link(nd);
        if (!IS_ERR(page))
index ed637db..b85ce61 100644 (file)
@@ -8,10 +8,10 @@
 #include "sysv.h"
 #include <linux/namei.h>
 
-static int sysv_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *sysv_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        nd_set_link(nd, (char *)SYSV_I(dentry->d_inode)->i_data);
-       return 0;
+       return NULL;
 }
 
 struct inode_operations sysv_fast_symlink_inode_operations = {
index a0e4914..337512e 100644 (file)
 #include <linux/namei.h>
 #include <linux/ufs_fs.h>
 
-static int ufs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *ufs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct ufs_inode_info *p = UFS_I(dentry->d_inode);
        nd_set_link(nd, (char*)p->i_u1.i_symlink);
-       return 0;
+       return NULL;
 }
 
 struct inode_operations ufs_fast_symlink_inode_operations = {
index 407e993..f252605 100644 (file)
@@ -374,7 +374,7 @@ linvfs_rename(
  * we need to be very careful about how much stack we use.
  * uio is kmalloced for this reason...
  */
-STATIC int
+STATIC void *
 linvfs_follow_link(
        struct dentry           *dentry,
        struct nameidata        *nd)
@@ -391,14 +391,14 @@ linvfs_follow_link(
        link = (char *)kmalloc(MAXNAMELEN+1, GFP_KERNEL);
        if (!link) {
                nd_set_link(nd, ERR_PTR(-ENOMEM));
-               return 0;
+               return NULL;
        }
 
        uio = (uio_t *)kmalloc(sizeof(uio_t), GFP_KERNEL);
        if (!uio) {
                kfree(link);
                nd_set_link(nd, ERR_PTR(-ENOMEM));
-               return 0;
+               return NULL;
        }
 
        vp = LINVFS_GET_VP(dentry->d_inode);
@@ -422,10 +422,10 @@ linvfs_follow_link(
        kfree(uio);
 
        nd_set_link(nd, link);
-       return 0;
+       return NULL;
 }
 
-static void linvfs_put_link(struct dentry *dentry, struct nameidata *nd)
+static void linvfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
 {
        char *s = nd_get_link(nd);
        if (!IS_ERR(s))
index caeaa71..579fe19 100644 (file)
@@ -56,8 +56,9 @@
 /* ACPI PCI Interrupt Link (pci_link.c) */
 
 int acpi_irq_penalty_init (void);
-int acpi_pci_link_get_irq (acpi_handle handle, int index, int *edge_level,
+int acpi_pci_link_allocate_irq (acpi_handle handle, int index, int *edge_level,
        int *active_high_low, char **name);
+int acpi_pci_link_free_irq(acpi_handle handle);
 
 /* ACPI PCI Interrupt Routing (pci_irq.c) */
 
index 2895769..f681e67 100644 (file)
@@ -251,6 +251,9 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 extern void pcibios_resource_to_bus(struct pci_dev *, struct pci_bus_region *,
                                    struct resource *);
 
+extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+                                   struct pci_bus_region *region);
+
 #define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
 
 static inline int pci_proc_domain(struct pci_bus *bus)
index c08ce97..bdb4d66 100644 (file)
@@ -443,22 +443,19 @@ __xchg_u64(volatile long *m, unsigned long val)
    if something tries to do an invalid xchg().  */
 extern void __xchg_called_with_bad_pointer(void);
 
-static inline unsigned long
-__xchg(volatile void *ptr, unsigned long x, int size)
-{
-       switch (size) {
-               case 1:
-                       return __xchg_u8(ptr, x);
-               case 2:
-                       return __xchg_u16(ptr, x);
-               case 4:
-                       return __xchg_u32(ptr, x);
-               case 8:
-                       return __xchg_u64(ptr, x);
-       }
-       __xchg_called_with_bad_pointer();
-       return x;
-}
+#define __xchg(ptr, x, size) \
+({ \
+       unsigned long __xchg__res; \
+       volatile void *__xchg__ptr = (ptr); \
+       switch (size) { \
+               case 1: __xchg__res = __xchg_u8(__xchg__ptr, x); break; \
+               case 2: __xchg__res = __xchg_u16(__xchg__ptr, x); break; \
+               case 4: __xchg__res = __xchg_u32(__xchg__ptr, x); break; \
+               case 8: __xchg__res = __xchg_u64(__xchg__ptr, x); break; \
+               default: __xchg_called_with_bad_pointer(); __xchg__res = x; \
+       } \
+       __xchg__res; \
+})
 
 #define xchg(ptr,x)                                                         \
   ({                                                                        \
index 38c9d77..3745e35 100644 (file)
@@ -7,7 +7,9 @@
 
 /*
  * We use IXP425 General purpose timer for our timer needs, it runs at 
- * 66.66... MHz
+ * 66.66... MHz. We do a convulted calculation of CLOCK_TICK_RATE b/c the
+ * timer register ignores the bottom 2 bits of the LATCH value.
  */
-#define CLOCK_TICK_RATE (66666666)
+#define FREQ 66666666
+#define CLOCK_TICK_RATE (((FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ)
 
index 1cc85a0..bd43b56 100644 (file)
@@ -12,6 +12,7 @@
  * Changelog:
  *  11-Sep-2004 BJD  Created file
  *  21-Sep-2004 BJD  Updated port info
+ *  09-Aug-2005 BJD  Renamed s3c2410_report_oc s3c2410_usb_report_oc
 */
 
 #ifndef __ASM_ARCH_USBCONTROL_H
@@ -35,7 +36,7 @@ struct s3c2410_hcd_info {
        void            (*report_oc)(struct s3c2410_hcd_info *, int ports);
 };
 
-static void inline s3c2410_report_oc(struct s3c2410_hcd_info *info, int ports)
+static void inline s3c2410_usb_report_oc(struct s3c2410_hcd_info *info, int ports)
 {
        if (info->report_oc != NULL) {
                (info->report_oc)(info, ports);
diff --git a/include/asm-arm/arch-sa1100/mcp.h b/include/asm-arm/arch-sa1100/mcp.h
new file mode 100644 (file)
index 0000000..f58a227
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ *  linux/include/asm-arm/arch-sa1100/mcp.h
+ *
+ *  Copyright (C) 2005 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_ARM_ARCH_MCP_H
+#define __ASM_ARM_ARCH_MCP_H
+
+#include <linux/types.h>
+
+struct mcp_plat_data {
+       u32 mccr0;
+       u32 mccr1;
+       unsigned int sclk_rate;
+};
+
+#endif
index 24d1167..7fb0213 100644 (file)
@@ -5,7 +5,7 @@
 
 #ifdef CONFIG_BUG
 #ifdef CONFIG_DEBUG_BUGVERBOSE
-extern volatile void __bug(const char *file, int line, void *data);
+extern void __bug(const char *file, int line, void *data) __attribute__((noreturn));
 
 /* give file/line information */
 #define BUG()          __bug(__FILE__, __LINE__, NULL)
index ff48022..4679f63 100644 (file)
@@ -31,7 +31,7 @@ extern struct processor {
        /*
         * Special stuff for a reset
         */
-       volatile void (*reset)(unsigned long addr);
+       void (*reset)(unsigned long addr) __attribute__((noreturn));
        /*
         * Idle the processor
         */
index b5ec5d5..6723e67 100644 (file)
@@ -41,4 +41,4 @@ extern int cpu_do_idle(void);
 extern void cpu_dcache_clean_area(void *, int);
 extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
 extern void cpu_set_pte(pte_t *ptep, pte_t pte);
-extern volatile void cpu_reset(unsigned long addr);
+extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
diff --git a/include/asm-arm/hardware/gic.h b/include/asm-arm/hardware/gic.h
new file mode 100644 (file)
index 0000000..3fa5eb7
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ *  linux/include/asm-arm/hardware/gic.h
+ *
+ *  Copyright (C) 2002 ARM Limited, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_ARM_HARDWARE_GIC_H
+#define __ASM_ARM_HARDWARE_GIC_H
+
+#include <linux/compiler.h>
+
+#define GIC_CPU_CTRL                   0x00
+#define GIC_CPU_PRIMASK                        0x04
+#define GIC_CPU_BINPOINT               0x08
+#define GIC_CPU_INTACK                 0x0c
+#define GIC_CPU_EOI                    0x10
+#define GIC_CPU_RUNNINGPRI             0x14
+#define GIC_CPU_HIGHPRI                        0x18
+
+#define GIC_DIST_CTRL                  0x000
+#define GIC_DIST_CTR                   0x004
+#define GIC_DIST_ENABLE_SET            0x100
+#define GIC_DIST_ENABLE_CLEAR          0x180
+#define GIC_DIST_PENDING_SET           0x200
+#define GIC_DIST_PENDING_CLEAR         0x280
+#define GIC_DIST_ACTIVE_BIT            0x300
+#define GIC_DIST_PRI                   0x400
+#define GIC_DIST_TARGET                        0x800
+#define GIC_DIST_CONFIG                        0xc00
+#define GIC_DIST_SOFTINT               0xf00
+
+#ifndef __ASSEMBLY__
+void gic_dist_init(void __iomem *base);
+void gic_cpu_init(void __iomem *base);
+void gic_raise_softirq(cpumask_t cpumask, unsigned int irq);
+#endif
+
+#endif
index b28f1c9..38ea589 100644 (file)
@@ -60,6 +60,10 @@ extern void
 pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
                         struct resource *res);
 
+extern void
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+                       struct pci_bus_region *region);
+
 static inline void pcibios_add_platform_entries(struct pci_dev *dev)
 {
 }
index a9892eb..478c49b 100644 (file)
@@ -188,12 +188,18 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
 /*
  *   - extended small page/tiny page
  */
+#define PTE_EXT_XN             (1 << 0)        /* v6 */
 #define PTE_EXT_AP_MASK                (3 << 4)
+#define PTE_EXT_AP0            (1 << 4)
+#define PTE_EXT_AP1            (2 << 4)
 #define PTE_EXT_AP_UNO_SRO     (0 << 4)
-#define PTE_EXT_AP_UNO_SRW     (1 << 4)
-#define PTE_EXT_AP_URO_SRW     (2 << 4)
-#define PTE_EXT_AP_URW_SRW     (3 << 4)
+#define PTE_EXT_AP_UNO_SRW     (PTE_EXT_AP0)
+#define PTE_EXT_AP_URO_SRW     (PTE_EXT_AP1)
+#define PTE_EXT_AP_URW_SRW     (PTE_EXT_AP1|PTE_EXT_AP0)
 #define PTE_EXT_TEX(x)         ((x) << 6)      /* v5 */
+#define PTE_EXT_APX            (1 << 9)        /* v6 */
+#define PTE_EXT_SHARED         (1 << 10)       /* v6 */
+#define PTE_EXT_NG             (1 << 11)       /* v6 */
 
 /*
  *   - small page
@@ -224,6 +230,8 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
 #define L_PTE_WRITE            (1 << 5)
 #define L_PTE_EXEC             (1 << 6)
 #define L_PTE_DIRTY            (1 << 7)
+#define L_PTE_SHARED           (1 << 10)       /* shared between CPUs (v6) */
+#define L_PTE_ASID             (1 << 11)       /* non-global (use ASID, v6) */
 
 #ifndef __ASSEMBLY__
 
index ace2748..abb36e5 100644 (file)
 #endif
 
 #define __NR_vserver                   (__NR_SYSCALL_BASE+313)
+#define __NR_ioprio_set                        (__NR_SYSCALL_BASE+314)
+#define __NR_ioprio_get                        (__NR_SYSCALL_BASE+315)
+#define __NR_inotify_init              (__NR_SYSCALL_BASE+316)
+#define __NR_inotify_add_watch         (__NR_SYSCALL_BASE+317)
+#define __NR_inotify_rm_watch          (__NR_SYSCALL_BASE+318)
 
 /*
  * The following SWIs are ARM private.
index 9d4cc47..ee1d8b5 100644 (file)
@@ -22,6 +22,14 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
        region->end = res->end;
 }
 
+static inline void
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+                       struct pci_bus_region *region)
+{
+       res->start = region->start;
+       res->end = region->end;
+}
+
 #define pcibios_scan_all_fns(a, b)     0
 
 #ifndef HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ
index 33acd50..92d638f 100644 (file)
@@ -1,6 +1,7 @@
 /* defines for inline arch setup functions */
 
 #include <asm/fixmap.h>
+#include <asm/i8259.h>
 #include "cobalt.h"
 
 static inline void do_timer_interrupt_hook(struct pt_regs *regs)
index 5d06e6b..d0d8b01 100644 (file)
@@ -29,7 +29,7 @@ struct desc_struct {
 };
 
 #define desc_empty(desc) \
-               (!((desc)->a + (desc)->b))
+               (!((desc)->a | (desc)->b))
 
 #define desc_equal(desc1, desc2) \
                (((desc1)->a == (desc2)->a) && ((desc1)->b == (desc2)->b))
index 491e9d1..54e7637 100644 (file)
@@ -120,14 +120,6 @@ static inline void ___ia64_mmiowb(void)
        ia64_mfa();
 }
 
-static inline const unsigned long
-__ia64_get_io_port_base (void)
-{
-       extern unsigned long ia64_iobase;
-
-       return ia64_iobase;
-}
-
 static inline void*
 __ia64_mk_io_addr (unsigned long port)
 {
index 1093f35..a429fe2 100644 (file)
@@ -75,6 +75,8 @@ extern int __devinit iosapic_init (unsigned long address,
                                    unsigned int gsi_base);
 #ifdef CONFIG_HOTPLUG
 extern int iosapic_remove (unsigned int gsi_base);
+#else
+#define iosapic_remove(gsi_base)                               (-EINVAL)
 #endif /* CONFIG_HOTPLUG */
 extern int gsi_to_vector (unsigned int gsi);
 extern int gsi_to_irq (unsigned int gsi);
@@ -102,9 +104,7 @@ extern void __devinit map_iosapic_to_node (unsigned int, int);
 #else
 #define iosapic_system_init(pcat_compat)                       do { } while (0)
 #define iosapic_init(address,gsi_base)                         (-EINVAL)
-#ifdef CONFIG_HOTPLUG
 #define iosapic_remove(gsi_base)                               (-ENODEV)
-#endif /* CONFIG_HOTPLUG */
 #define iosapic_register_intr(gsi,polarity,trigger)            (gsi)
 #define iosapic_unregister_intr(irq)                           do { } while (0)
 #define iosapic_override_isa_irq(isa_irq,gsi,polarity,trigger) do { } while (0)
index b9a20cd..7885b7d 100644 (file)
@@ -61,9 +61,7 @@ extern physid_mask_t phys_cpu_present_map;
  * Some lowlevel functions might want to know about
  * the real CPU ID <-> CPU # mapping.
  */
-extern volatile int physid_2_cpu[NR_CPUS];
 extern volatile int cpu_2_physid[NR_CPUS];
-#define physid_to_cpu(physid)  physid_2_cpu[physid]
 #define cpu_to_physid(cpu_id)  cpu_2_physid[cpu_id]
 
 #define raw_smp_processor_id() (current_thread_info()->cpu)
index 99a5167..206313e 100644 (file)
@@ -138,13 +138,13 @@ extern unsigned long m68k_memoffset;
 #define __pa(vaddr)            ((unsigned long)(vaddr)+m68k_memoffset)
 #define __va(paddr)            ((void *)((unsigned long)(paddr)-m68k_memoffset))
 #else
-#define __pa(vaddr)            virt_to_phys((void *)vaddr)
-#define __va(paddr)            phys_to_virt((unsigned long)paddr)
+#define __pa(vaddr)            virt_to_phys((void *)(vaddr))
+#define __va(paddr)            phys_to_virt((unsigned long)(paddr))
 #endif
 
 #else  /* !CONFIG_SUN3 */
 /* This #define is a horrible hack to suppress lots of warnings. --m */
-#define __pa(x) ___pa((unsigned long)x)
+#define __pa(x) ___pa((unsigned long)(x))
 static inline unsigned long ___pa(unsigned long x)
 {
      if(x == 0)
index ee741c1..98d79a3 100644 (file)
@@ -253,6 +253,10 @@ extern void
 pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
                         struct resource *res);
 
+extern void
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+                       struct pci_bus_region *region);
+
 static inline void pcibios_add_platform_entries(struct pci_dev *dev)
 {
 }
index 87f0511..e5374be 100644 (file)
 #define PPC44x_LOW_SLOT                63
 
 /* LS 32-bits of UART0 physical address location for early serial text debug */
-#ifdef CONFIG_440SP
+#if defined(CONFIG_440SP)
 #define UART0_PHYS_IO_BASE     0xf0000200
+#elif defined(CONFIG_440EP)
+#define UART0_PHYS_IO_BASE     0xe0000000
 #else
 #define UART0_PHYS_IO_BASE     0x40000200
 #endif
 /*
  * Standard 4GB "page" definitions
  */
-#ifdef CONFIG_440SP
+#if defined(CONFIG_440SP)
 #define        PPC44x_IO_PAGE          0x0000000100000000ULL
 #define        PPC44x_PCICFG_PAGE      0x0000000900000000ULL
 #define        PPC44x_PCIIO_PAGE       PPC44x_PCICFG_PAGE
 #define        PPC44x_PCIMEM_PAGE      0x0000000a00000000ULL
+#elif defined(CONFIG_440EP)
+#define PPC44x_IO_PAGE         0x0000000000000000ULL
+#define PPC44x_PCICFG_PAGE     0x0000000000000000ULL
+#define PPC44x_PCIIO_PAGE      PPC44x_PCICFG_PAGE
+#define PPC44x_PCIMEM_PAGE     0x0000000000000000ULL
 #else
 #define        PPC44x_IO_PAGE          0x0000000100000000ULL
 #define        PPC44x_PCICFG_PAGE      0x0000000200000000ULL
@@ -64,7 +71,7 @@
 /*
  * 36-bit trap ranges
  */
-#ifdef CONFIG_440SP
+#if defined(CONFIG_440SP)
 #define PPC44x_IO_LO           0xf0000000UL
 #define PPC44x_IO_HI           0xf0000fffUL
 #define PPC44x_PCI0CFG_LO      0x0ec00000UL
 #define PPC44x_PCI2CFG_HI      0x2ec00007UL
 #define PPC44x_PCIMEM_LO       0x80000000UL
 #define PPC44x_PCIMEM_HI       0xdfffffffUL
+#elif defined(CONFIG_440EP)
+#define PPC44x_IO_LO           0xef500000UL
+#define PPC44x_IO_HI           0xefffffffUL
+#define PPC44x_PCI0CFG_LO      0xeec00000UL
+#define PPC44x_PCI0CFG_HI      0xeecfffffUL
+#define PPC44x_PCIMEM_LO       0xa0000000UL
+#define PPC44x_PCIMEM_HI       0xdfffffffUL
 #else
 #define PPC44x_IO_LO           0x40000000UL
 #define PPC44x_IO_HI           0x40000fffUL
 #define DCRN_SDR_UART0         0x0120
 #define DCRN_SDR_UART1         0x0121
 
+#ifdef CONFIG_440EP
+#define DCRN_SDR_UART2         0x0122
+#define DCRN_SDR_UART3         0x0123
+#define DCRN_SDR_CUST0         0x4000
+#endif
+
 /* SDR read/write helper macros */
 #define SDR_READ(offset) ({\
        mtdcr(DCRN_SDR_CONFIG_ADDR, offset); \
 #define DCRNCAP_DMA_SG         1       /* have DMA scatter/gather capability */
 #define DCRN_MAL_BASE          0x180
 
+#ifdef CONFIG_440EP
+#define DCRN_DMA2P40_BASE      0x300
+#define DCRN_DMA2P41_BASE      0x308
+#define DCRN_DMA2P42_BASE      0x310
+#define DCRN_DMA2P43_BASE      0x318
+#define DCRN_DMA2P4SR_BASE     0x320
+#endif
+
 /* UIC */
 #define DCRN_UIC0_BASE 0xc0
 #define DCRN_UIC1_BASE 0xd0
 #define MQ0_CONFIG_SIZE_2G             0x0000c000
 
 /* Internal SRAM Controller 440GX/440SP */
-#ifdef CONFIG_440SP
-#define DCRN_SRAM0_BASE                0x100
-#else /* 440GX */
 #define DCRN_SRAM0_BASE                0x000
-#endif
 
 #define DCRN_SRAM0_SB0CR       (DCRN_SRAM0_BASE + 0x020)
 #define DCRN_SRAM0_SB1CR       (DCRN_SRAM0_BASE + 0x021)
index 35260af..e807be9 100644 (file)
@@ -97,6 +97,10 @@ void ppc4xx_init(unsigned long r3, unsigned long r4, unsigned long r5,
 
 #elif CONFIG_44x
 
+#if defined(CONFIG_BAMBOO)
+#include <platforms/4xx/bamboo.h>
+#endif
+
 #if defined(CONFIG_EBONY)
 #include <platforms/4xx/ebony.h>
 #endif
index 8c61d93..3f7b566 100644 (file)
@@ -71,6 +71,8 @@ struct ocp_func_emac_data {
 
 /* Sysfs support */
 #define OCP_SYSFS_EMAC_DATA()                                          \
+OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, rgmii_idx)    \
+OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, rgmii_mux)    \
 OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, zmii_idx)     \
 OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, zmii_mux)     \
 OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mal_idx)      \
@@ -78,9 +80,14 @@ OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mal_rx_chan)        \
 OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mal_tx_chan)  \
 OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, wol_irq)      \
 OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mdio_idx)     \
+OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, tah_idx)      \
+OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, phy_mode)     \
+OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "0x%08x\n", emac, phy_map)  \
                                                                        \
 void ocp_show_emac_data(struct device *dev)                            \
 {                                                                      \
+       device_create_file(dev, &dev_attr_emac_rgmii_idx);              \
+       device_create_file(dev, &dev_attr_emac_rgmii_mux);              \
        device_create_file(dev, &dev_attr_emac_zmii_idx);               \
        device_create_file(dev, &dev_attr_emac_zmii_mux);               \
        device_create_file(dev, &dev_attr_emac_mal_idx);                \
@@ -88,6 +95,9 @@ void ocp_show_emac_data(struct device *dev)                           \
        device_create_file(dev, &dev_attr_emac_mal_tx_chan);            \
        device_create_file(dev, &dev_attr_emac_wol_irq);                \
        device_create_file(dev, &dev_attr_emac_mdio_idx);               \
+       device_create_file(dev, &dev_attr_emac_tah_idx);                \
+       device_create_file(dev, &dev_attr_emac_phy_mode);               \
+       device_create_file(dev, &dev_attr_emac_phy_map);                \
 }
 
 #ifdef CONFIG_40x
@@ -157,7 +167,7 @@ OCP_SYSFS_ADDTL(struct ocp_func_iic_data, "%d\n", iic, fast_mode)   \
                                                                        \
 void ocp_show_iic_data(struct device *dev)                             \
 {                                                                      \
-       device_create_file(dev, &dev_attr_iic_fast_mode);                       \
+       device_create_file(dev, &dev_attr_iic_fast_mode);               \
 }
 #endif /* __IBM_OCP_H__ */
 #endif /* __KERNEL__ */
index a13d558..a811e44 100644 (file)
@@ -105,6 +105,10 @@ extern void
 pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
                        struct resource *res);
 
+extern void
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+                       struct pci_bus_region *region);
+
 extern void pcibios_add_platform_entries(struct pci_dev *dev);
 
 struct file;
index 4d4b20c..92f30b2 100644 (file)
@@ -202,18 +202,64 @@ extern unsigned long ioremap_bot, ioremap_base;
  *
  * Note that these bits preclude future use of a page size
  * less than 4KB.
+ *
+ *
+ * PPC 440 core has following TLB attribute fields;
+ *
+ *   TLB1:
+ *   0  1  2  3  4  ... 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ *   RPN.................................  -  -  -  -  -  - ERPN.......
+ *
+ *   TLB2:
+ *   0  1  2  3  4  ... 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ *   -  -  -  -  -    - U0 U1 U2 U3 W  I  M  G  E   - UX UW UR SX SW SR
+ *
+ * There are some constrains and options, to decide mapping software bits
+ * into TLB entry.
+ *
+ *   - PRESENT *must* be in the bottom three bits because swap cache
+ *     entries use the top 29 bits for TLB2.
+ *
+ *   - FILE *must* be in the bottom three bits because swap cache
+ *     entries use the top 29 bits for TLB2.
+ *
+ *   - CACHE COHERENT bit (M) has no effect on PPC440 core, because it
+ *     doesn't support SMP. So we can use this as software bit, like
+ *     DIRTY.
+ *
+ * With the PPC 44x Linux implementation, the 0-11th LSBs of the PTE are used
+ * for memory protection related functions (see PTE structure in
+ * include/asm-ppc/mmu.h).  The _PAGE_XXX definitions in this file map to the
+ * above bits.  Note that the bit values are CPU specific, not architecture
+ * specific.
+ *
+ * The kernel PTE entry holds an arch-dependent swp_entry structure under
+ * certain situations. In other words, in such situations some portion of
+ * the PTE bits are used as a swp_entry. In the PPC implementation, the
+ * 3-24th LSB are shared with swp_entry, however the 0-2nd three LSB still
+ * hold protection values. That means the three protection bits are
+ * reserved for both PTE and SWAP entry at the most significant three
+ * LSBs.
+ *
+ * There are three protection bits available for SWAP entry:
+ *     _PAGE_PRESENT
+ *     _PAGE_FILE
+ *     _PAGE_HASHPTE (if HW has)
+ *
+ * So those three bits have to be inside of 0-2nd LSB of PTE.
+ *
  */
+
 #define _PAGE_PRESENT  0x00000001              /* S: PTE valid */
 #define        _PAGE_RW        0x00000002              /* S: Write permission */
-#define        _PAGE_DIRTY     0x00000004              /* S: Page dirty */
+#define _PAGE_FILE     0x00000004              /* S: nonlinear file mapping */
 #define _PAGE_ACCESSED 0x00000008              /* S: Page referenced */
 #define _PAGE_HWWRITE  0x00000010              /* H: Dirty & RW */
 #define _PAGE_HWEXEC   0x00000020              /* H: Execute permission */
 #define        _PAGE_USER      0x00000040              /* S: User page */
 #define        _PAGE_ENDIAN    0x00000080              /* H: E bit */
 #define        _PAGE_GUARDED   0x00000100              /* H: G bit */
-#define        _PAGE_COHERENT  0x00000200              /* H: M bit */
-#define _PAGE_FILE     0x00000400              /* S: nonlinear file mapping */
+#define        _PAGE_DIRTY     0x00000200              /* S: Page dirty */
 #define        _PAGE_NO_CACHE  0x00000400              /* H: I bit */
 #define        _PAGE_WRITETHRU 0x00000800              /* H: W bit */
 
index 8636cdb..a415001 100644 (file)
@@ -285,7 +285,7 @@ typedef uint32_t sgl_handle_t;
 
 #define GET_DMA_POLARITY(chan) (DMAReq_ActiveLow(chan) | DMAAck_ActiveLow(chan) | EOT_ActiveLow(chan))
 
-#elif defined(CONFIG_STBXXX_DMA)               /* stb03xxx */
+#elif defined(CONFIG_STB03xxx)         /* stb03xxx */
 
 #define DMA_PPC4xx_SIZE        4096
 
index f76221d..bb53e2d 100644 (file)
@@ -186,6 +186,12 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
 #define PPC405_ERR77_SYNC
 #endif
 
+#ifdef CONFIG_IBM440EP_ERR42
+#define PPC440EP_ERR42 isync
+#else
+#define PPC440EP_ERR42
+#endif
+
 /* The boring bits... */
 
 /* Condition Register Bit Fields */
index ce09b47..321fb75 100644 (file)
@@ -58,7 +58,7 @@ static __inline__ void set_dec(unsigned int val)
 /* Accessor functions for the timebase (RTC on 601) registers. */
 /* If one day CONFIG_POWER is added just define __USE_RTC as 1 */
 #ifdef CONFIG_6xx
-extern __inline__ int const __USE_RTC(void) {
+extern __inline__ int __attribute_pure__ __USE_RTC(void) {
        return (mfspr(SPRN_PVR)>>16) == 1;
 }
 #else
index a7894e0..3173ab3 100644 (file)
 #define __NR_waitid            272
 #define __NR_ioprio_set                273
 #define __NR_ioprio_get                274
+#define __NR_inotify_init      275
+#define __NR_inotify_add_watch 276
+#define __NR_inotify_rm_watch  277
 
-#define __NR_syscalls          275
+#define __NR_syscalls          278
 
 #define __NR(n)        #n
 
index 169868f..1601782 100644 (file)
@@ -43,8 +43,8 @@ struct bug_entry *find_bug(unsigned long bugaddr);
                ".section __bug_table,\"a\"\n\t"                \
                "       .llong 1b,%1,%2,%3\n"                   \
                ".previous"                                     \
-               : : "r" (x), "i" (__LINE__), "i" (__FILE__),    \
-                   "i" (__FUNCTION__));                        \
+               : : "r" ((long long)(x)), "i" (__LINE__),       \
+                   "i" (__FILE__), "i" (__FUNCTION__));        \
 } while (0)
 
 #define WARN_ON(x) do {                                                \
@@ -53,7 +53,8 @@ struct bug_entry *find_bug(unsigned long bugaddr);
                ".section __bug_table,\"a\"\n\t"                \
                "       .llong 1b,%1,%2,%3\n"                   \
                ".previous"                                     \
-               : : "r" (x), "i" (__LINE__ + BUG_WARNING_TRAP), \
+               : : "r" ((long long)(x)),                       \
+                   "i" (__LINE__ + BUG_WARNING_TRAP),          \
                    "i" (__FILE__), "i" (__FUNCTION__));        \
 } while (0)
 
index 5c32e38..a6840b1 100644 (file)
@@ -19,6 +19,8 @@
 #ifndef _LPARMAP_H
 #define _LPARMAP_H
 
+#ifndef __ASSEMBLY__
+
 #include <asm/types.h>
 
 /*
@@ -71,6 +73,11 @@ struct LparMap {
        } xRanges[HvRangesToMap];
 };
 
-extern struct LparMap          xLparMap;
+extern const struct LparMap    xLparMap;
+
+#endif /* __ASSEMBLY__ */
+
+/* the fixed address where the LparMap exists */
+#define LPARMAP_PHYS           0x7000
 
 #endif /* _LPARMAP_H */
index f0c1d2d..f0ef063 100644 (file)
@@ -84,7 +84,7 @@ struct machdep_calls {
 
        void            (*init_IRQ)(void);
        int             (*get_irq)(struct pt_regs *);
-       void            (*cpu_irq_down)(void);
+       void            (*cpu_irq_down)(int secondary);
 
        /* PCI stuff */
        void            (*pcibios_fixup)(void);
index faa7722..4d05745 100644 (file)
@@ -134,6 +134,10 @@ extern void
 pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
                        struct resource *res);
 
+extern void
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+                       struct pci_bus_region *region);
+
 extern int
 unmap_bus_range(struct pci_bus *bus);
 
index fcdcfd2..1e9b190 100644 (file)
@@ -33,6 +33,7 @@ static inline int node_to_first_cpu(int node)
        return first_cpu(tmp);
 }
 
+#define pcibus_to_node(node)    (-1)
 #define pcibus_to_cpumask(bus) (cpu_online_map)
 
 #define nr_cpus_node(node)     (nr_cpus_in_node[node])
@@ -59,8 +60,10 @@ static inline int node_to_first_cpu(int node)
        .nr_balance_failed      = 0,                    \
 }
 
-#endif /* CONFIG_NUMA */
+#else
 
 #include <asm-generic/topology.h>
 
+#endif /* CONFIG_NUMA */
+
 #endif /* _ASM_PPC64_TOPOLOGY_H */
index 4a94acf..977bc98 100644 (file)
 #define __NR_waitid            272
 #define __NR_ioprio_set                273
 #define __NR_ioprio_get                274
+#define __NR_inotify_init      275
+#define __NR_inotify_add_watch 276
+#define __NR_inotify_rm_watch  277
 
-#define __NR_syscalls          275
+#define __NR_syscalls          278
 #ifdef __KERNEL__
 #define NR_syscalls    __NR_syscalls
 #endif
index 0c45e14..1092af5 100644 (file)
@@ -17,7 +17,7 @@
 void xics_init_IRQ(void);
 int xics_get_irq(struct pt_regs *);
 void xics_setup_cpu(void);
-void xics_teardown_cpu(void);
+void xics_teardown_cpu(int secondary);
 void xics_cause_IPI(int cpu);
 void xics_request_IPIs(void);
 void xics_migrate_irqs_away(void);
index a7f43a2..3e3bfe6 100644 (file)
@@ -149,11 +149,11 @@ struct exception_table_entry
 })
 #endif
 
-#ifndef __CHECKER__
 #define __put_user(x, ptr) \
 ({                                                             \
        __typeof__(*(ptr)) __x = (x);                           \
        int __pu_err;                                           \
+        __chk_user_ptr(ptr);                                    \
        switch (sizeof (*(ptr))) {                              \
        case 1:                                                 \
        case 2:                                                 \
@@ -167,14 +167,6 @@ struct exception_table_entry
         }                                                      \
        __pu_err;                                               \
 })
-#else
-#define __put_user(x, ptr)                     \
-({                                             \
-       void __user *p;                         \
-       p = (ptr);                              \
-       0;                                      \
-})
-#endif
 
 #define put_user(x, ptr)                                       \
 ({                                                             \
@@ -213,11 +205,11 @@ extern int __put_user_bad(void) __attribute__((noreturn));
 })
 #endif
 
-#ifndef __CHECKER__
 #define __get_user(x, ptr)                                     \
 ({                                                             \
        __typeof__(*(ptr)) __x;                                 \
        int __gu_err;                                           \
+        __chk_user_ptr(ptr);                                    \
        switch (sizeof(*(ptr))) {                               \
        case 1:                                                 \
        case 2:                                                 \
@@ -232,15 +224,6 @@ extern int __put_user_bad(void) __attribute__((noreturn));
        (x) = __x;                                              \
        __gu_err;                                               \
 })
-#else
-#define __get_user(x, ptr)                     \
-({                                             \
-       void __user *p;                         \
-       p = (ptr);                              \
-       0;                                      \
-})
-#endif
-
 
 #define get_user(x, ptr)                                       \
 ({                                                             \
index 363db45..221e965 100644 (file)
 #define __NR_request_key       279
 #define __NR_keyctl            280
 #define __NR_waitid            281
+#define __NR_ioprio_set                282
+#define __NR_ioprio_get                283
+#define __NR_inotify_init      284
+#define __NR_inotify_add_watch 285
+#define __NR_inotify_rm_watch  286
 
-#define NR_syscalls 282
+#define NR_syscalls 287
 
 /* 
  * There are some system calls that are not present on 64 bit, some
index 2454470..ea89e8f 100644 (file)
 #define __NR_add_key           285
 #define __NR_request_key       286
 #define __NR_keyctl            287
+#define __NR_ioprio_set                288
+#define __NR_ioprio_get                289
+#define __NR_inotify_init      290
+#define __NR_inotify_add_watch 291
+#define __NR_inotify_rm_watch  292
 
-#define NR_syscalls 288
+
+#define NR_syscalls 293
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-sh/errno.h> */
 
@@ -406,7 +412,7 @@ register long __sc6 __asm__ ("r6") = (long) arg3; \
 register long __sc7 __asm__ ("r7") = (long) arg4; \
 register long __sc0 __asm__ ("r0") = (long) arg5; \
 register long __sc1 __asm__ ("r1") = (long) arg6; \
-__asm__ __volatile__ ("trapa   #0x15" \
+__asm__ __volatile__ ("trapa   #0x16" \
        : "=z" (__sc0) \
        : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), "r" (__sc7),  \
          "r" (__sc3), "r" (__sc1) \
index 95f0b13..2a1cfa4 100644 (file)
 #define __NR_add_key           313
 #define __NR_request_key       314
 #define __NR_keyctl            315
+#define __NR_ioprio_set                316
+#define __NR_ioprio_get                317
+#define __NR_inotify_init      318
+#define __NR_inotify_add_watch 319
+#define __NR_inotify_rm_watch  320
 
-#define NR_syscalls 316
+#define NR_syscalls 321
 
 /* user-visible error numbers are in the range -1 - -125: see <asm-sh64/errno.h> */
 
index 352d994..c94d8b3 100644 (file)
@@ -68,6 +68,9 @@ struct thread_info {
 
        struct restart_block    restart_block;
 
+       struct pt_regs          *kern_una_regs;
+       unsigned int            kern_una_insn;
+
        unsigned long           fpregs[0] __attribute__ ((aligned(64)));
 };
 
@@ -103,6 +106,8 @@ struct thread_info {
 #define TI_PCR         0x00000490
 #define TI_CEE_STUFF   0x00000498
 #define TI_RESTART_BLOCK 0x000004a0
+#define TI_KUNA_REGS   0x000004c8
+#define TI_KUNA_INSN   0x000004d0
 #define TI_FPREGS      0x00000500
 
 /* We embed this in the uppermost byte of thread_info->flags */
index 5afee8a..f58aeda 100644 (file)
@@ -104,8 +104,8 @@ extern void *to_virt(unsigned long phys);
  * casting is the right thing, but 32-bit UML can't have 64-bit virtual
  * addresses
  */
-#define __pa(virt) to_phys((void *) (unsigned long) virt)
-#define __va(phys) to_virt((unsigned long) phys)
+#define __pa(virt) to_phys((void *) (unsigned long) (virt))
+#define __va(phys) to_virt((unsigned long) (phys))
 
 #define page_to_pfn(page) ((page) - mem_map)
 #define pfn_to_page(pfn) (mem_map + (pfn))
index 8e94edf..e682edc 100644 (file)
@@ -51,6 +51,8 @@ extern int e820_mapped(unsigned long start, unsigned long end, unsigned type);
 
 extern void e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned long end);
 extern void e820_setup_gap(void);
+extern unsigned long e820_hole_size(unsigned long start_pfn,
+                                   unsigned long end_pfn);
 
 extern void __init parse_memopt(char *p, char **end);
 
index 106f666..85549e6 100644 (file)
@@ -32,7 +32,7 @@
 #define ID_MASK                0x00200000
 
 #define desc_empty(desc) \
-               (!((desc)->a + (desc)->b))
+               (!((desc)->a | (desc)->b))
 
 #define desc_equal(desc1, desc2) \
                (((desc1)->a == (desc2)->a) && ((desc1)->b == (desc2)->b))
index 5f3ab21..3209dd4 100644 (file)
@@ -1,2 +1,37 @@
-int pci_siig10x_fn(struct pci_dev *dev, int enable);
-int pci_siig20x_fn(struct pci_dev *dev, int enable);
+/*
+ * Definitions for PCI support.
+ */
+#define FL_BASE_MASK           0x0007
+#define FL_BASE0               0x0000
+#define FL_BASE1               0x0001
+#define FL_BASE2               0x0002
+#define FL_BASE3               0x0003
+#define FL_BASE4               0x0004
+#define FL_GET_BASE(x)         (x & FL_BASE_MASK)
+
+/* Use successive BARs (PCI base address registers),
+   else use offset into some specified BAR */
+#define FL_BASE_BARS           0x0008
+
+/* do not assign an irq */
+#define FL_NOIRQ               0x0080
+
+/* Use the Base address register size to cap number of ports */
+#define FL_REGION_SZ_CAP       0x0100
+
+struct pciserial_board {
+       unsigned int flags;
+       unsigned int num_ports;
+       unsigned int base_baud;
+       unsigned int uart_offset;
+       unsigned int reg_shift;
+       unsigned int first_offset;
+};
+
+struct serial_private;
+
+struct serial_private *
+pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board);
+void pciserial_remove_ports(struct serial_private *priv);
+void pciserial_suspend_ports(struct serial_private *priv);
+void pciserial_resume_ports(struct serial_private *priv);
index f85cbe9..b46a520 100644 (file)
@@ -453,9 +453,7 @@ int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
  * If this matches the last registration, any IRQ resources for gsi
  * are freed.
  */
-#ifdef CONFIG_ACPI_DEALLOCATE_IRQ
 void acpi_unregister_gsi (u32 gsi);
-#endif
 
 #ifdef CONFIG_ACPI_PCI
 
@@ -480,9 +478,7 @@ struct pci_dev;
 int acpi_pci_irq_enable (struct pci_dev *dev);
 void acpi_penalize_isa_irq(int irq, int active);
 
-#ifdef CONFIG_ACPI_DEALLOCATE_IRQ
 void acpi_pci_irq_disable (struct pci_dev *dev);
-#endif
 
 struct acpi_pci_driver {
        struct acpi_pci_driver *next;
index ca5fcad..9d25e98 100644 (file)
@@ -108,6 +108,8 @@ enum {
 
        /* ATA device commands */
        ATA_CMD_CHK_POWER       = 0xE5, /* check power mode */
+       ATA_CMD_STANDBY         = 0xE2, /* place in standby power mode */
+       ATA_CMD_IDLE            = 0xE3, /* place in idle power mode */
        ATA_CMD_EDD             = 0x90, /* execute device diagnostic */
        ATA_CMD_FLUSH           = 0xE7,
        ATA_CMD_FLUSH_EXT       = 0xEA,
index 0881b5c..19bd8e7 100644 (file)
@@ -301,6 +301,7 @@ struct blk_queue_tag {
        struct list_head busy_list;     /* fifo list of busy tags */
        int busy;                       /* current depth */
        int max_depth;                  /* what we will send to device */
+       int real_max_depth;             /* what the array can hold */
        atomic_t refcnt;                /* map can be shared */
 };
 
index c280501..1d68428 100644 (file)
@@ -48,12 +48,12 @@ int get_dcookie(struct dentry * dentry, struct vfsmount * vfsmnt,
 
 #else
 
-struct dcookie_user * dcookie_register(void)
+static inline struct dcookie_user * dcookie_register(void)
 {
        return NULL;
 }
 
-void dcookie_unregister(struct dcookie_user * user)
+static inline void dcookie_unregister(struct dcookie_user * user)
 {
        return;
 }
index a0ab26a..d7021c3 100644 (file)
@@ -408,6 +408,8 @@ struct ethtool_ops {
 #define SUPPORTED_FIBRE                        (1 << 10)
 #define SUPPORTED_BNC                  (1 << 11)
 #define SUPPORTED_10000baseT_Full      (1 << 12)
+#define SUPPORTED_Pause                        (1 << 13)
+#define SUPPORTED_Asym_Pause           (1 << 14)
 
 /* Indicates what features are advertised by the interface. */
 #define ADVERTISED_10baseT_Half                (1 << 0)
@@ -423,6 +425,8 @@ struct ethtool_ops {
 #define ADVERTISED_FIBRE               (1 << 10)
 #define ADVERTISED_BNC                 (1 << 11)
 #define ADVERTISED_10000baseT_Full     (1 << 12)
+#define ADVERTISED_Pause               (1 << 13)
+#define ADVERTISED_Asym_Pause          (1 << 14)
 
 /* The following are all involved in forcing a particular link
  * mode for the device for setting things.  When getting the
index f9adf75..67e6732 100644 (file)
@@ -993,8 +993,8 @@ struct inode_operations {
        int (*rename) (struct inode *, struct dentry *,
                        struct inode *, struct dentry *);
        int (*readlink) (struct dentry *, char __user *,int);
-       int (*follow_link) (struct dentry *, struct nameidata *);
-       void (*put_link) (struct dentry *, struct nameidata *);
+       void * (*follow_link) (struct dentry *, struct nameidata *);
+       void (*put_link) (struct dentry *, struct nameidata *, void *);
        void (*truncate) (struct inode *);
        int (*permission) (struct inode *, int, struct nameidata *);
        int (*setattr) (struct dentry *, struct iattr *);
@@ -1602,8 +1602,8 @@ extern struct file_operations generic_ro_fops;
 extern int vfs_readlink(struct dentry *, char __user *, int, const char *);
 extern int vfs_follow_link(struct nameidata *, const char *);
 extern int page_readlink(struct dentry *, char __user *, int);
-extern int page_follow_link_light(struct dentry *, struct nameidata *);
-extern void page_put_link(struct dentry *, struct nameidata *);
+extern void *page_follow_link_light(struct dentry *, struct nameidata *);
+extern void page_put_link(struct dentry *, struct nameidata *, void *);
 extern int page_symlink(struct inode *inode, const char *symname, int len);
 extern struct inode_operations page_symlink_inode_operations;
 extern int generic_readlink(struct dentry *, char __user *, int);
index d07a92c..03b8e79 100644 (file)
@@ -21,7 +21,7 @@
  */
 static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
                                 const char *old_name, const char *new_name,
-                                int isdir)
+                                int isdir, struct inode *target, struct inode *source)
 {
        u32 cookie = inotify_get_cookie();
 
@@ -36,31 +36,34 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
                isdir = IN_ISDIR;
        inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir,cookie,old_name);
        inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, cookie, new_name);
+
+       if (target) {
+               inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL);
+               inotify_inode_is_dead(target);
+       }
+
+       if (source) {
+               inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL);
+       }
 }
 
 /*
- * fsnotify_unlink - file was unlinked
+ * fsnotify_nameremove - a filename was removed from a directory
  */
-static inline void fsnotify_unlink(struct dentry *dentry, struct inode *dir)
+static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
 {
-       struct inode *inode = dentry->d_inode;
-
-       inode_dir_notify(dir, DN_DELETE);
-       inotify_inode_queue_event(dir, IN_DELETE, 0, dentry->d_name.name);
-       inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL);
-
-       inotify_inode_is_dead(inode);
+       if (isdir)
+               isdir = IN_ISDIR;
+       dnotify_parent(dentry, DN_DELETE);
+       inotify_dentry_parent_queue_event(dentry, IN_DELETE|isdir, 0, dentry->d_name.name);
 }
 
 /*
- * fsnotify_rmdir - directory was removed
+ * fsnotify_inoderemove - an inode is going away
  */
-static inline void fsnotify_rmdir(struct dentry *dentry, struct inode *inode,
-                                 struct inode *dir)
+static inline void fsnotify_inoderemove(struct inode *inode)
 {
-       inode_dir_notify(dir, DN_DELETE);
-       inotify_inode_queue_event(dir,IN_DELETE|IN_ISDIR,0,dentry->d_name.name);
-       inotify_inode_queue_event(inode, IN_DELETE_SELF | IN_ISDIR, 0, NULL);
+       inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL);
        inotify_inode_is_dead(inode);
 }
 
index 9212907..a6dbb51 100644 (file)
@@ -1501,4 +1501,10 @@ extern struct bus_type ide_bus_type;
 #define ide_id_has_flush_cache_ext(id) \
        (((id)->cfs_enable_2 & 0x2400) == 0x2400)
 
+static inline int hwif_to_node(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = hwif->pci_dev;
+       return dev ? pcibus_to_node(dev->bus) : -1;
+}
+
 #endif /* _IDE_H */
index a40c2bf..93bb3af 100644 (file)
@@ -35,6 +35,7 @@ struct inotify_event {
 #define IN_CREATE              0x00000100      /* Subfile was created */
 #define IN_DELETE              0x00000200      /* Subfile was deleted */
 #define IN_DELETE_SELF         0x00000400      /* Self was deleted */
+#define IN_MOVE_SELF           0x00000800      /* Self was moved */
 
 /* the following are legal events.  they are sent as needed to any watch */
 #define IN_UNMOUNT             0x00002000      /* Backing fs was unmounted */
@@ -56,7 +57,8 @@ struct inotify_event {
  */
 #define IN_ALL_EVENTS  (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \
                         IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \
-                        IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF)
+                        IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | \
+                        IN_MOVE_SELF)
 
 #ifdef __KERNEL__
 
index 6cd9ba6..7c09540 100644 (file)
@@ -113,6 +113,8 @@ enum {
        ATA_FLAG_MMIO           = (1 << 6), /* use MMIO, not PIO */
        ATA_FLAG_SATA_RESET     = (1 << 7), /* use COMRESET */
        ATA_FLAG_PIO_DMA        = (1 << 8), /* PIO cmds via DMA */
+       ATA_FLAG_NOINTR         = (1 << 9), /* FIXME: Remove this once
+                                            * proper HSM is in place. */
 
        ATA_QCFLAG_ACTIVE       = (1 << 1), /* cmd not yet ack'd to scsi lyer */
        ATA_QCFLAG_SG           = (1 << 3), /* have s/g table? */
@@ -363,7 +365,7 @@ struct ata_port_operations {
 
        void (*host_stop) (struct ata_host_set *host_set);
 
-       void (*bmdma_stop) (struct ata_port *ap);
+       void (*bmdma_stop) (struct ata_queued_cmd *qc);
        u8   (*bmdma_status) (struct ata_port *ap);
 };
 
@@ -424,7 +426,7 @@ extern void ata_dev_id_string(u16 *id, unsigned char *s,
 extern void ata_dev_config(struct ata_port *ap, unsigned int i);
 extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
 extern void ata_bmdma_start (struct ata_queued_cmd *qc);
-extern void ata_bmdma_stop(struct ata_port *ap);
+extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
 extern u8   ata_bmdma_status(struct ata_port *ap);
 extern void ata_bmdma_irq_clear(struct ata_port *ap);
 extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat);
@@ -644,7 +646,7 @@ static inline void scr_write(struct ata_port *ap, unsigned int reg, u32 val)
        ap->ops->scr_write(ap, reg, val);
 }
 
-static inline void scr_write_flush(struct ata_port *ap, unsigned int reg, 
+static inline void scr_write_flush(struct ata_port *ap, unsigned int reg,
                                   u32 val)
 {
        ap->ops->scr_write(ap, reg, val);
index 374b615..9b8d047 100644 (file)
@@ -22,6 +22,7 @@
 #define MII_EXPANSION       0x06        /* Expansion register          */
 #define MII_CTRL1000        0x09        /* 1000BASE-T control          */
 #define MII_STAT1000        0x0a        /* 1000BASE-T status           */
+#define MII_ESTATUS        0x0f        /* Extended Status */
 #define MII_DCOUNTER        0x12        /* Disconnect counter          */
 #define MII_FCSCOUNTER      0x13        /* False carrier counter       */
 #define MII_NWAYTEST        0x14        /* N-way auto-neg test reg     */
 #define BMSR_ANEGCAPABLE        0x0008  /* Able to do auto-negotiation */
 #define BMSR_RFAULT             0x0010  /* Remote fault detected       */
 #define BMSR_ANEGCOMPLETE       0x0020  /* Auto-negotiation complete   */
-#define BMSR_RESV               0x07c0  /* Unused...                   */
+#define BMSR_RESV               0x00c0  /* Unused...                   */
+#define BMSR_ESTATEN           0x0100  /* Extended Status in R15 */
+#define BMSR_100FULL2          0x0200  /* Can do 100BASE-T2 HDX */
+#define BMSR_100HALF2          0x0400  /* Can do 100BASE-T2 FDX */
 #define BMSR_10HALF             0x0800  /* Can do 10mbps, half-duplex  */
 #define BMSR_10FULL             0x1000  /* Can do 10mbps, full-duplex  */
 #define BMSR_100HALF            0x2000  /* Can do 100mbps, half-duplex */
 #define EXPANSION_MFAULTS       0x0010  /* Multiple faults detected    */
 #define EXPANSION_RESV          0xffe0  /* Unused...                   */
 
+#define ESTATUS_1000_TFULL     0x2000  /* Can do 1000BT Full */
+#define ESTATUS_1000_THALF     0x1000  /* Can do 1000BT Half */
+
 /* N-way test register. */
 #define NWAYTEST_RESV1          0x00ff  /* Unused...                   */
 #define NWAYTEST_LOOPBACK       0x0100  /* Enable loopback for N-way   */
index 6eb7f48..82d7024 100644 (file)
@@ -625,10 +625,16 @@ static inline int page_mapped(struct page *page)
  * Used to decide whether a process gets delivered SIGBUS or
  * just gets major/minor fault counters bumped up.
  */
-#define VM_FAULT_OOM   (-1)
-#define VM_FAULT_SIGBUS        0
-#define VM_FAULT_MINOR 1
-#define VM_FAULT_MAJOR 2
+#define VM_FAULT_OOM   0x00
+#define VM_FAULT_SIGBUS        0x01
+#define VM_FAULT_MINOR 0x02
+#define VM_FAULT_MAJOR 0x03
+
+/* 
+ * Special case for get_user_pages.
+ * Must be in a distinct bit from the above VM_FAULT_ flags.
+ */
+#define VM_FAULT_WRITE 0x10
 
 #define offset_in_page(p)      ((unsigned long)(p) & ~PAGE_MASK)
 
@@ -704,7 +710,13 @@ extern pte_t *FASTCALL(pte_alloc_kernel(struct mm_struct *mm, pmd_t *pmd, unsign
 extern pte_t *FASTCALL(pte_alloc_map(struct mm_struct *mm, pmd_t *pmd, unsigned long address));
 extern int install_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, struct page *page, pgprot_t prot);
 extern int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, unsigned long pgoff, pgprot_t prot);
-extern int handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, unsigned long address, int write_access);
+extern int __handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, unsigned long address, int write_access);
+
+static inline int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, int write_access)
+{
+       return __handle_mm_fault(mm, vma, address, write_access) & (~VM_FAULT_WRITE);
+}
+
 extern int make_pages_present(unsigned long addr, unsigned long end);
 extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write);
 void install_arg_page(struct vm_area_struct *, struct page *, unsigned long);
index f90f674..9a0893f 100644 (file)
@@ -63,11 +63,12 @@ struct device;
 
 struct mmc_host {
        struct device           *dev;
+       struct class_device     class_dev;
+       int                     index;
        struct mmc_host_ops     *ops;
        unsigned int            f_min;
        unsigned int            f_max;
        u32                     ocr_avail;
-       char                    host_name[8];
 
        /* host specific block data */
        unsigned int            max_seg_size;   /* see blk_queue_max_segment_size */
@@ -97,6 +98,7 @@ extern void mmc_free_host(struct mmc_host *);
 
 #define mmc_priv(x)    ((void *)((x) + 1))
 #define mmc_dev(x)     ((x)->dev)
+#define mmc_hostname(x)        ((x)->class_dev.class_id)
 
 extern int mmc_suspend_host(struct mmc_host *, pm_message_t);
 extern int mmc_resume_host(struct mmc_host *);
index dce53ac..97bbccd 100644 (file)
@@ -33,7 +33,8 @@ struct ieee1394_device_id {
        __u32 model_id;
        __u32 specifier_id;
        __u32 version;
-       kernel_ulong_t driver_data;
+       kernel_ulong_t driver_data
+               __attribute__((aligned(sizeof(kernel_ulong_t))));
 };
 
 
@@ -182,7 +183,11 @@ struct of_device_id
        char    name[32];
        char    type[32];
        char    compatible[128];
+#if __KERNEL__
        void    *data;
+#else
+       kernel_ulong_t data;
+#endif
 };
 
 
@@ -208,7 +213,8 @@ struct pcmcia_device_id {
 #ifdef __KERNEL__
        const char *    prod_id[4];
 #else
-       kernel_ulong_t  prod_id[4];
+       kernel_ulong_t  prod_id[4]
+               __attribute__((aligned(sizeof(kernel_ulong_t))));
 #endif
 
        /* not matched against */
index 70c2a9d..6552b71 100644 (file)
 #define NETLINK_NFLOG          5       /* netfilter/iptables ULOG */
 #define NETLINK_XFRM           6       /* ipsec */
 #define NETLINK_SELINUX                7       /* SELinux event notifications */
-#define NETLINK_ARPD           8
+#define NETLINK_ISCSI          8       /* Open-iSCSI */
 #define NETLINK_AUDIT          9       /* auditing */
 #define NETLINK_FIB_LOOKUP     10      
-#define NETLINK_ROUTE6         11      /* af_inet6 route comm channel */
 #define NETLINK_NETFILTER      12      /* netfilter subsystem */
 #define NETLINK_IP6_FW         13
 #define NETLINK_DNRTMSG                14      /* DECnet routing messages */
 #define NETLINK_KOBJECT_UEVENT 15      /* Kernel messages to userspace */
-#define NETLINK_TAPBASE                16      /* 16 to 31 are ethertap */
 
 #define MAX_LINKS 32           
 
index bcd0ac3..5ade54a 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/netdevice.h>
 #include <linux/interrupt.h>
+#include <linux/rcupdate.h>
 #include <linux/list.h>
 
 struct netpoll;
@@ -26,6 +27,7 @@ struct netpoll {
 struct netpoll_info {
        spinlock_t poll_lock;
        int poll_owner;
+       int tries;
        int rx_flags;
        spinlock_t rx_lock;
        struct netpoll *rx_np; /* netpoll that registered an rx_hook */
@@ -60,25 +62,31 @@ static inline int netpoll_rx(struct sk_buff *skb)
        return ret;
 }
 
-static inline void netpoll_poll_lock(struct net_device *dev)
+static inline void *netpoll_poll_lock(struct net_device *dev)
 {
+       rcu_read_lock(); /* deal with race on ->npinfo */
        if (dev->npinfo) {
                spin_lock(&dev->npinfo->poll_lock);
                dev->npinfo->poll_owner = smp_processor_id();
+               return dev->npinfo;
        }
+       return NULL;
 }
 
-static inline void netpoll_poll_unlock(struct net_device *dev)
+static inline void netpoll_poll_unlock(void *have)
 {
-       if (dev->npinfo) {
-               dev->npinfo->poll_owner = -1;
-               spin_unlock(&dev->npinfo->poll_lock);
+       struct netpoll_info *npi = have;
+
+       if (npi) {
+               npi->poll_owner = -1;
+               spin_unlock(&npi->poll_lock);
        }
+       rcu_read_unlock();
 }
 
 #else
 #define netpoll_rx(a) 0
-#define netpoll_poll_lock(a)
+#define netpoll_poll_lock(a) 0
 #define netpoll_poll_unlock(a)
 #endif
 
index 8ea2491..9a6047f 100644 (file)
@@ -112,7 +112,8 @@ struct nfs_inode {
        /*
         * Various flags
         */
-       unsigned int            flags;
+       unsigned long           flags;                  /* atomic bit ops */
+       unsigned long           cache_validity;         /* bit mask */
 
        /*
         * read_cache_jiffies is when we started read-caching this inode,
@@ -174,8 +175,6 @@ struct nfs_inode {
        /* Open contexts for shared mmap writes */
        struct list_head        open_files;
 
-       wait_queue_head_t       nfs_i_wait;
-
 #ifdef CONFIG_NFS_V4
        struct nfs4_cached_acl  *nfs4_acl;
         /* NFSv4 state */
@@ -188,17 +187,21 @@ struct nfs_inode {
 };
 
 /*
- * Legal inode flag values
+ * Cache validity bit flags
  */
-#define NFS_INO_STALE          0x0001          /* possible stale inode */
-#define NFS_INO_ADVISE_RDPLUS   0x0002          /* advise readdirplus */
-#define NFS_INO_REVALIDATING   0x0004          /* revalidating attrs */
-#define NFS_INO_INVALID_ATTR   0x0008          /* cached attrs are invalid */
-#define NFS_INO_INVALID_DATA   0x0010          /* cached data is invalid */
-#define NFS_INO_INVALID_ATIME  0x0020          /* cached atime is invalid */
-#define NFS_INO_INVALID_ACCESS 0x0040          /* cached access cred invalid */
-#define NFS_INO_INVALID_ACL    0x0080          /* cached acls are invalid */
-#define NFS_INO_REVAL_PAGECACHE        0x1000          /* must revalidate pagecache */
+#define NFS_INO_INVALID_ATTR   0x0001          /* cached attrs are invalid */
+#define NFS_INO_INVALID_DATA   0x0002          /* cached data is invalid */
+#define NFS_INO_INVALID_ATIME  0x0004          /* cached atime is invalid */
+#define NFS_INO_INVALID_ACCESS 0x0008          /* cached access cred invalid */
+#define NFS_INO_INVALID_ACL    0x0010          /* cached acls are invalid */
+#define NFS_INO_REVAL_PAGECACHE        0x0020          /* must revalidate pagecache */
+
+/*
+ * Bit offsets in flags field
+ */
+#define NFS_INO_REVALIDATING   (0)             /* revalidating attrs */
+#define NFS_INO_ADVISE_RDPLUS  (1)             /* advise readdirplus */
+#define NFS_INO_STALE          (2)             /* possible stale inode */
 
 static inline struct nfs_inode *NFS_I(struct inode *inode)
 {
@@ -224,8 +227,7 @@ static inline struct nfs_inode *NFS_I(struct inode *inode)
 #define NFS_ATTRTIMEO_UPDATE(inode)    (NFS_I(inode)->attrtimeo_timestamp)
 
 #define NFS_FLAGS(inode)               (NFS_I(inode)->flags)
-#define NFS_REVALIDATING(inode)                (NFS_FLAGS(inode) & NFS_INO_REVALIDATING)
-#define NFS_STALE(inode)               (NFS_FLAGS(inode) & NFS_INO_STALE)
+#define NFS_STALE(inode)               (test_bit(NFS_INO_STALE, &NFS_FLAGS(inode)))
 
 #define NFS_FILEID(inode)              (NFS_I(inode)->fileid)
 
@@ -236,8 +238,11 @@ static inline int nfs_caches_unstable(struct inode *inode)
 
 static inline void NFS_CACHEINV(struct inode *inode)
 {
-       if (!nfs_caches_unstable(inode))
-               NFS_FLAGS(inode) |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
+       if (!nfs_caches_unstable(inode)) {
+               spin_lock(&inode->i_lock);
+               NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
+               spin_unlock(&inode->i_lock);
+       }
 }
 
 static inline int nfs_server_capable(struct inode *inode, int cap)
@@ -247,7 +252,7 @@ static inline int nfs_server_capable(struct inode *inode, int cap)
 
 static inline int NFS_USE_READDIRPLUS(struct inode *inode)
 {
-       return NFS_FLAGS(inode) & NFS_INO_ADVISE_RDPLUS;
+       return test_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode));
 }
 
 /**
@@ -292,6 +297,7 @@ extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode);
 extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
 extern void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
 extern int nfs_setattr(struct dentry *, struct iattr *);
+extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
 extern void nfs_begin_attr_update(struct inode *);
 extern void nfs_end_attr_update(struct inode *);
 extern void nfs_begin_data_update(struct inode *);
index 8621cf4..bc4c400 100644 (file)
@@ -556,7 +556,8 @@ struct pci_dev {
        /* keep track of device state */
        unsigned int    is_enabled:1;   /* pci_enable_device has been called */
        unsigned int    is_busmaster:1; /* device is busmaster */
-       
+       unsigned int    no_msi:1;       /* device may not use msi */
+
        u32             saved_config_space[16]; /* config space saved at suspend time */
        struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */
        int rom_attr_enabled;           /* has display of the rom attribute been enabled? */
index bc4cc10..499a532 100644 (file)
 #define PCI_DEVICE_ID_APPLE_UNI_N_PCI15        0x002e
 #define PCI_DEVICE_ID_APPLE_UNI_N_FW2  0x0030
 #define PCI_DEVICE_ID_APPLE_UNI_N_GMAC2        0x0032
-#define PCI_DEVIEC_ID_APPLE_UNI_N_ATA  0x0033
+#define PCI_DEVICE_ID_APPLE_UNI_N_ATA  0x0033
 #define PCI_DEVICE_ID_APPLE_UNI_N_AGP2 0x0034
 #define PCI_DEVICE_ID_APPLE_IPID_ATA100        0x003b
 #define PCI_DEVICE_ID_APPLE_KEYLARGO_I 0x003e
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA 0x0266
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2        0x0267
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE  0x036E
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA 0x036F
 #define PCI_DEVICE_ID_NVIDIA_NVENET_12         0x0268
 #define PCI_DEVICE_ID_NVIDIA_NVENET_13         0x0269
 #define PCI_DEVICE_ID_NVIDIA_MCP51_AUDIO       0x026B
 #define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211
 #define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212
 #define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213
+#define PCI_DEVICE_ID_SERVERWORKS_HT1000IDE 0x0214
 #define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2 0x0217
 #define PCI_DEVICE_ID_SERVERWORKS_OSB4USB 0x0220
 #define PCI_DEVICE_ID_SERVERWORKS_CSB5USB PCI_DEVICE_ID_SERVERWORKS_OSB4USB
 #define PCI_VENDOR_ID_SIBYTE           0x166d
 #define PCI_DEVICE_ID_BCM1250_HT       0x0002
 
+#define PCI_VENDOR_ID_NETCELL          0x169c
+#define PCI_DEVICE_ID_REVOLUTION       0x0044
+
 #define PCI_VENDOR_ID_LINKSYS          0x1737
 #define PCI_DEVICE_ID_LINKSYS_EG1032   0x1032
 #define PCI_DEVICE_ID_LINKSYS_EG1064   0x1064
 #define PCI_VENDOR_ID_INTEL            0x8086
 #define PCI_DEVICE_ID_INTEL_EESSC      0x0008
 #define PCI_DEVICE_ID_INTEL_21145      0x0039
+#define PCI_DEVICE_ID_INTEL_PXHD_0     0x0320
+#define PCI_DEVICE_ID_INTEL_PXHD_1     0x0321
+#define PCI_DEVICE_ID_INTEL_PXH_0      0x0329
+#define PCI_DEVICE_ID_INTEL_PXH_1      0x032A
+#define PCI_DEVICE_ID_INTEL_PXHV       0x032C
 #define PCI_DEVICE_ID_INTEL_82375      0x0482
 #define PCI_DEVICE_ID_INTEL_82424      0x0483
 #define PCI_DEVICE_ID_INTEL_82378      0x0484
diff --git a/include/linux/phy.h b/include/linux/phy.h
new file mode 100644 (file)
index 0000000..72cb67b
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ * include/linux/phy.h
+ *
+ * Framework and drivers for configuring and reading different PHYs
+ * Based on code in sungem_phy.c and gianfar_phy.c
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __PHY_H
+#define __PHY_H
+
+#include <linux/spinlock.h>
+#include <linux/device.h>
+
+#define PHY_BASIC_FEATURES     (SUPPORTED_10baseT_Half | \
+                                SUPPORTED_10baseT_Full | \
+                                SUPPORTED_100baseT_Half | \
+                                SUPPORTED_100baseT_Full | \
+                                SUPPORTED_Autoneg | \
+                                SUPPORTED_TP | \
+                                SUPPORTED_MII)
+
+#define PHY_GBIT_FEATURES      (PHY_BASIC_FEATURES | \
+                                SUPPORTED_1000baseT_Half | \
+                                SUPPORTED_1000baseT_Full)
+
+/* Set phydev->irq to PHY_POLL if interrupts are not supported,
+ * or not desired for this PHY.  Set to PHY_IGNORE_INTERRUPT if
+ * the attached driver handles the interrupt
+ */
+#define PHY_POLL               -1
+#define PHY_IGNORE_INTERRUPT   -2
+
+#define PHY_HAS_INTERRUPT      0x00000001
+#define PHY_HAS_MAGICANEG      0x00000002
+
+#define MII_BUS_MAX 4
+
+
+#define PHY_INIT_TIMEOUT 100000
+#define PHY_STATE_TIME         1
+#define PHY_FORCE_TIMEOUT      10
+#define PHY_AN_TIMEOUT         10
+
+#define PHY_MAX_ADDR 32
+
+/* The Bus class for PHYs.  Devices which provide access to
+ * PHYs should register using this structure */
+struct mii_bus {
+       const char *name;
+       int id;
+       void *priv;
+       int (*read)(struct mii_bus *bus, int phy_id, int regnum);
+       int (*write)(struct mii_bus *bus, int phy_id, int regnum, u16 val);
+       int (*reset)(struct mii_bus *bus);
+
+       /* A lock to ensure that only one thing can read/write
+        * the MDIO bus at a time */
+       spinlock_t mdio_lock;
+
+       struct device *dev;
+
+       /* list of all PHYs on bus */
+       struct phy_device *phy_map[PHY_MAX_ADDR];
+
+       /* Pointer to an array of interrupts, each PHY's
+        * interrupt at the index matching its address */
+       int *irq;
+};
+
+#define PHY_INTERRUPT_DISABLED 0x0
+#define PHY_INTERRUPT_ENABLED 0x80000000
+
+/* PHY state machine states:
+ *
+ * DOWN: PHY device and driver are not ready for anything.  probe
+ * should be called if and only if the PHY is in this state,
+ * given that the PHY device exists.
+ * - PHY driver probe function will, depending on the PHY, set
+ * the state to STARTING or READY
+ *
+ * STARTING:  PHY device is coming up, and the ethernet driver is
+ * not ready.  PHY drivers may set this in the probe function.
+ * If they do, they are responsible for making sure the state is
+ * eventually set to indicate whether the PHY is UP or READY,
+ * depending on the state when the PHY is done starting up.
+ * - PHY driver will set the state to READY
+ * - start will set the state to PENDING
+ *
+ * READY: PHY is ready to send and receive packets, but the
+ * controller is not.  By default, PHYs which do not implement
+ * probe will be set to this state by phy_probe().  If the PHY
+ * driver knows the PHY is ready, and the PHY state is STARTING,
+ * then it sets this STATE.
+ * - start will set the state to UP
+ *
+ * PENDING: PHY device is coming up, but the ethernet driver is
+ * ready.  phy_start will set this state if the PHY state is
+ * STARTING.
+ * - PHY driver will set the state to UP when the PHY is ready
+ *
+ * UP: The PHY and attached device are ready to do work.
+ * Interrupts should be started here.
+ * - timer moves to AN
+ *
+ * AN: The PHY is currently negotiating the link state.  Link is
+ * therefore down for now.  phy_timer will set this state when it
+ * detects the state is UP.  config_aneg will set this state
+ * whenever called with phydev->autoneg set to AUTONEG_ENABLE.
+ * - If autonegotiation finishes, but there's no link, it sets
+ *   the state to NOLINK.
+ * - If aneg finishes with link, it sets the state to RUNNING,
+ *   and calls adjust_link
+ * - If autonegotiation did not finish after an arbitrary amount
+ *   of time, autonegotiation should be tried again if the PHY
+ *   supports "magic" autonegotiation (back to AN)
+ * - If it didn't finish, and no magic_aneg, move to FORCING.
+ *
+ * NOLINK: PHY is up, but not currently plugged in.
+ * - If the timer notes that the link comes back, we move to RUNNING
+ * - config_aneg moves to AN
+ * - phy_stop moves to HALTED
+ *
+ * FORCING: PHY is being configured with forced settings
+ * - if link is up, move to RUNNING
+ * - If link is down, we drop to the next highest setting, and
+ *   retry (FORCING) after a timeout
+ * - phy_stop moves to HALTED
+ *
+ * RUNNING: PHY is currently up, running, and possibly sending
+ * and/or receiving packets
+ * - timer will set CHANGELINK if we're polling (this ensures the
+ *   link state is polled every other cycle of this state machine,
+ *   which makes it every other second)
+ * - irq will set CHANGELINK
+ * - config_aneg will set AN
+ * - phy_stop moves to HALTED
+ *
+ * CHANGELINK: PHY experienced a change in link state
+ * - timer moves to RUNNING if link
+ * - timer moves to NOLINK if the link is down
+ * - phy_stop moves to HALTED
+ *
+ * HALTED: PHY is up, but no polling or interrupts are done. Or
+ * PHY is in an error state.
+ *
+ * - phy_start moves to RESUMING
+ *
+ * RESUMING: PHY was halted, but now wants to run again.
+ * - If we are forcing, or aneg is done, timer moves to RUNNING
+ * - If aneg is not done, timer moves to AN
+ * - phy_stop moves to HALTED
+ */
+enum phy_state {
+       PHY_DOWN=0,
+       PHY_STARTING,
+       PHY_READY,
+       PHY_PENDING,
+       PHY_UP,
+       PHY_AN,
+       PHY_RUNNING,
+       PHY_NOLINK,
+       PHY_FORCING,
+       PHY_CHANGELINK,
+       PHY_HALTED,
+       PHY_RESUMING
+};
+
+/* phy_device: An instance of a PHY
+ *
+ * drv: Pointer to the driver for this PHY instance
+ * bus: Pointer to the bus this PHY is on
+ * dev: driver model device structure for this PHY
+ * phy_id: UID for this device found during discovery
+ * state: state of the PHY for management purposes
+ * dev_flags: Device-specific flags used by the PHY driver.
+ * addr: Bus address of PHY
+ * link_timeout: The number of timer firings to wait before the
+ * giving up on the current attempt at acquiring a link
+ * irq: IRQ number of the PHY's interrupt (-1 if none)
+ * phy_timer: The timer for handling the state machine
+ * phy_queue: A work_queue for the interrupt
+ * attached_dev: The attached enet driver's device instance ptr
+ * adjust_link: Callback for the enet controller to respond to
+ * changes in the link state.
+ * adjust_state: Callback for the enet driver to respond to
+ * changes in the state machine.
+ *
+ * speed, duplex, pause, supported, advertising, and
+ * autoneg are used like in mii_if_info
+ *
+ * interrupts currently only supports enabled or disabled,
+ * but could be changed in the future to support enabling
+ * and disabling specific interrupts
+ *
+ * Contains some infrastructure for polling and interrupt
+ * handling, as well as handling shifts in PHY hardware state
+ */
+struct phy_device {
+       /* Information about the PHY type */
+       /* And management functions */
+       struct phy_driver *drv;
+
+       struct mii_bus *bus;
+
+       struct device dev;
+
+       u32 phy_id;
+
+       enum phy_state state;
+
+       u32 dev_flags;
+
+       /* Bus address of the PHY (0-32) */
+       int addr;
+
+       /* forced speed & duplex (no autoneg)
+        * partner speed & duplex & pause (autoneg)
+        */
+       int speed;
+       int duplex;
+       int pause;
+       int asym_pause;
+
+       /* The most recently read link state */
+       int link;
+
+       /* Enabled Interrupts */
+       u32 interrupts;
+
+       /* Union of PHY and Attached devices' supported modes */
+       /* See mii.h for more info */
+       u32 supported;
+       u32 advertising;
+
+       int autoneg;
+
+       int link_timeout;
+
+       /* Interrupt number for this PHY
+        * -1 means no interrupt */
+       int irq;
+
+       /* private data pointer */
+       /* For use by PHYs to maintain extra state */
+       void *priv;
+
+       /* Interrupt and Polling infrastructure */
+       struct work_struct phy_queue;
+       struct timer_list phy_timer;
+
+       spinlock_t lock;
+
+       struct net_device *attached_dev;
+
+       void (*adjust_link)(struct net_device *dev);
+
+       void (*adjust_state)(struct net_device *dev);
+};
+#define to_phy_device(d) container_of(d, struct phy_device, dev)
+
+/* struct phy_driver: Driver structure for a particular PHY type
+ *
+ * phy_id: The result of reading the UID registers of this PHY
+ *   type, and ANDing them with the phy_id_mask.  This driver
+ *   only works for PHYs with IDs which match this field
+ * name: The friendly name of this PHY type
+ * phy_id_mask: Defines the important bits of the phy_id
+ * features: A list of features (speed, duplex, etc) supported
+ *   by this PHY
+ * flags: A bitfield defining certain other features this PHY
+ *   supports (like interrupts)
+ *
+ * The drivers must implement config_aneg and read_status.  All
+ * other functions are optional. Note that none of these
+ * functions should be called from interrupt time.  The goal is
+ * for the bus read/write functions to be able to block when the
+ * bus transaction is happening, and be freed up by an interrupt
+ * (The MPC85xx has this ability, though it is not currently
+ * supported in the driver).
+ */
+struct phy_driver {
+       u32 phy_id;
+       char *name;
+       unsigned int phy_id_mask;
+       u32 features;
+       u32 flags;
+
+       /* Called to initialize the PHY,
+        * including after a reset */
+       int (*config_init)(struct phy_device *phydev);
+
+       /* Called during discovery.  Used to set
+        * up device-specific structures, if any */
+       int (*probe)(struct phy_device *phydev);
+
+       /* PHY Power Management */
+       int (*suspend)(struct phy_device *phydev);
+       int (*resume)(struct phy_device *phydev);
+
+       /* Configures the advertisement and resets
+        * autonegotiation if phydev->autoneg is on,
+        * forces the speed to the current settings in phydev
+        * if phydev->autoneg is off */
+       int (*config_aneg)(struct phy_device *phydev);
+
+       /* Determines the negotiated speed and duplex */
+       int (*read_status)(struct phy_device *phydev);
+
+       /* Clears any pending interrupts */
+       int (*ack_interrupt)(struct phy_device *phydev);
+
+       /* Enables or disables interrupts */
+       int (*config_intr)(struct phy_device *phydev);
+
+       /* Clears up any memory if needed */
+       void (*remove)(struct phy_device *phydev);
+
+       struct device_driver driver;
+};
+#define to_phy_driver(d) container_of(d, struct phy_driver, driver)
+
+int phy_read(struct phy_device *phydev, u16 regnum);
+int phy_write(struct phy_device *phydev, u16 regnum, u16 val);
+struct phy_device* get_phy_device(struct mii_bus *bus, int addr);
+int phy_clear_interrupt(struct phy_device *phydev);
+int phy_config_interrupt(struct phy_device *phydev, u32 interrupts);
+struct phy_device * phy_attach(struct net_device *dev,
+               const char *phy_id, u32 flags);
+struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
+               void (*handler)(struct net_device *), u32 flags);
+void phy_disconnect(struct phy_device *phydev);
+void phy_detach(struct phy_device *phydev);
+void phy_start(struct phy_device *phydev);
+void phy_stop(struct phy_device *phydev);
+int phy_start_aneg(struct phy_device *phydev);
+
+int mdiobus_register(struct mii_bus *bus);
+void mdiobus_unregister(struct mii_bus *bus);
+void phy_sanitize_settings(struct phy_device *phydev);
+int phy_stop_interrupts(struct phy_device *phydev);
+
+static inline int phy_read_status(struct phy_device *phydev) {
+       return phydev->drv->read_status(phydev);
+}
+
+int genphy_config_advert(struct phy_device *phydev);
+int genphy_setup_forced(struct phy_device *phydev);
+int genphy_restart_aneg(struct phy_device *phydev);
+int genphy_config_aneg(struct phy_device *phydev);
+int genphy_update_link(struct phy_device *phydev);
+int genphy_read_status(struct phy_device *phydev);
+void phy_driver_unregister(struct phy_driver *drv);
+int phy_driver_register(struct phy_driver *new_driver);
+void phy_prepare_link(struct phy_device *phydev,
+               void (*adjust_link)(struct net_device *));
+void phy_start_machine(struct phy_device *phydev,
+               void (*handler)(struct net_device *));
+void phy_stop_machine(struct phy_device *phydev);
+int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
+int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
+int phy_mii_ioctl(struct phy_device *phydev,
+               struct mii_ioctl_data *mii_data, int cmd);
+int phy_start_interrupts(struct phy_device *phydev);
+void phy_print_status(struct phy_device *phydev);
+
+extern struct bus_type mdio_bus_type;
+#endif /* __PHY_H */
index 6213e97..4bf1659 100644 (file)
@@ -248,6 +248,7 @@ struct bitmap {
 
 /* these are used only by md/bitmap */
 int  bitmap_create(mddev_t *mddev);
+void bitmap_flush(mddev_t *mddev);
 void bitmap_destroy(mddev_t *mddev);
 int  bitmap_active(struct bitmap *bitmap);
 
index 2b2f35a..2b9e6b9 100644 (file)
@@ -140,44 +140,4 @@ struct rs_multiport_struct {
 #define ALPHA_KLUDGE_MCR 0
 #endif
 
-/*
- * Definitions for PCI support.
- */
-#define SPCI_FL_BASE_MASK      0x0007
-#define SPCI_FL_BASE0  0x0000
-#define SPCI_FL_BASE1  0x0001
-#define SPCI_FL_BASE2  0x0002
-#define SPCI_FL_BASE3  0x0003
-#define SPCI_FL_BASE4  0x0004
-#define SPCI_FL_GET_BASE(x)    (x & SPCI_FL_BASE_MASK)
-
-#define SPCI_FL_IRQ_MASK       (0x0007 << 4)
-#define SPCI_FL_IRQBASE0       (0x0000 << 4)
-#define SPCI_FL_IRQBASE1       (0x0001 << 4)
-#define SPCI_FL_IRQBASE2       (0x0002 << 4)
-#define SPCI_FL_IRQBASE3       (0x0003 << 4)
-#define SPCI_FL_IRQBASE4       (0x0004 << 4)
-#define SPCI_FL_GET_IRQBASE(x)        ((x & SPCI_FL_IRQ_MASK) >> 4)
-
-/* Use successive BARs (PCI base address registers), 
-   else use offset into some specified BAR */
-#define SPCI_FL_BASE_TABLE     0x0100
-
-/* Use successive entries in the irq resource table */
-#define SPCI_FL_IRQ_TABLE      0x0200
-
-/* Use the irq resource table instead of dev->irq */
-#define SPCI_FL_IRQRESOURCE    0x0400
-
-/* Use the Base address register size to cap number of ports */
-#define SPCI_FL_REGION_SZ_CAP  0x0800
-
-/* Do not use irq sharing for this device */
-#define SPCI_FL_NO_SHIRQ       0x1000
-
-/* This is a PNP device */
-#define SPCI_FL_ISPNP          0x2000
-
-#define SPCI_FL_PNPDEFAULT     (SPCI_FL_IRQRESOURCE|SPCI_FL_ISPNP)
-
 #endif /* _LINUX_SERIAL_H */
index 0061c94..948527e 100644 (file)
@@ -255,7 +255,7 @@ struct sk_buff {
                                nohdr:1;
                                /* 3 bits spare */
        __u8                    pkt_type;
-       __u16                   protocol;
+       __be16                  protocol;
 
        void                    (*destructor)(struct sk_buff *skb);
 #ifdef CONFIG_NETFILTER
index 34ec3e8..23448d0 100644 (file)
@@ -177,6 +177,7 @@ typedef int (*xdr_xcode_elem_t)(struct xdr_array2_desc *desc, void *elem);
 struct xdr_array2_desc {
        unsigned int elem_size;
        unsigned int array_len;
+       unsigned int array_maxlen;
        xdr_xcode_elem_t xcode;
 };
 
index 239f520..bfe3e76 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/mmzone.h>
 #include <linux/list.h>
 #include <linux/sched.h>
-#include <linux/pagemap.h>
 
 #include <asm/atomic.h>
 #include <asm/page.h>
@@ -255,6 +254,8 @@ static inline void put_swap_token(struct mm_struct *mm)
 
 #define si_swapinfo(val) \
        do { (val)->freeswap = (val)->totalswap = 0; } while (0)
+/* only sparc can not include linux/pagemap.h in this file
+ * so leave page_cache_release and release_pages undeclared... */
 #define free_page_and_swap_cache(page) \
        page_cache_release(page)
 #define free_pages_and_swap_cache(pages, nr) \
index 850076e..74f7b78 100644 (file)
@@ -506,6 +506,11 @@ extern int zlib_deflateReset (z_streamp strm);
    stream state was inconsistent (such as zalloc or state being NULL).
 */
 
+static inline unsigned long deflateBound(unsigned long s)
+{
+       return s + ((s + 7) >> 3) + ((s + 63) >> 6) + 11;
+}
+
 extern int zlib_deflateParams (z_streamp strm, int level, int strategy);
 /*
      Dynamically update the compression level and compression strategy.  The
index d8c0a55..eeaa15d 100644 (file)
@@ -1,5 +1,5 @@
 
-/* $Id: tuner.h,v 1.42 2005/07/06 09:42:19 mchehab Exp $
+/* $Id: tuner.h,v 1.45 2005/07/28 18:41:21 mchehab Exp $
  *
     tuner.h - definition for different tuners
 
 
 #define TUNER_TEA5767         62       /* Only FM Radio Tuner */
 #define TUNER_PHILIPS_FMD1216ME_MK3 63
+#define TUNER_LG_TDVS_H062F   64       /* DViCO FusionHDTV 5 */
+#define TUNER_YMEC_TVF66T5_B_DFF 65    /* Acorp Y878F */
 
 #define NOTUNER 0
 #define PAL     1      /* PAL_BG */
index 828a3a9..3696f98 100644 (file)
@@ -139,11 +139,25 @@ enum {
 #define AX25_DEF_DS_TIMEOUT    (3 * 60 * HZ)           /* DAMA timeout 3 minutes */
 
 typedef struct ax25_uid_assoc {
-       struct ax25_uid_assoc   *next;
+       struct hlist_node       uid_node;
+       atomic_t                refcount;
        uid_t                   uid;
        ax25_address            call;
 } ax25_uid_assoc;
 
+#define ax25_uid_for_each(__ax25, node, list) \
+       hlist_for_each_entry(__ax25, node, list, uid_node)
+
+#define ax25_uid_hold(ax25) \
+       atomic_inc(&((ax25)->refcount))
+
+static inline void ax25_uid_put(ax25_uid_assoc *assoc)
+{
+       if (atomic_dec_and_test(&assoc->refcount)) {
+               kfree(assoc);
+       }
+}
+
 typedef struct {
        ax25_address            calls[AX25_MAX_DIGIS];
        unsigned char           repeated[AX25_MAX_DIGIS];
@@ -376,7 +390,7 @@ extern unsigned long ax25_display_timer(struct timer_list *);
 
 /* ax25_uid.c */
 extern int  ax25_uid_policy;
-extern ax25_address *ax25_findbyuid(uid_t);
+extern ax25_uid_assoc *ax25_findbyuid(uid_t);
 extern int  ax25_uid_ioctl(int, struct sockaddr_ax25 *);
 extern struct file_operations ax25_uid_fops;
 extern void ax25_uid_free(void);
index 42a84c5..06b24f6 100644 (file)
 #define BT_DBG(fmt, arg...)  printk(KERN_INFO "%s: " fmt "\n" , __FUNCTION__ , ## arg)
 #define BT_ERR(fmt, arg...)  printk(KERN_ERR  "%s: " fmt "\n" , __FUNCTION__ , ## arg)
 
-#ifdef HCI_DATA_DUMP
-#define BT_DMP(buf, len) bt_dump(__FUNCTION__, buf, len)
-#else
-#define BT_DMP(D...)
-#endif
-
 extern struct proc_dir_entry *proc_bt;
 
 /* Connection and socket states */
@@ -174,8 +168,6 @@ static inline int skb_frags_no(struct sk_buff *skb)
        return n;
 }
 
-void bt_dump(char *pref, __u8 *buf, int count);
-
 int bt_err(__u16 code);
 
 #endif /* __BLUETOOTH_H */
index a1042d0..e9b1dba 100644 (file)
@@ -384,6 +384,11 @@ enum sock_flags {
        SOCK_QUEUE_SHRUNK, /* write queue has been shrunk recently */
 };
 
+static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
+{
+       nsk->sk_flags = osk->sk_flags;
+}
+
 static inline void sock_set_flag(struct sock *sk, enum sock_flags flag)
 {
        __set_bit(flag, &sk->sk_flags);
index f4f9aba..5010f0c 100644 (file)
@@ -1236,7 +1236,7 @@ static inline void tcp_sync_left_out(struct tcp_sock *tp)
        tp->left_out = tp->sacked_out + tp->lost_out;
 }
 
-/* Set slow start threshould and cwnd not falling to slow start */
+/* Set slow start threshold and cwnd not falling to slow start */
 static inline void __tcp_enter_cwr(struct tcp_sock *tp)
 {
        tp->undo_marker = 0;
similarity index 96%
rename from drivers/infiniband/include/ib_cache.h
rename to include/rdma/ib_cache.h
index 44ef6bb..5bf9834 100644 (file)
@@ -1,5 +1,7 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Intel Corporation. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -35,7 +37,7 @@
 #ifndef _IB_CACHE_H
 #define _IB_CACHE_H
 
-#include <ib_verbs.h>
+#include <rdma/ib_verbs.h>
 
 /**
  * ib_get_cached_gid - Returns a cached GID table entry
similarity index 89%
rename from drivers/infiniband/include/ib_cm.h
rename to include/rdma/ib_cm.h
index e5d74a7..77fe903 100644 (file)
@@ -37,8 +37,8 @@
 #if !defined(IB_CM_H)
 #define IB_CM_H
 
-#include <ib_mad.h>
-#include <ib_sa.h>
+#include <rdma/ib_mad.h>
+#include <rdma/ib_sa.h>
 
 enum ib_cm_state {
        IB_CM_IDLE,
@@ -115,7 +115,7 @@ struct ib_cm_req_event_param {
        struct ib_sa_path_rec   *primary_path;
        struct ib_sa_path_rec   *alternate_path;
 
-       u64                     remote_ca_guid;
+       __be64                  remote_ca_guid;
        u32                     remote_qkey;
        u32                     remote_qpn;
        enum ib_qp_type         qp_type;
@@ -132,7 +132,7 @@ struct ib_cm_req_event_param {
 };
 
 struct ib_cm_rep_event_param {
-       u64                     remote_ca_guid;
+       __be64                  remote_ca_guid;
        u32                     remote_qkey;
        u32                     remote_qpn;
        u32                     starting_psn;
@@ -146,38 +146,39 @@ struct ib_cm_rep_event_param {
 };
 
 enum ib_cm_rej_reason {
-       IB_CM_REJ_NO_QP                         = __constant_htons(1),
-       IB_CM_REJ_NO_EEC                        = __constant_htons(2),
-       IB_CM_REJ_NO_RESOURCES                  = __constant_htons(3),
-       IB_CM_REJ_TIMEOUT                       = __constant_htons(4),
-       IB_CM_REJ_UNSUPPORTED                   = __constant_htons(5),
-       IB_CM_REJ_INVALID_COMM_ID               = __constant_htons(6),
-       IB_CM_REJ_INVALID_COMM_INSTANCE         = __constant_htons(7),
-       IB_CM_REJ_INVALID_SERVICE_ID            = __constant_htons(8),
-       IB_CM_REJ_INVALID_TRANSPORT_TYPE        = __constant_htons(9),
-       IB_CM_REJ_STALE_CONN                    = __constant_htons(10),
-       IB_CM_REJ_RDC_NOT_EXIST                 = __constant_htons(11),
-       IB_CM_REJ_INVALID_GID                   = __constant_htons(12),
-       IB_CM_REJ_INVALID_LID                   = __constant_htons(13),
-       IB_CM_REJ_INVALID_SL                    = __constant_htons(14),
-       IB_CM_REJ_INVALID_TRAFFIC_CLASS         = __constant_htons(15),
-       IB_CM_REJ_INVALID_HOP_LIMIT             = __constant_htons(16),
-       IB_CM_REJ_INVALID_PACKET_RATE           = __constant_htons(17),
-       IB_CM_REJ_INVALID_ALT_GID               = __constant_htons(18),
-       IB_CM_REJ_INVALID_ALT_LID               = __constant_htons(19),
-       IB_CM_REJ_INVALID_ALT_SL                = __constant_htons(20),
-       IB_CM_REJ_INVALID_ALT_TRAFFIC_CLASS     = __constant_htons(21),
-       IB_CM_REJ_INVALID_ALT_HOP_LIMIT         = __constant_htons(22),
-       IB_CM_REJ_INVALID_ALT_PACKET_RATE       = __constant_htons(23),
-       IB_CM_REJ_PORT_REDIRECT                 = __constant_htons(24),
-       IB_CM_REJ_INVALID_MTU                   = __constant_htons(26),
-       IB_CM_REJ_INSUFFICIENT_RESP_RESOURCES   = __constant_htons(27),
-       IB_CM_REJ_CONSUMER_DEFINED              = __constant_htons(28),
-       IB_CM_REJ_INVALID_RNR_RETRY             = __constant_htons(29),
-       IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID       = __constant_htons(30),
-       IB_CM_REJ_INVALID_CLASS_VERSION         = __constant_htons(31),
-       IB_CM_REJ_INVALID_FLOW_LABEL            = __constant_htons(32),
-       IB_CM_REJ_INVALID_ALT_FLOW_LABEL        = __constant_htons(33)
+       IB_CM_REJ_NO_QP                         = 1,
+       IB_CM_REJ_NO_EEC                        = 2,
+       IB_CM_REJ_NO_RESOURCES                  = 3,
+       IB_CM_REJ_TIMEOUT                       = 4,
+       IB_CM_REJ_UNSUPPORTED                   = 5,
+       IB_CM_REJ_INVALID_COMM_ID               = 6,
+       IB_CM_REJ_INVALID_COMM_INSTANCE         = 7,
+       IB_CM_REJ_INVALID_SERVICE_ID            = 8,
+       IB_CM_REJ_INVALID_TRANSPORT_TYPE        = 9,
+       IB_CM_REJ_STALE_CONN                    = 10,
+       IB_CM_REJ_RDC_NOT_EXIST                 = 11,
+       IB_CM_REJ_INVALID_GID                   = 12,
+       IB_CM_REJ_INVALID_LID                   = 13,
+       IB_CM_REJ_INVALID_SL                    = 14,
+       IB_CM_REJ_INVALID_TRAFFIC_CLASS         = 15,
+       IB_CM_REJ_INVALID_HOP_LIMIT             = 16,
+       IB_CM_REJ_INVALID_PACKET_RATE           = 17,
+       IB_CM_REJ_INVALID_ALT_GID               = 18,
+       IB_CM_REJ_INVALID_ALT_LID               = 19,
+       IB_CM_REJ_INVALID_ALT_SL                = 20,
+       IB_CM_REJ_INVALID_ALT_TRAFFIC_CLASS     = 21,
+       IB_CM_REJ_INVALID_ALT_HOP_LIMIT         = 22,
+       IB_CM_REJ_INVALID_ALT_PACKET_RATE       = 23,
+       IB_CM_REJ_PORT_CM_REDIRECT              = 24,
+       IB_CM_REJ_PORT_REDIRECT                 = 25,
+       IB_CM_REJ_INVALID_MTU                   = 26,
+       IB_CM_REJ_INSUFFICIENT_RESP_RESOURCES   = 27,
+       IB_CM_REJ_CONSUMER_DEFINED              = 28,
+       IB_CM_REJ_INVALID_RNR_RETRY             = 29,
+       IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID       = 30,
+       IB_CM_REJ_INVALID_CLASS_VERSION         = 31,
+       IB_CM_REJ_INVALID_FLOW_LABEL            = 32,
+       IB_CM_REJ_INVALID_ALT_FLOW_LABEL        = 33
 };
 
 struct ib_cm_rej_event_param {
@@ -221,8 +222,7 @@ struct ib_cm_sidr_req_event_param {
        struct ib_cm_id         *listen_id;
        struct ib_device        *device;
        u8                      port;
-
-       u16     pkey;
+       u16                     pkey;
 };
 
 enum ib_cm_sidr_status {
@@ -284,12 +284,12 @@ typedef int (*ib_cm_handler)(struct ib_cm_id *cm_id,
 struct ib_cm_id {
        ib_cm_handler           cm_handler;
        void                    *context;
-       u64                     service_id;
-       u64                     service_mask;
+       __be64                  service_id;
+       __be64                  service_mask;
        enum ib_cm_state        state;          /* internal CM/debug use */
        enum ib_cm_lap_state    lap_state;      /* internal CM/debug use */
-       u32                     local_id;
-       u32                     remote_id;
+       __be32                  local_id;
+       __be32                  remote_id;
 };
 
 /**
@@ -329,13 +329,13 @@ void ib_destroy_cm_id(struct ib_cm_id *cm_id);
  *   IB_CM_ASSIGN_SERVICE_ID.
  */
 int ib_cm_listen(struct ib_cm_id *cm_id,
-                u64 service_id,
-                u64 service_mask);
+                __be64 service_id,
+                __be64 service_mask);
 
 struct ib_cm_req_param {
        struct ib_sa_path_rec   *primary_path;
        struct ib_sa_path_rec   *alternate_path;
-       u64                     service_id;
+       __be64                  service_id;
        u32                     qp_num;
        enum ib_qp_type         qp_type;
        u32                     starting_psn;
@@ -527,7 +527,7 @@ int ib_send_cm_apr(struct ib_cm_id *cm_id,
 
 struct ib_cm_sidr_req_param {
        struct ib_sa_path_rec   *path;
-       u64                     service_id;
+       __be64                  service_id;
        int                     timeout_ms;
        const void              *private_data;
        u8                      private_data_len;
similarity index 99%
rename from drivers/infiniband/include/ib_fmr_pool.h
rename to include/rdma/ib_fmr_pool.h
index 6c9e24d..86b7e93 100644 (file)
@@ -36,7 +36,7 @@
 #if !defined(IB_FMR_POOL_H)
 #define IB_FMR_POOL_H
 
-#include <ib_verbs.h>
+#include <rdma/ib_verbs.h>
 
 struct ib_fmr_pool;
 
similarity index 98%
rename from drivers/infiniband/include/ib_mad.h
rename to include/rdma/ib_mad.h
index 491b6f2..fc6b1c1 100644 (file)
@@ -41,7 +41,7 @@
 
 #include <linux/pci.h>
 
-#include <ib_verbs.h>
+#include <rdma/ib_verbs.h>
 
 /* Management base version */
 #define IB_MGMT_BASE_VERSION                   1
@@ -90,6 +90,7 @@
 
 #define        IB_MGMT_RMPP_STATUS_SUCCESS             0
 #define        IB_MGMT_RMPP_STATUS_RESX                1
+#define        IB_MGMT_RMPP_STATUS_ABORT_MIN           118
 #define        IB_MGMT_RMPP_STATUS_T2L                 118
 #define        IB_MGMT_RMPP_STATUS_BAD_LEN             119
 #define        IB_MGMT_RMPP_STATUS_BAD_SEG             120
 #define        IB_MGMT_RMPP_STATUS_UNV                 125
 #define        IB_MGMT_RMPP_STATUS_TMR                 126
 #define        IB_MGMT_RMPP_STATUS_UNSPEC              127
+#define        IB_MGMT_RMPP_STATUS_ABORT_MAX           127
 
 #define IB_QP0         0
 #define IB_QP1         __constant_htonl(1)
@@ -111,12 +113,12 @@ struct ib_mad_hdr {
        u8      mgmt_class;
        u8      class_version;
        u8      method;
-       u16     status;
-       u16     class_specific;
-       u64     tid;
-       u16     attr_id;
-       u16     resv;
-       u32     attr_mod;
+       __be16  status;
+       __be16  class_specific;
+       __be64  tid;
+       __be16  attr_id;
+       __be16  resv;
+       __be32  attr_mod;
 };
 
 struct ib_rmpp_hdr {
@@ -124,8 +126,8 @@ struct ib_rmpp_hdr {
        u8      rmpp_type;
        u8      rmpp_rtime_flags;
        u8      rmpp_status;
-       u32     seg_num;
-       u32     paylen_newwin;
+       __be32  seg_num;
+       __be32  paylen_newwin;
 };
 
 typedef u64 __bitwise ib_sa_comp_mask;
@@ -139,9 +141,9 @@ typedef u64 __bitwise ib_sa_comp_mask;
  * the wire so we can't change the layout)
  */
 struct ib_sa_hdr {
-       u64                     sm_key;
-       u16                     attr_offset;
-       u16                     reserved;
+       __be64                  sm_key;
+       __be16                  attr_offset;
+       __be16                  reserved;
        ib_sa_comp_mask         comp_mask;
 } __attribute__ ((packed));
 
similarity index 99%
rename from drivers/infiniband/include/ib_pack.h
rename to include/rdma/ib_pack.h
index fe480f3..f926020 100644 (file)
@@ -35,7 +35,7 @@
 #ifndef IB_PACK_H
 #define IB_PACK_H
 
-#include <ib_verbs.h>
+#include <rdma/ib_verbs.h>
 
 enum {
        IB_LRH_BYTES  = 8,
similarity index 98%
rename from drivers/infiniband/include/ib_sa.h
rename to include/rdma/ib_sa.h
index 6d999f7..c022edf 100644 (file)
@@ -38,8 +38,8 @@
 
 #include <linux/compiler.h>
 
-#include <ib_verbs.h>
-#include <ib_mad.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_mad.h>
 
 enum {
        IB_SA_CLASS_VERSION             = 2,    /* IB spec version 1.1/1.2 */
@@ -133,16 +133,16 @@ struct ib_sa_path_rec {
        /* reserved */
        union ib_gid dgid;
        union ib_gid sgid;
-       u16          dlid;
-       u16          slid;
+       __be16       dlid;
+       __be16       slid;
        int          raw_traffic;
        /* reserved */
-       u32          flow_label;
+       __be32       flow_label;
        u8           hop_limit;
        u8           traffic_class;
        int          reversible;
        u8           numb_path;
-       u16          pkey;
+       __be16       pkey;
        /* reserved */
        u8           sl;
        u8           mtu_selector;
@@ -176,18 +176,18 @@ struct ib_sa_path_rec {
 struct ib_sa_mcmember_rec {
        union ib_gid mgid;
        union ib_gid port_gid;
-       u32          qkey;
-       u16          mlid;
+       __be32       qkey;
+       __be16       mlid;
        u8           mtu_selector;
        u8           mtu;
        u8           traffic_class;
-       u16          pkey;
+       __be16       pkey;
        u8           rate_selector;
        u8           rate;
        u8           packet_life_time_selector;
        u8           packet_life_time;
        u8           sl;
-       u32          flow_label;
+       __be32       flow_label;
        u8           hop_limit;
        u8           scope;
        u8           join_state;
@@ -238,7 +238,7 @@ struct ib_sa_mcmember_rec {
 struct ib_sa_service_rec {
        u64             id;
        union ib_gid    gid;
-       u16             pkey;
+       __be16          pkey;
        /* reserved */
        u32             lease;
        u8              key[16];
similarity index 95%
rename from drivers/infiniband/include/ib_smi.h
rename to include/rdma/ib_smi.h
index ca82165..87f6073 100644 (file)
@@ -39,9 +39,7 @@
 #if !defined( IB_SMI_H )
 #define IB_SMI_H
 
-#include <ib_mad.h>
-
-#define IB_LID_PERMISSIVE                      0xFFFF
+#include <rdma/ib_mad.h>
 
 #define IB_SMP_DATA_SIZE                       64
 #define IB_SMP_MAX_PATH_HOPS                   64
@@ -51,16 +49,16 @@ struct ib_smp {
        u8      mgmt_class;
        u8      class_version;
        u8      method;
-       u16     status;
+       __be16  status;
        u8      hop_ptr;
        u8      hop_cnt;
-       u64     tid;
-       u16     attr_id;
-       u16     resv;
-       u32     attr_mod;
-       u64     mkey;
-       u16     dr_slid;
-       u16     dr_dlid;
+       __be64  tid;
+       __be16  attr_id;
+       __be16  resv;
+       __be32  attr_mod;
+       __be64  mkey;
+       __be16  dr_slid;
+       __be16  dr_dlid;
        u8      reserved[28];
        u8      data[IB_SMP_DATA_SIZE];
        u8      initial_path[IB_SMP_MAX_PATH_HOPS];
similarity index 95%
rename from drivers/infiniband/include/ib_user_cm.h
rename to include/rdma/ib_user_cm.h
index 500b1af..72182d1 100644 (file)
@@ -88,15 +88,15 @@ struct ib_ucm_attr_id {
 };
 
 struct ib_ucm_attr_id_resp {
-       __u64 service_id;
-       __u64 service_mask;
-       __u32 local_id;
-       __u32 remote_id;
+       __be64 service_id;
+       __be64 service_mask;
+       __be32 local_id;
+       __be32 remote_id;
 };
 
 struct ib_ucm_listen {
-       __u64 service_id;
-       __u64 service_mask;
+       __be64 service_id;
+       __be64 service_mask;
        __u32 id;
 };
 
@@ -114,13 +114,13 @@ struct ib_ucm_private_data {
 struct ib_ucm_path_rec {
        __u8  dgid[16];
        __u8  sgid[16];
-       __u16 dlid;
-       __u16 slid;
+       __be16 dlid;
+       __be16 slid;
        __u32 raw_traffic;
-       __u32 flow_label;
+       __be32 flow_label;
        __u32 reversible;
        __u32 mtu;
-       __u16 pkey;
+       __be16 pkey;
        __u8  hop_limit;
        __u8  traffic_class;
        __u8  numb_path;
@@ -138,7 +138,7 @@ struct ib_ucm_req {
        __u32 qpn;
        __u32 qp_type;
        __u32 psn;
-       __u64 sid;
+       __be64 sid;
        __u64 data;
        __u64 primary_path;
        __u64 alternate_path;
@@ -200,7 +200,7 @@ struct ib_ucm_lap {
 struct ib_ucm_sidr_req {
        __u32 id;
        __u32 timeout;
-       __u64 sid;
+       __be64 sid;
        __u64 data;
        __u64 path;
        __u16 pkey;
@@ -237,7 +237,7 @@ struct ib_ucm_req_event_resp {
        /* port */
        struct ib_ucm_path_rec primary_path;
        struct ib_ucm_path_rec alternate_path;
-       __u64                  remote_ca_guid;
+       __be64                 remote_ca_guid;
        __u32                  remote_qkey;
        __u32                  remote_qpn;
        __u32                  qp_type;
@@ -253,7 +253,7 @@ struct ib_ucm_req_event_resp {
 };
 
 struct ib_ucm_rep_event_resp {
-       __u64 remote_ca_guid;
+       __be64 remote_ca_guid;
        __u32 remote_qkey;
        __u32 remote_qpn;
        __u32 starting_psn;
similarity index 97%
rename from drivers/infiniband/include/ib_user_mad.h
rename to include/rdma/ib_user_mad.h
index a9a56b5..44537aa 100644 (file)
@@ -70,8 +70,6 @@
  * @traffic_class - Traffic class in GRH
  * @gid - Remote GID in GRH
  * @flow_label - Flow label in GRH
- *
- * All multi-byte quantities are stored in network (big endian) byte order.
  */
 struct ib_user_mad_hdr {
        __u32   id;
@@ -79,9 +77,9 @@ struct ib_user_mad_hdr {
        __u32   timeout_ms;
        __u32   retries;
        __u32   length;
-       __u32   qpn;
-       __u32   qkey;
-       __u16   lid;
+       __be32  qpn;
+       __be32  qkey;
+       __be16  lid;
        __u8    sl;
        __u8    path_bits;
        __u8    grh_present;
@@ -89,7 +87,7 @@ struct ib_user_mad_hdr {
        __u8    hop_limit;
        __u8    traffic_class;
        __u8    gid[16];
-       __u32   flow_label;
+       __be32  flow_label;
 };
 
 /**
similarity index 92%
rename from drivers/infiniband/include/ib_user_verbs.h
rename to include/rdma/ib_user_verbs.h
index 7c61370..7ebb01c 100644 (file)
@@ -78,7 +78,12 @@ enum {
        IB_USER_VERBS_CMD_POST_SEND,
        IB_USER_VERBS_CMD_POST_RECV,
        IB_USER_VERBS_CMD_ATTACH_MCAST,
-       IB_USER_VERBS_CMD_DETACH_MCAST
+       IB_USER_VERBS_CMD_DETACH_MCAST,
+       IB_USER_VERBS_CMD_CREATE_SRQ,
+       IB_USER_VERBS_CMD_MODIFY_SRQ,
+       IB_USER_VERBS_CMD_QUERY_SRQ,
+       IB_USER_VERBS_CMD_DESTROY_SRQ,
+       IB_USER_VERBS_CMD_POST_SRQ_RECV
 };
 
 /*
@@ -143,8 +148,8 @@ struct ib_uverbs_query_device {
 
 struct ib_uverbs_query_device_resp {
        __u64 fw_ver;
-       __u64 node_guid;
-       __u64 sys_image_guid;
+       __be64 node_guid;
+       __be64 sys_image_guid;
        __u64 max_mr_size;
        __u64 page_size_cap;
        __u32 vendor_id;
@@ -386,4 +391,32 @@ struct ib_uverbs_detach_mcast {
        __u64 driver_data[0];
 };
 
+struct ib_uverbs_create_srq {
+       __u64 response;
+       __u64 user_handle;
+       __u32 pd_handle;
+       __u32 max_wr;
+       __u32 max_sge;
+       __u32 srq_limit;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_create_srq_resp {
+       __u32 srq_handle;
+};
+
+struct ib_uverbs_modify_srq {
+       __u32 srq_handle;
+       __u32 attr_mask;
+       __u32 max_wr;
+       __u32 max_sge;
+       __u32 srq_limit;
+       __u32 reserved;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_destroy_srq {
+       __u32 srq_handle;
+};
+
 #endif /* IB_USER_VERBS_H */
similarity index 91%
rename from drivers/infiniband/include/ib_verbs.h
rename to include/rdma/ib_verbs.h
index 5d24eda..e16cf94 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (c) 2004 Intel Corporation.  All rights reserved.
  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
  * Copyright (c) 2004 Voltaire Corporation.  All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -50,8 +51,8 @@
 union ib_gid {
        u8      raw[16];
        struct {
-               u64     subnet_prefix;
-               u64     interface_id;
+               __be64  subnet_prefix;
+               __be64  interface_id;
        } global;
 };
 
@@ -87,8 +88,8 @@ enum ib_atomic_cap {
 
 struct ib_device_attr {
        u64                     fw_ver;
-       u64                     node_guid;
-       u64                     sys_image_guid;
+       __be64                  node_guid;
+       __be64                  sys_image_guid;
        u64                     max_mr_size;
        u64                     page_size_cap;
        u32                     vendor_id;
@@ -255,7 +256,10 @@ enum ib_event_type {
        IB_EVENT_PORT_ERR,
        IB_EVENT_LID_CHANGE,
        IB_EVENT_PKEY_CHANGE,
-       IB_EVENT_SM_CHANGE
+       IB_EVENT_SM_CHANGE,
+       IB_EVENT_SRQ_ERR,
+       IB_EVENT_SRQ_LIMIT_REACHED,
+       IB_EVENT_QP_LAST_WQE_REACHED
 };
 
 struct ib_event {
@@ -263,6 +267,7 @@ struct ib_event {
        union {
                struct ib_cq    *cq;
                struct ib_qp    *qp;
+               struct ib_srq   *srq;
                u8              port_num;
        } element;
        enum ib_event_type      event;
@@ -290,8 +295,8 @@ struct ib_global_route {
 };
 
 struct ib_grh {
-       u32             version_tclass_flow;
-       u16             paylen;
+       __be32          version_tclass_flow;
+       __be16          paylen;
        u8              next_hdr;
        u8              hop_limit;
        union ib_gid    sgid;
@@ -302,6 +307,8 @@ enum {
        IB_MULTICAST_QPN = 0xffffff
 };
 
+#define IB_LID_PERMISSIVE      __constant_htons(0xFFFF)
+
 enum ib_ah_flags {
        IB_AH_GRH       = 1
 };
@@ -383,6 +390,23 @@ enum ib_cq_notify {
        IB_CQ_NEXT_COMP
 };
 
+enum ib_srq_attr_mask {
+       IB_SRQ_MAX_WR   = 1 << 0,
+       IB_SRQ_LIMIT    = 1 << 1,
+};
+
+struct ib_srq_attr {
+       u32     max_wr;
+       u32     max_sge;
+       u32     srq_limit;
+};
+
+struct ib_srq_init_attr {
+       void                  (*event_handler)(struct ib_event *, void *);
+       void                   *srq_context;
+       struct ib_srq_attr      attr;
+};
+
 struct ib_qp_cap {
        u32     max_send_wr;
        u32     max_recv_wr;
@@ -710,10 +734,11 @@ struct ib_cq {
 };
 
 struct ib_srq {
-       struct ib_device        *device;
-       struct ib_uobject       *uobject;
-       struct ib_pd            *pd;
-       void                    *srq_context;
+       struct ib_device       *device;
+       struct ib_pd           *pd;
+       struct ib_uobject      *uobject;
+       void                  (*event_handler)(struct ib_event *, void *);
+       void                   *srq_context;
        atomic_t                usecnt;
 };
 
@@ -827,6 +852,18 @@ struct ib_device {
        int                        (*query_ah)(struct ib_ah *ah,
                                               struct ib_ah_attr *ah_attr);
        int                        (*destroy_ah)(struct ib_ah *ah);
+       struct ib_srq *            (*create_srq)(struct ib_pd *pd,
+                                                struct ib_srq_init_attr *srq_init_attr,
+                                                struct ib_udata *udata);
+       int                        (*modify_srq)(struct ib_srq *srq,
+                                                struct ib_srq_attr *srq_attr,
+                                                enum ib_srq_attr_mask srq_attr_mask);
+       int                        (*query_srq)(struct ib_srq *srq,
+                                               struct ib_srq_attr *srq_attr);
+       int                        (*destroy_srq)(struct ib_srq *srq);
+       int                        (*post_srq_recv)(struct ib_srq *srq,
+                                                   struct ib_recv_wr *recv_wr,
+                                                   struct ib_recv_wr **bad_recv_wr);
        struct ib_qp *             (*create_qp)(struct ib_pd *pd,
                                                struct ib_qp_init_attr *qp_init_attr,
                                                struct ib_udata *udata);
@@ -1038,6 +1075,65 @@ int ib_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr);
  */
 int ib_destroy_ah(struct ib_ah *ah);
 
+/**
+ * ib_create_srq - Creates a SRQ associated with the specified protection
+ *   domain.
+ * @pd: The protection domain associated with the SRQ.
+ * @srq_init_attr: A list of initial attributes required to create the SRQ.
+ *
+ * srq_attr->max_wr and srq_attr->max_sge are read the determine the
+ * requested size of the SRQ, and set to the actual values allocated
+ * on return.  If ib_create_srq() succeeds, then max_wr and max_sge
+ * will always be at least as large as the requested values.
+ */
+struct ib_srq *ib_create_srq(struct ib_pd *pd,
+                            struct ib_srq_init_attr *srq_init_attr);
+
+/**
+ * ib_modify_srq - Modifies the attributes for the specified SRQ.
+ * @srq: The SRQ to modify.
+ * @srq_attr: On input, specifies the SRQ attributes to modify.  On output,
+ *   the current values of selected SRQ attributes are returned.
+ * @srq_attr_mask: A bit-mask used to specify which attributes of the SRQ
+ *   are being modified.
+ *
+ * The mask may contain IB_SRQ_MAX_WR to resize the SRQ and/or
+ * IB_SRQ_LIMIT to set the SRQ's limit and request notification when
+ * the number of receives queued drops below the limit.
+ */
+int ib_modify_srq(struct ib_srq *srq,
+                 struct ib_srq_attr *srq_attr,
+                 enum ib_srq_attr_mask srq_attr_mask);
+
+/**
+ * ib_query_srq - Returns the attribute list and current values for the
+ *   specified SRQ.
+ * @srq: The SRQ to query.
+ * @srq_attr: The attributes of the specified SRQ.
+ */
+int ib_query_srq(struct ib_srq *srq,
+                struct ib_srq_attr *srq_attr);
+
+/**
+ * ib_destroy_srq - Destroys the specified SRQ.
+ * @srq: The SRQ to destroy.
+ */
+int ib_destroy_srq(struct ib_srq *srq);
+
+/**
+ * ib_post_srq_recv - Posts a list of work requests to the specified SRQ.
+ * @srq: The SRQ to post the work request on.
+ * @recv_wr: A list of work requests to post on the receive queue.
+ * @bad_recv_wr: On an immediate failure, this parameter will reference
+ *   the work request that failed to be posted on the QP.
+ */
+static inline int ib_post_srq_recv(struct ib_srq *srq,
+                                  struct ib_recv_wr *recv_wr,
+                                  struct ib_recv_wr **bad_recv_wr)
+{
+       return srq->device->post_srq_recv(srq, recv_wr, bad_recv_wr);
+}
+
 /**
  * ib_create_qp - Creates a QP associated with the specified protection
  *   domain.
index a4f1837..f6e0bb4 100644 (file)
@@ -29,6 +29,14 @@ struct scsi_transport_template {
        struct transport_container target_attrs;
        struct transport_container device_attrs;
 
+       /*
+        * If set, call target_parent prior to allocating a scsi_target,
+        * so we get the appropriate parent for the target. This function
+        * is required for transports like FC and iSCSI that do not put the
+        * scsi_target under scsi_host.
+        */
+       struct device *(*target_parent)(struct Scsi_Host *, int, uint);
+
        /* The size of the specific transport attribute structure (a
         * space of this size will be left at the end of the
         * scsi_* structure */
index 38b357f..f72b3ef 100644 (file)
@@ -360,11 +360,13 @@ int snd_device_free_all(snd_card_t *card, snd_device_cmd_t cmd);
 
 /* isadma.c */
 
+#ifdef CONFIG_ISA_DMA_API
 #define DMA_MODE_NO_ENABLE     0x0100
 
 void snd_dma_program(unsigned long dma, unsigned long addr, unsigned int size, unsigned short mode);
 void snd_dma_disable(unsigned long dma);
 unsigned int snd_dma_pointer(unsigned long dma, unsigned int size);
+#endif
 
 /* misc.c */
 
index 7e8a25c..70975ce 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -895,7 +895,7 @@ static inline void lock_semundo(void)
        struct sem_undo_list *undo_list;
 
        undo_list = current->sysvsem.undo_list;
-       if ((undo_list != NULL) && (atomic_read(&undo_list->refcnt) != 1))
+       if (undo_list)
                spin_lock(&undo_list->lock);
 }
 
@@ -915,7 +915,7 @@ static inline void unlock_semundo(void)
        struct sem_undo_list *undo_list;
 
        undo_list = current->sysvsem.undo_list;
-       if ((undo_list != NULL) && (atomic_read(&undo_list->refcnt) != 1))
+       if (undo_list)
                spin_unlock(&undo_list->lock);
 }
 
@@ -943,9 +943,7 @@ static inline int get_undo_list(struct sem_undo_list **undo_listp)
                if (undo_list == NULL)
                        return -ENOMEM;
                memset(undo_list, 0, size);
-               /* don't initialize unodhd->lock here.  It's done
-                * in copy_semundo() instead.
-                */
+               spin_lock_init(&undo_list->lock);
                atomic_set(&undo_list->refcnt, 1);
                current->sysvsem.undo_list = undo_list;
        }
@@ -1231,8 +1229,6 @@ int copy_semundo(unsigned long clone_flags, struct task_struct *tsk)
                error = get_undo_list(&undo_list);
                if (error)
                        return error;
-               if (atomic_read(&undo_list->refcnt) == 1)
-                       spin_lock_init(&undo_list->lock);
                atomic_inc(&undo_list->refcnt);
                tsk->sysvsem.undo_list = undo_list;
        } else 
index cce0224..1d6cf08 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -170,7 +170,7 @@ static struct vm_operations_struct shm_vm_ops = {
        .open   = shm_open,     /* callback for a new vm-area open */
        .close  = shm_close,    /* callback for when the vm-area is released */
        .nopage = shmem_nopage,
-#ifdef CONFIG_NUMA
+#if defined(CONFIG_NUMA) && defined(CONFIG_SHMEM)
        .set_policy = shmem_set_policy,
        .get_policy = shmem_get_policy,
 #endif
index 805fb90..8ab1b4e 100644 (file)
@@ -398,21 +398,31 @@ static int cpuset_path(const struct cpuset *cs, char *buf, int buflen)
  * to continue to serve a useful existence.  Next time it's released,
  * we will get notified again, if it still has 'notify_on_release' set.
  *
- * Note final arg to call_usermodehelper() is 0 - that means
- * don't wait.  Since we are holding the global cpuset_sem here,
- * and we are asking another thread (started from keventd) to rmdir a
- * cpuset, we can't wait - or we'd deadlock with the removing thread
- * on cpuset_sem.
+ * The final arg to call_usermodehelper() is 0, which means don't
+ * wait.  The separate /sbin/cpuset_release_agent task is forked by
+ * call_usermodehelper(), then control in this thread returns here,
+ * without waiting for the release agent task.  We don't bother to
+ * wait because the caller of this routine has no use for the exit
+ * status of the /sbin/cpuset_release_agent task, so no sense holding
+ * our caller up for that.
+ *
+ * The simple act of forking that task might require more memory,
+ * which might need cpuset_sem.  So this routine must be called while
+ * cpuset_sem is not held, to avoid a possible deadlock.  See also
+ * comments for check_for_release(), below.
  */
 
-static int cpuset_release_agent(char *cpuset_str)
+static void cpuset_release_agent(const char *pathbuf)
 {
        char *argv[3], *envp[3];
        int i;
 
+       if (!pathbuf)
+               return;
+
        i = 0;
        argv[i++] = "/sbin/cpuset_release_agent";
-       argv[i++] = cpuset_str;
+       argv[i++] = (char *)pathbuf;
        argv[i] = NULL;
 
        i = 0;
@@ -421,17 +431,29 @@ static int cpuset_release_agent(char *cpuset_str)
        envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
        envp[i] = NULL;
 
-       return call_usermodehelper(argv[0], argv, envp, 0);
+       call_usermodehelper(argv[0], argv, envp, 0);
+       kfree(pathbuf);
 }
 
 /*
  * Either cs->count of using tasks transitioned to zero, or the
  * cs->children list of child cpusets just became empty.  If this
  * cs is notify_on_release() and now both the user count is zero and
- * the list of children is empty, send notice to user land.
+ * the list of children is empty, prepare cpuset path in a kmalloc'd
+ * buffer, to be returned via ppathbuf, so that the caller can invoke
+ * cpuset_release_agent() with it later on, once cpuset_sem is dropped.
+ * Call here with cpuset_sem held.
+ *
+ * This check_for_release() routine is responsible for kmalloc'ing
+ * pathbuf.  The above cpuset_release_agent() is responsible for
+ * kfree'ing pathbuf.  The caller of these routines is responsible
+ * for providing a pathbuf pointer, initialized to NULL, then
+ * calling check_for_release() with cpuset_sem held and the address
+ * of the pathbuf pointer, then dropping cpuset_sem, then calling
+ * cpuset_release_agent() with pathbuf, as set by check_for_release().
  */
 
-static void check_for_release(struct cpuset *cs)
+static void check_for_release(struct cpuset *cs, char **ppathbuf)
 {
        if (notify_on_release(cs) && atomic_read(&cs->count) == 0 &&
            list_empty(&cs->children)) {
@@ -441,10 +463,9 @@ static void check_for_release(struct cpuset *cs)
                if (!buf)
                        return;
                if (cpuset_path(cs, buf, PAGE_SIZE) < 0)
-                       goto out;
-               cpuset_release_agent(buf);
-out:
-               kfree(buf);
+                       kfree(buf);
+               else
+                       *ppathbuf = buf;
        }
 }
 
@@ -606,6 +627,14 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
  * Call with cpuset_sem held.  May nest a call to the
  * lock_cpu_hotplug()/unlock_cpu_hotplug() pair.
  */
+
+/*
+ * Hack to avoid 2.6.13 partial node dynamic sched domain bug.
+ * Disable letting 'cpu_exclusive' cpusets define dynamic sched
+ * domains, until the sched domain can handle partial nodes.
+ * Remove this #if hackery when sched domains fixed.
+ */
+#if 0
 static void update_cpu_domains(struct cpuset *cur)
 {
        struct cpuset *c, *par = cur->parent;
@@ -646,6 +675,11 @@ static void update_cpu_domains(struct cpuset *cur)
        partition_sched_domains(&pspan, &cspan);
        unlock_cpu_hotplug();
 }
+#else
+static void update_cpu_domains(struct cpuset *cur)
+{
+}
+#endif
 
 static int update_cpumask(struct cpuset *cs, char *buf)
 {
@@ -727,14 +761,14 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf)
        return 0;
 }
 
-static int attach_task(struct cpuset *cs, char *buf)
+static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf)
 {
        pid_t pid;
        struct task_struct *tsk;
        struct cpuset *oldcs;
        cpumask_t cpus;
 
-       if (sscanf(buf, "%d", &pid) != 1)
+       if (sscanf(pidbuf, "%d", &pid) != 1)
                return -EIO;
        if (cpus_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed))
                return -ENOSPC;
@@ -777,7 +811,7 @@ static int attach_task(struct cpuset *cs, char *buf)
 
        put_task_struct(tsk);
        if (atomic_dec_and_test(&oldcs->count))
-               check_for_release(oldcs);
+               check_for_release(oldcs, ppathbuf);
        return 0;
 }
 
@@ -801,6 +835,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us
        struct cftype *cft = __d_cft(file->f_dentry);
        cpuset_filetype_t type = cft->private;
        char *buffer;
+       char *pathbuf = NULL;
        int retval = 0;
 
        /* Crude upper limit on largest legitimate cpulist user might write. */
@@ -841,7 +876,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us
                retval = update_flag(CS_NOTIFY_ON_RELEASE, cs, buffer);
                break;
        case FILE_TASKLIST:
-               retval = attach_task(cs, buffer);
+               retval = attach_task(cs, buffer, &pathbuf);
                break;
        default:
                retval = -EINVAL;
@@ -852,6 +887,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us
                retval = nbytes;
 out2:
        up(&cpuset_sem);
+       cpuset_release_agent(pathbuf);
 out1:
        kfree(buffer);
        return retval;
@@ -1357,6 +1393,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
        struct cpuset *cs = dentry->d_fsdata;
        struct dentry *d;
        struct cpuset *parent;
+       char *pathbuf = NULL;
 
        /* the vfs holds both inode->i_sem already */
 
@@ -1376,7 +1413,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
                update_cpu_domains(cs);
        list_del(&cs->sibling); /* delete my sibling from parent->children */
        if (list_empty(&parent->children))
-               check_for_release(parent);
+               check_for_release(parent, &pathbuf);
        spin_lock(&cs->dentry->d_lock);
        d = dget(cs->dentry);
        cs->dentry = NULL;
@@ -1384,6 +1421,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
        cpuset_d_remove_dir(d);
        dput(d);
        up(&cpuset_sem);
+       cpuset_release_agent(pathbuf);
        return 0;
 }
 
@@ -1483,10 +1521,13 @@ void cpuset_exit(struct task_struct *tsk)
        task_unlock(tsk);
 
        if (notify_on_release(cs)) {
+               char *pathbuf = NULL;
+
                down(&cpuset_sem);
                if (atomic_dec_and_test(&cs->count))
-                       check_for_release(cs);
+                       check_for_release(cs, &pathbuf);
                up(&cpuset_sem);
+               cpuset_release_agent(pathbuf);
        } else {
                atomic_dec(&cs->count);
        }
index 9d1b10e..5b0fb9f 100644 (file)
@@ -829,8 +829,10 @@ fastcall NORET_TYPE void do_exit(long code)
        acct_update_integrals(tsk);
        update_mem_hiwater(tsk);
        group_dead = atomic_dec_and_test(&tsk->signal->live);
-       if (group_dead)
+       if (group_dead) {
+               del_timer_sync(&tsk->signal->real_timer);
                acct_process(code);
+       }
        exit_mm(tsk);
 
        exit_sem(tsk);
index 068e271..c32995f 100644 (file)
@@ -250,13 +250,18 @@ static inline unsigned int block_size(int val)
 /* Created by linker magic */
 extern char __per_cpu_start[], __per_cpu_end[];
 
-static void *percpu_modalloc(unsigned long size, unsigned long align)
+static void *percpu_modalloc(unsigned long size, unsigned long align,
+                            const char *name)
 {
        unsigned long extra;
        unsigned int i;
        void *ptr;
 
-       BUG_ON(align > SMP_CACHE_BYTES);
+       if (align > SMP_CACHE_BYTES) {
+               printk(KERN_WARNING "%s: per-cpu alignment %li > %i\n",
+                      name, align, SMP_CACHE_BYTES);
+               align = SMP_CACHE_BYTES;
+       }
 
        ptr = __per_cpu_start;
        for (i = 0; i < pcpu_num_used; ptr += block_size(pcpu_size[i]), i++) {
@@ -348,7 +353,8 @@ static int percpu_modinit(void)
 }      
 __initcall(percpu_modinit);
 #else /* ... !CONFIG_SMP */
-static inline void *percpu_modalloc(unsigned long size, unsigned long align)
+static inline void *percpu_modalloc(unsigned long size, unsigned long align,
+                                   const char *name)
 {
        return NULL;
 }
@@ -1644,7 +1650,8 @@ static struct module *load_module(void __user *umod,
        if (pcpuindex) {
                /* We have a special allocation for this section. */
                percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size,
-                                        sechdrs[pcpuindex].sh_addralign);
+                                        sechdrs[pcpuindex].sh_addralign,
+                                        mod->name);
                if (!percpu) {
                        err = -ENOMEM;
                        goto free_mod;
index 10b2ad7..38798a2 100644 (file)
@@ -1166,7 +1166,6 @@ void exit_itimers(struct signal_struct *sig)
                tmr = list_entry(sig->posix_timers.next, struct k_itimer, list);
                itimer_delete(tmr);
        }
-       del_timer_sync(&sig->real_timer);
 }
 
 /*
index a646e4f..5f889d0 100644 (file)
@@ -3378,8 +3378,8 @@ EXPORT_SYMBOL(set_user_nice);
  */
 int can_nice(const task_t *p, const int nice)
 {
-       /* convert nice value [19,-20] to rlimit style value [0,39] */
-       int nice_rlim = 19 - nice;
+       /* convert nice value [19,-20] to rlimit style value [1,40] */
+       int nice_rlim = 20 - nice;
        return (nice_rlim <= p->signal->rlim[RLIMIT_NICE].rlim_cur ||
                capable(CAP_SYS_NICE));
 }
index ca1186e..d282fea 100644 (file)
@@ -692,7 +692,7 @@ static void handle_stop_signal(int sig, struct task_struct *p)
 {
        struct task_struct *t;
 
-       if (p->flags & SIGNAL_GROUP_EXIT)
+       if (p->signal->flags & SIGNAL_GROUP_EXIT)
                /*
                 * The process is in the middle of dying already.
                 */
index 31007d6..b4ab6af 100644 (file)
@@ -86,7 +86,7 @@ restart:
        /* Reset the pending bitmask before enabling irqs */
        local_softirq_pending() = 0;
 
-       //local_irq_enable();
+       local_irq_enable();
 
        h = softirq_vec;
 
@@ -99,7 +99,7 @@ restart:
                pending >>= 1;
        } while (pending);
 
-       //local_irq_disable();
+       local_irq_disable();
 
        pending = local_softirq_pending();
        if (pending && --max_restart)
index 000e81a..0bcaed6 100644 (file)
@@ -404,7 +404,6 @@ void kernel_halt(void)
 {
        notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
        system_state = SYSTEM_HALT;
-       device_suspend(PMSG_SUSPEND);
        device_shutdown();
        printk(KERN_EMERG "System halted.\n");
        machine_halt();
@@ -415,7 +414,6 @@ void kernel_power_off(void)
 {
        notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
        system_state = SYSTEM_POWER_OFF;
-       device_suspend(PMSG_SUSPEND);
        device_shutdown();
        printk(KERN_EMERG "Power down.\n");
        machine_power_off();
index 42b40ae..1ab2370 100644 (file)
@@ -79,7 +79,6 @@ cond_syscall(sys_request_key);
 cond_syscall(sys_keyctl);
 cond_syscall(compat_sys_keyctl);
 cond_syscall(compat_sys_socketcall);
-cond_syscall(sys_set_zone_reclaim);
 cond_syscall(sys_inotify_init);
 cond_syscall(sys_inotify_add_watch);
 cond_syscall(sys_inotify_rm_watch);
index f2a1188..5377f40 100644 (file)
@@ -1023,7 +1023,7 @@ asmlinkage long sys_getppid(void)
        parent = me->group_leader->real_parent;
        for (;;) {
                pid = parent->tgid;
-#ifdef CONFIG_SMP
+#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
 {
                struct task_struct *old = parent;
 
index 259cf55..c7e36d4 100644 (file)
@@ -308,8 +308,6 @@ struct workqueue_struct *__create_workqueue(const char *name,
        struct workqueue_struct *wq;
        struct task_struct *p;
 
-       BUG_ON(strlen(name) > 10);
-
        wq = kmalloc(sizeof(*wq), GFP_KERNEL);
        if (!wq)
                return NULL;
index 58b2227..065198f 100644 (file)
@@ -473,7 +473,7 @@ static u32 test_step(u32 init, unsigned char *buf, size_t len)
        init = bitreverse(init);
        crc2 = bitreverse(crc1);
        if (crc1 != bitreverse(crc2))
-               printf("\nBit reversal fail: 0x%08x -> %0x08x -> 0x%08x\n",
+               printf("\nBit reversal fail: 0x%08x -> 0x%08x -> 0x%08x\n",
                       crc1, crc2, bitreverse(crc2));
        crc1 = crc32_le(init, buf, len);
        if (crc1 != crc2)
index c5be889..6415d05 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -207,7 +207,7 @@ build_up:
 }
 
 /**
- * idr_get_new_above - allocate new idr entry above a start id
+ * idr_get_new_above - allocate new idr entry above or equal to a start id
  * @idp: idr handle
  * @ptr: pointer you want associated with the ide
  * @start_id: id to start search at
index 75e7d30..6db6e98 100644 (file)
@@ -326,7 +326,7 @@ DEBG("huft1 ");
   {
     *t = (struct huft *)NULL;
     *m = 0;
-    return 0;
+    return 2;
   }
 
 DEBG("huft2 ");
@@ -374,6 +374,7 @@ DEBG("huft5 ");
     if ((j = *p++) != 0)
       v[x[j]++] = i;
   } while (++i < n);
+  n = x[g];                   /* set n to length of v */
 
 DEBG("h6 ");
 
@@ -410,12 +411,13 @@ DEBG1("1 ");
 DEBG1("2 ");
           f -= a + 1;           /* deduct codes from patterns left */
           xp = c + k;
-          while (++j < z)       /* try smaller tables up to z bits */
-          {
-            if ((f <<= 1) <= *++xp)
-              break;            /* enough codes to use up j bits */
-            f -= *xp;           /* else deduct codes from patterns */
-          }
+          if (j < z)
+            while (++j < z)       /* try smaller tables up to z bits */
+            {
+              if ((f <<= 1) <= *++xp)
+                break;            /* enough codes to use up j bits */
+              f -= *xp;           /* else deduct codes from patterns */
+            }
         }
 DEBG1("3 ");
         z = 1 << j;             /* table entries for j-bit table */
index a9bda0a..e4e9031 100644 (file)
@@ -269,6 +269,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
        int qualifier;          /* 'h', 'l', or 'L' for integer fields */
                                /* 'z' support added 23/7/1999 S.H.    */
                                /* 'z' changed to 'Z' --davidm 1/25/99 */
+                               /* 't' added for ptrdiff_t */
 
        /* Reject out-of-range values early */
        if (unlikely((int) size < 0)) {
@@ -339,7 +340,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
                /* get the conversion qualifier */
                qualifier = -1;
                if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
-                   *fmt =='Z' || *fmt == 'z') {
+                   *fmt =='Z' || *fmt == 'z' || *fmt == 't') {
                        qualifier = *fmt;
                        ++fmt;
                        if (qualifier == 'l' && *fmt == 'l') {
@@ -467,6 +468,8 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
                                num = (signed long) num;
                } else if (qualifier == 'Z' || qualifier == 'z') {
                        num = va_arg(args, size_t);
+               } else if (qualifier == 't') {
+                       num = va_arg(args, ptrdiff_t);
                } else if (qualifier == 'h') {
                        num = (unsigned short) va_arg(args, int);
                        if (flags & SIGN)
index fbd1111..6bf720b 100644 (file)
@@ -301,6 +301,7 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
 {
        struct mm_struct *mm = vma->vm_mm;
        unsigned long address;
+       pte_t *ptep;
        pte_t pte;
        struct page *page;
 
@@ -309,9 +310,17 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
        BUG_ON(end & ~HPAGE_MASK);
 
        for (address = start; address < end; address += HPAGE_SIZE) {
-               pte = huge_ptep_get_and_clear(mm, address, huge_pte_offset(mm, address));
+               ptep = huge_pte_offset(mm, address);
+               if (! ptep)
+                       /* This can happen on truncate, or if an
+                        * mmap() is aborted due to an error before
+                        * the prefault */
+                       continue;
+
+               pte = huge_ptep_get_and_clear(mm, address, ptep);
                if (pte_none(pte))
                        continue;
+
                page = pte_page(pte);
                put_page(page);
        }
index 6fe77ac..e046b7e 100644 (file)
@@ -913,9 +913,13 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                        pud = pud_offset(pgd, pg);
                        BUG_ON(pud_none(*pud));
                        pmd = pmd_offset(pud, pg);
-                       BUG_ON(pmd_none(*pmd));
+                       if (pmd_none(*pmd))
+                               return i ? : -EFAULT;
                        pte = pte_offset_map(pmd, pg);
-                       BUG_ON(pte_none(*pte));
+                       if (pte_none(*pte)) {
+                               pte_unmap(pte);
+                               return i ? : -EFAULT;
+                       }
                        if (pages) {
                                pages[i] = pte_page(*pte);
                                get_page(pages[i]);
@@ -940,11 +944,13 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                }
                spin_lock(&mm->page_table_lock);
                do {
+                       int write_access = write;
                        struct page *page;
-                       int lookup_write = write;
 
                        cond_resched_lock(&mm->page_table_lock);
-                       while (!(page = follow_page(mm, start, lookup_write))) {
+                       while (!(page = follow_page(mm, start, write_access))) {
+                               int ret;
+
                                /*
                                 * Shortcut for anonymous pages. We don't want
                                 * to force the creation of pages tables for
@@ -952,13 +958,23 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                                 * nobody touched so far. This is important
                                 * for doing a core dump for these mappings.
                                 */
-                               if (!lookup_write &&
-                                   untouched_anonymous_page(mm,vma,start)) {
+                               if (!write && untouched_anonymous_page(mm,vma,start)) {
                                        page = ZERO_PAGE(start);
                                        break;
                                }
                                spin_unlock(&mm->page_table_lock);
-                               switch (handle_mm_fault(mm,vma,start,write)) {
+                               ret = __handle_mm_fault(mm, vma, start, write_access);
+
+                               /*
+                                * The VM_FAULT_WRITE bit tells us that do_wp_page has
+                                * broken COW when necessary, even if maybe_mkwrite
+                                * decided not to set pte_write. We can thus safely do
+                                * subsequent page lookups as if they were reads.
+                                */
+                               if (ret & VM_FAULT_WRITE)
+                                       write_access = 0;
+                               
+                               switch (ret & ~VM_FAULT_WRITE) {
                                case VM_FAULT_MINOR:
                                        tsk->min_flt++;
                                        break;
@@ -972,14 +988,6 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                                default:
                                        BUG();
                                }
-                               /*
-                                * Now that we have performed a write fault
-                                * and surely no longer have a shared page we
-                                * shouldn't write, we shouldn't ignore an
-                                * unwritable page in the page table if
-                                * we are forcing write access.
-                                */
-                               lookup_write = write && !force;
                                spin_lock(&mm->page_table_lock);
                        }
                        if (pages) {
@@ -1229,6 +1237,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
        struct page *old_page, *new_page;
        unsigned long pfn = pte_pfn(pte);
        pte_t entry;
+       int ret;
 
        if (unlikely(!pfn_valid(pfn))) {
                /*
@@ -1256,7 +1265,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
                        lazy_mmu_prot_update(entry);
                        pte_unmap(page_table);
                        spin_unlock(&mm->page_table_lock);
-                       return VM_FAULT_MINOR;
+                       return VM_FAULT_MINOR|VM_FAULT_WRITE;
                }
        }
        pte_unmap(page_table);
@@ -1283,6 +1292,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
        /*
         * Re-check the pte - we dropped the lock
         */
+       ret = VM_FAULT_MINOR;
        spin_lock(&mm->page_table_lock);
        page_table = pte_offset_map(pmd, address);
        if (likely(pte_same(*page_table, pte))) {
@@ -1299,12 +1309,13 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
 
                /* Free the old page.. */
                new_page = old_page;
+               ret |= VM_FAULT_WRITE;
        }
        pte_unmap(page_table);
        page_cache_release(new_page);
        page_cache_release(old_page);
        spin_unlock(&mm->page_table_lock);
-       return VM_FAULT_MINOR;
+       return ret;
 
 no_new_page:
        page_cache_release(old_page);
@@ -1996,7 +2007,6 @@ static inline int handle_pte_fault(struct mm_struct *mm,
        if (write_access) {
                if (!pte_write(entry))
                        return do_wp_page(mm, vma, address, pte, pmd, entry);
-
                entry = pte_mkdirty(entry);
        }
        entry = pte_mkyoung(entry);
@@ -2011,7 +2021,7 @@ static inline int handle_pte_fault(struct mm_struct *mm,
 /*
  * By the time we get here, we already hold the mm semaphore
  */
-int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma,
+int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma,
                unsigned long address, int write_access)
 {
        pgd_t *pgd;
index 1694845..b4eabab 100644 (file)
@@ -443,7 +443,7 @@ asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask,
        struct mempolicy *new;
        DECLARE_BITMAP(nodes, MAX_NUMNODES);
 
-       if (mode > MPOL_MAX)
+       if (mode < 0 || mode > MPOL_MAX)
                return -EINVAL;
        err = get_nodes(nodes, nmask, maxnode, mode);
        if (err)
index da3fa90..4043194 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -143,7 +143,11 @@ int __vm_enough_memory(long pages, int cap_sys_admin)
           leave 3% of the size of this process for other processes */
        allowed -= current->mm->total_vm / 32;
 
-       if (atomic_read(&vm_committed_space) < allowed)
+       /*
+        * cast `allowed' as a signed long because vm_committed_space
+        * sometimes has a negative value
+        */
+       if (atomic_read(&vm_committed_space) < (long)allowed)
                return 0;
 
        vm_unacct_memory(pages);
index ec7238a..fc45dc9 100644 (file)
@@ -229,6 +229,7 @@ static unsigned long move_vma(struct vm_area_struct *vma,
         * since do_munmap() will decrement it by old_len == new_len
         */
        mm->total_vm += new_len >> PAGE_SHIFT;
+       __vm_stat_account(mm, vma->vm_flags, vma->vm_file, new_len>>PAGE_SHIFT);
 
        if (do_munmap(mm, old_addr, old_len) < 0) {
                /* OOM: unable to split vma, just get accounts right */
@@ -243,7 +244,6 @@ static unsigned long move_vma(struct vm_area_struct *vma,
                        vma->vm_next->vm_flags |= VM_ACCOUNT;
        }
 
-       __vm_stat_account(mm, vma->vm_flags, vma->vm_file, new_len>>PAGE_SHIFT);
        if (vm_flags & VM_LOCKED) {
                mm->locked_vm += new_len >> PAGE_SHIFT;
                if (new_len > old_len)
index ce74452..fd4e8df 100644 (file)
@@ -1167,7 +1167,11 @@ int __vm_enough_memory(long pages, int cap_sys_admin)
           leave 3% of the size of this process for other processes */
        allowed -= current->mm->total_vm / 32;
 
-       if (atomic_read(&vm_committed_space) < allowed)
+       /*
+        * cast `allowed' as a signed long because vm_committed_space
+        * sometimes has a negative value
+        */
+       if (atomic_read(&vm_committed_space) < (long)allowed)
                return 0;
 
        vm_unacct_memory(pages);
index 42bccfb..8d08837 100644 (file)
@@ -1061,20 +1061,19 @@ unsigned int nr_free_pages_pgdat(pg_data_t *pgdat)
 
 static unsigned int nr_free_zone_pages(int offset)
 {
-       pg_data_t *pgdat;
+       /* Just pick one node, since fallback list is circular */
+       pg_data_t *pgdat = NODE_DATA(numa_node_id());
        unsigned int sum = 0;
 
-       for_each_pgdat(pgdat) {
-               struct zonelist *zonelist = pgdat->node_zonelists + offset;
-               struct zone **zonep = zonelist->zones;
-               struct zone *zone;
+       struct zonelist *zonelist = pgdat->node_zonelists + offset;
+       struct zone **zonep = zonelist->zones;
+       struct zone *zone;
 
-               for (zone = *zonep++; zone; zone = *zonep++) {
-                       unsigned long size = zone->present_pages;
-                       unsigned long high = zone->pages_high;
-                       if (size > high)
-                               sum += size - high;
-               }
+       for (zone = *zonep++; zone; zone = *zonep++) {
+               unsigned long size = zone->present_pages;
+               unsigned long high = zone->pages_high;
+               if (size > high)
+                       sum += size - high;
        }
 
        return sum;
index e64fa72..5a81b1e 100644 (file)
@@ -1773,32 +1773,27 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
        return 0;
 }
 
-static int shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd)
+static void *shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd)
 {
        nd_set_link(nd, (char *)SHMEM_I(dentry->d_inode));
-       return 0;
+       return NULL;
 }
 
-static int shmem_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *shmem_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct page *page = NULL;
        int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ, NULL);
        nd_set_link(nd, res ? ERR_PTR(res) : kmap(page));
-       return 0;
+       return page;
 }
 
-static void shmem_put_link(struct dentry *dentry, struct nameidata *nd)
+static void shmem_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
 {
        if (!IS_ERR(nd_get_link(nd))) {
-               struct page *page;
-
-               page = find_get_page(dentry->d_inode->i_mapping, 0);
-               if (!page)
-                       BUG();
+               struct page *page = cookie;
                kunmap(page);
                mark_page_accessed(page);
                page_cache_release(page);
-               page_cache_release(page);
        }
 }
 
index a755e88..1bb7dc1 100644 (file)
@@ -251,10 +251,11 @@ void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh,struct net_device *
        unsigned int hash;
        struct rif_cache *entry;
        unsigned char *olddata;
+       unsigned long flags;
        static const unsigned char mcast_func_addr[] 
                = {0xC0,0x00,0x00,0x04,0x00,0x00};
        
-       spin_lock_bh(&rif_lock);
+       spin_lock_irqsave(&rif_lock, flags);
 
        /*
         *      Broadcasts are single route as stated in RFC 1042 
@@ -323,7 +324,7 @@ printk("source routing for %02X:%02X:%02X:%02X:%02X:%02X\n",trh->daddr[0],
        else 
                slack = 18 - ((ntohs(trh->rcf) & TR_RCF_LEN_MASK)>>8);
        olddata = skb->data;
-       spin_unlock_bh(&rif_lock);
+       spin_unlock_irqrestore(&rif_lock, flags);
 
        skb_pull(skb, slack);
        memmove(skb->data, olddata, sizeof(struct trh_hdr) - slack);
@@ -337,10 +338,11 @@ printk("source routing for %02X:%02X:%02X:%02X:%02X:%02X\n",trh->daddr[0],
 static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev)
 {
        unsigned int hash, rii_p = 0;
+       unsigned long flags;
        struct rif_cache *entry;
 
 
-       spin_lock_bh(&rif_lock);
+       spin_lock_irqsave(&rif_lock, flags);
        
        /*
         *      Firstly see if the entry exists
@@ -378,7 +380,7 @@ printk("adding rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n",
                if(!entry) 
                {
                        printk(KERN_DEBUG "tr.c: Couldn't malloc rif cache entry !\n");
-                       spin_unlock_bh(&rif_lock);
+                       spin_unlock_irqrestore(&rif_lock, flags);
                        return;
                }
 
@@ -420,7 +422,7 @@ printk("updating rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n",
                    }                                         
                entry->last_used=jiffies;               
        }
-       spin_unlock_bh(&rif_lock);
+       spin_unlock_irqrestore(&rif_lock, flags);
 }
 
 /*
@@ -430,9 +432,9 @@ printk("updating rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n",
 static void rif_check_expire(unsigned long dummy) 
 {
        int i;
-       unsigned long next_interval = jiffies + sysctl_tr_rif_timeout/2;
+       unsigned long flags, next_interval = jiffies + sysctl_tr_rif_timeout/2;
 
-       spin_lock_bh(&rif_lock);
+       spin_lock_irqsave(&rif_lock, flags);
        
        for(i =0; i < RIF_TABLE_SIZE; i++) {
                struct rif_cache *entry, **pentry;
@@ -454,7 +456,7 @@ static void rif_check_expire(unsigned long dummy)
                }
        }
        
-       spin_unlock_bh(&rif_lock);
+       spin_unlock_irqrestore(&rif_lock, flags);
 
        mod_timer(&rif_timer, next_interval);
 
@@ -485,7 +487,7 @@ static struct rif_cache *rif_get_idx(loff_t pos)
 
 static void *rif_seq_start(struct seq_file *seq, loff_t *pos)
 {
-       spin_lock_bh(&rif_lock);
+       spin_lock_irq(&rif_lock);
 
        return *pos ? rif_get_idx(*pos - 1) : SEQ_START_TOKEN;
 }
@@ -516,7 +518,7 @@ static void *rif_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 
 static void rif_seq_stop(struct seq_file *seq, void *v)
 {
-       spin_unlock_bh(&rif_lock);
+       spin_unlock_irq(&rif_lock);
 }
 
 static int rif_seq_show(struct seq_file *seq, void *v)
index 707097d..a5c94f1 100644 (file)
@@ -875,12 +875,7 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
        sk->sk_sndbuf   = osk->sk_sndbuf;
        sk->sk_state    = TCP_ESTABLISHED;
        sk->sk_sleep    = osk->sk_sleep;
-
-       if (sock_flag(osk, SOCK_DBG))
-               sock_set_flag(sk, SOCK_DBG);
-
-       if (sock_flag(osk, SOCK_ZAPPED))
-               sock_set_flag(sk, SOCK_ZAPPED);
+       sock_copy_flags(sk, osk);
 
        oax25 = ax25_sk(osk);
 
@@ -1007,7 +1002,8 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        struct sock *sk = sock->sk;
        struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr;
        ax25_dev *ax25_dev = NULL;
-       ax25_address *call;
+       ax25_uid_assoc *user;
+       ax25_address call;
        ax25_cb *ax25;
        int err = 0;
 
@@ -1026,9 +1022,15 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        if (addr->fsa_ax25.sax25_family != AF_AX25)
                return -EINVAL;
 
-       call = ax25_findbyuid(current->euid);
-       if (call == NULL && ax25_uid_policy && !capable(CAP_NET_ADMIN)) {
-               return -EACCES;
+       user = ax25_findbyuid(current->euid);
+       if (user) {
+               call = user->call;
+               ax25_uid_put(user);
+       } else {
+               if (ax25_uid_policy && !capable(CAP_NET_ADMIN))
+                       return -EACCES;
+
+               call = addr->fsa_ax25.sax25_call;
        }
 
        lock_sock(sk);
@@ -1039,10 +1041,7 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                goto out;
        }
 
-       if (call == NULL)
-               ax25->source_addr = addr->fsa_ax25.sax25_call;
-       else
-               ax25->source_addr = *call;
+       ax25->source_addr = call;
 
        /*
         * User already set interface with SO_BINDTODEVICE
index 44b99b1..c288526 100644 (file)
@@ -422,8 +422,8 @@ static inline void ax25_adjust_path(ax25_address *addr, ax25_digi *digipeat)
  */
 int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
 {
+       ax25_uid_assoc *user;
        ax25_route *ax25_rt;
-       ax25_address *call;
        int err;
 
        if ((ax25_rt = ax25_get_route(addr, NULL)) == NULL)
@@ -434,16 +434,18 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
                goto put;
        }
 
-       if ((call = ax25_findbyuid(current->euid)) == NULL) {
+       user = ax25_findbyuid(current->euid);
+       if (user) {
+               ax25->source_addr = user->call;
+               ax25_uid_put(user);
+       } else {
                if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) {
                        err = -EPERM;
                        goto put;
                }
-               call = (ax25_address *)ax25->ax25_dev->dev->dev_addr;
+               ax25->source_addr = *(ax25_address *)ax25->ax25_dev->dev->dev_addr;
        }
 
-       ax25->source_addr = *call;
-
        if (ax25_rt->digipeat != NULL) {
                if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
                        err = -ENOMEM;
index cea6b7d..a8b3822 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
+#include <linux/list.h>
 #include <linux/notifier.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
  *     Callsign/UID mapper. This is in kernel space for security on multi-amateur machines.
  */
 
-static ax25_uid_assoc *ax25_uid_list;
+HLIST_HEAD(ax25_uid_list);
 static DEFINE_RWLOCK(ax25_uid_lock);
 
 int ax25_uid_policy = 0;
 
-ax25_address *ax25_findbyuid(uid_t uid)
+ax25_uid_assoc *ax25_findbyuid(uid_t uid)
 {
-       ax25_uid_assoc *ax25_uid;
-       ax25_address *res = NULL;
+       ax25_uid_assoc *ax25_uid, *res = NULL;
+       struct hlist_node *node;
 
        read_lock(&ax25_uid_lock);
-       for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
+       ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) {
                if (ax25_uid->uid == uid) {
-                       res = &ax25_uid->call;
+                       ax25_uid_hold(ax25_uid);
+                       res = ax25_uid;
                        break;
                }
        }
        read_unlock(&ax25_uid_lock);
 
-       return NULL;
+       return res;
 }
 
 int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
 {
-       ax25_uid_assoc *s, *ax25_uid;
+       ax25_uid_assoc *ax25_uid;
+       struct hlist_node *node;
+       ax25_uid_assoc *user;
        unsigned long res;
 
        switch (cmd) {
        case SIOCAX25GETUID:
                res = -ENOENT;
                read_lock(&ax25_uid_lock);
-               for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
+               ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) {
                        if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) {
                                res = ax25_uid->uid;
                                break;
@@ -85,19 +89,22 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
        case SIOCAX25ADDUID:
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
-               if (ax25_findbyuid(sax->sax25_uid))
+               user = ax25_findbyuid(sax->sax25_uid);
+               if (user) {
+                       ax25_uid_put(user);
                        return -EEXIST;
+               }
                if (sax->sax25_uid == 0)
                        return -EINVAL;
                if ((ax25_uid = kmalloc(sizeof(*ax25_uid), GFP_KERNEL)) == NULL)
                        return -ENOMEM;
 
+               atomic_set(&ax25_uid->refcount, 1);
                ax25_uid->uid  = sax->sax25_uid;
                ax25_uid->call = sax->sax25_call;
 
                write_lock(&ax25_uid_lock);
-               ax25_uid->next = ax25_uid_list;
-               ax25_uid_list  = ax25_uid;
+               hlist_add_head(&ax25_uid->uid_node, &ax25_uid_list);
                write_unlock(&ax25_uid_lock);
 
                return 0;
@@ -106,34 +113,21 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
 
+               ax25_uid = NULL;
                write_lock(&ax25_uid_lock);
-               for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
-                       if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) {
+               ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) {
+                       if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0)
                                break;
-                       }
                }
                if (ax25_uid == NULL) {
                        write_unlock(&ax25_uid_lock);
                        return -ENOENT;
                }
-               if ((s = ax25_uid_list) == ax25_uid) {
-                       ax25_uid_list = s->next;
-                       write_unlock(&ax25_uid_lock);
-                       kfree(ax25_uid);
-                       return 0;
-               }
-               while (s != NULL && s->next != NULL) {
-                       if (s->next == ax25_uid) {
-                               s->next = ax25_uid->next;
-                               write_unlock(&ax25_uid_lock);
-                               kfree(ax25_uid);
-                               return 0;
-                       }
-                       s = s->next;
-               }
+               hlist_del_init(&ax25_uid->uid_node);
+               ax25_uid_put(ax25_uid);
                write_unlock(&ax25_uid_lock);
 
-               return -ENOENT;
+               return 0;
 
        default:
                return -EINVAL;
@@ -147,13 +141,11 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
 static void *ax25_uid_seq_start(struct seq_file *seq, loff_t *pos)
 {
        struct ax25_uid_assoc *pt;
-       int i = 1;
+       struct hlist_node *node;
+       int i = 0;
 
        read_lock(&ax25_uid_lock);
-       if (*pos == 0)
-               return SEQ_START_TOKEN;
-
-       for (pt = ax25_uid_list; pt != NULL; pt = pt->next) {
+       ax25_uid_for_each(pt, node, &ax25_uid_list) {
                if (i == *pos)
                        return pt;
                ++i;
@@ -164,8 +156,9 @@ static void *ax25_uid_seq_start(struct seq_file *seq, loff_t *pos)
 static void *ax25_uid_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
        ++*pos;
-       return (v == SEQ_START_TOKEN) ? ax25_uid_list : 
-               ((struct ax25_uid_assoc *) v)->next;
+
+       return hlist_entry(((ax25_uid_assoc *)v)->uid_node.next,
+                          ax25_uid_assoc, uid_node);
 }
 
 static void ax25_uid_seq_stop(struct seq_file *seq, void *v)
@@ -179,7 +172,6 @@ static int ax25_uid_seq_show(struct seq_file *seq, void *v)
                seq_printf(seq, "Policy: %d\n", ax25_uid_policy);
        else {
                struct ax25_uid_assoc *pt = v;
-               
 
                seq_printf(seq, "%6d %s\n", pt->uid, ax2asc(&pt->call));
        }
@@ -213,16 +205,13 @@ struct file_operations ax25_uid_fops = {
  */
 void __exit ax25_uid_free(void)
 {
-       ax25_uid_assoc *s, *ax25_uid;
+       ax25_uid_assoc *ax25_uid;
+       struct hlist_node *node;
 
        write_lock(&ax25_uid_lock);
-       ax25_uid = ax25_uid_list;
-       while (ax25_uid != NULL) {
-               s        = ax25_uid;
-               ax25_uid = ax25_uid->next;
-
-               kfree(s);
+       ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) {
+               hlist_del_init(&ax25_uid->uid_node);
+               ax25_uid_put(ax25_uid);
        }
-       ax25_uid_list = NULL;
        write_unlock(&ax25_uid_lock);
 }
index fb55243..ffa26c1 100644 (file)
@@ -299,7 +299,6 @@ struct hci_dev *hci_dev_get(int index)
        read_unlock(&hci_dev_list_lock);
        return hdev;
 }
-EXPORT_SYMBOL(hci_dev_get);
 
 /* ---- Inquiry support ---- */
 static void inquiry_cache_flush(struct hci_dev *hdev)
@@ -1042,7 +1041,6 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *p
 
        return 0;
 }
-EXPORT_SYMBOL(hci_send_cmd);
 
 /* Get data from the previously sent command */
 void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 ogf, __u16 ocf)
index c4b592b..46367bd 100644 (file)
@@ -1035,9 +1035,11 @@ void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
        ev->type = type;
        memcpy(ev->data, data, dlen);
 
+       bt_cb(skb)->incoming = 1;
+       do_gettimeofday(&skb->stamp);
+
        skb->pkt_type = HCI_EVENT_PKT;
        skb->dev = (void *) hdev;
        hci_send_to_sock(hdev, skb);
        kfree_skb(skb);
 }
-EXPORT_SYMBOL(hci_si_event);
index 9efb0a0..ee6a669 100644 (file)
 
 #include <net/bluetooth/bluetooth.h>
 
-void bt_dump(char *pref, __u8 *buf, int count)
-{
-       char *ptr;
-       char line[100];
-       unsigned int i;
-
-       printk(KERN_INFO "%s: dump, len %d\n", pref, count);
-
-       ptr = line;
-       *ptr = 0;
-       for (i = 0; i < count; i++) {
-               ptr += sprintf(ptr, " %2.2X", buf[i]);
-
-               if (i && !((i + 1) % 20)) {
-                       printk(KERN_INFO "%s:%s\n", pref, line);
-                       ptr = line;
-                       *ptr = 0;
-               }
-       }
-
-       if (line[0])
-               printk(KERN_INFO "%s:%s\n", pref, line);
-}
-EXPORT_SYMBOL(bt_dump);
-
 void baswap(bdaddr_t *dst, bdaddr_t *src)
 {
        unsigned char *d = (unsigned char *) dst;
index e9e6fda..27bf504 100644 (file)
@@ -389,8 +389,6 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
                rfcomm_dlc_unlock(d);
 
                skb_queue_purge(&d->tx_queue);
-               rfcomm_session_put(s);
-
                rfcomm_dlc_unlink(d);
        }
 
@@ -600,8 +598,6 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst
                goto failed;
        }
 
-       rfcomm_session_hold(s);
-
        s->initiator = 1;
 
        bacpy(&addr.l2_bdaddr, dst);
index be5d936..d99ab96 100644 (file)
@@ -91,20 +91,11 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov,
        } else
                kern_msg->msg_name = NULL;
 
-       if(kern_msg->msg_iovlen > UIO_FASTIOV) {
-               kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
-                                  GFP_KERNEL);
-               if(!kern_iov)
-                       return -ENOMEM;
-       }
-
        tot_len = iov_from_user_compat_to_kern(kern_iov,
                                          (struct compat_iovec __user *)kern_msg->msg_iov,
                                          kern_msg->msg_iovlen);
        if(tot_len >= 0)
                kern_msg->msg_iov = kern_iov;
-       else if(kern_msg->msg_iovlen > UIO_FASTIOV)
-               kfree(kern_iov);
 
        return tot_len;
 }
index 52a3bf7..faf59b0 100644 (file)
@@ -1696,7 +1696,8 @@ static void net_rx_action(struct softirq_action *h)
        struct softnet_data *queue = &__get_cpu_var(softnet_data);
        unsigned long start_time = jiffies;
        int budget = netdev_budget;
-       
+       void *have;
+
        local_irq_disable();
 
        while (!list_empty(&queue->poll_list)) {
@@ -1709,10 +1710,10 @@ static void net_rx_action(struct softirq_action *h)
 
                dev = list_entry(queue->poll_list.next,
                                 struct net_device, poll_list);
-               netpoll_poll_lock(dev);
+               have = netpoll_poll_lock(dev);
 
                if (dev->quota <= 0 || dev->poll(dev, &budget)) {
-                       netpoll_poll_unlock(dev);
+                       netpoll_poll_unlock(have);
                        local_irq_disable();
                        list_del(&dev->poll_list);
                        list_add_tail(&dev->poll_list, &queue->poll_list);
@@ -1721,7 +1722,7 @@ static void net_rx_action(struct softirq_action *h)
                        else
                                dev->quota = dev->weight;
                } else {
-                       netpoll_poll_unlock(dev);
+                       netpoll_poll_unlock(have);
                        dev_put(dev);
                        local_irq_disable();
                }
index fc434ad..334790d 100644 (file)
@@ -45,6 +45,7 @@ static struct timer_list dst_gc_timer =
 static void dst_run_gc(unsigned long dummy)
 {
        int    delayed = 0;
+       int    work_performed;
        struct dst_entry * dst, **dstp;
 
        if (!spin_trylock(&dst_lock)) {
@@ -52,9 +53,9 @@ static void dst_run_gc(unsigned long dummy)
                return;
        }
 
-
        del_timer(&dst_gc_timer);
        dstp = &dst_garbage_list;
+       work_performed = 0;
        while ((dst = *dstp) != NULL) {
                if (atomic_read(&dst->__refcnt)) {
                        dstp = &dst->next;
@@ -62,6 +63,7 @@ static void dst_run_gc(unsigned long dummy)
                        continue;
                }
                *dstp = dst->next;
+               work_performed = 1;
 
                dst = dst_destroy(dst);
                if (dst) {
@@ -86,9 +88,14 @@ static void dst_run_gc(unsigned long dummy)
                dst_gc_timer_inc = DST_GC_MAX;
                goto out;
        }
-       if ((dst_gc_timer_expires += dst_gc_timer_inc) > DST_GC_MAX)
-               dst_gc_timer_expires = DST_GC_MAX;
-       dst_gc_timer_inc += DST_GC_INC;
+       if (!work_performed) {
+               if ((dst_gc_timer_expires += dst_gc_timer_inc) > DST_GC_MAX)
+                       dst_gc_timer_expires = DST_GC_MAX;
+               dst_gc_timer_inc += DST_GC_INC;
+       } else {
+               dst_gc_timer_inc = DST_GC_INC;
+               dst_gc_timer_expires = DST_GC_MIN;
+       }
        dst_gc_timer.expires = jiffies + dst_gc_timer_expires;
 #if RT_CACHE_DEBUG >= 2
        printk("dst_total: %d/%d %ld\n",
index c327c9e..a1a9a7a 100644 (file)
@@ -33,6 +33,7 @@
 #define MAX_UDP_CHUNK 1460
 #define MAX_SKBS 32
 #define MAX_QUEUE_DEPTH (MAX_SKBS / 2)
+#define MAX_RETRIES 20000
 
 static DEFINE_SPINLOCK(skb_list_lock);
 static int nr_skbs;
@@ -248,14 +249,14 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
        int status;
        struct netpoll_info *npinfo;
 
-repeat:
-       if(!np || !np->dev || !netif_running(np->dev)) {
+       if (!np || !np->dev || !netif_running(np->dev)) {
                __kfree_skb(skb);
                return;
        }
 
-       /* avoid recursion */
        npinfo = np->dev->npinfo;
+
+       /* avoid recursion */
        if (npinfo->poll_owner == smp_processor_id() ||
            np->dev->xmit_lock_owner == smp_processor_id()) {
                if (np->drop)
@@ -265,30 +266,37 @@ repeat:
                return;
        }
 
-       spin_lock(&np->dev->xmit_lock);
-       np->dev->xmit_lock_owner = smp_processor_id();
+       do {
+               npinfo->tries--;
+               spin_lock(&np->dev->xmit_lock);
+               np->dev->xmit_lock_owner = smp_processor_id();
 
-       /*
-        * network drivers do not expect to be called if the queue is
-        * stopped.
-        */
-       if (netif_queue_stopped(np->dev)) {
+               /*
+                * network drivers do not expect to be called if the queue is
+                * stopped.
+                */
+               if (netif_queue_stopped(np->dev)) {
+                       np->dev->xmit_lock_owner = -1;
+                       spin_unlock(&np->dev->xmit_lock);
+                       netpoll_poll(np);
+                       udelay(50);
+                       continue;
+               }
+
+               status = np->dev->hard_start_xmit(skb, np->dev);
                np->dev->xmit_lock_owner = -1;
                spin_unlock(&np->dev->xmit_lock);
 
-               netpoll_poll(np);
-               goto repeat;
-       }
-
-       status = np->dev->hard_start_xmit(skb, np->dev);
-       np->dev->xmit_lock_owner = -1;
-       spin_unlock(&np->dev->xmit_lock);
+               /* success */
+               if(!status) {
+                       npinfo->tries = MAX_RETRIES; /* reset */
+                       return;
+               }
 
-       /* transmit busy */
-       if(status) {
+               /* transmit busy */
                netpoll_poll(np);
-               goto repeat;
-       }
+               udelay(50);
+       } while (npinfo->tries > 0);
 }
 
 void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
@@ -349,15 +357,11 @@ static void arp_reply(struct sk_buff *skb)
        unsigned char *arp_ptr;
        int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
        u32 sip, tip;
-       unsigned long flags;
        struct sk_buff *send_skb;
        struct netpoll *np = NULL;
 
-       spin_lock_irqsave(&npinfo->rx_lock, flags);
        if (npinfo->rx_np && npinfo->rx_np->dev == skb->dev)
                np = npinfo->rx_np;
-       spin_unlock_irqrestore(&npinfo->rx_lock, flags);
-
        if (!np)
                return;
 
@@ -639,9 +643,11 @@ int netpoll_setup(struct netpoll *np)
                if (!npinfo)
                        goto release;
 
+               npinfo->rx_flags = 0;
                npinfo->rx_np = NULL;
                npinfo->poll_lock = SPIN_LOCK_UNLOCKED;
                npinfo->poll_owner = -1;
+               npinfo->tries = MAX_RETRIES;
                npinfo->rx_lock = SPIN_LOCK_UNLOCKED;
        } else
                npinfo = ndev->npinfo;
@@ -718,9 +724,16 @@ int netpoll_setup(struct netpoll *np)
                npinfo->rx_np = np;
                spin_unlock_irqrestore(&npinfo->rx_lock, flags);
        }
+
+       /* fill up the skb queue */
+       refill_skbs();
+
        /* last thing to do is link it to the net device structure */
        ndev->npinfo = npinfo;
 
+       /* avoid racing with NAPI reading npinfo */
+       synchronize_rcu();
+
        return 0;
 
  release:
index 96a0280..acdd18e 100644 (file)
@@ -1876,15 +1876,6 @@ static inline unsigned int dn_current_mss(struct sock *sk, int flags)
        return mss_now;
 }
 
-static int dn_error(struct sock *sk, int flags, int err)
-{
-       if (err == -EPIPE)
-               err = sock_error(sk) ? : -EPIPE;
-       if (err == -EPIPE && !(flags & MSG_NOSIGNAL))
-               send_sig(SIGPIPE, current, 0);
-       return err;
-}
-
 static int dn_sendmsg(struct kiocb *iocb, struct socket *sock,
           struct msghdr *msg, size_t size)
 {
@@ -2045,7 +2036,7 @@ out:
        return sent ? sent : err;
 
 out_err:
-       err = dn_error(sk, flags, err);
+       err = sk_stream_error(sk, flags, err);
        release_sock(sk);
        return err;
 }
index f32dba9..8d0cc3c 100644 (file)
@@ -148,12 +148,12 @@ static int dn_neigh_construct(struct neighbour *neigh)
 
        __neigh_parms_put(neigh->parms);
        neigh->parms = neigh_parms_clone(parms);
-       rcu_read_unlock();
 
        if (dn_db->use_long)
                neigh->ops = &dn_long_ops;
        else
                neigh->ops = &dn_short_ops;
+       rcu_read_unlock();
 
        if (dn->flags & DN_NDFLAG_P3)
                neigh->ops = &dn_phase3_ops;
index c886b28..e278cb9 100644 (file)
@@ -593,10 +593,13 @@ static void fib_hash_move(struct hlist_head *new_info_hash,
                          struct hlist_head *new_laddrhash,
                          unsigned int new_size)
 {
+       struct hlist_head *old_info_hash, *old_laddrhash;
        unsigned int old_size = fib_hash_size;
-       unsigned int i;
+       unsigned int i, bytes;
 
        write_lock(&fib_info_lock);
+       old_info_hash = fib_info_hash;
+       old_laddrhash = fib_info_laddrhash;
        fib_hash_size = new_size;
 
        for (i = 0; i < old_size; i++) {
@@ -636,6 +639,10 @@ static void fib_hash_move(struct hlist_head *new_info_hash,
        fib_info_laddrhash = new_laddrhash;
 
        write_unlock(&fib_info_lock);
+
+       bytes = old_size * sizeof(struct hlist_head *);
+       fib_hash_free(old_info_hash, bytes);
+       fib_hash_free(old_laddrhash, bytes);
 }
 
 struct fib_info *
index a701405..45efd5f 100644 (file)
@@ -1333,9 +1333,9 @@ err:;
 }
 
 static inline int check_leaf(struct trie *t, struct leaf *l,  t_key key, int *plen, const struct flowi *flp,
-                            struct fib_result *res, int *err)
+                            struct fib_result *res)
 {
-       int i;
+       int err, i;
        t_key mask;
        struct leaf_info *li;
        struct hlist_head *hhead = &l->list;
@@ -1348,18 +1348,18 @@ static inline int check_leaf(struct trie *t, struct leaf *l,  t_key key, int *pl
                if (l->key != (key & mask))
                        continue;
 
-               if (((*err) = fib_semantic_match(&li->falh, flp, res, l->key, mask, i)) == 0) {
+               if ((err = fib_semantic_match(&li->falh, flp, res, l->key, mask, i)) <= 0) {
                        *plen = i;
 #ifdef CONFIG_IP_FIB_TRIE_STATS
                        t->stats.semantic_match_passed++;
 #endif
-                       return 1;
+                       return err;
                }
 #ifdef CONFIG_IP_FIB_TRIE_STATS
                t->stats.semantic_match_miss++;
 #endif
        }
-       return 0;
+       return 1;
 }
 
 static int
@@ -1386,7 +1386,7 @@ fn_trie_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result
 
        /* Just a leaf? */
        if (IS_LEAF(n)) {
-               if (check_leaf(t, (struct leaf *)n, key, &plen, flp, res, &ret))
+               if ((ret = check_leaf(t, (struct leaf *)n, key, &plen, flp, res)) <= 0)
                        goto found;
                goto failed;
        }
@@ -1508,7 +1508,7 @@ fn_trie_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result
                       continue;
                }
                if (IS_LEAF(n)) {
-                       if (check_leaf(t, (struct leaf *)n, key, &plen, flp, res, &ret))
+                       if ((ret = check_leaf(t, (struct leaf *)n, key, &plen, flp, res)) <= 0)
                                goto found;
               }
 backtrace:
index 279f57a..badfc58 100644 (file)
@@ -349,12 +349,12 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
 {
        struct sk_buff *skb;
 
-       ip_append_data(icmp_socket->sk, icmp_glue_bits, icmp_param,
-                      icmp_param->data_len+icmp_param->head_len,
-                      icmp_param->head_len,
-                      ipc, rt, MSG_DONTWAIT);
-
-       if ((skb = skb_peek(&icmp_socket->sk->sk_write_queue)) != NULL) {
+       if (ip_append_data(icmp_socket->sk, icmp_glue_bits, icmp_param,
+                          icmp_param->data_len+icmp_param->head_len,
+                          icmp_param->head_len,
+                          ipc, rt, MSG_DONTWAIT) < 0)
+               ip_flush_pending_frames(icmp_socket->sk);
+       else if ((skb = skb_peek(&icmp_socket->sk->sk_write_queue)) != NULL) {
                struct icmphdr *icmph = skb->h.icmph;
                unsigned int csum = 0;
                struct sk_buff *skb1;
@@ -936,8 +936,7 @@ int icmp_rcv(struct sk_buff *skb)
        case CHECKSUM_HW:
                if (!(u16)csum_fold(skb->csum))
                        break;
-               NETDEBUG(if (net_ratelimit())
-                               printk(KERN_DEBUG "icmp v4 hw csum failure\n"));
+               LIMIT_NETDEBUG(printk(KERN_DEBUG "icmp v4 hw csum failure\n"));
        case CHECKSUM_NONE:
                if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0)))
                        goto error;
index 9547395..ab18a85 100644 (file)
@@ -450,10 +450,13 @@ static void peer_check_expire(unsigned long dummy)
        /* Trigger the timer after inet_peer_gc_mintime .. inet_peer_gc_maxtime
         * interval depending on the total number of entries (more entries,
         * less interval). */
-       peer_periodic_timer.expires = jiffies
-               + inet_peer_gc_maxtime
-               - (inet_peer_gc_maxtime - inet_peer_gc_mintime) / HZ *
-                       peer_total / inet_peer_threshold * HZ;
+       if (peer_total >= inet_peer_threshold)
+               peer_periodic_timer.expires = jiffies + inet_peer_gc_mintime;
+       else
+               peer_periodic_timer.expires = jiffies
+                       + inet_peer_gc_maxtime
+                       - (inet_peer_gc_maxtime - inet_peer_gc_mintime) / HZ *
+                               peer_total / inet_peer_threshold * HZ;
        add_timer(&peer_periodic_timer);
 }
 
index 7f68e27..eb377ae 100644 (file)
@@ -377,7 +377,7 @@ static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)
        return ip_frag_intern(hash, qp);
 
 out_nomem:
-       NETDEBUG(if (net_ratelimit()) printk(KERN_ERR "ip_frag_create: no memory left !\n"));
+       LIMIT_NETDEBUG(printk(KERN_ERR "ip_frag_create: no memory left !\n"));
        return NULL;
 }
 
@@ -625,10 +625,8 @@ static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev)
        return head;
 
 out_nomem:
-       NETDEBUG(if (net_ratelimit())
-                printk(KERN_ERR 
-                       "IP: queue_glue: no memory for gluing queue %p\n",
-                       qp));
+       LIMIT_NETDEBUG(printk(KERN_ERR "IP: queue_glue: no memory for gluing "
+                             "queue %p\n", qp));
        goto out_fail;
 out_oversize:
        if (net_ratelimit())
index 8848355..f0d5740 100644 (file)
@@ -290,7 +290,6 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int
 
        dev_hold(dev);
        ipgre_tunnel_link(nt);
-       /* Do not decrement MOD_USE_COUNT here. */
        return nt;
 
 failed:
@@ -1277,12 +1276,28 @@ err1:
        goto out;
 }
 
-static void ipgre_fini(void)
+static void __exit ipgre_destroy_tunnels(void)
+{
+       int prio;
+
+       for (prio = 0; prio < 4; prio++) {
+               int h;
+               for (h = 0; h < HASH_SIZE; h++) {
+                       struct ip_tunnel *t;
+                       while ((t = tunnels[prio][h]) != NULL)
+                               unregister_netdevice(t->dev);
+               }
+       }
+}
+
+static void __exit ipgre_fini(void)
 {
        if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
                printk(KERN_INFO "ipgre close: can't remove protocol\n");
 
-       unregister_netdev(ipgre_fb_tunnel_dev);
+       rtnl_lock();
+       ipgre_destroy_tunnels();
+       rtnl_unlock();
 }
 
 module_init(ipgre_init);
index fc7c481..ff4bd06 100644 (file)
@@ -848,6 +848,9 @@ mc_msf_out:
  
                case IP_IPSEC_POLICY:
                case IP_XFRM_POLICY:
+                       err = -EPERM;
+                       if (!capable(CAP_NET_ADMIN))
+                               break;
                        err = xfrm_user_policy(sk, optname, optval, optlen);
                        break;
 
index 2065944..7ded6e6 100644 (file)
@@ -358,7 +358,7 @@ static struct crypto_tfm **ipcomp_alloc_tfms(const char *alg_name)
        int cpu;
 
        /* This can be any valid CPU ID so we don't need locking. */
-       cpu = smp_processor_id();
+       cpu = raw_smp_processor_id();
 
        list_for_each_entry(pos, &ipcomp_tfms_list, list) {
                struct crypto_tfm *tfm;
index c3947cd..c05c1df 100644 (file)
@@ -255,7 +255,6 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c
 
        dev_hold(dev);
        ipip_tunnel_link(nt);
-       /* Do not decrement MOD_USE_COUNT here. */
        return nt;
 
 failed:
@@ -920,12 +919,29 @@ static int __init ipip_init(void)
        goto out;
 }
 
+static void __exit ipip_destroy_tunnels(void)
+{
+       int prio;
+
+       for (prio = 1; prio < 4; prio++) {
+               int h;
+               for (h = 0; h < HASH_SIZE; h++) {
+                       struct ip_tunnel *t;
+                       while ((t = tunnels[prio][h]) != NULL)
+                               unregister_netdevice(t->dev);
+               }
+       }
+}
+
 static void __exit ipip_fini(void)
 {
        if (ipip_unregister() < 0)
                printk(KERN_INFO "ipip close: can't deregister tunnel\n");
 
-       unregister_netdev(ipip_fb_tunnel_dev);
+       rtnl_lock();
+       ipip_destroy_tunnels();
+       unregister_netdevice(ipip_fb_tunnel_dev);
+       rtnl_unlock();
 }
 
 module_init(ipip_init);
index 7833d92..dc806b5 100644 (file)
@@ -362,7 +362,7 @@ out:
 
 /* Fill oifs list. It is called under write locked mrt_lock. */
 
-static void ipmr_update_threshoulds(struct mfc_cache *cache, unsigned char *ttls)
+static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls)
 {
        int vifi;
 
@@ -727,7 +727,7 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock)
        if (c != NULL) {
                write_lock_bh(&mrt_lock);
                c->mfc_parent = mfc->mfcc_parent;
-               ipmr_update_threshoulds(c, mfc->mfcc_ttls);
+               ipmr_update_thresholds(c, mfc->mfcc_ttls);
                if (!mrtsock)
                        c->mfc_flags |= MFC_STATIC;
                write_unlock_bh(&mrt_lock);
@@ -744,7 +744,7 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock)
        c->mfc_origin=mfc->mfcc_origin.s_addr;
        c->mfc_mcastgrp=mfc->mfcc_mcastgrp.s_addr;
        c->mfc_parent=mfc->mfcc_parent;
-       ipmr_update_threshoulds(c, mfc->mfcc_ttls);
+       ipmr_update_thresholds(c, mfc->mfcc_ttls);
        if (!mrtsock)
                c->mfc_flags |= MFC_STATIC;
 
index 86f04e4..a7f0c82 100644 (file)
@@ -512,6 +512,11 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
                conntrack->master = exp->master;
 #ifdef CONFIG_IP_NF_CONNTRACK_MARK
                conntrack->mark = exp->master->mark;
+#endif
+#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
+    defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
+               /* this is ugly, but there is no other place where to put it */
+               conntrack->nat.masq_index = exp->master->nat.masq_index;
 #endif
                nf_conntrack_get(&conntrack->master->ct_general);
                CONNTRACK_STAT_INC(expect_new);
index bc59d0d..91d5ea1 100644 (file)
@@ -102,6 +102,10 @@ ip_nat_fn(unsigned int hooknum,
                return NF_ACCEPT;
        }
 
+       /* Don't try to NAT if this packet is not conntracked */
+       if (ct == &ip_conntrack_untracked)
+               return NF_ACCEPT;
+
        switch (ctinfo) {
        case IP_CT_RELATED:
        case IP_CT_RELATED+IP_CT_IS_REPLY:
index eda1fba..c6baa81 100644 (file)
@@ -214,6 +214,12 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
                break;
        
        case IPQ_COPY_PACKET:
+               if (entry->skb->ip_summed == CHECKSUM_HW &&
+                   (*errp = skb_checksum_help(entry->skb,
+                                              entry->info->outdev == NULL))) {
+                       read_unlock_bh(&queue_lock);
+                       return NULL;
+               }
                if (copy_range == 0 || copy_range > entry->skb->len)
                        data_len = entry->skb->len;
                else
@@ -385,6 +391,7 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
        if (!skb_ip_make_writable(&e->skb, v->data_len))
                return -ENOMEM;
        memcpy(e->skb->data, v->payload, v->data_len);
+       e->skb->ip_summed = CHECKSUM_NONE;
        e->skb->nfcache |= NFC_ALTERED;
 
        /*
index ada9911..94a0ce1 100644 (file)
@@ -61,16 +61,20 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo, int inward)
        if (!tcph)
                return 0;
 
-       if (!(einfo->operation & IPT_ECN_OP_SET_ECE
-             || tcph->ece == einfo->proto.tcp.ece)
-           && (!(einfo->operation & IPT_ECN_OP_SET_CWR
-                 || tcph->cwr == einfo->proto.tcp.cwr)))
+       if ((!(einfo->operation & IPT_ECN_OP_SET_ECE) ||
+            tcph->ece == einfo->proto.tcp.ece) &&
+           ((!(einfo->operation & IPT_ECN_OP_SET_CWR) ||
+            tcph->cwr == einfo->proto.tcp.cwr)))
                return 1;
 
        if (!skb_ip_make_writable(pskb, (*pskb)->nh.iph->ihl*4+sizeof(*tcph)))
                return 0;
        tcph = (void *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl*4;
 
+       if ((*pskb)->ip_summed == CHECKSUM_HW &&
+           skb_checksum_help(*pskb, inward))
+               return 0;
+
        diffs[0] = ((u_int16_t *)tcph)[6];
        if (einfo->operation & IPT_ECN_OP_SET_ECE)
                tcph->ece = einfo->proto.tcp.ece;
@@ -79,13 +83,10 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo, int inward)
        diffs[1] = ((u_int16_t *)tcph)[6];
        diffs[0] = diffs[0] ^ 0xFFFF;
 
-       if ((*pskb)->ip_summed != CHECKSUM_HW)
+       if ((*pskb)->ip_summed != CHECKSUM_UNNECESSARY)
                tcph->check = csum_fold(csum_partial((char *)diffs,
                                                     sizeof(diffs),
                                                     tcph->check^0xFFFF));
-       else
-               if (skb_checksum_help(*pskb, inward))
-                       return 0;
        (*pskb)->nfcache |= NFC_ALTERED;
        return 1;
 }
index 1049050..7b84a25 100644 (file)
@@ -61,6 +61,10 @@ ipt_tcpmss_target(struct sk_buff **pskb,
        if (!skb_ip_make_writable(pskb, (*pskb)->len))
                return NF_DROP;
 
+       if ((*pskb)->ip_summed == CHECKSUM_HW &&
+           skb_checksum_help(*pskb, out == NULL))
+               return NF_DROP;
+
        iph = (*pskb)->nh.iph;
        tcplen = (*pskb)->len - iph->ihl*4;
 
@@ -186,9 +190,6 @@ ipt_tcpmss_target(struct sk_buff **pskb,
               newmss);
 
  retmodified:
-       /* We never hw checksum SYN packets.  */
-       BUG_ON((*pskb)->ip_summed == CHECKSUM_HW);
-
        (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED;
        return IPT_CONTINUE;
 }
index ddb6ce4..69b1fcf 100644 (file)
@@ -584,7 +584,7 @@ static inline void skb_entail(struct sock *sk, struct tcp_sock *tp,
        sk_charge_skb(sk, skb);
        if (!sk->sk_send_head)
                sk->sk_send_head = skb;
-       else if (tp->nonagle&TCP_NAGLE_PUSH)
+       if (tp->nonagle & TCP_NAGLE_PUSH)
                tp->nonagle &= ~TCP_NAGLE_PUSH; 
 }
 
index 62f62bb..67c6708 100644 (file)
@@ -242,9 +242,14 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
                tcp_port_rover = rover;
                spin_unlock(&tcp_portalloc_lock);
 
-               /* Exhausted local port range during search? */
+               /* Exhausted local port range during search?  It is not
+                * possible for us to be holding one of the bind hash
+                * locks if this test triggers, because if 'remaining'
+                * drops to zero, we broke out of the do/while loop at
+                * the top level, not from the 'break;' statement.
+                */
                ret = 1;
-               if (remaining <= 0)
+               if (unlikely(remaining <= 0))
                        goto fail;
 
                /* OK, here is the one we will use.  HEAD is
@@ -1494,12 +1499,11 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
                         * to destinations, already remembered
                         * to the moment of synflood.
                         */
-                       NETDEBUG(if (net_ratelimit()) \
-                                       printk(KERN_DEBUG "TCP: drop open "
-                                                         "request from %u.%u."
-                                                         "%u.%u/%u\n", \
-                                              NIPQUAD(saddr),
-                                              ntohs(skb->h.th->source)));
+                       LIMIT_NETDEBUG(printk(KERN_DEBUG "TCP: drop open "
+                                             "request from %u.%u."
+                                             "%u.%u/%u\n",
+                                             NIPQUAD(saddr),
+                                             ntohs(skb->h.th->source)));
                        dst_release(dst);
                        goto drop_and_free;
                }
@@ -1627,8 +1631,7 @@ static int tcp_v4_checksum_init(struct sk_buff *skb)
                                  skb->nh.iph->daddr, skb->csum))
                        return 0;
 
-               NETDEBUG(if (net_ratelimit())
-                               printk(KERN_DEBUG "hw tcp v4 csum failed\n"));
+               LIMIT_NETDEBUG(printk(KERN_DEBUG "hw tcp v4 csum failed\n"));
                skb->ip_summed = CHECKSUM_NONE;
        }
        if (skb->len <= 76) {
index e3f8ea1..dd30dd1 100644 (file)
@@ -403,11 +403,9 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb)
                sk->sk_send_head = skb;
 }
 
-static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb)
+static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned int mss_now)
 {
-       struct tcp_sock *tp = tcp_sk(sk);
-
-       if (skb->len <= tp->mss_cache ||
+       if (skb->len <= mss_now ||
            !(sk->sk_route_caps & NETIF_F_TSO)) {
                /* Avoid the costly divide in the normal
                 * non-TSO case.
@@ -417,10 +415,10 @@ static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb)
        } else {
                unsigned int factor;
 
-               factor = skb->len + (tp->mss_cache - 1);
-               factor /= tp->mss_cache;
+               factor = skb->len + (mss_now - 1);
+               factor /= mss_now;
                skb_shinfo(skb)->tso_segs = factor;
-               skb_shinfo(skb)->tso_size = tp->mss_cache;
+               skb_shinfo(skb)->tso_size = mss_now;
        }
 }
 
@@ -429,7 +427,7 @@ static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb)
  * packet to the list.  This won't be called frequently, I hope. 
  * Remember, these are still headerless SKBs at this point.
  */
-static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len)
+static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss_now)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        struct sk_buff *buff;
@@ -492,8 +490,8 @@ static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len)
        }
 
        /* Fix up tso_factor for both original and new SKB.  */
-       tcp_set_skb_tso_segs(sk, skb);
-       tcp_set_skb_tso_segs(sk, buff);
+       tcp_set_skb_tso_segs(sk, skb, mss_now);
+       tcp_set_skb_tso_segs(sk, buff, mss_now);
 
        if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
                tp->lost_out += tcp_skb_pcount(skb);
@@ -569,7 +567,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
         * factor and mss.
         */
        if (tcp_skb_pcount(skb) > 1)
-               tcp_set_skb_tso_segs(sk, skb);
+               tcp_set_skb_tso_segs(sk, skb, tcp_current_mss(sk, 1));
 
        return 0;
 }
@@ -734,12 +732,14 @@ static inline unsigned int tcp_cwnd_test(struct tcp_sock *tp, struct sk_buff *sk
 /* This must be invoked the first time we consider transmitting
  * SKB onto the wire.
  */
-static inline int tcp_init_tso_segs(struct sock *sk, struct sk_buff *skb)
+static inline int tcp_init_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned int mss_now)
 {
        int tso_segs = tcp_skb_pcount(skb);
 
-       if (!tso_segs) {
-               tcp_set_skb_tso_segs(sk, skb);
+       if (!tso_segs ||
+           (tso_segs > 1 &&
+            skb_shinfo(skb)->tso_size != mss_now)) {
+               tcp_set_skb_tso_segs(sk, skb, mss_now);
                tso_segs = tcp_skb_pcount(skb);
        }
        return tso_segs;
@@ -817,7 +817,7 @@ static unsigned int tcp_snd_test(struct sock *sk, struct sk_buff *skb,
        struct tcp_sock *tp = tcp_sk(sk);
        unsigned int cwnd_quota;
 
-       tcp_init_tso_segs(sk, skb);
+       tcp_init_tso_segs(sk, skb, cur_mss);
 
        if (!tcp_nagle_test(tp, skb, cur_mss, nonagle))
                return 0;
@@ -854,14 +854,15 @@ int tcp_may_send_now(struct sock *sk, struct tcp_sock *tp)
  * know that all the data is in scatter-gather pages, and that the
  * packet has never been sent out before (and thus is not cloned).
  */
-static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len)
+static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len, unsigned int mss_now)
 {
        struct sk_buff *buff;
        int nlen = skb->len - len;
        u16 flags;
 
        /* All of a TSO frame must be composed of paged data.  */
-       BUG_ON(skb->len != skb->data_len);
+       if (skb->len != skb->data_len)
+               return tcp_fragment(sk, skb, len, mss_now);
 
        buff = sk_stream_alloc_pskb(sk, 0, 0, GFP_ATOMIC);
        if (unlikely(buff == NULL))
@@ -887,8 +888,8 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len)
        skb_split(skb, buff, len);
 
        /* Fix up tso_factor for both original and new SKB.  */
-       tcp_set_skb_tso_segs(sk, skb);
-       tcp_set_skb_tso_segs(sk, buff);
+       tcp_set_skb_tso_segs(sk, skb, mss_now);
+       tcp_set_skb_tso_segs(sk, buff, mss_now);
 
        /* Link BUFF into the send queue. */
        skb_header_release(buff);
@@ -924,10 +925,6 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
 
        limit = min(send_win, cong_win);
 
-       /* If sk_send_head can be sent fully now, just do it.  */
-       if (skb->len <= limit)
-               return 0;
-
        if (sysctl_tcp_tso_win_divisor) {
                u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache);
 
@@ -972,19 +969,20 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle)
        if (unlikely(sk->sk_state == TCP_CLOSE))
                return 0;
 
-       skb = sk->sk_send_head;
-       if (unlikely(!skb))
-               return 0;
-
-       tso_segs = tcp_init_tso_segs(sk, skb);
-       cwnd_quota = tcp_cwnd_test(tp, skb);
-       if (unlikely(!cwnd_quota))
-               goto out;
-
        sent_pkts = 0;
-       while (likely(tcp_snd_wnd_test(tp, skb, mss_now))) {
+       while ((skb = sk->sk_send_head)) {
+               unsigned int limit;
+
+               tso_segs = tcp_init_tso_segs(sk, skb, mss_now);
                BUG_ON(!tso_segs);
 
+               cwnd_quota = tcp_cwnd_test(tp, skb);
+               if (!cwnd_quota)
+                       break;
+
+               if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now)))
+                       break;
+
                if (tso_segs == 1) {
                        if (unlikely(!tcp_nagle_test(tp, skb, mss_now,
                                                     (tcp_skb_is_last(sk, skb) ?
@@ -995,9 +993,10 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle)
                                break;
                }
 
+               limit = mss_now;
                if (tso_segs > 1) {
-                       u32 limit = tcp_window_allows(tp, skb,
-                                                     mss_now, cwnd_quota);
+                       limit = tcp_window_allows(tp, skb,
+                                                 mss_now, cwnd_quota);
 
                        if (skb->len < limit) {
                                unsigned int trim = skb->len % mss_now;
@@ -1005,15 +1004,12 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle)
                                if (trim)
                                        limit = skb->len - trim;
                        }
-                       if (skb->len > limit) {
-                               if (tso_fragment(sk, skb, limit))
-                                       break;
-                       }
-               } else if (unlikely(skb->len > mss_now)) {
-                       if (unlikely(tcp_fragment(sk, skb,  mss_now)))
-                               break;
                }
 
+               if (skb->len > limit &&
+                   unlikely(tso_fragment(sk, skb, limit, mss_now)))
+                       break;
+
                TCP_SKB_CB(skb)->when = tcp_time_stamp;
 
                if (unlikely(tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC))))
@@ -1026,27 +1022,12 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle)
 
                tcp_minshall_update(tp, mss_now, skb);
                sent_pkts++;
-
-               /* Do not optimize this to use tso_segs. If we chopped up
-                * the packet above, tso_segs will no longer be valid.
-                */
-               cwnd_quota -= tcp_skb_pcount(skb);
-
-               BUG_ON(cwnd_quota < 0);
-               if (!cwnd_quota)
-                       break;
-
-               skb = sk->sk_send_head;
-               if (!skb)
-                       break;
-               tso_segs = tcp_init_tso_segs(sk, skb);
        }
 
        if (likely(sent_pkts)) {
                tcp_cwnd_validate(sk, tp);
                return 0;
        }
-out:
        return !tp->packets_out && sk->sk_send_head;
 }
 
@@ -1076,15 +1057,18 @@ void tcp_push_one(struct sock *sk, unsigned int mss_now)
 
        BUG_ON(!skb || skb->len < mss_now);
 
-       tso_segs = tcp_init_tso_segs(sk, skb);
+       tso_segs = tcp_init_tso_segs(sk, skb, mss_now);
        cwnd_quota = tcp_snd_test(sk, skb, mss_now, TCP_NAGLE_PUSH);
 
        if (likely(cwnd_quota)) {
+               unsigned int limit;
+
                BUG_ON(!tso_segs);
 
+               limit = mss_now;
                if (tso_segs > 1) {
-                       u32 limit = tcp_window_allows(tp, skb,
-                                                     mss_now, cwnd_quota);
+                       limit = tcp_window_allows(tp, skb,
+                                                 mss_now, cwnd_quota);
 
                        if (skb->len < limit) {
                                unsigned int trim = skb->len % mss_now;
@@ -1092,15 +1076,12 @@ void tcp_push_one(struct sock *sk, unsigned int mss_now)
                                if (trim)
                                        limit = skb->len - trim;
                        }
-                       if (skb->len > limit) {
-                               if (unlikely(tso_fragment(sk, skb, limit)))
-                                       return;
-                       }
-               } else if (unlikely(skb->len > mss_now)) {
-                       if (unlikely(tcp_fragment(sk, skb, mss_now)))
-                               return;
                }
 
+               if (skb->len > limit &&
+                   unlikely(tso_fragment(sk, skb, limit, mss_now)))
+                       return;
+
                /* Send it out now. */
                TCP_SKB_CB(skb)->when = tcp_time_stamp;
 
@@ -1386,15 +1367,21 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
 
        if (skb->len > cur_mss) {
                int old_factor = tcp_skb_pcount(skb);
-               int new_factor;
+               int diff;
 
-               if (tcp_fragment(sk, skb, cur_mss))
+               if (tcp_fragment(sk, skb, cur_mss, cur_mss))
                        return -ENOMEM; /* We'll try again later. */
 
                /* New SKB created, account for it. */
-               new_factor = tcp_skb_pcount(skb);
-               tp->packets_out -= old_factor - new_factor;
-               tp->packets_out += tcp_skb_pcount(skb->next);
+               diff = old_factor - tcp_skb_pcount(skb) -
+                      tcp_skb_pcount(skb->next);
+               tp->packets_out -= diff;
+
+               if (diff > 0) {
+                       tp->fackets_out -= diff;
+                       if ((int)tp->fackets_out < 0)
+                               tp->fackets_out = 0;
+               }
        }
 
        /* Collapse two adjacent packets if worthwhile and we can. */
@@ -1991,7 +1978,7 @@ int tcp_write_wakeup(struct sock *sk)
                            skb->len > mss) {
                                seg_size = min(seg_size, mss);
                                TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
-                               if (tcp_fragment(sk, skb, seg_size))
+                               if (tcp_fragment(sk, skb, seg_size, mss))
                                        return -1;
                                /* SWS override triggered forced fragmentation.
                                 * Disable TSO, the connection is too sick. */
@@ -2000,7 +1987,7 @@ int tcp_write_wakeup(struct sock *sk)
                                        sk->sk_route_caps &= ~NETIF_F_TSO;
                                }
                        } else if (!tcp_skb_pcount(skb))
-                               tcp_set_skb_tso_segs(sk, skb);
+                               tcp_set_skb_tso_segs(sk, skb, mss);
 
                        TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
                        TCP_SKB_CB(skb)->when = tcp_time_stamp;
index 7c24e64..dc4d073 100644 (file)
@@ -628,7 +628,7 @@ back_from_confirm:
                /* ... which is an evident application bug. --ANK */
                release_sock(sk);
 
-               NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "udp cork app bug 2\n"));
+               LIMIT_NETDEBUG(printk(KERN_DEBUG "udp cork app bug 2\n"));
                err = -EINVAL;
                goto out;
        }
@@ -693,7 +693,7 @@ static int udp_sendpage(struct sock *sk, struct page *page, int offset,
        if (unlikely(!up->pending)) {
                release_sock(sk);
 
-               NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "udp cork app bug 3\n"));
+               LIMIT_NETDEBUG(printk(KERN_DEBUG "udp cork app bug 3\n"));
                return -EINVAL;
        }
 
@@ -1102,7 +1102,7 @@ static int udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
                skb->ip_summed = CHECKSUM_UNNECESSARY;
                if (!udp_check(uh, ulen, saddr, daddr, skb->csum))
                        return 0;
-               NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "udp v4 hw csum failure.\n"));
+               LIMIT_NETDEBUG(printk(KERN_DEBUG "udp v4 hw csum failure.\n"));
                skb->ip_summed = CHECKSUM_NONE;
        }
        if (skb->ip_summed != CHECKSUM_UNNECESSARY)
@@ -1181,14 +1181,13 @@ int udp_rcv(struct sk_buff *skb)
        return(0);
 
 short_packet:
-       NETDEBUG(if (net_ratelimit())
-               printk(KERN_DEBUG "UDP: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n",
-                       NIPQUAD(saddr),
-                       ntohs(uh->source),
-                       ulen,
-                       len,
-                       NIPQUAD(daddr),
-                       ntohs(uh->dest)));
+       LIMIT_NETDEBUG(printk(KERN_DEBUG "UDP: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n",
+                             NIPQUAD(saddr),
+                             ntohs(uh->source),
+                             ulen,
+                             len,
+                             NIPQUAD(daddr),
+                             ntohs(uh->dest)));
 no_header:
        UDP_INC_STATS_BH(UDP_MIB_INERRORS);
        kfree_skb(skb);
@@ -1199,13 +1198,12 @@ csum_error:
         * RFC1122: OK.  Discards the bad packet silently (as far as 
         * the network is concerned, anyway) as per 4.1.3.4 (MUST). 
         */
-       NETDEBUG(if (net_ratelimit())
-                printk(KERN_DEBUG "UDP: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
-                       NIPQUAD(saddr),
-                       ntohs(uh->source),
-                       NIPQUAD(daddr),
-                       ntohs(uh->dest),
-                       ulen));
+       LIMIT_NETDEBUG(printk(KERN_DEBUG "UDP: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
+                             NIPQUAD(saddr),
+                             ntohs(uh->source),
+                             NIPQUAD(daddr),
+                             ntohs(uh->dest),
+                             ulen));
 drop:
        UDP_INC_STATS_BH(UDP_MIB_INERRORS);
        kfree_skb(skb);
index 866f107..10fbb50 100644 (file)
@@ -198,12 +198,13 @@ resubmit:
                if (!raw_sk) {
                        if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
                                IP6_INC_STATS_BH(IPSTATS_MIB_INUNKNOWNPROTOS);
-                               icmpv6_param_prob(skb, ICMPV6_UNK_NEXTHDR, nhoff);
+                               icmpv6_send(skb, ICMPV6_PARAMPROB,
+                                           ICMPV6_UNK_NEXTHDR, nhoff,
+                                           skb->dev);
                        }
-               } else {
+               } else
                        IP6_INC_STATS_BH(IPSTATS_MIB_INDELIVERS);
-                       kfree_skb(skb);
-               }
+               kfree_skb(skb);
        }
        rcu_read_unlock();
        return 0;
index 423feb4..135383e 100644 (file)
@@ -354,7 +354,7 @@ static struct crypto_tfm **ipcomp6_alloc_tfms(const char *alg_name)
        int cpu;
 
        /* This can be any valid CPU ID so we don't need locking. */
-       cpu = smp_processor_id();
+       cpu = raw_smp_processor_id();
 
        list_for_each_entry(pos, &ipcomp6_tfms_list, list) {
                struct crypto_tfm *tfm;
index f3ef4c3..3bc144a 100644 (file)
@@ -504,6 +504,9 @@ done:
                break;
        case IPV6_IPSEC_POLICY:
        case IPV6_XFRM_POLICY:
+               retv = -EPERM;
+               if (!capable(CAP_NET_ADMIN))
+                       break;
                retv = xfrm_user_policy(sk, optname, optval, optlen);
                break;
 
index 5493180..a16df5b 100644 (file)
@@ -211,6 +211,12 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
                break;
        
        case IPQ_COPY_PACKET:
+               if (entry->skb->ip_summed == CHECKSUM_HW &&
+                   (*errp = skb_checksum_help(entry->skb,
+                                              entry->info->outdev == NULL))) {
+                       read_unlock_bh(&queue_lock);
+                       return NULL;
+               }
                if (copy_range == 0 || copy_range > entry->skb->len)
                        data_len = entry->skb->len;
                else
@@ -381,6 +387,7 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
        if (!skb_ip_make_writable(&e->skb, v->data_len))
                return -ENOMEM;
        memcpy(e->skb->data, v->payload, v->data_len);
+       e->skb->ip_summed = CHECKSUM_NONE;
        e->skb->nfcache |= NFC_ALTERED;
 
        /*
index e2b848e..1d4d75b 100644 (file)
@@ -328,6 +328,8 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
 
        if (skb->ip_summed != CHECKSUM_UNNECESSARY) {
                if (skb->ip_summed == CHECKSUM_HW) {
+                       skb_postpull_rcsum(skb, skb->nh.raw,
+                                          skb->h.raw - skb->nh.raw);
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        if (csum_ipv6_magic(&skb->nh.ipv6h->saddr,
                                            &skb->nh.ipv6h->daddr,
index b788f55..e553e5b 100644 (file)
@@ -195,7 +195,6 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int
        dev_hold(dev);
 
        ipip6_tunnel_link(nt);
-       /* Do not decrement MOD_USE_COUNT here. */
        return nt;
 
 failed:
@@ -794,10 +793,28 @@ static struct net_protocol sit_protocol = {
        .err_handler    =       ipip6_err,
 };
 
+static void __exit sit_destroy_tunnels(void)
+{
+       int prio;
+
+       for (prio = 1; prio < 4; prio++) {
+               int h;
+               for (h = 0; h < HASH_SIZE; h++) {
+                       struct ip_tunnel *t;
+                       while ((t = tunnels[prio][h]) != NULL)
+                               unregister_netdevice(t->dev);
+               }
+       }
+}
+
 void __exit sit_cleanup(void)
 {
        inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
-       unregister_netdev(ipip6_fb_tunnel_dev);
+
+       rtnl_lock();
+       sit_destroy_tunnels();
+       unregister_netdevice(ipip6_fb_tunnel_dev);
+       rtnl_unlock();
 }
 
 int __init sit_init(void)
index f6e288d..ef29cfd 100644 (file)
@@ -158,9 +158,14 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
                tcp_port_rover = rover;
                spin_unlock(&tcp_portalloc_lock);
 
-               /* Exhausted local port range during search? */
+               /* Exhausted local port range during search?  It is not
+                * possible for us to be holding one of the bind hash
+                * locks if this test triggers, because if 'remaining'
+                * drops to zero, we broke out of the do/while loop at
+                * the top level, not from the 'break;' statement.
+                */
                ret = 1;
-               if (remaining <= 0)
+               if (unlikely(remaining <= 0))
                        goto fail;
 
                /* OK, here is the one we will use. */
index 31ed4a9..162a85f 100644 (file)
@@ -459,12 +459,7 @@ static struct sock *nr_make_new(struct sock *osk)
        sk->sk_sndbuf   = osk->sk_sndbuf;
        sk->sk_state    = TCP_ESTABLISHED;
        sk->sk_sleep    = osk->sk_sleep;
-
-       if (sock_flag(osk, SOCK_ZAPPED))
-               sock_set_flag(sk, SOCK_ZAPPED);
-
-       if (sock_flag(osk, SOCK_DBG))
-               sock_set_flag(sk, SOCK_DBG);
+       sock_copy_flags(sk, osk);
 
        skb_queue_head_init(&nr->ack_queue);
        skb_queue_head_init(&nr->reseq_queue);
@@ -541,7 +536,8 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        struct nr_sock *nr = nr_sk(sk);
        struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr;
        struct net_device *dev;
-       ax25_address *user, *source;
+       ax25_uid_assoc *user;
+       ax25_address *source;
 
        lock_sock(sk);
        if (!sock_flag(sk, SOCK_ZAPPED)) {
@@ -580,16 +576,19 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        } else {
                source = &addr->fsa_ax25.sax25_call;
 
-               if ((user = ax25_findbyuid(current->euid)) == NULL) {
+               user = ax25_findbyuid(current->euid);
+               if (user) {
+                       nr->user_addr   = user->call;
+                       ax25_uid_put(user);
+               } else {
                        if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) {
                                release_sock(sk);
                                dev_put(dev);
                                return -EPERM;
                        }
-                       user = source;
+                       nr->user_addr   = *source;
                }
 
-               nr->user_addr   = *user;
                nr->source_addr = *source;
        }
 
@@ -609,7 +608,8 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr,
        struct sock *sk = sock->sk;
        struct nr_sock *nr = nr_sk(sk);
        struct sockaddr_ax25 *addr = (struct sockaddr_ax25 *)uaddr;
-       ax25_address *user, *source = NULL;
+       ax25_address *source = NULL;
+       ax25_uid_assoc *user;
        struct net_device *dev;
 
        lock_sock(sk);
@@ -650,16 +650,19 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr,
                }
                source = (ax25_address *)dev->dev_addr;
 
-               if ((user = ax25_findbyuid(current->euid)) == NULL) {
+               user = ax25_findbyuid(current->euid);
+               if (user) {
+                       nr->user_addr   = user->call;
+                       ax25_uid_put(user);
+               } else {
                        if (ax25_uid_policy && !capable(CAP_NET_ADMIN)) {
                                dev_put(dev);
                                release_sock(sk);
                                return -EPERM;
                        }
-                       user = source;
+                       nr->user_addr   = *source;
                }
 
-               nr->user_addr   = *user;
                nr->source_addr = *source;
                nr->device      = dev;
 
index 7eb6a5b..5480caf 100644 (file)
@@ -556,12 +556,7 @@ static struct sock *rose_make_new(struct sock *osk)
        sk->sk_sndbuf   = osk->sk_sndbuf;
        sk->sk_state    = TCP_ESTABLISHED;
        sk->sk_sleep    = osk->sk_sleep;
-
-       if (sock_flag(osk, SOCK_ZAPPED))
-               sock_set_flag(sk, SOCK_ZAPPED);
-
-       if (sock_flag(osk, SOCK_DBG))
-               sock_set_flag(sk, SOCK_DBG);
+       sock_copy_flags(sk, osk);
 
        init_timer(&rose->timer);
        init_timer(&rose->idletimer);
@@ -631,7 +626,8 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        struct rose_sock *rose = rose_sk(sk);
        struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;
        struct net_device *dev;
-       ax25_address *user, *source;
+       ax25_address *source;
+       ax25_uid_assoc *user;
        int n;
 
        if (!sock_flag(sk, SOCK_ZAPPED))
@@ -656,14 +652,17 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 
        source = &addr->srose_call;
 
-       if ((user = ax25_findbyuid(current->euid)) == NULL) {
+       user = ax25_findbyuid(current->euid);
+       if (user) {
+               rose->source_call = user->call;
+               ax25_uid_put(user);
+       } else {
                if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE))
                        return -EACCES;
-               user = source;
+               rose->source_call   = *source;
        }
 
        rose->source_addr   = addr->srose_addr;
-       rose->source_call   = *user;
        rose->device        = dev;
        rose->source_ndigis = addr->srose_ndigis;
 
@@ -690,8 +689,8 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
        struct rose_sock *rose = rose_sk(sk);
        struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;
        unsigned char cause, diagnostic;
-       ax25_address *user;
        struct net_device *dev;
+       ax25_uid_assoc *user;
        int n;
 
        if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
@@ -741,12 +740,14 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
                if ((dev = rose_dev_first()) == NULL)
                        return -ENETUNREACH;
 
-               if ((user = ax25_findbyuid(current->euid)) == NULL)
+               user = ax25_findbyuid(current->euid);
+               if (!user)
                        return -EINVAL;
 
                memcpy(&rose->source_addr, dev->dev_addr, ROSE_ADDR_LEN);
-               rose->source_call = *user;
+               rose->source_call = user->call;
                rose->device      = dev;
+               ax25_uid_put(user);
 
                rose_insert_socket(sk);         /* Finish the bind */
        }
index ff73ebb..25da6f6 100644 (file)
@@ -994,8 +994,10 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
         *      1. The frame isn't for us,
         *      2. It isn't "owned" by any existing route.
         */
-       if (frametype != ROSE_CALL_REQUEST)     /* XXX */
-               return 0;
+       if (frametype != ROSE_CALL_REQUEST) {   /* XXX */
+               res = 0;
+               goto out;
+       }
 
        len  = (((skb->data[3] >> 4) & 0x0F) + 1) / 2;
        len += (((skb->data[3] >> 0) & 0x0F) + 1) / 2;
index 8edefd5..0d066c9 100644 (file)
@@ -438,6 +438,7 @@ struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops)
        if (!ops->init || ops->init(sch, NULL) == 0)
                return sch;
 
+       qdisc_destroy(sch);
 errout:
        return NULL;
 }
index 98d49ec..b74f777 100644 (file)
@@ -57,6 +57,7 @@ static struct snmp_mib sctp_snmp_list[] = {
        SNMP_MIB_ITEM("SctpReasmUsrMsgs", SCTP_MIB_REASMUSRMSGS),
        SNMP_MIB_ITEM("SctpOutSCTPPacks", SCTP_MIB_OUTSCTPPACKS),
        SNMP_MIB_ITEM("SctpInSCTPPacks", SCTP_MIB_INSCTPPACKS),
+       SNMP_MIB_SENTINEL
 };
 
 /* Return the current value of a particular entry in the mib by adding its
index 24c21f2..5a7265a 100644 (file)
@@ -185,9 +185,7 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
                        sg->page = body->pages[i];
                        sg->offset = offset;
                        sg->length = thislen;
-                       kmap(sg->page); /* XXX kmap_atomic? */
                        crypto_digest_update(tfm, sg, 1);
-                       kunmap(sg->page);
                        len -= thislen;
                        i++;
                        offset = 0;
index 56db8f1..d0c3120 100644 (file)
@@ -586,7 +586,7 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
        }
        if (skb->stamp.tv_sec == 0) {
                skb->stamp.tv_sec = xtime.tv_sec; 
-               skb->stamp.tv_usec = xtime.tv_nsec * 1000
+               skb->stamp.tv_usec = xtime.tv_nsec / NSEC_PER_USEC
                /* Don't enable netstamp, sunrpc doesn't 
                   need that much accuracy */
        }
index 8a4d9c1..fde16f4 100644 (file)
@@ -993,6 +993,7 @@ xdr_xcode_array2(struct xdr_buf *buf, unsigned int base,
                        return -EINVAL;
        } else {
                if (xdr_decode_word(buf, base, &desc->array_len) != 0 ||
+                   desc->array_len > desc->array_maxlen ||
                    (unsigned long) base + 4 + desc->array_len *
                                    desc->elem_size > buf->len)
                        return -EINVAL;
index 9b9f94c..09ffca5 100644 (file)
@@ -359,11 +359,16 @@ handle_modversions(struct module *mod, struct elf_info *info,
                /* ignore __this_module, it will be resolved shortly */
                if (strcmp(symname, MODULE_SYMBOL_PREFIX "__this_module") == 0)
                        break;
-#ifdef STT_REGISTER
+/* cope with newer glibc (2.3.4 or higher) STT_ definition in elf.h */
+#if defined(STT_REGISTER) || defined(STT_SPARC_REGISTER)
+/* add compatibility with older glibc */
+#ifndef STT_SPARC_REGISTER
+#define STT_SPARC_REGISTER STT_REGISTER
+#endif
                if (info->hdr->e_machine == EM_SPARC ||
                    info->hdr->e_machine == EM_SPARCV9) {
                        /* Ignore register directives. */
-                       if (ELF_ST_TYPE(sym->st_info) == STT_REGISTER)
+                       if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER)
                                break;
                }
 #endif
index fea2628..a6516a6 100644 (file)
@@ -49,9 +49,6 @@ asmlinkage long sys_add_key(const char __user *_type,
                goto error;
        type[31] = '\0';
 
-       if (!type[0])
-               goto error;
-
        ret = -EPERM;
        if (type[0] == '.')
                goto error;
@@ -144,6 +141,10 @@ asmlinkage long sys_request_key(const char __user *_type,
                goto error;
        type[31] = '\0';
 
+       ret = -EPERM;
+       if (type[0] == '.')
+               goto error;
+
        /* pull the description into kernel space */
        ret = -EFAULT;
        dlen = strnlen_user(_description, PAGE_SIZE - 1);
@@ -362,7 +363,7 @@ long keyctl_revoke_key(key_serial_t id)
 
        key_put(key);
  error:
-       return 0;
+       return ret;
 
 } /* end keyctl_revoke_key() */
 
@@ -685,6 +686,8 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
                        goto can_read_key2;
 
                ret = PTR_ERR(skey);
+               if (ret == -EAGAIN)
+                       ret = -EACCES;
                goto error2;
        }
 
index a1f6bac..9c208c7 100644 (file)
@@ -201,7 +201,11 @@ static void keyring_destroy(struct key *keyring)
 
        if (keyring->description) {
                write_lock(&keyring_name_lock);
-               list_del(&keyring->type_data.link);
+
+               if (keyring->type_data.link.next != NULL &&
+                   !list_empty(&keyring->type_data.link))
+                       list_del(&keyring->type_data.link);
+
                write_unlock(&keyring_name_lock);
        }
 
index 9b0369c..c089f78 100644 (file)
@@ -678,7 +678,7 @@ long join_session_keyring(const char *name)
                keyring = keyring_alloc(name, tsk->uid, tsk->gid, 0, NULL);
                if (IS_ERR(keyring)) {
                        ret = PTR_ERR(keyring);
-                       goto error;
+                       goto error2;
                }
        }
        else if (IS_ERR(keyring)) {
index dfcd983..90c1506 100644 (file)
@@ -405,7 +405,7 @@ struct key *request_key_and_link(struct key_type *type,
                key_user_put(user);
 
                /* link the new key into the appropriate keyring */
-               if (!PTR_ERR(key))
+               if (!IS_ERR(key))
                        request_key_link(key, dest_keyring);
        }
 
index ee794ae..b65ee47 100644 (file)
@@ -77,7 +77,7 @@ source "sound/parisc/Kconfig"
 endmenu
 
 menu "Open Sound System"
-       depends on SOUND!=n && (BROKEN || (!SPARC32 && !SPARC64))
+       depends on SOUND!=n
 
 config SOUND_PRIME
        tristate "Open Sound System (DEPRECATED)"
index 764ac18..969d755 100644 (file)
@@ -5,7 +5,7 @@
 
 snd-objs     := sound.o init.o memory.o info.o control.o misc.o \
                 device.o wrappers.o
-ifeq ($(CONFIG_ISA),y)
+ifeq ($(CONFIG_ISA_DMA_API),y)
 snd-objs     += isadma.o
 endif
 ifeq ($(CONFIG_SND_OSSEMUL),y)
index 7612884..3271e92 100644 (file)
@@ -432,7 +432,7 @@ EXPORT_SYMBOL(snd_device_new);
 EXPORT_SYMBOL(snd_device_register);
 EXPORT_SYMBOL(snd_device_free);
   /* isadma.c */
-#ifdef CONFIG_ISA
+#ifdef CONFIG_ISA_DMA_API
 EXPORT_SYMBOL(snd_dma_program);
 EXPORT_SYMBOL(snd_dma_disable);
 EXPORT_SYMBOL(snd_dma_pointer);
index 148a856..be4ea60 100644 (file)
@@ -1,7 +1,7 @@
 # ALSA ISA drivers
 
 menu "ISA devices"
-       depends on SND!=n && ISA
+       depends on SND!=n && ISA && ISA_DMA_API
 
 config SND_AD1848_LIB
         tristate
index 7bd95ce..953e5f3 100644 (file)
@@ -6,7 +6,7 @@
 # Prompt user for primary drivers.
 config SOUND_BT878
        tristate "BT878 audio dma"
-       depends on SOUND_PRIME
+       depends on SOUND_PRIME && PCI
        ---help---
          Audio DMA support for bt878 based grabber boards.  As you might have
          already noticed, bt878 is listed with two functions in /proc/pci.
@@ -80,14 +80,14 @@ config SOUND_EMU10K1
 
 config MIDI_EMU10K1
        bool "Creative SBLive! MIDI (EXPERIMENTAL)"
-       depends on SOUND_EMU10K1 && EXPERIMENTAL
+       depends on SOUND_EMU10K1 && EXPERIMENTAL && ISA_DMA_API
        help
          Say Y if you want to be able to use the OSS /dev/sequencer
          interface.  This code is still experimental.
 
 config SOUND_FUSION
        tristate "Crystal SoundFusion (CS4280/461x)"
-       depends on SOUND_PRIME
+       depends on SOUND_PRIME && PCI
        help
          This module drives the Crystal SoundFusion devices (CS4280/46xx
          series) when wired as native sound drivers with AC97 codecs.  If
@@ -95,7 +95,7 @@ config SOUND_FUSION
 
 config SOUND_CS4281
        tristate "Crystal Sound CS4281"
-       depends on SOUND_PRIME
+       depends on SOUND_PRIME && PCI
        help
          Picture and feature list at
          <http://www.pcbroker.com/crystal4281.html>.
@@ -179,7 +179,7 @@ config SOUND_HARMONY
 
 config SOUND_SONICVIBES
        tristate "S3 SonicVibes"
-       depends on SOUND_PRIME
+       depends on SOUND_PRIME && PCI
        help
          Say Y or M if you have a PCI sound card utilizing the S3
          SonicVibes chipset. To find out if your sound card uses a
@@ -226,7 +226,7 @@ config SOUND_AU1550_AC97
 
 config SOUND_TRIDENT
        tristate "Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core"
-       depends on SOUND_PRIME
+       depends on SOUND_PRIME && PCI
        ---help---
          Say Y or M if you have a PCI sound card utilizing the Trident
          4DWave-DX/NX chipset or your mother board chipset has SiS 7018
@@ -503,7 +503,7 @@ config SOUND_VIA82CXXX
 
 config MIDI_VIA82CXXX
        bool "VIA 82C686 MIDI"
-       depends on SOUND_VIA82CXXX
+       depends on SOUND_VIA82CXXX && ISA_DMA_API
        help
          Answer Y to use the MIDI interface of the Via686. You may need to
          enable this in the BIOS before it will work. This is for connection
@@ -512,7 +512,7 @@ config MIDI_VIA82CXXX
 
 config SOUND_OSS
        tristate "OSS sound modules"
-       depends on SOUND_PRIME
+       depends on SOUND_PRIME && ISA_DMA_API
        help
          OSS is the Open Sound System suite of sound card drivers.  They make
          sound programming easier since they provide a common API.  Say Y or
index db9afb6..9bf3ee5 100644 (file)
@@ -80,7 +80,7 @@ obj-$(CONFIG_SOUND_ALI5455)   += ali5455.o ac97_codec.o
 obj-$(CONFIG_SOUND_IT8172)     += ite8172.o ac97_codec.o
 obj-$(CONFIG_SOUND_FORTE)      += forte.o ac97_codec.o
 
-obj-$(CONFIG_SOUND_AD1980)     += ac97_plugin_ad1980.o
+obj-$(CONFIG_SOUND_AD1980)     += ac97_plugin_ad1980.o ac97_codec.o
 obj-$(CONFIG_SOUND_WM97XX)     += ac97_plugin_wm97xx.o
 
 ifeq ($(CONFIG_MIDI_EMU10K1),y)
index 7e9f667..b9a640f 100644 (file)
@@ -3430,9 +3430,9 @@ out_iospace:
                release_mem_region(card->iobase_mmio_phys, 256);
        }
 out_pio:       
-       release_region(card->iobase, 64);
-out_region2:
        release_region(card->ac97base, 256);
+out_region2:
+       release_region(card->iobase, 64);
 out_region1:
        pci_free_consistent(pci_dev, sizeof(struct i810_channel)*NR_HW_CH,
            card->channel, card->chandma);
index bab7044..d5b8064 100644 (file)
  *  VIDC sound function prototypes
  */
 
-/* vidc.c */
-
-extern int vidc_busy;
-
 /* vidc_fill.S */
 
 /*
index 6d7a00f..26b42bb 100644 (file)
@@ -314,7 +314,7 @@ config SND_YMFPCI
 
 config SND_ALS4000
        tristate "Avance Logic ALS4000"
-       depends on SND
+       depends on SND && ISA_DMA_API
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_PCM
index 7c806bd..d7af3e4 100644 (file)
@@ -2376,6 +2376,9 @@ static int intel8x0_suspend(snd_card_t *card, pm_message_t state)
                        snd_ac97_suspend(chip->ac97[i]);
        if (chip->device_type == DEVICE_INTEL_ICH4)
                chip->sdm_saved = igetbyte(chip, ICHREG(SDM));
+
+       if (chip->irq >= 0)
+               free_irq(chip->irq, (void *)chip);
        pci_disable_device(chip->pci);
        return 0;
 }
@@ -2387,7 +2390,9 @@ static int intel8x0_resume(snd_card_t *card)
 
        pci_enable_device(chip->pci);
        pci_set_master(chip->pci);
-       snd_intel8x0_chip_init(chip, 0);
+       request_irq(chip->irq, snd_intel8x0_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip);
+       synchronize_irq(chip->irq);
+       snd_intel8x0_chip_init(chip, 1);
 
        /* re-initialize mixer stuff */
        if (chip->device_type == DEVICE_INTEL_ICH4) {
index 844d761..c89e82e 100644 (file)
@@ -765,7 +765,8 @@ snd_pmac_ctrl_intr(int irq, void *devid, struct pt_regs *regs)
  */
 static void snd_pmac_sound_feature(pmac_t *chip, int enable)
 {
-       ppc_md.feature_call(PMAC_FTR_SOUND_CHIP_ENABLE, chip->node, 0, enable);
+       if (ppc_md.feature_call)
+               ppc_md.feature_call(PMAC_FTR_SOUND_CHIP_ENABLE, chip->node, 0, enable);
 }
 
 /*