]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
Merge branch 'upstream-fixes' of git://lost.foo-projects.org/~ahkok/git/netdev-2...
authorJeff Garzik <jeff@garzik.org>
Thu, 24 Aug 2006 04:45:36 +0000 (00:45 -0400)
committerJeff Garzik <jeff@garzik.org>
Thu, 24 Aug 2006 04:45:36 +0000 (00:45 -0400)
349 files changed:
Documentation/fb/imacfb.txt [new file with mode: 0644]
Documentation/kobject.txt
Documentation/networking/LICENSE.qla3xxx [new file with mode: 0644]
Documentation/networking/ip-sysctl.txt
Documentation/powerpc/booting-without-of.txt
MAINTAINERS
Makefile
arch/arm/common/rtctime.c
arch/arm/kernel/traps.c
arch/arm/mach-ixp4xx/common-pci.c
arch/arm/mach-ixp4xx/gtwx5715-setup.c
arch/i386/kernel/traps.c
arch/ia64/kernel/traps.c
arch/powerpc/Kconfig
arch/powerpc/boot/dts/mpc8641_hpcn.dts [new file with mode: 0644]
arch/powerpc/configs/g5_defconfig
arch/powerpc/configs/iseries_defconfig
arch/powerpc/configs/pseries_defconfig
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/cpu_setup_power4.S
arch/powerpc/kernel/crash.c
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/kprobes.c
arch/powerpc/kernel/machine_kexec.c
arch/powerpc/kernel/machine_kexec_64.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/traps.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/platforms/pseries/xics.c
arch/powerpc/sysdev/fsl_soc.c
arch/ppc/platforms/85xx/mpc8560_ads.c
arch/ppc/platforms/85xx/mpc85xx_ads_common.h
arch/ppc/platforms/mpc8272ads_setup.c
arch/ppc/platforms/mpc866ads_setup.c
arch/ppc/platforms/mpc885ads_setup.c
arch/ppc/platforms/pq2ads_pd.h
arch/ppc/syslib/mpc85xx_devices.c
arch/ppc/syslib/mpc8xx_devices.c
arch/ppc/syslib/mpc8xx_sys.c
arch/ppc/syslib/pq2_devices.c
arch/ppc/syslib/pq2_sys.c
arch/s390/appldata/appldata_base.c
arch/s390/mm/init.c
arch/x86_64/kernel/traps.c
arch/xtensa/kernel/traps.c
drivers/char/watchdog/Kconfig
drivers/ide/pci/generic.c
drivers/isdn/i4l/Kconfig
drivers/md/dm-mpath.c
drivers/media/dvb/bt8xx/dst.c
drivers/media/dvb/dvb-core/Makefile
drivers/media/radio/Kconfig
drivers/media/radio/Makefile
drivers/media/radio/dsbr100.c [new file with mode: 0644]
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/compat_ioctl32.c
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/dsbr100.c [deleted file]
drivers/media/video/msp3400-kthreads.c
drivers/media/video/pwc/Kconfig
drivers/media/video/pwc/pwc-if.c
drivers/media/video/saa7134/saa7134-video.c
drivers/media/video/tuner-types.c
drivers/media/video/v4l1-compat.c
drivers/media/video/v4l2-common.c
drivers/media/video/videodev.c
drivers/media/video/vivi.c
drivers/mmc/mmc_queue.c
drivers/mmc/wbsd.c
drivers/net/3c501.c
drivers/net/3c515.c
drivers/net/3c59x.c
drivers/net/8139cp.c
drivers/net/8139too.c
drivers/net/82596.c
drivers/net/8390.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/ac3200.c
drivers/net/acenic.c
drivers/net/amd8111e.c
drivers/net/appletalk/cops.c
drivers/net/arcnet/com20020-pci.c
drivers/net/at1700.c
drivers/net/b44.c
drivers/net/bnx2.c
drivers/net/bnx2.h
drivers/net/cassini.c
drivers/net/chelsio/cxgb2.c
drivers/net/cs89x0.c
drivers/net/defxx.c
drivers/net/dl2k.c
drivers/net/dm9000.c
drivers/net/e100.c
drivers/net/e1000/e1000_hw.c
drivers/net/e1000/e1000_hw.h
drivers/net/e1000/e1000_main.c
drivers/net/e2100.c
drivers/net/eepro.c
drivers/net/eepro100.c
drivers/net/eexpress.c
drivers/net/epic100.c
drivers/net/es3210.c
drivers/net/eth16i.c
drivers/net/fealnx.c
drivers/net/forcedeth.c
drivers/net/fs_enet/Makefile
drivers/net/fs_enet/fec.h [new file with mode: 0644]
drivers/net/fs_enet/fs_enet-main.c
drivers/net/fs_enet/fs_enet-mii.c [deleted file]
drivers/net/fs_enet/fs_enet.h
drivers/net/fs_enet/mac-fcc.c
drivers/net/fs_enet/mac-fec.c
drivers/net/fs_enet/mac-scc.c
drivers/net/fs_enet/mii-bitbang.c
drivers/net/fs_enet/mii-fec.c [new file with mode: 0644]
drivers/net/fs_enet/mii-fixed.c [deleted file]
drivers/net/hp100.c
drivers/net/irda/mcs7780.c
drivers/net/irda/w83977af_ir.c
drivers/net/ixgb/ixgb_main.c
drivers/net/lance.c
drivers/net/lne390.c
drivers/net/myri10ge/myri10ge.c
drivers/net/myri10ge/myri10ge_mcp.h
drivers/net/natsemi.c
drivers/net/ne2k-pci.c
drivers/net/netx-eth.c
drivers/net/ni52.c
drivers/net/ni65.c
drivers/net/ns83820.c
drivers/net/pci-skeleton.c
drivers/net/pcmcia/axnet_cs.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/pcmcia/xirc2ps_cs.c
drivers/net/pcnet32.c
drivers/net/phy/Kconfig
drivers/net/phy/Makefile
drivers/net/phy/fixed.c [new file with mode: 0644]
drivers/net/phy/mdio_bus.c
drivers/net/phy/phy_device.c
drivers/net/phy/smsc.c
drivers/net/phy/vitesse.c
drivers/net/ppp_generic.c
drivers/net/qla3xxx.c [new file with mode: 0644]
drivers/net/qla3xxx.h [new file with mode: 0644]
drivers/net/r8169.c
drivers/net/rrunner.c
drivers/net/s2io.c
drivers/net/saa9730.c
drivers/net/seeq8005.c
drivers/net/sis190.c
drivers/net/sis900.c
drivers/net/sk98lin/skge.c
drivers/net/skfp/skfddi.c
drivers/net/skge.c
drivers/net/sky2.c
drivers/net/slhc.c
drivers/net/smc911x.c
drivers/net/smc91x.c
drivers/net/smc91x.h
drivers/net/spider_net.c
drivers/net/spider_net.h
drivers/net/spider_net_ethtool.c
drivers/net/starfire.c
drivers/net/sundance.c
drivers/net/sungem.c
drivers/net/tc35815.c
drivers/net/tg3.c
drivers/net/tg3.h
drivers/net/tokenring/3c359.c
drivers/net/tokenring/ibmtr.c
drivers/net/tokenring/lanstreamer.c
drivers/net/tokenring/smctr.c
drivers/net/tulip/de2104x.c
drivers/net/tulip/de4x5.c
drivers/net/tulip/dmfe.c
drivers/net/tulip/tulip_core.c
drivers/net/tulip/uli526x.c
drivers/net/tulip/winbond-840.c
drivers/net/tulip/xircom_cb.c
drivers/net/tulip/xircom_tulip_cb.c
drivers/net/typhoon.c
drivers/net/ucc_geth.c [new file with mode: 0644]
drivers/net/ucc_geth.h [new file with mode: 0644]
drivers/net/ucc_geth_phy.c [new file with mode: 0644]
drivers/net/ucc_geth_phy.h [new file with mode: 0644]
drivers/net/via-rhine.c
drivers/net/via-velocity.c
drivers/net/via-velocity.h
drivers/net/wan/c101.c
drivers/net/wan/cycx_main.c
drivers/net/wan/dlci.c
drivers/net/wan/dscc4.c
drivers/net/wan/farsync.c
drivers/net/wan/lmc/lmc_main.c
drivers/net/wan/pc300_drv.c
drivers/net/wan/pci200syn.c
drivers/net/wan/sdla.c
drivers/net/wan/wanxl.c
drivers/net/wd.c
drivers/net/wireless/airo.c
drivers/net/wireless/atmel_pci.c
drivers/net/wireless/bcm43xx/bcm43xx.h
drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
drivers/net/wireless/bcm43xx/bcm43xx_leds.c
drivers/net/wireless/bcm43xx/bcm43xx_main.c
drivers/net/wireless/bcm43xx/bcm43xx_main.h
drivers/net/wireless/bcm43xx/bcm43xx_phy.c
drivers/net/wireless/bcm43xx/bcm43xx_pio.c
drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
drivers/net/wireless/bcm43xx/bcm43xx_wx.c
drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
drivers/net/wireless/hostap/hostap_hw.c
drivers/net/wireless/ipw2100.c
drivers/net/wireless/ipw2200.c
drivers/net/wireless/orinoco_nortel.c
drivers/net/wireless/orinoco_pci.c
drivers/net/wireless/orinoco_plx.c
drivers/net/wireless/orinoco_tmd.c
drivers/net/wireless/prism54/isl_ioctl.c
drivers/net/wireless/prism54/isl_ioctl.h
drivers/net/wireless/prism54/islpci_dev.c
drivers/net/wireless/prism54/islpci_dev.h
drivers/net/wireless/prism54/islpci_hotplug.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/spectrum_cs.c
drivers/net/wireless/zd1211rw/Makefile
drivers/net/wireless/zd1211rw/zd_chip.c
drivers/net/wireless/zd1211rw/zd_chip.h
drivers/net/wireless/zd1211rw/zd_def.h
drivers/net/wireless/zd1211rw/zd_mac.c
drivers/net/wireless/zd1211rw/zd_mac.h
drivers/net/wireless/zd1211rw/zd_netdev.c
drivers/net/wireless/zd1211rw/zd_rf.c
drivers/net/wireless/zd1211rw/zd_rf.h
drivers/net/wireless/zd1211rw/zd_rf_al2230.c
drivers/net/wireless/zd1211rw/zd_rf_al7230b.c [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_usb.c
drivers/net/wireless/zd1211rw/zd_usb.h
drivers/net/yellowfin.c
drivers/pci/hotplug/Kconfig
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_hpc.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_devmap.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/xpram.c
drivers/s390/char/tape_class.c
drivers/s390/cio/device_fsm.c
drivers/s390/cio/device_ops.c
drivers/s390/net/qeth_main.c
drivers/scsi/arm/Kconfig
drivers/scsi/arm/scsi.h
drivers/scsi/ata_piix.c
drivers/scsi/libata-core.c
drivers/scsi/libata-scsi.c
drivers/scsi/sata_sil24.c
drivers/usb/host/ohci-au1xxx.c
drivers/usb/input/appletouch.c
drivers/usb/misc/usbtest.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.h
drivers/usb/serial/ipaq.c
drivers/usb/storage/unusual_devs.h
drivers/video/Kconfig
drivers/video/imacfb.c
fs/adfs/super.c
fs/fuse/file.c
fs/jfs/inode.c
fs/jfs/jfs_inode.h
fs/jfs/super.c
fs/locks.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlm/dlmunlock.c
fs/ocfs2/localalloc.c
fs/ocfs2/ocfs2.h
fs/ocfs2/suballoc.c
fs/ocfs2/suballoc.h
fs/ocfs2/super.c
fs/udf/super.c
fs/xfs/xfs_alloc.c
include/asm-powerpc/kexec.h
include/asm-powerpc/rtas.h
include/asm-ppc/cpm2.h
include/asm-ppc/mpc8260.h
include/asm-ppc/mpc8xx.h
include/linux/fb.h
include/linux/fs_enet_pd.h
include/linux/if_vlan.h
include/linux/kernel.h
include/linux/mm.h
include/linux/netdevice.h
include/linux/phy.h
include/linux/skbuff.h
include/media/v4l2-dev.h
include/net/ieee80211.h
include/net/ieee80211softmac.h
kernel/futex.c
kernel/hrtimer.c
kernel/panic.c
kernel/timer.c
kernel/workqueue.c
mm/swap.c
net/atm/proc.c
net/bridge/br_if.c
net/bridge/netfilter/ebt_ulog.c
net/core/dev.c
net/core/dst.c
net/core/pktgen.c
net/core/rtnetlink.c
net/core/skbuff.c
net/core/utils.c
net/ieee80211/ieee80211_rx.c
net/ieee80211/softmac/ieee80211softmac_assoc.c
net/ieee80211/softmac/ieee80211softmac_io.c
net/ieee80211/softmac/ieee80211softmac_module.c
net/ieee80211/softmac/ieee80211softmac_priv.h
net/ipv4/fib_semantics.c
net/ipv4/igmp.c
net/ipv4/ip_output.c
net/ipv4/netfilter/arp_tables.c
net/ipv4/netfilter/ip_conntrack_netlink.c
net/ipv4/netfilter/ip_tables.c
net/ipv4/netfilter/ipt_ULOG.c
net/ipv4/netfilter/ipt_hashlimit.c
net/ipv4/route.c
net/ipv4/tcp_output.c
net/ipv4/tcp_probe.c
net/ipv6/addrconf.c
net/ipv6/icmp.c
net/ipv6/ip6_output.c
net/ipv6/mcast.c
net/ipv6/netfilter/ip6_tables.c
net/ipx/af_ipx.c
net/llc/llc_sap.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nfnetlink_log.c
net/netfilter/xt_physdev.c
net/netfilter/xt_string.c
net/sched/cls_u32.c
net/xfrm/xfrm_policy.c
scripts/mod/file2alias.c
sound/oss/Kconfig
sound/pci/Kconfig
usr/Makefile

diff --git a/Documentation/fb/imacfb.txt b/Documentation/fb/imacfb.txt
new file mode 100644 (file)
index 0000000..7590285
--- /dev/null
@@ -0,0 +1,31 @@
+
+What is imacfb?
+===============
+
+This is a generic EFI platform driver for Intel based Apple computers.
+Imacfb is only for EFI booted Intel Macs.
+
+Supported Hardware
+==================
+
+iMac 17"/20"
+Macbook
+Macbook Pro 15"/17"
+MacMini
+
+How to use it?
+==============
+
+Imacfb does not have any kind of autodetection of your machine.
+You have to add the fillowing kernel parameters in your elilo.conf:
+       Macbook :
+               video=imacfb:macbook
+       MacMini :
+               video=imacfb:mini
+       Macbook Pro 15", iMac 17" :
+               video=imacfb:i17
+       Macbook Pro 17", iMac 20" :
+               video=imacfb:i20
+
+--
+Edgar Hucek <gimli@dark-green.com>
index 8d9bffbd192cad1f2f28f396be8a4ee9a4a0f9b7..949f7b5a20538aa3537078d0eafd636df4a5991b 100644 (file)
@@ -247,7 +247,7 @@ the object-specific fields, which include:
 - default_attrs: Default attributes to be exported via sysfs when the
   object is registered.Note that the last attribute has to be
   initialized to NULL ! You can find a complete implementation
-  in drivers/block/genhd.c
+  in block/genhd.c
 
 
 Instances of struct kobj_type are not registered; only referenced by
diff --git a/Documentation/networking/LICENSE.qla3xxx b/Documentation/networking/LICENSE.qla3xxx
new file mode 100644 (file)
index 0000000..2f2077e
--- /dev/null
@@ -0,0 +1,46 @@
+Copyright (c)  2003-2006 QLogic Corporation
+QLogic Linux Networking HBA Driver
+
+This program includes a device driver for Linux 2.6 that may be
+distributed with QLogic hardware specific firmware binary file.
+You may modify and redistribute the device driver code under the
+GNU General Public License as published by the Free Software
+Foundation (version 2 or a later version).
+
+You may redistribute the hardware specific firmware binary file
+under the following terms:
+
+       1. Redistribution of source code (only if applicable),
+          must retain the above copyright notice, this list of
+          conditions and the following disclaimer.
+
+       2. Redistribution 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.
+
+       3. The name of QLogic Corporation may not be used to
+          endorse or promote products derived from this software
+          without specific prior written permission
+
+REGARDLESS OF WHAT LICENSING MECHANISM IS USED OR APPLICABLE,
+THIS PROGRAM IS PROVIDED BY QLOGIC CORPORATION "AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+USER ACKNOWLEDGES AND AGREES THAT USE OF THIS PROGRAM WILL NOT
+CREATE OR GIVE GROUNDS FOR A LICENSE BY IMPLICATION, ESTOPPEL, OR
+OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT,
+TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN
+ANY OTHER QLOGIC HARDWARE OR SOFTWARE EITHER SOLELY OR IN
+COMBINATION WITH THIS PROGRAM.
+
index d46338af6002997b0593d4875a6aee825c77126f..3e0c017e78772aba2857aca4d78ac24364a1e15d 100644 (file)
@@ -294,15 +294,15 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max
        Default: 87380*2 bytes.
 
 tcp_mem - vector of 3 INTEGERs: min, pressure, max
-       low: below this number of pages TCP is not bothered about its
+       min: below this number of pages TCP is not bothered about its
        memory appetite.
 
        pressure: when amount of memory allocated by TCP exceeds this number
        of pages, TCP moderates its memory consumption and enters memory
        pressure mode, which is exited when memory consumption falls
-       under "low".
+       under "min".
 
-       high: number of pages allowed for queueing by all TCP sockets.
+       max: number of pages allowed for queueing by all TCP sockets.
 
        Defaults are calculated at boot time from amount of available
        memory.
index 3c62e66e1fcc01999d939c8be8837285d6b18add..8c48b8a27b9c95a3ec4038f604d3e1ee424bdae0 100644 (file)
@@ -1196,7 +1196,7 @@ platforms are moved over to use the flattened-device-tree model.
     - model : Model of the device.  Can be "TSEC", "eTSEC", or "FEC"
     - compatible : Should be "gianfar"
     - reg : Offset and length of the register set for the device
-    - address : List of bytes representing the ethernet address of
+    - mac-address : List of bytes representing the ethernet address of
       this controller
     - interrupts : <a b> where a is the interrupt number and b is a
       field that represents an encoding of the sense and level
@@ -1216,7 +1216,7 @@ platforms are moved over to use the flattened-device-tree model.
                model = "TSEC";
                compatible = "gianfar";
                reg = <24000 1000>;
-               address = [ 00 E0 0C 00 73 00 ];
+               mac-address = [ 00 E0 0C 00 73 00 ];
                interrupts = <d 3 e 3 12 3>;
                interrupt-parent = <40000>;
                phy-handle = <2452000>
@@ -1498,7 +1498,7 @@ not necessary as they are usually the same as the root node.
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <24000 1000>;
-                       address = [ 00 E0 0C 00 73 00 ];
+                       mac-address = [ 00 E0 0C 00 73 00 ];
                        interrupts = <d 3 e 3 12 3>;
                        interrupt-parent = <40000>;
                        phy-handle = <2452000>;
@@ -1511,7 +1511,7 @@ not necessary as they are usually the same as the root node.
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <25000 1000>;
-                       address = [ 00 E0 0C 00 73 01 ];
+                       mac-address = [ 00 E0 0C 00 73 01 ];
                        interrupts = <13 3 14 3 18 3>;
                        interrupt-parent = <40000>;
                        phy-handle = <2452001>;
@@ -1524,7 +1524,7 @@ not necessary as they are usually the same as the root node.
                        model = "FEC";
                        compatible = "gianfar";
                        reg = <26000 1000>;
-                       address = [ 00 E0 0C 00 73 02 ];
+                       mac-address = [ 00 E0 0C 00 73 02 ];
                        interrupts = <19 3>;
                        interrupt-parent = <40000>;
                        phy-handle = <2452002>;
index e3e1515ba5a9065308e588b5fa2e480bcd039132..d3315a552be185c0e2686b4bcd355d7cb91b89b1 100644 (file)
@@ -2360,6 +2360,12 @@ M:       linux-driver@qlogic.com
 L:     linux-scsi@vger.kernel.org
 S:     Supported
 
+QLOGIC QLA3XXX NETWORK DRIVER
+P:     Ron Mercer
+M:     linux-driver@qlogic.com
+L:     netdev@vger.kernel.org
+S:     Supported
+
 QNX4 FILESYSTEM
 P:     Anders Larsen
 M:     al@alarsen.net
@@ -2610,6 +2616,18 @@ P:       Nicolas Pitre
 M:     nico@cam.org
 S:     Maintained
 
+SOFTMAC LAYER (IEEE 802.11)
+P:     Johannes Berg
+M:     johannes@sipsolutions.net
+P:     Joe Jezak
+M:     josejx@gentoo.org
+P:     Daniel Drake
+M:     dsd@gentoo.org
+W:     http://softmac.sipsolutions.net/
+L:     softmac-dev@sipsolutions.net
+L:     netdev@vger.kernel.org
+S:     Maintained
+
 SOFTWARE RAID (Multiple Disks) SUPPORT
 P:     Ingo Molnar
 M:     mingo@redhat.com
@@ -2656,6 +2674,14 @@ M:       chrisw@sous-sol.org
 L:     stable@kernel.org
 S:     Maintained
 
+STABLE BRANCH:
+P:     Greg Kroah-Hartman
+M:     greg@kroah.com
+P:     Chris Wright
+M:     chrisw@sous-sol.org
+L:     stable@kernel.org
+S:     Maintained
+
 TPM DEVICE DRIVER
 P:     Kylene Hall
 M:     kjhall@us.ibm.com
@@ -3326,6 +3352,15 @@ W:       http://www.qsl.net/dl1bke/
 L:     linux-hams@vger.kernel.org
 S:     Maintained
 
+ZD1211RW WIRELESS DRIVER
+P:     Daniel Drake
+M:     dsd@gentoo.org
+P:     Ulrich Kunitz
+M:     kune@deine-taler.de
+W:     http://zd1211.ath.cx/wiki/DriverRewrite
+L:     zd1211-devs@lists.sourceforge.net (subscribers-only)
+S:     Maintained
+
 ZF MACHZ WATCHDOG
 P:     Fernando Fuganti
 M:     fuganti@netbank.com.br
index c2f78a5a549390223a5dd76ee0543f1a5d36a55c..8406d02c638501d5902595daff5b1b631186f299 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -309,9 +309,6 @@ CPPFLAGS        := -D__KERNEL__ $(LINUXINCLUDE)
 
 CFLAGS          := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
                    -fno-strict-aliasing -fno-common
-# Force gcc to behave correct even for buggy distributions
-CFLAGS          += $(call cc-option, -fno-stack-protector)
-
 AFLAGS          := -D__ASSEMBLY__
 
 # Read KERNELRELEASE from include/config/kernel.release (if it exists)
@@ -436,12 +433,13 @@ core-y            := usr/
 endif # KBUILD_EXTMOD
 
 ifeq ($(dot-config),1)
-# In this section, we need .config
+# Read in config
+-include include/config/auto.conf
 
+ifeq ($(KBUILD_EXTMOD),)
 # Read in dependencies to all Kconfig* files, make sure to run
 # oldconfig if changes are detected.
 -include include/config/auto.conf.cmd
--include include/config/auto.conf
 
 # To avoid any implicit rule to kick in, define an empty command
 $(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
@@ -451,16 +449,27 @@ $(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
 # if auto.conf.cmd is missing then we are probably in a cleaned tree so
 # we execute the config step to be sure to catch updated Kconfig files
 include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
-ifeq ($(KBUILD_EXTMOD),)
        $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
 else
-       $(error kernel configuration not valid - run 'make prepare' in $(srctree) to update it)
-endif
+# external modules needs include/linux/autoconf.h and include/config/auto.conf
+# but do not care if they are up-to-date. Use auto.conf to trigger the test
+PHONY += include/config/auto.conf
+
+include/config/auto.conf:
+       $(Q)test -e include/linux/autoconf.h -a -e $@ || (              \
+       echo;                                                           \
+       echo "  ERROR: Kernel configuration is invalid.";               \
+       echo "         include/linux/autoconf.h or $@ are missing.";    \
+       echo "         Run 'make oldconfig && make prepare' on kernel src to fix it.";  \
+       echo;                                                           \
+       /bin/false)
+
+endif # KBUILD_EXTMOD
 
 else
 # Dummy target needed, because used as prerequisite
 include/config/auto.conf: ;
-endif
+endif # $(dot-config)
 
 # The all: target is the default when no target is given on the
 # command line.
@@ -474,6 +483,8 @@ else
 CFLAGS         += -O2
 endif
 
+include $(srctree)/arch/$(ARCH)/Makefile
+
 ifdef CONFIG_FRAME_POINTER
 CFLAGS         += -fno-omit-frame-pointer $(call cc-option,-fno-optimize-sibling-calls,)
 else
@@ -488,7 +499,8 @@ ifdef CONFIG_DEBUG_INFO
 CFLAGS         += -g
 endif
 
-include $(srctree)/arch/$(ARCH)/Makefile
+# Force gcc to behave correct even for buggy distributions
+CFLAGS          += $(call cc-option, -fno-stack-protector)
 
 # arch Makefile may override CC so keep this after arch Makefile is included
 NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
index 35c9a64ac14cb81ef93f6309bae4c2f88c4d6f15..4e5445cfb0ea696eff688baf7ecd364f9697fc80 100644 (file)
@@ -68,6 +68,7 @@ void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc
                rtc_time_to_tm(next_time, next);
        }
 }
+EXPORT_SYMBOL(rtc_next_alarm_time);
 
 static inline int rtc_arm_read_time(struct rtc_ops *ops, struct rtc_time *tm)
 {
index 4e29dd03e58297725af0dd5203ac6c55d5317a14..aeeed806f9915574576e5ea628562a86d8f3a7b1 100644 (file)
@@ -233,7 +233,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
        spin_unlock_irq(&die_lock);
 
        if (panic_on_oops)
-               panic("Fatal exception: panic_on_oops");
+               panic("Fatal exception");
 
        do_exit(SIGSEGV);
 }
index 2d40fe1145f0d2f1f68272d3a46d99772323b463..9562177b5fe1454c680a2ed0dc151cd25dbbc503 100644 (file)
@@ -532,8 +532,6 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
        return -EIO;
 }
 
-EXPORT_SYMBOL(pci_set_dma_mask);
-EXPORT_SYMBOL(pci_set_consistent_dma_mask);
 EXPORT_SYMBOL(ixp4xx_pci_read);
 EXPORT_SYMBOL(ixp4xx_pci_write);
 
index 654e2eed81fb26d9b839dbcdbaa4c5e7eb6ed624..30f1300e0e211ef13ee660ef1ba4efdb2f7454f2 100644 (file)
@@ -107,9 +107,9 @@ static struct flash_platform_data gtwx5715_flash_data = {
        .width          = 2,
 };
 
-static struct gtw5715_flash_resource = {
+static struct resource gtwx5715_flash_resource = {
        .flags          = IORESOURCE_MEM,
-}
+};
 
 static struct platform_device gtwx5715_flash = {
        .name           = "IXP4XX-Flash",
@@ -130,9 +130,6 @@ static void __init gtwx5715_init(void)
 {
        ixp4xx_sys_init();
 
-       if (!flash_resource)
-               printk(KERN_ERR "Could not allocate flash resource\n");
-
        gtwx5715_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
        gtwx5715_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_8M - 1;
 
index 0d4005dc06c545b2c488e01ea523a1c80a2892bb..82e0fd02af1c5b7dcaf92a98c76899684e77b85b 100644 (file)
@@ -454,7 +454,7 @@ void die(const char * str, struct pt_regs * regs, long err)
                panic("Fatal exception in interrupt");
 
        if (panic_on_oops)
-               panic("Fatal exception: panic_on_oops");
+               panic("Fatal exception");
 
        oops_exit();
        do_exit(SIGSEGV);
index 5a0420464c6ca747bcf8243646541b33e3b9a2b8..fffa9e0826bc3b8eab092da56ead23c7349d27b6 100644 (file)
@@ -118,7 +118,7 @@ die (const char *str, struct pt_regs *regs, long err)
        spin_unlock_irq(&die.lock);
 
        if (panic_on_oops)
-               panic("Fatal exception: panic_on_oops");
+               panic("Fatal exception");
 
        do_exit(SIGSEGV);
 }
index 13e583f16ede5738c2777dfbdb552d326d7be489..abb325eb8f757e60283110d03e99fc49c2c81e4e 100644 (file)
@@ -836,9 +836,10 @@ config MCA
        bool
 
 config PCI
-       bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) \
-                                 || MPC7448HPC2
-       default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && !PPC_85xx && !PPC_86xx
+       bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
+               || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) || MPC7448HPC2
+       default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \
+               && !PPC_85xx && !PPC_86xx
        default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
        default PCI_QSPAN if !4xx && !CPM2 && 8xx
        help
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
new file mode 100644 (file)
index 0000000..f0c7731
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ * MPC8641 HPCN Device Tree Source
+ *
+ * Copyright 2006 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.
+ */
+
+
+/ {
+       model = "MPC8641HPCN";
+       compatible = "mpc86xx";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpus {
+               #cpus = <2>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,8641@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       d-cache-line-size = <20>;       // 32 bytes
+                       i-cache-line-size = <20>;       // 32 bytes
+                       d-cache-size = <8000>;          // L1, 32K
+                       i-cache-size = <8000>;          // L1, 32K
+                       timebase-frequency = <0>;       // 33 MHz, from uboot
+                       bus-frequency = <0>;            // From uboot
+                       clock-frequency = <0>;          // From uboot
+                       32-bit;
+                       linux,boot-cpu;
+               };
+               PowerPC,8641@1 {
+                       device_type = "cpu";
+                       reg = <1>;
+                       d-cache-line-size = <20>;       // 32 bytes
+                       i-cache-line-size = <20>;       // 32 bytes
+                       d-cache-size = <8000>;          // L1, 32K
+                       i-cache-size = <8000>;          // L1, 32K
+                       timebase-frequency = <0>;       // 33 MHz, from uboot
+                       bus-frequency = <0>;            // From uboot
+                       clock-frequency = <0>;          // From uboot
+                       32-bit;
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <00000000 40000000>;      // 1G at 0x0
+       };
+
+       soc8641@f8000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               #interrupt-cells = <2>;
+               device_type = "soc";
+               ranges = <0 f8000000 00100000>;
+               reg = <f8000000 00100000>;      // CCSRBAR 1M
+               bus-frequency = <0>;
+
+               i2c@3000 {
+                       device_type = "i2c";
+                       compatible = "fsl-i2c";
+                       reg = <3000 100>;
+                       interrupts = <2b 2>;
+                       interrupt-parent = <40000>;
+                       dfsrr;
+               };
+
+               i2c@3100 {
+                       device_type = "i2c";
+                       compatible = "fsl-i2c";
+                       reg = <3100 100>;
+                       interrupts = <2b 2>;
+                       interrupt-parent = <40000>;
+                       dfsrr;
+               };
+
+               mdio@24520 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "mdio";
+                       compatible = "gianfar";
+                       reg = <24520 20>;
+                       linux,phandle = <24520>;
+                       ethernet-phy@0 {
+                               linux,phandle = <2452000>;
+                               interrupt-parent = <40000>;
+                               interrupts = <4a 1>;
+                               reg = <0>;
+                               device_type = "ethernet-phy";
+                       };
+                       ethernet-phy@1 {
+                               linux,phandle = <2452001>;
+                               interrupt-parent = <40000>;
+                               interrupts = <4a 1>;
+                               reg = <1>;
+                               device_type = "ethernet-phy";
+                       };
+                       ethernet-phy@2 {
+                               linux,phandle = <2452002>;
+                               interrupt-parent = <40000>;
+                               interrupts = <4a 1>;
+                               reg = <2>;
+                               device_type = "ethernet-phy";
+                       };
+                       ethernet-phy@3 {
+                               linux,phandle = <2452003>;
+                               interrupt-parent = <40000>;
+                               interrupts = <4a 1>;
+                               reg = <3>;
+                               device_type = "ethernet-phy";
+                       };
+               };
+
+               ethernet@24000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <24000 1000>;
+                       mac-address = [ 00 E0 0C 00 73 00 ];
+                       interrupts = <1d 2 1e 2 22 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452000>;
+               };
+
+               ethernet@25000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <25000 1000>;
+                       mac-address = [ 00 E0 0C 00 73 01 ];
+                       interrupts = <23 2 24 2 28 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452001>;
+               };
+               
+               ethernet@26000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <26000 1000>;
+                       mac-address = [ 00 E0 0C 00 02 FD ];
+                       interrupts = <1F 2 20 2 21 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452002>;
+               };
+
+               ethernet@27000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <27000 1000>;
+                       mac-address = [ 00 E0 0C 00 03 FD ];
+                       interrupts = <25 2 26 2 27 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452003>;
+               };
+               serial@4500 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <4500 100>;
+                       clock-frequency = <0>;
+                       interrupts = <2a 2>;
+                       interrupt-parent = <40000>;
+               };
+
+               serial@4600 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <4600 100>;
+                       clock-frequency = <0>;
+                       interrupts = <1c 2>;
+                       interrupt-parent = <40000>;
+               };
+
+               pci@8000 {
+                       compatible = "86xx";
+                       device_type = "pci";
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg = <8000 1000>;
+                       bus-range = <0 fe>;
+                       ranges = <02000000 0 80000000 80000000 0 20000000
+                                 01000000 0 00000000 e2000000 0 00100000>;
+                       clock-frequency = <1fca055>;
+                       interrupt-parent = <40000>;
+                       interrupts = <18 2>;
+                       interrupt-map-mask = <f800 0 0 7>;
+                       interrupt-map = <
+                               /* IDSEL 0x11 */
+                               8800 0 0 1 4d0 3 2
+                               8800 0 0 2 4d0 4 2
+                               8800 0 0 3 4d0 5 2
+                               8800 0 0 4 4d0 6 2
+
+                               /* IDSEL 0x12 */
+                               9000 0 0 1 4d0 4 2
+                               9000 0 0 2 4d0 5 2
+                               9000 0 0 3 4d0 6 2
+                               9000 0 0 4 4d0 3 2
+
+                               /* IDSEL 0x13 */
+                               9800 0 0 1 4d0 0 0
+                               9800 0 0 2 4d0 0 0
+                               9800 0 0 3 4d0 0 0
+                               9800 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x14 */
+                               a000 0 0 1 4d0 0 0
+                               a000 0 0 2 4d0 0 0
+                               a000 0 0 3 4d0 0 0
+                               a000 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x15 */
+                               a800 0 0 1 4d0 0 0
+                               a800 0 0 2 4d0 0 0
+                               a800 0 0 3 4d0 0 0
+                               a800 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x16 */
+                               b000 0 0 1 4d0 0 0
+                               b000 0 0 2 4d0 0 0
+                               b000 0 0 3 4d0 0 0
+                               b000 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x17 */
+                               b800 0 0 1 4d0 0 0
+                               b800 0 0 2 4d0 0 0
+                               b800 0 0 3 4d0 0 0
+                               b800 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x18 */
+                               c000 0 0 1 4d0 0 0
+                               c000 0 0 2 4d0 0 0
+                               c000 0 0 3 4d0 0 0
+                               c000 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x19 */
+                               c800 0 0 1 4d0 0 0
+                               c800 0 0 2 4d0 0 0
+                               c800 0 0 3 4d0 0 0
+                               c800 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x1a */
+                               d000 0 0 1 4d0 6 2
+                               d000 0 0 2 4d0 3 2
+                               d000 0 0 3 4d0 4 2
+                               d000 0 0 4 4d0 5 2
+
+
+                               /* IDSEL 0x1b */
+                               d800 0 0 1 4d0 5 2
+                               d800 0 0 2 4d0 0 0
+                               d800 0 0 3 4d0 0 0
+                               d800 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x1c */
+                               e000 0 0 1 4d0 9 2
+                               e000 0 0 2 4d0 a 2
+                               e000 0 0 3 4d0 c 2
+                               e000 0 0 4 4d0 7 2
+
+                               /* IDSEL 0x1d */
+                               e800 0 0 1 4d0 9 2
+                               e800 0 0 2 4d0 a 2
+                               e800 0 0 3 4d0 b 2
+                               e800 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x1e */
+                               f000 0 0 1 4d0 c 2
+                               f000 0 0 2 4d0 0 0
+                               f000 0 0 3 4d0 0 0
+                               f000 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x1f */
+                               f800 0 0 1 4d0 6 2
+                               f800 0 0 2 4d0 0 0
+                               f800 0 0 3 4d0 0 0
+                               f800 0 0 4 4d0 0 0
+                               >;
+                       i8259@4d0 {
+                               linux,phandle = <4d0>;
+                               clock-frequency = <0>;
+                               interrupt-controller;
+                               device_type = "interrupt-controller";
+                               #address-cells = <0>;
+                               #interrupt-cells = <2>;
+                               built-in;
+                               compatible = "chrp,iic";
+                               big-endian;
+                               interrupts = <49 2>;
+                               interrupt-parent = <40000>;
+                       };
+
+               };
+               pic@40000 {
+                       linux,phandle = <40000>;
+                       clock-frequency = <0>;
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       #interrupt-cells = <2>;
+                       reg = <40000 40000>;
+                       built-in;
+                       compatible = "chrp,open-pic";
+                       device_type = "open-pic";
+                        big-endian;
+                       interrupts = <
+                               10 2 11 2 12 2 13 2
+                               14 2 15 2 16 2 17 2
+                               18 2 19 2 1a 2 1b 2
+                               1c 2 1d 2 1e 2 1f 2
+                               20 2 21 2 22 2 23 2
+                               24 2 25 2 26 2 27 2
+                               28 2 29 2 2a 2 2b 2
+                               2c 2 2d 2 2e 2 2f 2
+                               30 2 31 2 32 2 33 2
+                               34 2 35 2 36 2 37 2
+                               38 2 39 2 2a 2 3b 2
+                               3c 2 3d 2 3e 2 3f 2
+                               48 1 49 2 4a 1
+                               >;
+                       interrupt-parent = <40000>;
+               };
+       };
+};
index a45627547d03f235716138346a9f929c24ca0ead..8c6bd17c6929c5be6c40f32cb0b3a6a59155a009 100644 (file)
@@ -1,16 +1,18 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc1
-# Wed Apr 19 13:24:37 2006
+# Linux kernel version: 2.6.18-rc3
+# Tue Aug  8 09:12:29 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
 CONFIG_PPC_MERGE=y
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_COMPAT=y
@@ -33,6 +35,7 @@ CONFIG_PPC_STD_MMU=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=4
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
@@ -50,6 +53,7 @@ CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
@@ -67,10 +71,12 @@ CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -116,12 +122,16 @@ CONFIG_PPC_PMAC=y
 CONFIG_PPC_PMAC64=y
 # CONFIG_PPC_MAPLE is not set
 # CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_IBM_CELL_BLADE is not set
+# CONFIG_UDBG_RTAS_CONSOLE is not set
 CONFIG_U3_DART=y
 CONFIG_MPIC=y
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
 CONFIG_MPIC_BROKEN_U3=y
 # CONFIG_PPC_MPC106 is not set
+CONFIG_PPC_970_NAP=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_TABLE=y
 # CONFIG_CPU_FREQ_DEBUG is not set
@@ -153,6 +163,7 @@ CONFIG_BINFMT_ELF=y
 CONFIG_FORCE_MAX_ZONEORDER=13
 CONFIG_IOMMU_VMERGE=y
 # CONFIG_HOTPLUG_CPU is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_KEXEC=y
 # CONFIG_CRASH_DUMP is not set
 CONFIG_IRQ_ALL_CPUS=y
@@ -168,6 +179,7 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
 # CONFIG_PPC_64K_PAGES is not set
 # CONFIG_SCHED_SMT is not set
 CONFIG_PROC_DEVICETREE=y
@@ -184,6 +196,7 @@ CONFIG_GENERIC_ISA_DMA=y
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -227,6 +240,8 @@ CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -239,6 +254,7 @@ CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -263,6 +279,7 @@ CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_PPTP is not set
 # CONFIG_IP_NF_H323 is not set
+# CONFIG_IP_NF_SIP is not set
 CONFIG_IP_NF_QUEUE=m
 
 #
@@ -318,6 +335,7 @@ CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -355,6 +373,7 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -417,7 +436,6 @@ CONFIG_IDEDMA_PCI_AUTO=y
 CONFIG_BLK_DEV_IDE_PMAC=y
 CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
 CONFIG_BLK_DEV_IDEDMA_PMAC=y
-# CONFIG_BLK_DEV_IDE_PMAC_BLINK is not set
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -478,6 +496,7 @@ CONFIG_SCSI_SATA_SVW=y
 # CONFIG_SCSI_SATA_MV is not set
 # CONFIG_SCSI_SATA_NV is not set
 # CONFIG_SCSI_PDC_ADMA is not set
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_SATA_QSTOR is not set
 # CONFIG_SCSI_SATA_PROMISE is not set
 # CONFIG_SCSI_SATA_SX4 is not set
@@ -497,7 +516,6 @@ CONFIG_SCSI_SATA_SVW=y
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 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_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -514,9 +532,7 @@ CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID10=m
-CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID5_RESHAPE is not set
-CONFIG_MD_RAID6=m
+# CONFIG_MD_RAID456 is not set
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=y
@@ -559,7 +575,6 @@ CONFIG_IEEE1394_OHCI1394=y
 #
 CONFIG_IEEE1394_VIDEO1394=m
 CONFIG_IEEE1394_SBP2=m
-# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
 CONFIG_IEEE1394_ETH1394=m
 CONFIG_IEEE1394_DV1394=m
 CONFIG_IEEE1394_RAWIO=y
@@ -573,6 +588,7 @@ CONFIG_IEEE1394_RAWIO=y
 # Macintosh device drivers
 #
 CONFIG_ADB_PMU=y
+# CONFIG_ADB_PMU_LED is not set
 CONFIG_PMAC_SMU=y
 CONFIG_THERM_PM72=y
 CONFIG_WINDFARM=y
@@ -643,6 +659,7 @@ CONFIG_TIGON3=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
 
 #
 # Token Ring devices
@@ -739,6 +756,7 @@ CONFIG_SERIO=y
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -754,6 +772,7 @@ CONFIG_HW_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_BRIQ_PANEL is not set
 
 #
 # IPMI
@@ -764,6 +783,7 @@ CONFIG_LEGACY_PTY_COUNT=256
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
 # CONFIG_DTLK is not set
@@ -774,6 +794,7 @@ CONFIG_GEN_RTC=y
 # Ftape, the floppy tape device driver
 #
 CONFIG_AGP=m
+# CONFIG_AGP_SIS is not set
 # CONFIG_AGP_VIA is not set
 CONFIG_AGP_UNINORTH=m
 # CONFIG_DRM is not set
@@ -813,6 +834,7 @@ CONFIG_I2C_ALGOBIT=y
 # CONFIG_I2C_PIIX4 is not set
 CONFIG_I2C_POWERMAC=y
 # CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
@@ -849,7 +871,6 @@ CONFIG_I2C_POWERMAC=y
 #
 # Dallas's 1-wire bus
 #
-# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -865,6 +886,7 @@ CONFIG_I2C_POWERMAC=y
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -875,22 +897,19 @@ CONFIG_I2C_POWERMAC=y
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 CONFIG_FB=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 CONFIG_FB_MACMODES=y
-CONFIG_FB_FIRMWARE_EDID=y
+# CONFIG_FB_BACKLIGHT is not set
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 CONFIG_FB_OF=y
-# CONFIG_FB_CONTROL is not set
-# CONFIG_FB_PLATINUM is not set
-# CONFIG_FB_VALKYRIE is not set
-# CONFIG_FB_CT65550 is not set
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
 # CONFIG_FB_VGA16 is not set
@@ -990,6 +1009,18 @@ CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_CMIPCI is not set
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
 # CONFIG_SND_EMU10K1 is not set
 # CONFIG_SND_EMU10K1X is not set
 # CONFIG_SND_ENS1370 is not set
@@ -1026,6 +1057,17 @@ CONFIG_SND_VERBOSE_PROCFS=y
 CONFIG_SND_POWERMAC=m
 CONFIG_SND_POWERMAC_AUTO_DRC=y
 
+#
+# Apple Onboard Audio driver
+#
+CONFIG_SND_AOA=m
+CONFIG_SND_AOA_FABRIC_LAYOUT=m
+CONFIG_SND_AOA_ONYX=m
+CONFIG_SND_AOA_TAS=m
+CONFIG_SND_AOA_TOONIE=m
+CONFIG_SND_AOA_SOUNDBUS=m
+CONFIG_SND_AOA_SOUNDBUS_I2S=m
+
 #
 # USB devices
 #
@@ -1060,6 +1102,7 @@ CONFIG_USB_DEVICEFS=y
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN is not set
@@ -1110,9 +1153,7 @@ CONFIG_USB_HIDDEV=y
 # 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_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -1155,6 +1196,7 @@ CONFIG_USB_SERIAL=m
 CONFIG_USB_SERIAL_GENERIC=y
 # CONFIG_USB_SERIAL_AIRPRIME is not set
 # CONFIG_USB_SERIAL_ANYDATA is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
 CONFIG_USB_SERIAL_BELKIN=m
 # CONFIG_USB_SERIAL_WHITEHEAT is not set
 CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
@@ -1162,6 +1204,7 @@ CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
 CONFIG_USB_SERIAL_CYPRESS_M8=m
 CONFIG_USB_SERIAL_EMPEG=m
 CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
 CONFIG_USB_SERIAL_VISOR=m
 CONFIG_USB_SERIAL_IPAQ=m
 CONFIG_USB_SERIAL_IR=m
@@ -1191,9 +1234,11 @@ CONFIG_USB_SERIAL_PL2303=m
 # CONFIG_USB_SERIAL_HP4X is not set
 CONFIG_USB_SERIAL_SAFE=m
 CONFIG_USB_SERIAL_SAFE_PADDED=y
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
 CONFIG_USB_SERIAL_TI=m
 CONFIG_USB_SERIAL_CYBERJACK=m
 CONFIG_USB_SERIAL_XIRCOM=m
+# CONFIG_USB_SERIAL_OPTION is not set
 CONFIG_USB_SERIAL_OMNINET=m
 CONFIG_USB_EZUSB=y
 
@@ -1207,10 +1252,12 @@ CONFIG_USB_EZUSB=y
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 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
+CONFIG_USB_APPLEDISPLAY=m
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
@@ -1234,6 +1281,14 @@ CONFIG_USB_EZUSB=y
 #
 # CONFIG_NEW_LEDS is not set
 
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
 #
 # InfiniBand support
 #
@@ -1248,6 +1303,19 @@ CONFIG_USB_EZUSB=y
 #
 # CONFIG_RTC_CLASS is not set
 
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
 #
 # File systems
 #
@@ -1273,7 +1341,6 @@ CONFIG_REISERFS_FS_SECURITY=y
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
-CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_QUOTA is not set
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
@@ -1282,6 +1349,7 @@ CONFIG_XFS_POSIX_ACL=y
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
@@ -1363,7 +1431,9 @@ CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_SMB_FS is not set
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
 # CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_CIFS_EXPERIMENTAL is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
@@ -1444,6 +1514,9 @@ CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_PLIST=y
 
 #
 # Instrumentation Support
@@ -1457,14 +1530,19 @@ CONFIG_OPROFILE=y
 #
 # CONFIG_PRINTK_TIME is not set
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
@@ -1476,11 +1554,7 @@ CONFIG_FORCED_INLINING=y
 # CONFIG_DEBUGGER is not set
 CONFIG_IRQSTACKS=y
 CONFIG_BOOTX_TEXT=y
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
 
 #
 # Security options
index a95e455a1944a9a2102af115416a43eeeb867daa..72ed95b3ead63bb25dab624fb8b61b8ca44a81d2 100644 (file)
@@ -1,16 +1,18 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc1
-# Wed Apr 19 11:46:44 2006
+# Linux kernel version: 2.6.18-rc3
+# Tue Aug  8 09:15:46 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
 CONFIG_PPC_MERGE=y
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_COMPAT=y
@@ -34,6 +36,7 @@ CONFIG_PPC_STD_MMU=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
@@ -51,6 +54,7 @@ CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
 CONFIG_SYSCTL=y
 CONFIG_AUDIT=y
 CONFIG_AUDITSYSCALL=y
@@ -69,10 +73,12 @@ CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -113,10 +119,14 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 CONFIG_PPC_ISERIES=y
 # CONFIG_EMBEDDED6xx is not set
 # CONFIG_APUS is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_UDBG_RTAS_CONSOLE is not set
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
 CONFIG_IBMVIO=y
 # CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
 # CONFIG_CPU_FREQ is not set
 # CONFIG_WANT_EARLY_SERIAL is not set
 
@@ -135,6 +145,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_FORCE_MAX_ZONEORDER=13
 CONFIG_IOMMU_VMERGE=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_LPARCFG=y
 # CONFIG_NUMA is not set
@@ -149,6 +160,7 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
 # CONFIG_PPC_64K_PAGES is not set
 # CONFIG_SCHED_SMT is not set
 CONFIG_PROC_DEVICETREE=y
@@ -164,6 +176,7 @@ CONFIG_GENERIC_ISA_DMA=y
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -207,6 +220,8 @@ CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -219,6 +234,7 @@ CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -246,9 +262,11 @@ CONFIG_NETFILTER_XT_MATCH_MARK=m
 # CONFIG_NETFILTER_XT_MATCH_POLICY is not set
 # CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 
@@ -267,6 +285,7 @@ CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_PPTP is not set
 # CONFIG_IP_NF_H323 is not set
+# CONFIG_IP_NF_SIP is not set
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
@@ -360,6 +379,7 @@ CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=m
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -396,6 +416,7 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
@@ -453,6 +474,7 @@ CONFIG_SCSI_FC_ATTRS=y
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
 # CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
@@ -464,7 +486,6 @@ CONFIG_SCSI_IBMVSCSI=m
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 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_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -481,9 +502,7 @@ CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID10=m
-CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID5_RESHAPE is not set
-CONFIG_MD_RAID6=m
+# CONFIG_MD_RAID456 is not set
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=y
@@ -596,6 +615,7 @@ CONFIG_E1000=m
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
 
 #
 # Token Ring devices
@@ -696,6 +716,7 @@ CONFIG_SERIAL_ICOM=m
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_BRIQ_PANEL is not set
 
 #
 # IPMI
@@ -706,6 +727,7 @@ CONFIG_LEGACY_PTY_COUNT=256
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
 # CONFIG_DTLK is not set
@@ -741,7 +763,6 @@ CONFIG_MAX_RAW_DEVS=256
 #
 # Dallas's 1-wire bus
 #
-# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -757,6 +778,7 @@ CONFIG_MAX_RAW_DEVS=256
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -766,7 +788,9 @@ CONFIG_MAX_RAW_DEVS=256
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -800,6 +824,14 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 #
 # CONFIG_NEW_LEDS is not set
 
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
 #
 # InfiniBand support
 #
@@ -814,6 +846,19 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 #
 # CONFIG_RTC_CLASS is not set
 
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
 #
 # File systems
 #
@@ -843,7 +888,6 @@ CONFIG_JFS_SECURITY=y
 # CONFIG_JFS_STATISTICS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
-CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_QUOTA is not set
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
@@ -852,6 +896,7 @@ CONFIG_XFS_POSIX_ACL=y
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
@@ -933,8 +978,10 @@ CONFIG_RPCSEC_GSS_SPKM3=m
 # CONFIG_SMB_FS is not set
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
 CONFIG_CIFS_XATTR=y
 CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_CIFS_EXPERIMENTAL is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
@@ -1013,10 +1060,12 @@ CONFIG_TEXTSEARCH=y
 CONFIG_TEXTSEARCH_KMP=m
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
 
 #
 # Instrumentation Support
 #
+# CONFIG_PROFILING is not set
 # CONFIG_KPROBES is not set
 
 #
@@ -1024,14 +1073,19 @@ CONFIG_TEXTSEARCH_FSM=m
 #
 # CONFIG_PRINTK_TIME is not set
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
@@ -1042,11 +1096,7 @@ CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
 # CONFIG_DEBUGGER is not set
 CONFIG_IRQSTACKS=y
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
 
 #
 # Security options
index 31708ad4574e20e3a3bcb9bf764e8d34ecaee79e..c18e8600d78f6d46ba2d3dde6d08cb2ee9bc2c01 100644 (file)
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc4
-# Sun May 28 07:26:56 2006
+# Linux kernel version: 2.6.18-rc3
+# Tue Aug  8 09:14:48 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
 CONFIG_PPC_MERGE=y
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -35,6 +36,7 @@ CONFIG_PPC_STD_MMU=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=128
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
@@ -52,6 +54,7 @@ CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
 CONFIG_SYSCTL=y
 CONFIG_AUDIT=y
 CONFIG_AUDITSYSCALL=y
@@ -70,10 +73,12 @@ CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -118,6 +123,9 @@ CONFIG_PPC_PSERIES=y
 # CONFIG_PPC_PMAC is not set
 # CONFIG_PPC_MAPLE is not set
 # CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_IBM_CELL_BLADE is not set
+# CONFIG_UDBG_RTAS_CONSOLE is not set
 CONFIG_XICS=y
 # CONFIG_U3_DART is not set
 CONFIG_MPIC=y
@@ -149,6 +157,7 @@ CONFIG_BINFMT_MISC=m
 CONFIG_FORCE_MAX_ZONEORDER=13
 CONFIG_IOMMU_VMERGE=y
 CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_KEXEC=y
 # CONFIG_CRASH_DUMP is not set
 CONFIG_IRQ_ALL_CPUS=y
@@ -173,6 +182,7 @@ CONFIG_SPARSEMEM_EXTREME=y
 # CONFIG_MEMORY_HOTPLUG is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_MIGRATION=y
+CONFIG_RESOURCES_64BIT=y
 CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
 # CONFIG_PPC_64K_PAGES is not set
 CONFIG_SCHED_SMT=y
@@ -190,6 +200,7 @@ CONFIG_PPC_I8259=y
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -238,6 +249,8 @@ CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -250,6 +263,7 @@ CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -277,6 +291,7 @@ CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_PPTP is not set
 # CONFIG_IP_NF_H323 is not set
+# CONFIG_IP_NF_SIP is not set
 CONFIG_IP_NF_QUEUE=m
 
 #
@@ -316,6 +331,7 @@ CONFIG_LLC=y
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -332,6 +348,7 @@ CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -352,6 +369,7 @@ CONFIG_PARPORT_PC=m
 # CONFIG_PARPORT_PC_FIFO is not set
 # CONFIG_PARPORT_PC_SUPERIO is not set
 # CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
 # CONFIG_PARPORT_1284 is not set
 
 #
@@ -376,6 +394,7 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
@@ -487,6 +506,7 @@ CONFIG_SCSI_SAS_ATTRS=m
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
 # CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
@@ -508,12 +528,6 @@ CONFIG_SCSI_IPR_TRACE=y
 CONFIG_SCSI_IPR_DUMP=y
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA_FC=m
-CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE=y
-CONFIG_SCSI_QLA21XX=m
-CONFIG_SCSI_QLA22XX=m
-CONFIG_SCSI_QLA2300=m
-CONFIG_SCSI_QLA2322=m
-CONFIG_SCSI_QLA24XX=m
 CONFIG_SCSI_LPFC=m
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -528,9 +542,7 @@ CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID10=m
-CONFIG_MD_RAID5=y
-CONFIG_MD_RAID5_RESHAPE=y
-CONFIG_MD_RAID6=m
+# CONFIG_MD_RAID456 is not set
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=y
@@ -651,6 +663,7 @@ CONFIG_IXGB=m
 # CONFIG_IXGB_NAPI is not set
 CONFIG_S2IO=m
 # CONFIG_S2IO_NAPI is not set
+# CONFIG_MYRI10GE is not set
 
 #
 # Token Ring devices
@@ -754,6 +767,7 @@ CONFIG_SERIO_LIBPS2=y
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -776,6 +790,7 @@ CONFIG_SERIAL_JSM=m
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_BRIQ_PANEL is not set
 # CONFIG_PRINTER is not set
 # CONFIG_PPDEV is not set
 # CONFIG_TIPAR is not set
@@ -793,6 +808,7 @@ CONFIG_HVCS=m
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
 # CONFIG_DTLK is not set
@@ -839,6 +855,7 @@ CONFIG_I2C_ALGOBIT=y
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
@@ -876,7 +893,6 @@ CONFIG_I2C_ALGOBIT=y
 #
 # Dallas's 1-wire bus
 #
-# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -892,6 +908,7 @@ CONFIG_I2C_ALGOBIT=y
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -902,19 +919,19 @@ CONFIG_I2C_ALGOBIT=y
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 CONFIG_FB=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 CONFIG_FB_MACMODES=y
-CONFIG_FB_FIRMWARE_EDID=y
+# CONFIG_FB_BACKLIGHT is not set
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 CONFIG_FB_OF=y
-# CONFIG_FB_CT65550 is not set
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
 # CONFIG_FB_VGA16 is not set
@@ -993,6 +1010,7 @@ CONFIG_USB_DEVICEFS=y
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN is not set
@@ -1083,10 +1101,12 @@ CONFIG_USB_MON=y
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 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
+# CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
@@ -1124,12 +1144,14 @@ CONFIG_USB_MON=y
 CONFIG_INFINIBAND=m
 CONFIG_INFINIBAND_USER_MAD=m
 CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
 CONFIG_INFINIBAND_MTHCA=m
 CONFIG_INFINIBAND_MTHCA_DEBUG=y
 CONFIG_INFINIBAND_IPOIB=m
 CONFIG_INFINIBAND_IPOIB_DEBUG=y
 # CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
 CONFIG_INFINIBAND_SRP=m
+# CONFIG_INFINIBAND_ISER is not set
 
 #
 # EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
@@ -1140,6 +1162,19 @@ CONFIG_INFINIBAND_SRP=m
 #
 # CONFIG_RTC_CLASS is not set
 
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
 #
 # File systems
 #
@@ -1169,15 +1204,16 @@ CONFIG_JFS_SECURITY=y
 # CONFIG_JFS_STATISTICS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
-CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_QUOTA is not set
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
 # CONFIG_XFS_RT is not set
 CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_DEBUG_MASKLOG=y
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
@@ -1259,8 +1295,10 @@ CONFIG_RPCSEC_GSS_SPKM3=m
 # CONFIG_SMB_FS is not set
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
 CONFIG_CIFS_XATTR=y
 CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_CIFS_EXPERIMENTAL is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
@@ -1326,6 +1364,9 @@ CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_PLIST=y
 
 #
 # Instrumentation Support
@@ -1339,14 +1380,19 @@ CONFIG_KPROBES=y
 #
 # CONFIG_PRINTK_TIME is not set
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
index 814f242aeb8cc06348603c2df8478b0dd0d4e274..956c2e5564b7a647592c51910b086a7812f2c285 100644 (file)
@@ -67,9 +67,9 @@ pci64-$(CONFIG_PPC64)         += pci_64.o pci_dn.o pci_iommu.o \
                                   pci_direct_iommu.o iomap.o
 pci32-$(CONFIG_PPC32)          := pci_32.o
 obj-$(CONFIG_PCI)              += $(pci64-y) $(pci32-y)
-kexec-$(CONFIG_PPC64)          := machine_kexec_64.o crash.o
+kexec-$(CONFIG_PPC64)          := machine_kexec_64.o
 kexec-$(CONFIG_PPC32)          := machine_kexec_32.o
-obj-$(CONFIG_KEXEC)            += machine_kexec.o $(kexec-y)
+obj-$(CONFIG_KEXEC)            += machine_kexec.o crash.o $(kexec-y)
 
 ifeq ($(CONFIG_PPC_ISERIES),y)
 $(obj)/head_64.o: $(obj)/lparmap.s
index f69af2c5d7b30faaead1c3f9473e6c8b91182674..76e97aa71c45b307347e58f031cf97ecd20dd348 100644 (file)
@@ -76,6 +76,8 @@ _GLOBAL(__setup_cpu_ppc970)
        mfspr   r0,SPRN_HID0
        li      r11,5                   /* clear DOZE and SLEEP */
        rldimi  r0,r11,52,8             /* set NAP and DPM */
+       li      r11,0
+       rldimi  r0,r11,32,31            /* clear EN_ATTN */
        mtspr   SPRN_HID0,r0
        mfspr   r0,SPRN_HID0
        mfspr   r0,SPRN_HID0
index 358cecdc6aef2e1ab8e91778897db3accce3fd11..f04c18e08b8b6dcf9f52e422db1c4aa2b0a2854a 100644 (file)
@@ -44,6 +44,7 @@
 /* This keeps a track of which one is crashing cpu. */
 int crashing_cpu = -1;
 static cpumask_t cpus_in_crash = CPU_MASK_NONE;
+cpumask_t cpus_in_sr = CPU_MASK_NONE;
 
 static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
                                                               size_t data_len)
@@ -139,7 +140,13 @@ void crash_ipi_callback(struct pt_regs *regs)
 
        if (ppc_md.kexec_cpu_down)
                ppc_md.kexec_cpu_down(1, 1);
+
+#ifdef CONFIG_PPC64
        kexec_smp_wait();
+#else
+       for (;;);       /* FIXME */
+#endif
+
        /* NOTREACHED */
 }
 
@@ -255,7 +262,11 @@ static void crash_kexec_prepare_cpus(int cpu)
         *
         * do this if kexec in setup.c ?
         */
+#ifdef CONFIG_PPC64
        smp_release_cpus();
+#else
+       /* FIXME */
+#endif
 }
 
 void crash_kexec_secondary(struct pt_regs *regs)
index 01bdae35cb5590ed1aff66f6f6cfcb945be99495..7ee6854333191b420472b7234e0db5713b80335b 100644 (file)
@@ -693,7 +693,7 @@ unsigned int irq_radix_revmap(struct irq_host *host,
        /* If not there, try to insert it */
        virq = irq_find_mapping(host, hwirq);
        if (virq != NO_IRQ)
-               radix_tree_insert(tree, virq, &irq_map[virq]);
+               radix_tree_insert(tree, hwirq, &irq_map[virq]);
  bail:
        spin_unlock_irqrestore(&irq_big_lock, flags);
        return virq;
index 9f0898c897592d41760817b396adeff3b15b3784..cd65c367b8b6d5c9abcc23fe7cbf595931814a5d 100644 (file)
@@ -61,6 +61,8 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
        if (!ret) {
                memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
                p->opcode = *p->addr;
+               flush_icache_range((unsigned long)p->ainsn.insn,
+                       (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
        }
 
        return ret;
index a81ca1b841ec89a0c5eff398b676dac5a3ae85fc..e60a0c544d6347684dda853203a30a9c362d3d8b 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/reboot.h>
 #include <linux/threads.h>
 #include <asm/machdep.h>
+#include <asm/lmb.h>
 
 void machine_crash_shutdown(struct pt_regs *regs)
 {
@@ -59,3 +60,58 @@ NORET_TYPE void machine_kexec(struct kimage *image)
        }
        for(;;);
 }
+
+static int __init early_parse_crashk(char *p)
+{
+       unsigned long size;
+
+       if (!p)
+               return 1;
+
+       size = memparse(p, &p);
+
+       if (*p == '@')
+               crashk_res.start = memparse(p + 1, &p);
+       else
+               crashk_res.start = KDUMP_KERNELBASE;
+
+       crashk_res.end = crashk_res.start + size - 1;
+
+       return 0;
+}
+early_param("crashkernel", early_parse_crashk);
+
+void __init reserve_crashkernel(void)
+{
+       unsigned long size;
+
+       if (crashk_res.start == 0)
+               return;
+
+       /* We might have got these values via the command line or the
+        * device tree, either way sanitise them now. */
+
+       size = crashk_res.end - crashk_res.start + 1;
+
+       if (crashk_res.start != KDUMP_KERNELBASE)
+               printk("Crash kernel location must be 0x%x\n",
+                               KDUMP_KERNELBASE);
+
+       crashk_res.start = KDUMP_KERNELBASE;
+       size = PAGE_ALIGN(size);
+       crashk_res.end = crashk_res.start + size - 1;
+
+       /* Crash kernel trumps memory limit */
+       if (memory_limit && memory_limit <= crashk_res.end) {
+               memory_limit = crashk_res.end + 1;
+               printk("Adjusted memory limit for crashkernel, now 0x%lx\n",
+                               memory_limit);
+       }
+
+       lmb_reserve(crashk_res.start, size);
+}
+
+int overlaps_crashkernel(unsigned long start, unsigned long size)
+{
+       return (start + size) > crashk_res.start && start <= crashk_res.end;
+}
index b438d45a068c6b0dd621b0f51520f9478b729539..be58985c7681edd8ffede42b4d32468494b2145f 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 
-#include <linux/cpumask.h>
 #include <linux/kexec.h>
 #include <linux/smp.h>
 #include <linux/thread_info.h>
@@ -21,7 +20,6 @@
 #include <asm/machdep.h>
 #include <asm/cacheflush.h>
 #include <asm/paca.h>
-#include <asm/lmb.h>
 #include <asm/mmu.h>
 #include <asm/sections.h>      /* _end */
 #include <asm/prom.h>
@@ -385,58 +383,3 @@ static int __init kexec_setup(void)
        return 0;
 }
 __initcall(kexec_setup);
-
-static int __init early_parse_crashk(char *p)
-{
-       unsigned long size;
-
-       if (!p)
-               return 1;
-
-       size = memparse(p, &p);
-
-       if (*p == '@')
-               crashk_res.start = memparse(p + 1, &p);
-       else
-               crashk_res.start = KDUMP_KERNELBASE;
-
-       crashk_res.end = crashk_res.start + size - 1;
-
-       return 0;
-}
-early_param("crashkernel", early_parse_crashk);
-
-void __init reserve_crashkernel(void)
-{
-       unsigned long size;
-
-       if (crashk_res.start == 0)
-               return;
-
-       /* We might have got these values via the command line or the
-        * device tree, either way sanitise them now. */
-
-       size = crashk_res.end - crashk_res.start + 1;
-
-       if (crashk_res.start != KDUMP_KERNELBASE)
-               printk("Crash kernel location must be 0x%x\n",
-                               KDUMP_KERNELBASE);
-
-       crashk_res.start = KDUMP_KERNELBASE;
-       size = PAGE_ALIGN(size);
-       crashk_res.end = crashk_res.start + size - 1;
-
-       /* Crash kernel trumps memory limit */
-       if (memory_limit && memory_limit <= crashk_res.end) {
-               memory_limit = crashk_res.end + 1;
-               printk("Adjusted memory limit for crashkernel, now 0x%lx\n",
-                               memory_limit);
-       }
-
-       lmb_reserve(crashk_res.start, size);
-}
-
-int overlaps_crashkernel(unsigned long start, unsigned long size)
-{
-       return (start + size) > crashk_res.start && start <= crashk_res.end;
-}
index 4a4cb5598402731afaa5717b25607a5272bab6ec..77f1e06d208d2984bf0b12d79f2d6733c8c53b5f 100644 (file)
@@ -569,6 +569,27 @@ int rtas_set_indicator(int indicator, int index, int new_value)
 }
 EXPORT_SYMBOL(rtas_set_indicator);
 
+/*
+ * Ignoring RTAS extended delay
+ */
+int rtas_set_indicator_fast(int indicator, int index, int new_value)
+{
+       int rc;
+       int token = rtas_token("set-indicator");
+
+       if (token == RTAS_UNKNOWN_SERVICE)
+               return -ENOENT;
+
+       rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value);
+
+       WARN_ON(rc == -2 || (rc >= 9900 && rc <= 9905));
+
+       if (rc < 0)
+               return rtas_error_rc(rc);
+
+       return rc;
+}
+
 void rtas_restart(char *cmd)
 {
        if (rtas_flash_term_hook)
index 2105767fcc57dff8b22c699aa2bdf0fbb63581cf..e4d1713e8aea30fe225d07c39b18cb9b2df5ca92 100644 (file)
@@ -55,9 +55,6 @@
 
 #ifdef CONFIG_PPC64    /* XXX */
 #define _IO_BASE       pci_io_base
-#ifdef CONFIG_KEXEC
-cpumask_t cpus_in_sr = CPU_MASK_NONE;
-#endif
 #endif
 
 #ifdef CONFIG_DEBUGGER
@@ -151,7 +148,7 @@ int die(const char *str, struct pt_regs *regs, long err)
                panic("Fatal exception in interrupt");
 
        if (panic_on_oops)
-               panic("Fatal exception: panic_on_oops");
+               panic("Fatal exception");
 
        do_exit(err);
 
@@ -211,6 +208,19 @@ void system_reset_exception(struct pt_regs *regs)
 
        die("System Reset", regs, SIGABRT);
 
+       /*
+        * Some CPUs when released from the debugger will execute this path.
+        * These CPUs entered the debugger via a soft-reset. If the CPU was
+        * hung before entering the debugger it will return to the hung
+        * state when exiting this function.  This causes a problem in
+        * kdump since the hung CPU(s) will not respond to the IPI sent
+        * from kdump. To prevent the problem we call crash_kexec_secondary()
+        * here. If a kdump had not been initiated or we exit the debugger
+        * with the "exit and recover" command (x) crash_kexec_secondary()
+        * will return after 5ms and the CPU returns to its previous state.
+        */
+       crash_kexec_secondary(regs);
+
        /* Must die if the interrupt is not recoverable */
        if (!(regs->msr & MSR_RI))
                panic("Unrecoverable System Reset");
index 71c634e0b87cdc1cbe30df395837a1b090815e84..31867a701fcbfe25b20b29ae02a3c4b04e714515 100644 (file)
@@ -213,8 +213,6 @@ static void pseries_lpar_enable_pmcs(void)
 {
        unsigned long set, reset;
 
-       power4_enable_pmcs();
-
        set = 1UL << 63;
        reset = 0;
        plpar_hcall_norets(H_PERFMON, set, reset);
index 2d0da6f9e244b9fa44c4f710828fd8a5c86d19a7..e98863025721d47e907fc35e94c8cace7ce1a5a0 100644 (file)
@@ -467,7 +467,7 @@ void xics_setup_cpu(void)
         *
         * XXX: undo of teardown on kexec needs this too, as may hotplug
         */
-       rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
+       rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
                (1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
 }
 
@@ -796,7 +796,7 @@ void xics_teardown_cpu(int secondary)
         * so leave the master cpu in the group.
         */
        if (secondary)
-               rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
+               rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
                                   (1UL << interrupt_server_size) - 1 -
                                   default_distrib_server, 0);
 }
@@ -813,7 +813,7 @@ void xics_migrate_irqs_away(void)
        xics_set_cpu_priority(cpu, 0);
 
        /* remove ourselves from the global interrupt queue */
-       status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
+       status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
                (1UL << interrupt_server_size) - 1 - default_distrib_server, 0);
        WARN_ON(status < 0);
 
index e983972132d8cf2f37d3cbd1fecf5ac19bb8eed3..12b65609c072cd801acb8f469a6b2e667f2147a3 100644 (file)
@@ -169,8 +169,16 @@ static int __init gfar_of_init(void)
                        goto err;
                }
 
-               mac_addr = get_property(np, "address", NULL);
-               memcpy(gfar_data.mac_addr, mac_addr, 6);
+               mac_addr = get_property(np, "local-mac-address", NULL);
+               if (mac_addr == NULL)
+                       mac_addr = get_property(np, "mac-address", NULL);
+               if (mac_addr == NULL) {
+                       /* Obsolete */
+                       mac_addr = get_property(np, "address", NULL);
+               }
+
+               if (mac_addr)
+                       memcpy(gfar_data.mac_addr, mac_addr, 6);
 
                if (model && !strcasecmp(model, "TSEC"))
                        gfar_data.device_flags =
index d90cd24d018e4e70f0f7df7a526cbdcd83f22d29..94badafe4ef18478c5cb353ca39980c3cd1e6585 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/initrd.h>
 #include <linux/module.h>
 #include <linux/fsl_devices.h>
+#include <linux/fs_enet_pd.h>
 
 #include <asm/system.h>
 #include <asm/pgtable.h>
  * Setup the architecture
  *
  */
+static void init_fcc_ioports(void)
+{
+       struct immap *immap;
+       struct io_port *io;
+       u32 tempval;
+
+       immap = cpm2_immr;
+
+       io = &immap->im_ioport;
+       /* FCC2/3 are on the ports B/C. */
+       tempval = in_be32(&io->iop_pdirb);
+       tempval &= ~PB2_DIRB0;
+       tempval |= PB2_DIRB1;
+       out_be32(&io->iop_pdirb, tempval);
+
+       tempval = in_be32(&io->iop_psorb);
+       tempval &= ~PB2_PSORB0;
+       tempval |= PB2_PSORB1;
+       out_be32(&io->iop_psorb, tempval);
+
+       tempval = in_be32(&io->iop_pparb);
+       tempval |= (PB2_DIRB0 | PB2_DIRB1);
+       out_be32(&io->iop_pparb, tempval);
+
+       tempval = in_be32(&io->iop_pdirb);
+       tempval &= ~PB3_DIRB0;
+       tempval |= PB3_DIRB1;
+       out_be32(&io->iop_pdirb, tempval);
+
+       tempval = in_be32(&io->iop_psorb);
+       tempval &= ~PB3_PSORB0;
+       tempval |= PB3_PSORB1;
+       out_be32(&io->iop_psorb, tempval);
+
+       tempval = in_be32(&io->iop_pparb);
+       tempval |= (PB3_DIRB0 | PB3_DIRB1);
+       out_be32(&io->iop_pparb, tempval);
+
+        tempval = in_be32(&io->iop_pdirc);
+        tempval |= PC3_DIRC1;
+        out_be32(&io->iop_pdirc, tempval);
+
+        tempval = in_be32(&io->iop_pparc);
+        tempval |= PC3_DIRC1;
+        out_be32(&io->iop_pparc, tempval);
+
+       /* Port C has clocks......  */
+       tempval = in_be32(&io->iop_psorc);
+       tempval &= ~(CLK_TRX);
+       out_be32(&io->iop_psorc, tempval);
+
+       tempval = in_be32(&io->iop_pdirc);
+       tempval &= ~(CLK_TRX);
+       out_be32(&io->iop_pdirc, tempval);
+       tempval = in_be32(&io->iop_pparc);
+       tempval |= (CLK_TRX);
+       out_be32(&io->iop_pparc, tempval);
+
+       /* Configure Serial Interface clock routing.
+        * First,  clear all FCC bits to zero,
+        * then set the ones we want.
+        */
+       immap->im_cpmux.cmx_fcr &= ~(CPMUX_CLK_MASK);
+       immap->im_cpmux.cmx_fcr |= CPMUX_CLK_ROUTE;
+}
 
 static void __init
 mpc8560ads_setup_arch(void)
@@ -66,6 +132,7 @@ mpc8560ads_setup_arch(void)
        unsigned int freq;
        struct gianfar_platform_data *pdata;
        struct gianfar_mdio_data *mdata;
+       struct fs_platform_info *fpi;
 
        cpm2_reset();
 
@@ -110,6 +177,28 @@ mpc8560ads_setup_arch(void)
                memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
        }
 
+       init_fcc_ioports();
+       ppc_sys_device_remove(MPC85xx_CPM_FCC1);
+
+       fpi = (struct fs_platform_info *) ppc_sys_get_pdata(MPC85xx_CPM_FCC2);
+       if (fpi) {
+               memcpy(fpi->macaddr, binfo->bi_enet2addr, 6);
+               fpi->bus_id = "0:02";
+               fpi->phy_addr = 2;
+               fpi->dpram_offset = (u32)cpm2_immr->im_dprambase;
+               fpi->fcc_regs_c = (u32)&cpm2_immr->im_fcc_c[1];
+       }
+
+       fpi = (struct fs_platform_info *) ppc_sys_get_pdata(MPC85xx_CPM_FCC3);
+       if (fpi) {
+               memcpy(fpi->macaddr, binfo->bi_enet2addr, 6);
+               fpi->macaddr[5] += 1;
+               fpi->bus_id = "0:03";
+               fpi->phy_addr = 3;
+               fpi->dpram_offset = (u32)cpm2_immr->im_dprambase;
+               fpi->fcc_regs_c = (u32)&cpm2_immr->im_fcc_c[2];
+       }
+
 #ifdef CONFIG_BLK_DEV_INITRD
        if (initrd_start)
                ROOT_DEV = Root_RAM0;
index abf32281655d77c557024f60fadfc51b43275d22..c8c322fe3680fdb110211c36f89802af552e5da3 100644 (file)
@@ -45,4 +45,23 @@ extern void mpc85xx_ads_map_io(void) __init;
 
 #define MPC85XX_PCI1_IO_SIZE   0x01000000
 
+/* FCC1 Clock Source Configuration.  These can be
+ * redefined in the board specific file.
+ *    Can only choose from CLK9-12 */
+#define F1_RXCLK       12
+#define F1_TXCLK       11
+
+/* FCC2 Clock Source Configuration.  These can be
+ * redefined in the board specific file.
+ *    Can only choose from CLK13-16 */
+#define F2_RXCLK       13
+#define F2_TXCLK       14
+
+/* FCC3 Clock Source Configuration.  These can be
+ * redefined in the board specific file.
+ *    Can only choose from CLK13-16 */
+#define F3_RXCLK       15
+#define F3_TXCLK       16
+
+
 #endif                         /* __MACH_MPC85XX_ADS_H__ */
index abb7154de2c7fcba30125b5b1971da761a2a59df..2a35fe2b9b9652784d80e9a1a0d8ddd629725e04 100644 (file)
@@ -56,64 +56,51 @@ static struct fs_uart_platform_info mpc8272_uart_pdata[] = {
        },
 };
 
-static struct fs_mii_bus_info mii_bus_info = {
-       .method                 = fsmii_bitbang,
-       .id                     = 0,
-       .i.bitbang = {
-               .mdio_port      = fsiop_portc,
-               .mdio_bit       = 18,
-               .mdc_port       = fsiop_portc,
-               .mdc_bit        = 19,
-               .delay          = 1,
-       },
-};
-
-static struct fs_platform_info mpc82xx_fcc1_pdata = {
-       .fs_no          = fsid_fcc1,
-       .cp_page        = CPM_CR_FCC1_PAGE,
-       .cp_block       = CPM_CR_FCC1_SBLOCK,
-       .clk_trx        = (PC_F1RXCLK | PC_F1TXCLK),
-       .clk_route      = CMX1_CLK_ROUTE,
-       .clk_mask       = CMX1_CLK_MASK,
-       .init_ioports   = init_fcc1_ioports,
-
-       .phy_addr       = 0,
-#ifdef PHY_INTERRUPT
-       .phy_irq        = PHY_INTERRUPT,
-#else
-       .phy_irq        = -1;
-#endif
-       .mem_offset     = FCC1_MEM_OFFSET,
-       .bus_info       = &mii_bus_info,
-       .rx_ring        = 32,
-       .tx_ring        = 32,
-       .rx_copybreak   = 240,
-       .use_napi       = 0,
-       .napi_weight    = 17,
+static struct fs_mii_bb_platform_info m82xx_mii_bb_pdata = {
+       .mdio_dat.bit   = 18,
+       .mdio_dir.bit   = 18,
+       .mdc_dat.bit    = 19,
+       .delay          = 1,
 };
 
-static struct fs_platform_info mpc82xx_fcc2_pdata = {
-       .fs_no          = fsid_fcc2,
-       .cp_page        = CPM_CR_FCC2_PAGE,
-       .cp_block       = CPM_CR_FCC2_SBLOCK,
-       .clk_trx        = (PC_F2RXCLK | PC_F2TXCLK),
-       .clk_route      = CMX2_CLK_ROUTE,
-       .clk_mask       = CMX2_CLK_MASK,
-       .init_ioports   = init_fcc2_ioports,
-
-       .phy_addr       = 3,
-#ifdef PHY_INTERRUPT
-       .phy_irq        = PHY_INTERRUPT,
-#else
-       .phy_irq        = -1;
-#endif
-       .mem_offset     = FCC2_MEM_OFFSET,
-       .bus_info       = &mii_bus_info,
-       .rx_ring        = 32,
-       .tx_ring        = 32,
-       .rx_copybreak   = 240,
-       .use_napi       = 0,
-       .napi_weight    = 17,
+static struct fs_platform_info mpc82xx_enet_pdata[] = {
+       [fsid_fcc1] = {
+               .fs_no          = fsid_fcc1,
+               .cp_page        = CPM_CR_FCC1_PAGE,
+               .cp_block       = CPM_CR_FCC1_SBLOCK,
+
+               .clk_trx        = (PC_F1RXCLK | PC_F1TXCLK),
+               .clk_route      = CMX1_CLK_ROUTE,
+               .clk_mask       = CMX1_CLK_MASK,
+               .init_ioports   = init_fcc1_ioports,
+
+               .mem_offset     = FCC1_MEM_OFFSET,
+
+               .rx_ring        = 32,
+               .tx_ring        = 32,
+               .rx_copybreak   = 240,
+               .use_napi       = 0,
+               .napi_weight    = 17,
+               .bus_id         = "0:00",
+       },
+       [fsid_fcc2] = {
+               .fs_no          = fsid_fcc2,
+               .cp_page        = CPM_CR_FCC2_PAGE,
+               .cp_block       = CPM_CR_FCC2_SBLOCK,
+               .clk_trx        = (PC_F2RXCLK | PC_F2TXCLK),
+               .clk_route      = CMX2_CLK_ROUTE,
+               .clk_mask       = CMX2_CLK_MASK,
+               .init_ioports   = init_fcc2_ioports,
+
+               .mem_offset     = FCC2_MEM_OFFSET,
+
+               .rx_ring        = 32,
+               .tx_ring        = 32,
+               .rx_copybreak   = 240,
+               .use_napi       = 0,
+               .napi_weight    = 17,
+               .bus_id         = "0:03",
+       },
 };
 
 static void init_fcc1_ioports(void)
@@ -209,20 +196,21 @@ static void __init mpc8272ads_fixup_enet_pdata(struct platform_device *pdev,
        bd_t* bi = (void*)__res;
        int fs_no = fsid_fcc1+pdev->id-1;
 
-       mpc82xx_fcc1_pdata.dpram_offset = mpc82xx_fcc2_pdata.dpram_offset = (u32)cpm2_immr->im_dprambase;
-       mpc82xx_fcc1_pdata.fcc_regs_c = mpc82xx_fcc2_pdata.fcc_regs_c = (u32)cpm2_immr->im_fcc_c;
-
-       switch(fs_no) {
-               case fsid_fcc1:
-                       memcpy(&mpc82xx_fcc1_pdata.macaddr,bi->bi_enetaddr,6);
-                       pdev->dev.platform_data = &mpc82xx_fcc1_pdata;
-               break;
-               case fsid_fcc2:
-                       memcpy(&mpc82xx_fcc2_pdata.macaddr,bi->bi_enetaddr,6);
-                       mpc82xx_fcc2_pdata.macaddr[5] ^= 1;
-                       pdev->dev.platform_data = &mpc82xx_fcc2_pdata;
-               break;
+       if(fs_no > ARRAY_SIZE(mpc82xx_enet_pdata)) {
+               return;
        }
+
+       mpc82xx_enet_pdata[fs_no].dpram_offset=
+                       (u32)cpm2_immr->im_dprambase;
+       mpc82xx_enet_pdata[fs_no].fcc_regs_c =
+                       (u32)cpm2_immr->im_fcc_c;
+       memcpy(&mpc82xx_enet_pdata[fs_no].macaddr,bi->bi_enetaddr,6);
+
+       /* prevent dup mac */
+       if(fs_no == fsid_fcc2)
+               mpc82xx_enet_pdata[fs_no].macaddr[5] ^= 1;
+
+       pdev->dev.platform_data = &mpc82xx_enet_pdata[fs_no];
 }
 
 static void mpc8272ads_fixup_uart_pdata(struct platform_device *pdev,
@@ -274,6 +262,29 @@ static void init_scc4_uart_ioports(void)
        iounmap(immap);
 }
 
+static void __init mpc8272ads_fixup_mdio_pdata(struct platform_device *pdev,
+                                             int idx)
+{
+       m82xx_mii_bb_pdata.irq[0] = PHY_INTERRUPT;
+       m82xx_mii_bb_pdata.irq[1] = -1;
+       m82xx_mii_bb_pdata.irq[2] = -1;
+       m82xx_mii_bb_pdata.irq[3] = PHY_INTERRUPT;
+       m82xx_mii_bb_pdata.irq[31] = -1;
+
+
+       m82xx_mii_bb_pdata.mdio_dat.offset =
+                               (u32)&cpm2_immr->im_ioport.iop_pdatc;
+
+       m82xx_mii_bb_pdata.mdio_dir.offset =
+                               (u32)&cpm2_immr->im_ioport.iop_pdirc;
+
+       m82xx_mii_bb_pdata.mdc_dat.offset =
+                               (u32)&cpm2_immr->im_ioport.iop_pdatc;
+
+
+       pdev->dev.platform_data = &m82xx_mii_bb_pdata;
+}
+
 static int mpc8272ads_platform_notify(struct device *dev)
 {
        static const struct platform_notify_dev_map dev_map[] = {
@@ -285,6 +296,10 @@ static int mpc8272ads_platform_notify(struct device *dev)
                        .bus_id = "fsl-cpm-scc:uart",
                        .rtn = mpc8272ads_fixup_uart_pdata,
                },
+               {
+                       .bus_id = "fsl-bb-mdio",
+                       .rtn = mpc8272ads_fixup_mdio_pdata,
+               },
                {
                        .bus_id = NULL
                }
@@ -319,6 +334,7 @@ int __init mpc8272ads_init(void)
        ppc_sys_device_enable(MPC82xx_CPM_SCC4);
 #endif
 
+       ppc_sys_device_enable(MPC82xx_MDIO_BB);
 
        return 0;
 }
index f19b6167c7700da2bc265cdc5979b1a242a8bd49..e12cece4c9fd056e1a2586d2feabc996d986ef7d 100644 (file)
@@ -1,10 +1,10 @@
-/*arch/ppc/platforms/mpc885ads-setup.c
+/*arch/ppc/platforms/mpc866ads-setup.c
  *
- * Platform setup for the Freescale mpc885ads board
+ * Platform setup for the Freescale mpc866ads board
  *
  * Vitaly Bordug <vbordug@ru.mvista.com>
  *
- * Copyright 2005 MontaVista Software Inc.
+ * Copyright 2005-2006 MontaVista Software Inc.
  *
  * This file is licensed under the terms of the GNU General Public License
  * version 2. This program is licensed "as is" without any warranty of any
@@ -42,49 +42,36 @@ static void setup_scc1_ioports(void);
 static void setup_smc1_ioports(void);
 static void setup_smc2_ioports(void);
 
-static struct fs_mii_bus_info fec_mii_bus_info = {
-       .method = fsmii_fec,
-       .id = 0,
-};
-
-static struct fs_mii_bus_info scc_mii_bus_info = {
-       .method = fsmii_fixed,
-       .id = 0,
-       .i.fixed.speed = 10,
-       .i.fixed.duplex = 0,
-};
+static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata;
 
-static struct fs_platform_info mpc8xx_fec_pdata[] = {
-       {
-        .rx_ring = 128,
-        .tx_ring = 16,
-        .rx_copybreak = 240,
+static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata;
 
-        .use_napi = 1,
-        .napi_weight = 17,
+static struct fs_platform_info mpc8xx_enet_pdata[] = {
+       [fsid_fec1] = {
+               .rx_ring = 128,
+               .tx_ring = 16,
+               .rx_copybreak = 240,
 
-        .phy_addr = 15,
-        .phy_irq = -1,
+               .use_napi = 1,
+               .napi_weight = 17,
 
-        .use_rmii = 0,
+               .init_ioports = setup_fec1_ioports,
 
-        .bus_info = &fec_mii_bus_info,
-        }
-};
+               .bus_id = "0:0f",
+               .has_phy = 1,
+       },
+       [fsid_scc1] = {
+               .rx_ring = 64,
+               .tx_ring = 8,
+               .rx_copybreak = 240,
+               .use_napi = 1,
+               .napi_weight = 17,
 
-static struct fs_platform_info mpc8xx_scc_pdata = {
-       .rx_ring = 64,
-       .tx_ring = 8,
-       .rx_copybreak = 240,
 
-       .use_napi = 1,
-       .napi_weight = 17,
-
-       .phy_addr = -1,
-       .phy_irq = -1,
-
-       .bus_info = &scc_mii_bus_info,
+               .init_ioports = setup_scc1_ioports,
 
+               .bus_id = "fixed@100:1",
+       },
 };
 
 static struct fs_uart_platform_info mpc866_uart_pdata[] = {
@@ -207,63 +194,6 @@ static void setup_scc1_ioports(void)
 
 }
 
-static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
-{
-       struct fs_platform_info *fpi = pdev->dev.platform_data;
-
-       volatile cpm8xx_t *cp;
-       bd_t *bd = (bd_t *) __res;
-       char *e;
-       int i;
-
-       /* Get pointer to Communication Processor */
-       cp = cpmp;
-       switch (fs_no) {
-       case fsid_fec1:
-               fpi = &mpc8xx_fec_pdata[0];
-               fpi->init_ioports = &setup_fec1_ioports;
-
-               break;
-       case fsid_scc1:
-               fpi = &mpc8xx_scc_pdata;
-               fpi->init_ioports = &setup_scc1_ioports;
-
-               break;
-       default:
-               printk(KERN_WARNING"Device %s is not supported!\n", pdev->name);
-               return;
-       }
-
-       pdev->dev.platform_data = fpi;
-       fpi->fs_no = fs_no;
-
-       e = (unsigned char *)&bd->bi_enetaddr;
-       for (i = 0; i < 6; i++)
-               fpi->macaddr[i] = *e++;
-
-       fpi->macaddr[5 - pdev->id]++;
-
-}
-
-static void mpc866ads_fixup_fec_enet_pdata(struct platform_device *pdev,
-                                          int idx)
-{
-       /* This is for FEC devices only */
-       if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
-               return;
-       mpc866ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
-}
-
-static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
-                                          int idx)
-{
-       /* This is for SCC devices only */
-       if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
-               return;
-
-       mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
-}
-
 static void setup_smc1_ioports(void)
 {
        immap_t *immap = (immap_t *) IMAP_ADDR;
@@ -315,6 +245,56 @@ static void setup_smc2_ioports(void)
 
 }
 
+static int ma_count = 0;
+
+static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
+{
+       struct fs_platform_info *fpi;
+
+       volatile cpm8xx_t *cp;
+       bd_t *bd = (bd_t *) __res;
+       char *e;
+       int i;
+
+       /* Get pointer to Communication Processor */
+       cp = cpmp;
+
+       if(fs_no > ARRAY_SIZE(mpc8xx_enet_pdata)) {
+               printk(KERN_ERR"No network-suitable #%d device on bus", fs_no);
+               return;
+       }
+
+
+       fpi = &mpc8xx_enet_pdata[fs_no];
+       fpi->fs_no = fs_no;
+       pdev->dev.platform_data = fpi;
+
+       e = (unsigned char *)&bd->bi_enetaddr;
+       for (i = 0; i < 6; i++)
+               fpi->macaddr[i] = *e++;
+
+       fpi->macaddr[5] += ma_count++;
+}
+
+static void mpc866ads_fixup_fec_enet_pdata(struct platform_device *pdev,
+                                          int idx)
+{
+       /* This is for FEC devices only */
+       if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
+               return;
+       mpc866ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
+}
+
+static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
+                                          int idx)
+{
+       /* This is for SCC devices only */
+       if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
+               return;
+
+       mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
+}
+
 static void __init mpc866ads_fixup_uart_pdata(struct platform_device *pdev,
                                               int idx)
 {
@@ -359,6 +339,9 @@ static int mpc866ads_platform_notify(struct device *dev)
 
 int __init mpc866ads_init(void)
 {
+       bd_t *bd = (bd_t *) __res;
+       struct fs_mii_fec_platform_info* fmpi;
+
        printk(KERN_NOTICE "mpc866ads: Init\n");
 
        platform_notify = mpc866ads_platform_notify;
@@ -366,11 +349,20 @@ int __init mpc866ads_init(void)
        ppc_sys_device_initfunc();
        ppc_sys_device_disable_all();
 
-#ifdef MPC8xx_SECOND_ETH_SCC1
+#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC1
        ppc_sys_device_enable(MPC8xx_CPM_SCC1);
 #endif
        ppc_sys_device_enable(MPC8xx_CPM_FEC1);
 
+       ppc_sys_device_enable(MPC8xx_MDIO_FEC);
+
+       fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
+               &mpc8xx_mdio_fec_pdata;
+
+       fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
+       /* No PHY interrupt line here */
+       fmpi->irq[0xf] = -1;
+
 /* Since either of the uarts could be used as console, they need to ready */
 #ifdef CONFIG_SERIAL_CPM_SMC1
        ppc_sys_device_enable(MPC8xx_CPM_SMC1);
@@ -381,6 +373,14 @@ int __init mpc866ads_init(void)
        ppc_sys_device_enable(MPC8xx_CPM_SMC2);
        ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
 #endif
+       ppc_sys_device_enable(MPC8xx_MDIO_FEC);
+
+       fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
+               &mpc8xx_mdio_fec_pdata;
+
+       fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
+       /* No PHY interrupt line here */
+       fmpi->irq[0xf] = -1;
 
        return 0;
 }
index c1fc4a16fea9d7f9aa95a1c1b124155d48ceee18..5dfa4e6c2af038e6c7d45578b68f07f44435f02f 100644 (file)
@@ -38,7 +38,10 @@ extern unsigned char __res[];
 static void setup_smc1_ioports(void);
 static void setup_smc2_ioports(void);
 
-static void __init mpc885ads_scc_phy_init(char);
+static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata;
+static void setup_fec1_ioports(void);
+static void setup_fec2_ioports(void);
+static void setup_scc3_ioports(void);
 
 static struct fs_uart_platform_info mpc885_uart_pdata[] = {
        [fsid_smc1_uart] = {
@@ -61,23 +64,8 @@ static struct fs_uart_platform_info mpc885_uart_pdata[] = {
        },
 };
 
-static struct fs_mii_bus_info fec_mii_bus_info = {
-       .method = fsmii_fec,
-       .id = 0,
-};
-
-static struct fs_mii_bus_info scc_mii_bus_info = {
-#ifdef CONFIG_SCC_ENET_8xx_FIXED
-       .method = fsmii_fixed,
-#else
-       .method = fsmii_fec,
-#endif
-
-       .id = 0,
-};
-
-static struct fs_platform_info mpc8xx_fec_pdata[] = {
-       {
+static struct fs_platform_info mpc8xx_enet_pdata[] = {
+       [fsid_fec1] = {
         .rx_ring = 128,
         .tx_ring = 16,
         .rx_copybreak = 240,
@@ -85,11 +73,12 @@ static struct fs_platform_info mpc8xx_fec_pdata[] = {
         .use_napi = 1,
         .napi_weight = 17,
 
-        .phy_addr = 0,
-        .phy_irq = SIU_IRQ7,
+        .init_ioports = setup_fec1_ioports,
 
-        .bus_info = &fec_mii_bus_info,
-        }, {
+          .bus_id = "0:00",
+          .has_phy = 1,
+        },
+       [fsid_fec2] = {
             .rx_ring = 128,
             .tx_ring = 16,
             .rx_copybreak = 240,
@@ -97,35 +86,32 @@ static struct fs_platform_info mpc8xx_fec_pdata[] = {
             .use_napi = 1,
             .napi_weight = 17,
 
-            .phy_addr = 1,
-            .phy_irq = SIU_IRQ7,
-
-            .bus_info = &fec_mii_bus_info,
-            }
-};
+            .init_ioports = setup_fec2_ioports,
 
-static struct fs_platform_info mpc8xx_scc_pdata = {
-       .rx_ring = 64,
-       .tx_ring = 8,
-       .rx_copybreak = 240,
+            .bus_id = "0:01",
+            .has_phy = 1,
+            },
+       [fsid_scc3] = {
+               .rx_ring = 64,
+               .tx_ring = 8,
+               .rx_copybreak = 240,
 
-       .use_napi = 1,
-       .napi_weight = 17,
+               .use_napi = 1,
+               .napi_weight = 17,
 
-       .phy_addr = 2,
-#ifdef CONFIG_MPC8xx_SCC_ENET_FIXED
-       .phy_irq = -1,
+               .init_ioports = setup_scc3_ioports,
+#ifdef CONFIG_FIXED_MII_10_FDX
+               .bus_id = "fixed@100:1",
 #else
-       .phy_irq = SIU_IRQ7,
-#endif
-
-       .bus_info = &scc_mii_bus_info,
+               .bus_id = "0:02",
+ #endif
+       },
 };
 
 void __init board_init(void)
 {
-       volatile cpm8xx_t *cp = cpmp;
-       unsigned int *bcsr_io;
+       cpm8xx_t *cp = cpmp;
+       unsigned int *bcsr_io;
 
 #ifdef CONFIG_FS_ENET
        immap_t *immap = (immap_t *) IMAP_ADDR;
@@ -164,6 +150,14 @@ void __init board_init(void)
        /* use MDC for MII (common) */
        setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
        clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
+       bcsr_io = ioremap(BCSR5, sizeof(unsigned long));
+       clrbits32(bcsr_io,BCSR5_MII1_EN);
+       clrbits32(bcsr_io,BCSR5_MII1_RST);
+#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
+       clrbits32(bcsr_io,BCSR5_MII2_EN);
+       clrbits32(bcsr_io,BCSR5_MII2_RST);
+#endif
+       iounmap(bcsr_io);
 #endif
 }
 
@@ -194,8 +188,8 @@ static void setup_fec2_ioports(void)
        /* configure FEC2 pins */
        setbits32(&immap->im_cpm.cp_pepar, 0x0003fffc);
        setbits32(&immap->im_cpm.cp_pedir, 0x0003fffc);
-       setbits32(&immap->im_cpm.cp_peso, 0x00037800);
        clrbits32(&immap->im_cpm.cp_peso, 0x000087fc);
+       setbits32(&immap->im_cpm.cp_peso, 0x00037800);
        clrbits32(&immap->im_cpm.cp_cptr, 0x00000080);
 }
 
@@ -213,6 +207,8 @@ static void setup_scc3_ioports(void)
 
        /* Enable the PHY.
         */
+       clrbits32(bcsr_io+4, BCSR4_ETH10_RST);
+       udelay(1000);
        setbits32(bcsr_io+4, BCSR4_ETH10_RST);
        /* Configure port A pins for Txd and Rxd.
         */
@@ -254,37 +250,38 @@ static void setup_scc3_ioports(void)
        clrbits32(&immap->im_cpm.cp_pedir, PE_ENET_TENA);
        setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA);
 
-       setbits32(bcsr_io+1, BCSR1_ETHEN);
+       setbits32(bcsr_io+4, BCSR1_ETHEN);
        iounmap(bcsr_io);
 }
 
+static int mac_count = 0;
+
 static void mpc885ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
 {
-       struct fs_platform_info *fpi = pdev->dev.platform_data;
-
-       volatile cpm8xx_t *cp;
+       struct fs_platform_info *fpi;
        bd_t *bd = (bd_t *) __res;
        char *e;
        int i;
 
-       /* Get pointer to Communication Processor */
-       cp = cpmp;
+       if(fs_no > ARRAY_SIZE(mpc8xx_enet_pdata)) {
+               printk(KERN_ERR"No network-suitable #%d device on bus", fs_no);
+               return;
+       }
+
+       fpi = &mpc8xx_enet_pdata[fs_no];
+
        switch (fs_no) {
        case fsid_fec1:
-               fpi = &mpc8xx_fec_pdata[0];
                fpi->init_ioports = &setup_fec1_ioports;
                break;
        case fsid_fec2:
-               fpi = &mpc8xx_fec_pdata[1];
                fpi->init_ioports = &setup_fec2_ioports;
                break;
        case fsid_scc3:
-               fpi = &mpc8xx_scc_pdata;
                fpi->init_ioports = &setup_scc3_ioports;
-               mpc885ads_scc_phy_init(fpi->phy_addr);
                break;
        default:
-               printk(KERN_WARNING"Device %s is not supported!\n", pdev->name);
+               printk(KERN_WARNING "Device %s is not supported!\n", pdev->name);
                return;
        }
 
@@ -295,7 +292,7 @@ static void mpc885ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
        for (i = 0; i < 6; i++)
                fpi->macaddr[i] = *e++;
 
-       fpi->macaddr[5 - pdev->id]++;
+       fpi->macaddr[5] += mac_count++;
 
 }
 
@@ -318,58 +315,6 @@ static void __init mpc885ads_fixup_scc_enet_pdata(struct platform_device *pdev,
        mpc885ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
 }
 
-/* SCC ethernet controller does not have MII management channel. FEC1 MII
- * channel is used to communicate with the 10Mbit PHY.
- */
-
-#define MII_ECNTRL_PINMUX        0x4
-#define FEC_ECNTRL_PINMUX        0x00000004
-#define FEC_RCNTRL_MII_MODE        0x00000004
-
-/* Make MII read/write commands.
- */
-#define mk_mii_write(REG, VAL, PHY_ADDR)    (0x50020000 | (((REG) & 0x1f) << 18) | \
-                ((VAL) & 0xffff) | ((PHY_ADDR) << 23))
-
-static void mpc885ads_scc_phy_init(char phy_addr)
-{
-       volatile immap_t *immap;
-       volatile fec_t *fecp;
-       bd_t *bd;
-
-       bd = (bd_t *) __res;
-       immap = (immap_t *) IMAP_ADDR;  /* pointer to internal registers */
-       fecp = &(immap->im_cpm.cp_fec);
-
-       /* Enable MII pins of the FEC1
-        */
-       setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
-       clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
-       /* Set MII speed to 2.5 MHz
-        */
-       out_be32(&fecp->fec_mii_speed,
-                ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1);
-
-       /* Enable FEC pin MUX
-        */
-       setbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
-       setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
-
-       out_be32(&fecp->fec_mii_data,
-                mk_mii_write(MII_BMCR, BMCR_ISOLATE, phy_addr));
-       udelay(100);
-       out_be32(&fecp->fec_mii_data,
-                mk_mii_write(MII_ADVERTISE,
-                             ADVERTISE_10HALF | ADVERTISE_CSMA, phy_addr));
-       udelay(100);
-
-       /* Disable FEC MII settings
-        */
-       clrbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
-       clrbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
-       out_be32(&fecp->fec_mii_speed, 0);
-}
-
 static void setup_smc1_ioports(void)
 {
         immap_t *immap = (immap_t *) IMAP_ADDR;
@@ -462,6 +407,9 @@ static int mpc885ads_platform_notify(struct device *dev)
 
 int __init mpc885ads_init(void)
 {
+       struct fs_mii_fec_platform_info* fmpi;
+       bd_t *bd = (bd_t *) __res;
+
        printk(KERN_NOTICE "mpc885ads: Init\n");
 
        platform_notify = mpc885ads_platform_notify;
@@ -471,8 +419,17 @@ int __init mpc885ads_init(void)
 
        ppc_sys_device_enable(MPC8xx_CPM_FEC1);
 
+       ppc_sys_device_enable(MPC8xx_MDIO_FEC);
+       fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
+               &mpc8xx_mdio_fec_pdata;
+
+       fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
+
+       /* No PHY interrupt line here */
+       fmpi->irq[0xf] = SIU_IRQ7;
+
 #ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3
-       ppc_sys_device_enable(MPC8xx_CPM_SCC1);
+       ppc_sys_device_enable(MPC8xx_CPM_SCC3);
 
 #endif
 #ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
index 8f14a43eafec0266a43027caab60f57eefb26e5e..672483df8079da4a502b522af2e4ab670d766cbc 100644 (file)
 #define F3_RXCLK       13
 #define F3_TXCLK       14
 
-/* Automatically generates register configurations */
-#define PC_CLK(x)      ((uint)(1<<(x-1)))      /* FCC CLK I/O ports */
-
-#define CMXFCR_RF1CS(x)        ((uint)((x-5)<<27))     /* FCC1 Receive Clock Source */
-#define CMXFCR_TF1CS(x)        ((uint)((x-5)<<24))     /* FCC1 Transmit Clock Source */
-#define CMXFCR_RF2CS(x)        ((uint)((x-9)<<19))     /* FCC2 Receive Clock Source */
-#define CMXFCR_TF2CS(x) ((uint)((x-9)<<16))    /* FCC2 Transmit Clock Source */
-#define CMXFCR_RF3CS(x)        ((uint)((x-9)<<11))     /* FCC3 Receive Clock Source */
-#define CMXFCR_TF3CS(x) ((uint)((x-9)<<8))     /* FCC3 Transmit Clock Source */
-
-#define PC_F1RXCLK     PC_CLK(F1_RXCLK)
-#define PC_F1TXCLK     PC_CLK(F1_TXCLK)
-#define CMX1_CLK_ROUTE (CMXFCR_RF1CS(F1_RXCLK) | CMXFCR_TF1CS(F1_TXCLK))
-#define CMX1_CLK_MASK  ((uint)0xff000000)
-
-#define PC_F2RXCLK     PC_CLK(F2_RXCLK)
-#define PC_F2TXCLK     PC_CLK(F2_TXCLK)
-#define CMX2_CLK_ROUTE (CMXFCR_RF2CS(F2_RXCLK) | CMXFCR_TF2CS(F2_TXCLK))
-#define CMX2_CLK_MASK  ((uint)0x00ff0000)
-
-#define PC_F3RXCLK     PC_CLK(F3_RXCLK)
-#define PC_F3TXCLK     PC_CLK(F3_TXCLK)
-#define CMX3_CLK_ROUTE (CMXFCR_RF3CS(F3_RXCLK) | CMXFCR_TF3CS(F3_TXCLK))
-#define CMX3_CLK_MASK  ((uint)0x0000ff00)
-
-/* I/O Pin assignment for FCC1.  I don't yet know the best way to do this,
- * but there is little variation among the choices.
- */
-#define PA1_COL                0x00000001U
-#define PA1_CRS                0x00000002U
-#define PA1_TXER       0x00000004U
-#define PA1_TXEN       0x00000008U
-#define PA1_RXDV       0x00000010U
-#define PA1_RXER       0x00000020U
-#define PA1_TXDAT      0x00003c00U
-#define PA1_RXDAT      0x0003c000U
-#define PA1_PSORA0     (PA1_RXDAT | PA1_TXDAT)
-#define PA1_PSORA1     (PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
-               PA1_RXDV | PA1_RXER)
-#define PA1_DIRA0      (PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
-#define PA1_DIRA1      (PA1_TXDAT | PA1_TXEN | PA1_TXER)
-
-
-/* I/O Pin assignment for FCC2.  I don't yet know the best way to do this,
- * but there is little variation among the choices.
- */
-#define PB2_TXER       0x00000001U
-#define PB2_RXDV       0x00000002U
-#define PB2_TXEN       0x00000004U
-#define PB2_RXER       0x00000008U
-#define PB2_COL                0x00000010U
-#define PB2_CRS                0x00000020U
-#define PB2_TXDAT      0x000003c0U
-#define PB2_RXDAT      0x00003c00U
-#define PB2_PSORB0     (PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
-               PB2_RXER | PB2_RXDV | PB2_TXER)
-#define PB2_PSORB1     (PB2_TXEN)
-#define PB2_DIRB0      (PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
-#define PB2_DIRB1      (PB2_TXDAT | PB2_TXEN | PB2_TXER)
-
-
-/* I/O Pin assignment for FCC3.  I don't yet know the best way to do this,
- * but there is little variation among the choices.
- */
-#define PB3_RXDV       0x00004000U
-#define PB3_RXER       0x00008000U
-#define PB3_TXER       0x00010000U
-#define PB3_TXEN       0x00020000U
-#define PB3_COL                0x00040000U
-#define PB3_CRS                0x00080000U
-#define PB3_TXDAT      0x0f000000U
-#define PB3_RXDAT      0x00f00000U
-#define PB3_PSORB0     (PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
-               PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
-#define PB3_PSORB1     0
-#define PB3_DIRB0      (PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
-#define PB3_DIRB1      (PB3_TXDAT | PB3_TXEN | PB3_TXER)
-
-#define FCC_MEM_OFFSET(x) (CPM_FCC_SPECIAL_BASE + (x*128))
-#define FCC1_MEM_OFFSET FCC_MEM_OFFSET(0)
-#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(1)
-
 #endif
index 7735336f5b8f51b758587053736c0f18ffad9ae9..325136e5aee0030403c68c553b47d943c4ca644b 100644 (file)
 #include <linux/device.h>
 #include <linux/serial_8250.h>
 #include <linux/fsl_devices.h>
+#include <linux/fs_enet_pd.h>
 #include <asm/mpc85xx.h>
 #include <asm/irq.h>
 #include <asm/ppc_sys.h>
+#include <asm/cpm2.h>
 
 /* We use offsets for IORESOURCE_MEM since we do not know at compile time
  * what CCSRBAR is, will get fixed up by mach_mpc85xx_fixup
@@ -82,6 +84,60 @@ static struct fsl_i2c_platform_data mpc85xx_fsl_i2c2_pdata = {
        .device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
 };
 
+static struct fs_platform_info mpc85xx_fcc1_pdata = {
+       .fs_no          = fsid_fcc1,
+       .cp_page        = CPM_CR_FCC1_PAGE,
+       .cp_block       = CPM_CR_FCC1_SBLOCK,
+
+       .rx_ring        = 32,
+       .tx_ring        = 32,
+       .rx_copybreak   = 240,
+       .use_napi       = 0,
+       .napi_weight    = 17,
+
+       .clk_mask       = CMX1_CLK_MASK,
+       .clk_route      = CMX1_CLK_ROUTE,
+       .clk_trx        = (PC_F1RXCLK | PC_F1TXCLK),
+
+       .mem_offset     = FCC1_MEM_OFFSET,
+};
+
+static struct fs_platform_info mpc85xx_fcc2_pdata = {
+       .fs_no          = fsid_fcc2,
+       .cp_page        = CPM_CR_FCC2_PAGE,
+       .cp_block       = CPM_CR_FCC2_SBLOCK,
+
+       .rx_ring        = 32,
+       .tx_ring        = 32,
+       .rx_copybreak   = 240,
+       .use_napi       = 0,
+       .napi_weight    = 17,
+
+       .clk_mask       = CMX2_CLK_MASK,
+       .clk_route      = CMX2_CLK_ROUTE,
+       .clk_trx        = (PC_F2RXCLK | PC_F2TXCLK),
+
+       .mem_offset     = FCC2_MEM_OFFSET,
+};
+
+static struct fs_platform_info mpc85xx_fcc3_pdata = {
+       .fs_no          = fsid_fcc3,
+       .cp_page        = CPM_CR_FCC3_PAGE,
+       .cp_block       = CPM_CR_FCC3_SBLOCK,
+
+       .rx_ring        = 32,
+       .tx_ring        = 32,
+       .rx_copybreak   = 240,
+       .use_napi       = 0,
+       .napi_weight    = 17,
+
+       .clk_mask       = CMX3_CLK_MASK,
+       .clk_route      = CMX3_CLK_ROUTE,
+       .clk_trx        = (PC_F3RXCLK | PC_F3TXCLK),
+
+       .mem_offset     = FCC3_MEM_OFFSET,
+};
+
 static struct plat_serial8250_port serial_platform_data[] = {
        [0] = {
                .mapbase        = 0x4500,
@@ -318,18 +374,27 @@ struct platform_device ppc_sys_platform_devices[] = {
        [MPC85xx_CPM_FCC1] = {
                .name = "fsl-cpm-fcc",
                .id     = 1,
-               .num_resources   = 3,
+               .num_resources   = 4,
+               .dev.platform_data = &mpc85xx_fcc1_pdata,
                .resource = (struct resource[]) {
                        {
+                               .name   = "fcc_regs",
                                .start  = 0x91300,
                                .end    = 0x9131F,
                                .flags  = IORESOURCE_MEM,
                        },
                        {
+                               .name   = "fcc_regs_c",
                                .start  = 0x91380,
                                .end    = 0x9139F,
                                .flags  = IORESOURCE_MEM,
                        },
+                       {
+                               .name   = "fcc_pram",
+                               .start  = 0x88400,
+                               .end    = 0x884ff,
+                               .flags  = IORESOURCE_MEM,
+                       },
                        {
                                .start  = SIU_INT_FCC1,
                                .end    = SIU_INT_FCC1,
@@ -340,18 +405,27 @@ struct platform_device ppc_sys_platform_devices[] = {
        [MPC85xx_CPM_FCC2] = {
                .name = "fsl-cpm-fcc",
                .id     = 2,
-               .num_resources   = 3,
+               .num_resources   = 4,
+               .dev.platform_data = &mpc85xx_fcc2_pdata,
                .resource = (struct resource[]) {
                        {
+                               .name   = "fcc_regs",
                                .start  = 0x91320,
                                .end    = 0x9133F,
                                .flags  = IORESOURCE_MEM,
                        },
                        {
+                               .name   = "fcc_regs_c",
                                .start  = 0x913A0,
                                .end    = 0x913CF,
                                .flags  = IORESOURCE_MEM,
                        },
+                       {
+                               .name   = "fcc_pram",
+                               .start  = 0x88500,
+                               .end    = 0x885ff,
+                               .flags  = IORESOURCE_MEM,
+                       },
                        {
                                .start  = SIU_INT_FCC2,
                                .end    = SIU_INT_FCC2,
@@ -362,18 +436,27 @@ struct platform_device ppc_sys_platform_devices[] = {
        [MPC85xx_CPM_FCC3] = {
                .name = "fsl-cpm-fcc",
                .id     = 3,
-               .num_resources   = 3,
+               .num_resources   = 4,
+               .dev.platform_data = &mpc85xx_fcc3_pdata,
                .resource = (struct resource[]) {
                        {
+                               .name   = "fcc_regs",
                                .start  = 0x91340,
                                .end    = 0x9135F,
                                .flags  = IORESOURCE_MEM,
                        },
                        {
+                               .name   = "fcc_regs_c",
                                .start  = 0x913D0,
                                .end    = 0x913FF,
                                .flags  = IORESOURCE_MEM,
                        },
+                       {
+                               .name   = "fcc_pram",
+                               .start  = 0x88600,
+                               .end    = 0x886ff,
+                               .flags  = IORESOURCE_MEM,
+                       },
                        {
                                .start  = SIU_INT_FCC3,
                                .end    = SIU_INT_FCC3,
index 6f536383866eddf8f32becbd3adb77435c27ac0a..cf5ab47487a752dd352b510643889c60c542ed4f 100644 (file)
@@ -218,6 +218,14 @@ struct platform_device ppc_sys_platform_devices[] = {
                        },
                },
        },
+
+        [MPC8xx_MDIO_FEC] = {
+                .name = "fsl-cpm-fec-mdio",
+                .id = 0,
+                .num_resources = 0,
+
+        },
+
 };
 
 static int __init mach_mpc8xx_fixup(struct platform_device *pdev)
index eee2132848559c3810adc2b7d5b95a2e2e71a2d0..18ba1d7ff9f19d712a53db382af582ca74c2ce93 100644 (file)
@@ -22,7 +22,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
                .ppc_sys_name   = "MPC86X",
                .mask           = 0xFFFFFFFF,
                .value          = 0x00000000,
-               .num_devices    = 7,
+               .num_devices    = 8,
                .device_list    = (enum ppc_sys_devices[])
                {
                        MPC8xx_CPM_FEC1,
@@ -32,13 +32,14 @@ struct ppc_sys_spec ppc_sys_specs[] = {
                        MPC8xx_CPM_SCC4,
                        MPC8xx_CPM_SMC1,
                        MPC8xx_CPM_SMC2,
+                       MPC8xx_MDIO_FEC,
                },
        },
        {
                .ppc_sys_name   = "MPC885",
                .mask           = 0xFFFFFFFF,
                .value          = 0x00000000,
-               .num_devices    = 8,
+               .num_devices    = 9,
                .device_list    = (enum ppc_sys_devices[])
                {
                        MPC8xx_CPM_FEC1,
@@ -49,6 +50,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
                        MPC8xx_CPM_SCC4,
                        MPC8xx_CPM_SMC1,
                        MPC8xx_CPM_SMC2,
+                       MPC8xx_MDIO_FEC,
                },
        },
        {       /* default match */
index 8692d00c08c42d7e3c33e59b57abbd7f75a6c5fb..fefbc217a56d0600726e6f4c788832c22648bc60 100644 (file)
@@ -369,6 +369,11 @@ struct platform_device ppc_sys_platform_devices[] = {
                        },
                },
        },
+       [MPC82xx_MDIO_BB] = {
+               .name = "fsl-bb-mdio",
+               .id = 0,
+               .num_resources = 0,
+       },
 };
 
 static int __init mach_mpc82xx_fixup(struct platform_device *pdev)
index fee8948162b9a49a7c9767cd6e389db223065ef3..f52600c0db202cd4078669c9623ddc9d5a11c0d1 100644 (file)
@@ -139,13 +139,14 @@ struct ppc_sys_spec ppc_sys_specs[] = {
                .ppc_sys_name   = "8272",
                .mask           = 0x0000ff00,
                .value          = 0x00000c00,
-               .num_devices    = 12,
+               .num_devices    = 13,
                .device_list = (enum ppc_sys_devices[])
                {
                        MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_SCC1,
                        MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SCC4,
                        MPC82xx_CPM_SMC1, MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI,
                        MPC82xx_CPM_I2C, MPC82xx_CPM_USB, MPC82xx_SEC1,
+                       MPC82xx_MDIO_BB,
                },
        },
        /* below is a list of the 8280 family of processors */
index 6a4b5f9715c902260cb7a2ea9e9e2f9e6be047e4..a0a94e0ef8d121b38542c965def18842cfc845f2 100644 (file)
@@ -618,7 +618,7 @@ appldata_offline_cpu(int cpu)
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static int
+static int __cpuinit
 appldata_cpu_notify(struct notifier_block *self,
                    unsigned long action, void *hcpu)
 {
index eb6ebfef134ae8b710def114b33533507e62a673..6e6b6de77770672968d528f42f5d824bca031e1a 100644 (file)
@@ -129,7 +129,7 @@ void __init paging_init(void)
                 /*
                  * pg_table is physical at this point
                  */
-               pg_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+               pg_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
 
                 pg_dir->pgd0 =  (_PAGE_TABLE | __pa(pg_table));
                 pg_dir->pgd1 =  (_PAGE_TABLE | (__pa(pg_table)+1024));
@@ -219,7 +219,7 @@ void __init paging_init(void)
                         continue;
                 }          
         
-               pm_dir = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE*4);
+               pm_dir = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE * 4);
                 pgd_populate(&init_mm, pg_dir, pm_dir);
 
                 for (j = 0 ; j < PTRS_PER_PMD ; j++,pm_dir++) {
@@ -228,7 +228,7 @@ void __init paging_init(void)
                                 continue; 
                         }          
                         
-                        pt_dir = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+                       pt_dir = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
                         pmd_populate_kernel(&init_mm, pm_dir, pt_dir);
        
                         for (k = 0 ; k < PTRS_PER_PTE ; k++,pt_dir++) {
index 4e9938dee0609489cfd0db60fbb6134e12617dcf..14052f08981498a2ef13c0b2feaab12498ca07e3 100644 (file)
@@ -529,7 +529,7 @@ void __kprobes oops_end(unsigned long flags)
                /* Nest count reaches zero, release the lock. */
                spin_unlock_irqrestore(&die_lock, flags);
        if (panic_on_oops)
-               panic("Fatal exception: panic_on_oops");
+               panic("Fatal exception");
 }
 
 void __kprobes __die(const char * str, struct pt_regs * regs, long err)
index 9734960a24519a625ad5e712ada896f3cd7e0f28..ce077d6bf3a02eff9c9d59165d60a7b43a521044 100644 (file)
@@ -488,7 +488,7 @@ void die(const char * str, struct pt_regs * regs, long err)
                panic("Fatal exception in interrupt");
 
        if (panic_on_oops)
-               panic("Fatal exception: panic_on_oops");
+               panic("Fatal exception");
 
        do_exit(err);
 }
index d53f664a4dd89215a3f9e7a66a2f8cf587ae3aea..fff89c2d88fda66ad93bb40e822137b2751477b5 100644 (file)
@@ -45,7 +45,7 @@ config WATCHDOG_NOWAYOUT
 comment "Watchdog Device Drivers"
        depends on WATCHDOG
 
-# Architecture Independant
+# Architecture Independent
 
 config SOFT_WATCHDOG
        tristate "Software watchdog"
@@ -127,7 +127,7 @@ config S3C2410_WATCHDOG
          enabled.
 
          The driver is limited by the speed of the system's PCLK
-         signal, so with reasonbaly fast systems (PCLK around 50-66MHz)
+         signal, so with reasonably fast systems (PCLK around 50-66MHz)
          then watchdog intervals of over approximately 20seconds are
          unavailable.
 
@@ -423,7 +423,7 @@ config SBC_EPX_C3_WATCHDOG
          is no way to know if writing to its IO address will corrupt
          your system or have any real effect.  The only way to be sure
          that this driver does what you want is to make sure you
-         are runnning it on an EPX-C3 from Winsystems with the watchdog
+         are running it on an EPX-C3 from Winsystems with the watchdog
          timer at IO address 0x1ee and 0x1ef.  It will write to both those
          IO ports.  Basically, the assumption is made that if you compile
          this driver into your kernel and/or load it as a module, that you
@@ -472,7 +472,7 @@ config INDYDOG
        tristate "Indy/I2 Hardware Watchdog"
        depends on WATCHDOG && SGI_IP22
        help
-         Hardwaredriver for the Indy's/I2's watchdog. This is a
+         Hardware driver for the Indy's/I2's watchdog. This is a
          watchdog timer that will reboot the machine after a 60 second
          timer expired and no process has written to /dev/watchdog during
          that time.
index 2f962cfa3f7f0f2e4a38af238cce287bd6d19f9a..78810ba982e9efb17b6713c1a12d480ec4e77491 100644 (file)
@@ -180,6 +180,36 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = {
                .channels       = 2,
                .autodma        = AUTODMA,
                .bootable       = OFF_BOARD,
+       },{     /* 15 */
+               .name           = "JMB361",
+               .init_hwif      = init_hwif_generic,
+               .channels       = 2,
+               .autodma        = AUTODMA,
+               .bootable       = OFF_BOARD,
+       },{     /* 16 */
+               .name           = "JMB363",
+               .init_hwif      = init_hwif_generic,
+               .channels       = 2,
+               .autodma        = AUTODMA,
+               .bootable       = OFF_BOARD,
+       },{     /* 17 */
+               .name           = "JMB365",
+               .init_hwif      = init_hwif_generic,
+               .channels       = 2,
+               .autodma        = AUTODMA,
+               .bootable       = OFF_BOARD,
+       },{     /* 18 */
+               .name           = "JMB366",
+               .init_hwif      = init_hwif_generic,
+               .channels       = 2,
+               .autodma        = AUTODMA,
+               .bootable       = OFF_BOARD,
+       },{     /* 19 */
+               .name           = "JMB368",
+               .init_hwif      = init_hwif_generic,
+               .channels       = 2,
+               .autodma        = AUTODMA,
+               .bootable       = OFF_BOARD,
        }
 };
 
index a4f7288a1fc80efff26c7af1f1a57fddec92e365..3ef567b99c740e22e85570d8cc2fec1ed239a5b3 100644 (file)
@@ -5,6 +5,7 @@
 config ISDN_PPP
        bool "Support synchronous PPP"
        depends on INET
+       select SLHC
        help
          Over digital connections such as ISDN, there is no need to
          synchronize sender and recipient's clocks with start and stop bits
index 217615b3322351f4d653b355d1b7290f36248631..93f701ea87bc3438bf5ab2426b74e5f43085827a 100644 (file)
@@ -710,6 +710,8 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
                return -EINVAL;
        }
 
+       m->ti = ti;
+
        r = parse_features(&as, m, ti);
        if (r)
                goto bad;
@@ -751,7 +753,6 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
        }
 
        ti->private = m;
-       m->ti = ti;
 
        return 0;
 
index d687a14ec0a7aa6b3b72d9fd322d9508cab8c2da..06ac899a9a26931f3bc23b87cf9a1ae7a351a1a4 100644 (file)
@@ -393,7 +393,7 @@ static int dst_set_bandwidth(struct dst_state *state, fe_bandwidth_t bandwidth)
        state->bandwidth = bandwidth;
 
        if (state->dst_type != DST_TYPE_IS_TERR)
-               return 0;
+               return -EOPNOTSUPP;
 
        switch (bandwidth) {
        case BANDWIDTH_6_MHZ:
@@ -462,7 +462,7 @@ static int dst_set_symbolrate(struct dst_state *state, u32 srate)
 
        state->symbol_rate = srate;
        if (state->dst_type == DST_TYPE_IS_TERR) {
-               return 0;
+               return -EOPNOTSUPP;
        }
        dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
        srate /= 1000;
@@ -504,7 +504,7 @@ static int dst_set_symbolrate(struct dst_state *state, u32 srate)
 static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation)
 {
        if (state->dst_type != DST_TYPE_IS_CABLE)
-               return 0;
+               return -EOPNOTSUPP;
 
        state->modulation = modulation;
        switch (modulation) {
@@ -1234,7 +1234,7 @@ int dst_command(struct dst_state *state, u8 *data, u8 len)
                goto error;
        }
        if (write_dst(state, data, len)) {
-               dprintk(verbose, DST_INFO, 1, "Tring to recover.. ");
+               dprintk(verbose, DST_INFO, 1, "Trying to recover.. ");
                if ((dst_error_recovery(state)) < 0) {
                        dprintk(verbose, DST_ERROR, 1, "Recovery Failed.");
                        goto error;
@@ -1328,15 +1328,13 @@ static int dst_tone_power_cmd(struct dst_state *state)
 {
        u8 paket[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 };
 
-       if (state->dst_type == DST_TYPE_IS_TERR)
-               return 0;
+       if (state->dst_type != DST_TYPE_IS_SAT)
+               return -EOPNOTSUPP;
        paket[4] = state->tx_tuna[4];
        paket[2] = state->tx_tuna[2];
        paket[3] = state->tx_tuna[3];
        paket[7] = dst_check_sum (paket, 7);
-       dst_command(state, paket, 8);
-
-       return 0;
+       return dst_command(state, paket, 8);
 }
 
 static int dst_get_tuna(struct dst_state *state)
@@ -1465,7 +1463,7 @@ static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd
        u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec };
 
        if (state->dst_type != DST_TYPE_IS_SAT)
-               return 0;
+               return -EOPNOTSUPP;
        if (cmd->msg_len > 0 && cmd->msg_len < 5)
                memcpy(&paket[3], cmd->msg, cmd->msg_len);
        else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5)
@@ -1473,18 +1471,17 @@ static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd
        else
                return -EINVAL;
        paket[7] = dst_check_sum(&paket[0], 7);
-       dst_command(state, paket, 8);
-       return 0;
+       return dst_command(state, paket, 8);
 }
 
 static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 {
-       int need_cmd;
+       int need_cmd, retval = 0;
        struct dst_state *state = fe->demodulator_priv;
 
        state->voltage = voltage;
        if (state->dst_type != DST_TYPE_IS_SAT)
-               return 0;
+               return -EOPNOTSUPP;
 
        need_cmd = 0;
 
@@ -1506,9 +1503,9 @@ static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
        }
 
        if (need_cmd)
-               dst_tone_power_cmd(state);
+               retval = dst_tone_power_cmd(state);
 
-       return 0;
+       return retval;
 }
 
 static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
@@ -1517,7 +1514,7 @@ static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
 
        state->tone = tone;
        if (state->dst_type != DST_TYPE_IS_SAT)
-               return 0;
+               return -EOPNOTSUPP;
 
        switch (tone) {
        case SEC_TONE_OFF:
@@ -1533,9 +1530,7 @@ static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
        default:
                return -EINVAL;
        }
-       dst_tone_power_cmd(state);
-
-       return 0;
+       return dst_tone_power_cmd(state);
 }
 
 static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
@@ -1543,7 +1538,7 @@ static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
        struct dst_state *state = fe->demodulator_priv;
 
        if (state->dst_type != DST_TYPE_IS_SAT)
-               return 0;
+               return -EOPNOTSUPP;
        state->minicmd = minicmd;
        switch (minicmd) {
        case SEC_MINI_A:
@@ -1553,9 +1548,7 @@ static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
                state->tx_tuna[3] = 0xff;
                break;
        }
-       dst_tone_power_cmd(state);
-
-       return 0;
+       return dst_tone_power_cmd(state);
 }
 
 
@@ -1608,28 +1601,31 @@ static int dst_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 {
        struct dst_state *state = fe->demodulator_priv;
 
-       dst_get_signal(state);
+       int retval = dst_get_signal(state);
        *strength = state->decode_strength;
 
-       return 0;
+       return retval;
 }
 
 static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
        struct dst_state *state = fe->demodulator_priv;
 
-       dst_get_signal(state);
+       int retval = dst_get_signal(state);
        *snr = state->decode_snr;
 
-       return 0;
+       return retval;
 }
 
 static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
 {
+       int retval = -EINVAL;
        struct dst_state *state = fe->demodulator_priv;
 
        if (p != NULL) {
-               dst_set_freq(state, p->frequency);
+               retval = dst_set_freq(state, p->frequency);
+               if(retval != 0)
+                       return retval;
                dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
 
                if (state->dst_type == DST_TYPE_IS_SAT) {
@@ -1647,10 +1643,10 @@ static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_paramet
                        dst_set_symbolrate(state, p->u.qam.symbol_rate);
                        dst_set_modulation(state, p->u.qam.modulation);
                }
-               dst_write_tuna(fe);
+               retval = dst_write_tuna(fe);
        }
 
-       return 0;
+       return retval;
 }
 
 static int dst_tune_frontend(struct dvb_frontend* fe,
index 11054657fdb507491dd4d944ace466bbc6ba7a35..0b5182835cc82d4205b06ac473073d3e1b6e0ac2 100644 (file)
@@ -2,8 +2,8 @@
 # Makefile for the kernel DVB device drivers.
 #
 
-dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o     \
-               dvb_ca_en50221.o dvb_frontend.o                 \
-               dvb_net.o dvb_ringbuffer.o dvb_math.o
+dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o    \
+                dvb_ca_en50221.o dvb_frontend.o                \
+                dvb_net.o dvb_ringbuffer.o dvb_math.o
 
 obj-$(CONFIG_DVB_CORE) += dvb-core.o
index de3128a31de825f6d31b2c9c7a2431d83f7f98b0..220076b1b956df5d20434a5c5d8b2d9b9c1e7583 100644 (file)
@@ -350,5 +350,15 @@ config RADIO_ZOLTRIX_PORT
        help
          Enter the I/O port of your Zoltrix radio card.
 
-endmenu
+config USB_DSBR
+       tristate "D-Link USB FM radio support (EXPERIMENTAL)"
+       depends on USB && VIDEO_V4L1 && EXPERIMENTAL
+       ---help---
+         Say Y here if you want to connect this type of radio to your
+         computer's USB port. Note that the audio is not digital, and
+         you must connect the line out connector to a sound card or a
+         set of speakers.
 
+         To compile this driver as a module, choose M here: the
+         module will be called dsbr100.
+endmenu
index e95b6805e00257ecdc752a405bc81eba2e443f8a..cf55a18e3ddf94bcd0c20a2d834db3a980f62d67 100644 (file)
@@ -20,5 +20,6 @@ obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o
 obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o
 obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
 obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
+obj-$(CONFIG_USB_DSBR) += dsbr100.o
 
 EXTRA_CFLAGS += -Isound
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
new file mode 100644 (file)
index 0000000..f7e33f9
--- /dev/null
@@ -0,0 +1,430 @@
+/* A driver for the D-Link DSB-R100 USB radio.  The R100 plugs
+ into both the USB and an analog audio input, so this thing
+ only deals with initialisation and frequency setting, the
+ audio data has to be handled by a sound driver.
+
+ Major issue: I can't find out where the device reports the signal
+ strength, and indeed the windows software appearantly just looks
+ at the stereo indicator as well.  So, scanning will only find
+ stereo stations.  Sad, but I can't help it.
+
+ Also, the windows program sends oodles of messages over to the
+ device, and I couldn't figure out their meaning.  My suspicion
+ is that they don't have any:-)
+
+ You might find some interesting stuff about this module at
+ http://unimut.fsk.uni-heidelberg.de/unimut/demi/dsbr
+
+ Copyright (c) 2000 Markus Demleitner <msdemlei@cl.uni-heidelberg.de>
+
+ 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.
+
+ 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
+
+ History:
+
+ Version 0.40:
+  Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing
+
+ Version 0.30:
+       Markus: Updates for 2.5.x kernel and more ISO compliant source
+
+ Version 0.25:
+       PSL and Markus: Cleanup, radio now doesn't stop on device close
+
+ Version 0.24:
+       Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally
+       right.  Some minor cleanup, improved standalone compilation
+
+ Version 0.23:
+       Markus: Sign extension bug fixed by declaring transfer_buffer unsigned
+
+ Version 0.22:
+       Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns,
+       thanks to Mike Cox for pointing the problem out.
+
+ Version 0.21:
+       Markus: Minor cleanup, warnings if something goes wrong, lame attempt
+       to adhere to Documentation/CodingStyle
+
+ Version 0.2:
+       Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module
+       Markus: Copyright clarification
+
+ Version 0.01: Markus: initial release
+
+*/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/videodev.h>
+#include <media/v4l2-common.h>
+#include <linux/usb.h>
+#include <linux/smp_lock.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.40"
+#define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
+#define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver"
+
+#define DSB100_VENDOR 0x04b4
+#define DSB100_PRODUCT 0x1002
+
+/* Commands the device appears to understand */
+#define DSB100_TUNE 1
+#define DSB100_ONOFF 2
+
+#define TB_LEN 16
+
+/* Frequency limits in MHz -- these are European values.  For Japanese
+devices, that would be 76 and 91.  */
+#define FREQ_MIN  87.5
+#define FREQ_MAX 108.0
+#define FREQ_MUL 16000
+
+
+static int usb_dsbr100_probe(struct usb_interface *intf,
+                            const struct usb_device_id *id);
+static void usb_dsbr100_disconnect(struct usb_interface *intf);
+static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
+                            unsigned int cmd, unsigned long arg);
+static int usb_dsbr100_open(struct inode *inode, struct file *file);
+static int usb_dsbr100_close(struct inode *inode, struct file *file);
+
+static int radio_nr = -1;
+module_param(radio_nr, int, 0);
+
+/* Data for one (physical) device */
+typedef struct {
+       struct usb_device *usbdev;
+       struct video_device *videodev;
+       unsigned char transfer_buffer[TB_LEN];
+       int curfreq;
+       int stereo;
+       int users;
+       int removed;
+} dsbr100_device;
+
+
+/* File system interface */
+static struct file_operations usb_dsbr100_fops = {
+       .owner =        THIS_MODULE,
+       .open =         usb_dsbr100_open,
+       .release =      usb_dsbr100_close,
+       .ioctl =        usb_dsbr100_ioctl,
+       .compat_ioctl = v4l_compat_ioctl32,
+       .llseek =       no_llseek,
+};
+
+/* V4L interface */
+static struct video_device dsbr100_videodev_template=
+{
+       .owner =        THIS_MODULE,
+       .name =         "D-Link DSB-R 100",
+       .type =         VID_TYPE_TUNER,
+       .hardware =     VID_HARDWARE_AZTECH,
+       .fops =         &usb_dsbr100_fops,
+       .release = video_device_release,
+};
+
+static struct usb_device_id usb_dsbr100_device_table [] = {
+       { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
+       { }                                             /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table);
+
+/* USB subsystem interface */
+static struct usb_driver usb_dsbr100_driver = {
+       .name =         "dsbr100",
+       .probe =        usb_dsbr100_probe,
+       .disconnect =   usb_dsbr100_disconnect,
+       .id_table =     usb_dsbr100_device_table,
+};
+
+/* Low-level device interface begins here */
+
+/* switch on radio */
+static int dsbr100_start(dsbr100_device *radio)
+{
+       if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
+                       USB_REQ_GET_STATUS,
+                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+                       0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 ||
+       usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
+                       DSB100_ONOFF,
+                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+                       0x01, 0x00, radio->transfer_buffer, 8, 300)<0)
+               return -1;
+       return (radio->transfer_buffer)[0];
+}
+
+
+/* switch off radio */
+static int dsbr100_stop(dsbr100_device *radio)
+{
+       if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
+                       USB_REQ_GET_STATUS,
+                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+                       0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 ||
+       usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
+                       DSB100_ONOFF,
+                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+                       0x00, 0x00, radio->transfer_buffer, 8, 300)<0)
+               return -1;
+       return (radio->transfer_buffer)[0];
+}
+
+/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
+static int dsbr100_setfreq(dsbr100_device *radio, int freq)
+{
+       freq = (freq/16*80)/1000+856;
+       if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
+                       DSB100_TUNE,
+                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+                       (freq>>8)&0x00ff, freq&0xff,
+                       radio->transfer_buffer, 8, 300)<0 ||
+          usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
+                       USB_REQ_GET_STATUS,
+                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+                       0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 ||
+       usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
+                       USB_REQ_GET_STATUS,
+                       USB_TYPE_VENDOR | USB_RECIP_DEVICE |  USB_DIR_IN,
+                       0x00, 0x24, radio->transfer_buffer, 8, 300)<0) {
+               radio->stereo = -1;
+               return -1;
+       }
+       radio->stereo = ! ((radio->transfer_buffer)[0]&0x01);
+       return (radio->transfer_buffer)[0];
+}
+
+/* return the device status.  This is, in effect, just whether it
+sees a stereo signal or not.  Pity. */
+static void dsbr100_getstat(dsbr100_device *radio)
+{
+       if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
+               USB_REQ_GET_STATUS,
+               USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+               0x00 , 0x24, radio->transfer_buffer, 8, 300)<0)
+               radio->stereo = -1;
+       else
+               radio->stereo = ! (radio->transfer_buffer[0]&0x01);
+}
+
+
+/* USB subsystem interface begins here */
+
+/* check if the device is present and register with v4l and
+usb if it is */
+static int usb_dsbr100_probe(struct usb_interface *intf,
+                        const struct usb_device_id *id)
+{
+       dsbr100_device *radio;
+
+       if (!(radio = kmalloc(sizeof(dsbr100_device), GFP_KERNEL)))
+               return -ENOMEM;
+       if (!(radio->videodev = video_device_alloc())) {
+               kfree(radio);
+               return -ENOMEM;
+       }
+       memcpy(radio->videodev, &dsbr100_videodev_template,
+               sizeof(dsbr100_videodev_template));
+       radio->removed = 0;
+       radio->users = 0;
+       radio->usbdev = interface_to_usbdev(intf);
+       radio->curfreq = FREQ_MIN*FREQ_MUL;
+       video_set_drvdata(radio->videodev, radio);
+       if (video_register_device(radio->videodev, VFL_TYPE_RADIO,
+               radio_nr)) {
+               warn("Could not register video device");
+               video_device_release(radio->videodev);
+               kfree(radio);
+               return -EIO;
+       }
+       usb_set_intfdata(intf, radio);
+       return 0;
+}
+
+/* handle unplugging of the device, release data structures
+if nothing keeps us from doing it.  If something is still
+keeping us busy, the release callback of v4l will take care
+of releasing it.  stv680.c does not relase its private
+data, so I don't do this here either.  Checking out the
+code I'd expect I better did that, but if there's a memory
+leak here it's tiny (~50 bytes per disconnect) */
+static void usb_dsbr100_disconnect(struct usb_interface *intf)
+{
+       dsbr100_device *radio = usb_get_intfdata(intf);
+
+       usb_set_intfdata (intf, NULL);
+       if (radio) {
+               video_unregister_device(radio->videodev);
+               radio->videodev = NULL;
+               if (radio->users) {
+                       kfree(radio);
+               } else {
+                       radio->removed = 1;
+               }
+       }
+}
+
+
+/* Video for Linux interface */
+
+static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file,
+                               unsigned int cmd, void *arg)
+{
+       dsbr100_device *radio=video_get_drvdata(video_devdata(file));
+
+       if (!radio)
+               return -EIO;
+
+       switch(cmd) {
+               case VIDIOCGCAP: {
+                       struct video_capability *v = arg;
+
+                       memset(v, 0, sizeof(*v));
+                       v->type = VID_TYPE_TUNER;
+                       v->channels = 1;
+                       v->audios = 1;
+                       strcpy(v->name, "D-Link R-100 USB FM Radio");
+                       return 0;
+               }
+               case VIDIOCGTUNER: {
+                       struct video_tuner *v = arg;
+
+                       dsbr100_getstat(radio);
+                       if(v->tuner)    /* Only 1 tuner */
+                               return -EINVAL;
+                       v->rangelow = FREQ_MIN*FREQ_MUL;
+                       v->rangehigh = FREQ_MAX*FREQ_MUL;
+                       v->flags = VIDEO_TUNER_LOW;
+                       v->mode = VIDEO_MODE_AUTO;
+                       v->signal = radio->stereo*0x7000;
+                               /* Don't know how to get signal strength */
+                       v->flags |= VIDEO_TUNER_STEREO_ON*radio->stereo;
+                       strcpy(v->name, "DSB R-100");
+                       return 0;
+               }
+               case VIDIOCSTUNER: {
+                       struct video_tuner *v = arg;
+
+                       if(v->tuner!=0)
+                               return -EINVAL;
+                       /* Only 1 tuner so no setting needed ! */
+                       return 0;
+               }
+               case VIDIOCGFREQ: {
+                       int *freq = arg;
+
+                       if (radio->curfreq==-1)
+                               return -EINVAL;
+                       *freq = radio->curfreq;
+                       return 0;
+               }
+               case VIDIOCSFREQ: {
+                       int *freq = arg;
+
+                       radio->curfreq = *freq;
+                       if (dsbr100_setfreq(radio, radio->curfreq)==-1)
+                               warn("Set frequency failed");
+                       return 0;
+               }
+               case VIDIOCGAUDIO: {
+                       struct video_audio *v = arg;
+
+                       memset(v, 0, sizeof(*v));
+                       v->flags |= VIDEO_AUDIO_MUTABLE;
+                       v->mode = VIDEO_SOUND_STEREO;
+                       v->volume = 1;
+                       v->step = 1;
+                       strcpy(v->name, "Radio");
+                       return 0;
+               }
+               case VIDIOCSAUDIO: {
+                       struct video_audio *v = arg;
+
+                       if (v->audio)
+                               return -EINVAL;
+                       if (v->flags&VIDEO_AUDIO_MUTE) {
+                               if (dsbr100_stop(radio)==-1)
+                                       warn("Radio did not respond properly");
+                       }
+                       else
+                               if (dsbr100_start(radio)==-1)
+                                       warn("Radio did not respond properly");
+                       return 0;
+               }
+               default:
+                       return -ENOIOCTLCMD;
+       }
+}
+
+static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
+                            unsigned int cmd, unsigned long arg)
+{
+       return video_usercopy(inode, file, cmd, arg, usb_dsbr100_do_ioctl);
+}
+
+static int usb_dsbr100_open(struct inode *inode, struct file *file)
+{
+       dsbr100_device *radio=video_get_drvdata(video_devdata(file));
+
+       radio->users = 1;
+       if (dsbr100_start(radio)<0) {
+               warn("Radio did not start up properly");
+               radio->users = 0;
+               return -EIO;
+       }
+       dsbr100_setfreq(radio, radio->curfreq);
+       return 0;
+}
+
+static int usb_dsbr100_close(struct inode *inode, struct file *file)
+{
+       dsbr100_device *radio=video_get_drvdata(video_devdata(file));
+
+       if (!radio)
+               return -ENODEV;
+       radio->users = 0;
+       if (radio->removed) {
+               kfree(radio);
+       }
+       return 0;
+}
+
+static int __init dsbr100_init(void)
+{
+       int retval = usb_register(&usb_dsbr100_driver);
+       info(DRIVER_VERSION ":" DRIVER_DESC);
+       return retval;
+}
+
+static void __exit dsbr100_exit(void)
+{
+       usb_deregister(&usb_dsbr100_driver);
+}
+
+module_init (dsbr100_init);
+module_exit (dsbr100_exit);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
index fe56862d51e4c6d299cea923deb4204a47527d48..732bf1e7c326bc806c46073d01d8f0891ec53c55 100644 (file)
@@ -449,18 +449,6 @@ source "drivers/media/video/pvrusb2/Kconfig"
 
 source "drivers/media/video/em28xx/Kconfig"
 
-config USB_DSBR
-       tristate "D-Link USB FM radio support (EXPERIMENTAL)"
-       depends on USB && VIDEO_V4L1 && EXPERIMENTAL
-       ---help---
-         Say Y here if you want to connect this type of radio to your
-         computer's USB port. Note that the audio is not digital, and
-         you must connect the line out connector to a sound card or a
-         set of speakers.
-
-         To compile this driver as a module, choose M here: the
-         module will be called dsbr100.
-
 source "drivers/media/video/usbvideo/Kconfig"
 
 source "drivers/media/video/et61x251/Kconfig"
index 353d61cfac1b2150021762ed5529ae3ad81b089f..e82e511f2a72782e343c6d19258d84f7aeeca6af 100644 (file)
@@ -77,7 +77,6 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
 obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
 
 obj-$(CONFIG_USB_DABUSB)        += dabusb.o
-obj-$(CONFIG_USB_DSBR)          += dsbr100.o
 obj-$(CONFIG_USB_OV511)         += ov511.o
 obj-$(CONFIG_USB_SE401)         += se401.o
 obj-$(CONFIG_USB_STV680)        += stv680.o
@@ -91,6 +90,7 @@ obj-$(CONFIG_USB_ZC0301)        += zc0301/
 obj-$(CONFIG_USB_IBMCAM)        += usbvideo/
 obj-$(CONFIG_USB_KONICAWC)      += usbvideo/
 obj-$(CONFIG_USB_VICAM)         += usbvideo/
+obj-$(CONFIG_USB_QUICKCAM_MESSENGER)   += usbvideo/
 
 obj-$(CONFIG_VIDEO_VIVI) += vivi.o
 
index 9dddff42ec1364d4cbd394bc0c4623a011d59cc6..b69ee1194815cf84155b109d0d8f801de4e3ff58 100644 (file)
@@ -21,7 +21,7 @@
 
 #ifdef CONFIG_COMPAT
 
-
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 struct video_tuner32 {
        compat_int_t tuner;
        char name[32];
@@ -107,6 +107,7 @@ struct video_window32 {
        compat_caddr_t clips;
        compat_int_t clipcount;
 };
+#endif
 
 static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
@@ -124,6 +125,7 @@ static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 }
 
 
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 /* You get back everything except the clips... */
 static int put_video_window32(struct video_window *kp, struct video_window32 __user *up)
 {
@@ -138,6 +140,7 @@ static int put_video_window32(struct video_window *kp, struct video_window32 __u
                        return -EFAULT;
        return 0;
 }
+#endif
 
 struct v4l2_clip32
 {
@@ -490,6 +493,7 @@ static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user
        return 0;
 }
 
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 struct video_code32
 {
        char            loadwhat[16];   /* name or tag of file being passed */
@@ -517,6 +521,8 @@ static inline int microcode32(struct video_code *kp, struct video_code32 __user
 #define VIDIOCSFREQ32          _IOW('v',15, u32)
 #define VIDIOCSMICROCODE32     _IOW('v',27, struct video_code32)
 
+#endif
+
 /* VIDIOC_ENUMINPUT32 is VIDIOC_ENUMINPUT minus 4 bytes of padding alignement */
 #define VIDIOC_ENUMINPUT32     VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4)
 #define VIDIOC_G_FMT32         _IOWR ('V',  4, struct v4l2_format32)
@@ -537,6 +543,7 @@ static inline int microcode32(struct video_code *kp, struct video_code32 __user
 #define VIDIOC_S_INPUT32       _IOWR ('V', 39, compat_int_t)
 #define VIDIOC_TRY_FMT32       _IOWR ('V', 64, struct v4l2_format32)
 
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 enum {
        MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip)
 };
@@ -601,14 +608,17 @@ static int do_set_window(struct file *file, unsigned int cmd, unsigned long arg)
 
        return native_ioctl(file, VIDIOCSWIN, (unsigned long)vw);
 }
+#endif
 
 static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        union {
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
                struct video_tuner vt;
                struct video_buffer vb;
                struct video_window vw;
                struct video_code vc;
+#endif
                struct v4l2_format v2f;
                struct v4l2_buffer v2b;
                struct v4l2_framebuffer v2fb;
@@ -624,6 +634,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
 
        /* First, convert the command. */
        switch(cmd) {
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
        case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;
        case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;
        case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;
@@ -631,6 +642,8 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
        case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;
        case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;
        case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;
+       case VIDIOCSMICROCODE32: cmd = VIDIOCSMICROCODE; break;
+#endif
        case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
        case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
        case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
@@ -647,10 +660,10 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
        case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
        case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
        case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;
-       case VIDIOCSMICROCODE32: cmd = VIDIOCSMICROCODE; break;
        };
 
        switch(cmd) {
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
        case VIDIOCSTUNER:
        case VIDIOCGTUNER:
                err = get_video_tuner32(&karg.vt, up);
@@ -664,6 +677,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
                break;
 
        case VIDIOCSFREQ:
+#endif
        case VIDIOC_S_INPUT:
        case VIDIOC_OVERLAY:
        case VIDIOC_STREAMON:
@@ -717,18 +731,21 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
                compatible_arg = 0;
                break;
 
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
        case VIDIOCGWIN:
        case VIDIOCGFBUF:
        case VIDIOCGFREQ:
+#endif
        case VIDIOC_G_FBUF:
        case VIDIOC_G_INPUT:
                compatible_arg = 0;
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
        case VIDIOCSMICROCODE:
                err = microcode32(&karg.vc, up);
                compatible_arg = 0;
                break;
+#endif
        };
-
        if(err)
                goto out;
 
@@ -743,6 +760,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
        }
        if(err == 0) {
                switch(cmd) {
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
                case VIDIOCGTUNER:
                        err = put_video_tuner32(&karg.vt, up);
                        break;
@@ -754,7 +772,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
                case VIDIOCGFBUF:
                        err = put_video_buffer32(&karg.vb, up);
                        break;
-
+#endif
                case VIDIOC_G_FBUF:
                        err = put_v4l2_framebuffer32(&karg.v2fb, up);
                        break;
@@ -792,7 +810,9 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
                        err = put_v4l2_input32(&karg.v2i, up);
                        break;
 
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
                case VIDIOCGFREQ:
+#endif
                case VIDIOC_G_INPUT:
                        err = put_user(((u32)karg.vx), (u32 __user *)up);
                        break;
@@ -810,6 +830,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
                return ret;
 
        switch (cmd) {
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
        case VIDIOCSWIN32:
                ret = do_set_window(file, cmd, arg);
                break;
@@ -820,6 +841,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
        case VIDIOCSFBUF32:
        case VIDIOCGFREQ32:
        case VIDIOCSFREQ32:
+#endif
        case VIDIOC_QUERYCAP:
        case VIDIOC_ENUM_FMT:
        case VIDIOC_G_FMT32:
@@ -851,6 +873,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
                ret = do_video_ioctl(file, cmd, arg);
                break;
 
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
        /* Little v, the video4linux ioctls (conflict?) */
        case VIDIOCGCAP:
        case VIDIOCGCHAN:
@@ -879,6 +902,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
        case _IOR('v' , BASE_VIDIOCPRIVATE+7, int):
                ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
                break;
+#endif
        default:
                v4l_print_ioctl("compat_ioctl32", cmd);
        }
index 5c2036b40ea11e8373b101a3a9c2844ddbcf0dd5..7bb7589a07c30719f7796e78081d01cc0e878ee7 100644 (file)
@@ -104,8 +104,8 @@ u32 cx25840_read4(struct i2c_client * client, u16 addr)
        if (i2c_master_recv(client, buffer, 4) < 4)
                return 0;
 
-       return (buffer[0] << 24) | (buffer[1] << 16) |
-           (buffer[2] << 8) | buffer[3];
+       return (buffer[3] << 24) | (buffer[2] << 16) |
+           (buffer[1] << 8) | buffer[0];
 }
 
 int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned and_mask,
index 547cdbdb644d7393b7f3ebfa7050c25a2ee17d47..94c92bacc342be219f78035e855c78d43ce1a763 100644 (file)
@@ -1225,7 +1225,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
                struct v4l2_format *f = arg;
                return cx8800_try_fmt(dev,fh,f);
        }
-#ifdef CONFIG_V4L1_COMPAT
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
        /* --- streaming capture ------------------------------------- */
        case VIDIOCGMBUF:
        {
@@ -1584,7 +1584,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
                *id = 0;
                return 0;
        }
-#ifdef CONFIG_V4L1_COMPAT
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
        case VIDIOCSTUNER:
        {
                struct video_tuner *v = arg;
diff --git a/drivers/media/video/dsbr100.c b/drivers/media/video/dsbr100.c
deleted file mode 100644 (file)
index f7e33f9..0000000
+++ /dev/null
@@ -1,430 +0,0 @@
-/* A driver for the D-Link DSB-R100 USB radio.  The R100 plugs
- into both the USB and an analog audio input, so this thing
- only deals with initialisation and frequency setting, the
- audio data has to be handled by a sound driver.
-
- Major issue: I can't find out where the device reports the signal
- strength, and indeed the windows software appearantly just looks
- at the stereo indicator as well.  So, scanning will only find
- stereo stations.  Sad, but I can't help it.
-
- Also, the windows program sends oodles of messages over to the
- device, and I couldn't figure out their meaning.  My suspicion
- is that they don't have any:-)
-
- You might find some interesting stuff about this module at
- http://unimut.fsk.uni-heidelberg.de/unimut/demi/dsbr
-
- Copyright (c) 2000 Markus Demleitner <msdemlei@cl.uni-heidelberg.de>
-
- 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.
-
- 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
-
- History:
-
- Version 0.40:
-  Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing
-
- Version 0.30:
-       Markus: Updates for 2.5.x kernel and more ISO compliant source
-
- Version 0.25:
-       PSL and Markus: Cleanup, radio now doesn't stop on device close
-
- Version 0.24:
-       Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally
-       right.  Some minor cleanup, improved standalone compilation
-
- Version 0.23:
-       Markus: Sign extension bug fixed by declaring transfer_buffer unsigned
-
- Version 0.22:
-       Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns,
-       thanks to Mike Cox for pointing the problem out.
-
- Version 0.21:
-       Markus: Minor cleanup, warnings if something goes wrong, lame attempt
-       to adhere to Documentation/CodingStyle
-
- Version 0.2:
-       Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module
-       Markus: Copyright clarification
-
- Version 0.01: Markus: initial release
-
-*/
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <linux/usb.h>
-#include <linux/smp_lock.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.40"
-#define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
-#define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver"
-
-#define DSB100_VENDOR 0x04b4
-#define DSB100_PRODUCT 0x1002
-
-/* Commands the device appears to understand */
-#define DSB100_TUNE 1
-#define DSB100_ONOFF 2
-
-#define TB_LEN 16
-
-/* Frequency limits in MHz -- these are European values.  For Japanese
-devices, that would be 76 and 91.  */
-#define FREQ_MIN  87.5
-#define FREQ_MAX 108.0
-#define FREQ_MUL 16000
-
-
-static int usb_dsbr100_probe(struct usb_interface *intf,
-                            const struct usb_device_id *id);
-static void usb_dsbr100_disconnect(struct usb_interface *intf);
-static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
-                            unsigned int cmd, unsigned long arg);
-static int usb_dsbr100_open(struct inode *inode, struct file *file);
-static int usb_dsbr100_close(struct inode *inode, struct file *file);
-
-static int radio_nr = -1;
-module_param(radio_nr, int, 0);
-
-/* Data for one (physical) device */
-typedef struct {
-       struct usb_device *usbdev;
-       struct video_device *videodev;
-       unsigned char transfer_buffer[TB_LEN];
-       int curfreq;
-       int stereo;
-       int users;
-       int removed;
-} dsbr100_device;
-
-
-/* File system interface */
-static struct file_operations usb_dsbr100_fops = {
-       .owner =        THIS_MODULE,
-       .open =         usb_dsbr100_open,
-       .release =      usb_dsbr100_close,
-       .ioctl =        usb_dsbr100_ioctl,
-       .compat_ioctl = v4l_compat_ioctl32,
-       .llseek =       no_llseek,
-};
-
-/* V4L interface */
-static struct video_device dsbr100_videodev_template=
-{
-       .owner =        THIS_MODULE,
-       .name =         "D-Link DSB-R 100",
-       .type =         VID_TYPE_TUNER,
-       .hardware =     VID_HARDWARE_AZTECH,
-       .fops =         &usb_dsbr100_fops,
-       .release = video_device_release,
-};
-
-static struct usb_device_id usb_dsbr100_device_table [] = {
-       { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
-       { }                                             /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table);
-
-/* USB subsystem interface */
-static struct usb_driver usb_dsbr100_driver = {
-       .name =         "dsbr100",
-       .probe =        usb_dsbr100_probe,
-       .disconnect =   usb_dsbr100_disconnect,
-       .id_table =     usb_dsbr100_device_table,
-};
-
-/* Low-level device interface begins here */
-
-/* switch on radio */
-static int dsbr100_start(dsbr100_device *radio)
-{
-       if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
-                       USB_REQ_GET_STATUS,
-                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-                       0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 ||
-       usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
-                       DSB100_ONOFF,
-                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-                       0x01, 0x00, radio->transfer_buffer, 8, 300)<0)
-               return -1;
-       return (radio->transfer_buffer)[0];
-}
-
-
-/* switch off radio */
-static int dsbr100_stop(dsbr100_device *radio)
-{
-       if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
-                       USB_REQ_GET_STATUS,
-                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-                       0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 ||
-       usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
-                       DSB100_ONOFF,
-                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-                       0x00, 0x00, radio->transfer_buffer, 8, 300)<0)
-               return -1;
-       return (radio->transfer_buffer)[0];
-}
-
-/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
-static int dsbr100_setfreq(dsbr100_device *radio, int freq)
-{
-       freq = (freq/16*80)/1000+856;
-       if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
-                       DSB100_TUNE,
-                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-                       (freq>>8)&0x00ff, freq&0xff,
-                       radio->transfer_buffer, 8, 300)<0 ||
-          usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
-                       USB_REQ_GET_STATUS,
-                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-                       0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 ||
-       usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
-                       USB_REQ_GET_STATUS,
-                       USB_TYPE_VENDOR | USB_RECIP_DEVICE |  USB_DIR_IN,
-                       0x00, 0x24, radio->transfer_buffer, 8, 300)<0) {
-               radio->stereo = -1;
-               return -1;
-       }
-       radio->stereo = ! ((radio->transfer_buffer)[0]&0x01);
-       return (radio->transfer_buffer)[0];
-}
-
-/* return the device status.  This is, in effect, just whether it
-sees a stereo signal or not.  Pity. */
-static void dsbr100_getstat(dsbr100_device *radio)
-{
-       if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
-               USB_REQ_GET_STATUS,
-               USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-               0x00 , 0x24, radio->transfer_buffer, 8, 300)<0)
-               radio->stereo = -1;
-       else
-               radio->stereo = ! (radio->transfer_buffer[0]&0x01);
-}
-
-
-/* USB subsystem interface begins here */
-
-/* check if the device is present and register with v4l and
-usb if it is */
-static int usb_dsbr100_probe(struct usb_interface *intf,
-                        const struct usb_device_id *id)
-{
-       dsbr100_device *radio;
-
-       if (!(radio = kmalloc(sizeof(dsbr100_device), GFP_KERNEL)))
-               return -ENOMEM;
-       if (!(radio->videodev = video_device_alloc())) {
-               kfree(radio);
-               return -ENOMEM;
-       }
-       memcpy(radio->videodev, &dsbr100_videodev_template,
-               sizeof(dsbr100_videodev_template));
-       radio->removed = 0;
-       radio->users = 0;
-       radio->usbdev = interface_to_usbdev(intf);
-       radio->curfreq = FREQ_MIN*FREQ_MUL;
-       video_set_drvdata(radio->videodev, radio);
-       if (video_register_device(radio->videodev, VFL_TYPE_RADIO,
-               radio_nr)) {
-               warn("Could not register video device");
-               video_device_release(radio->videodev);
-               kfree(radio);
-               return -EIO;
-       }
-       usb_set_intfdata(intf, radio);
-       return 0;
-}
-
-/* handle unplugging of the device, release data structures
-if nothing keeps us from doing it.  If something is still
-keeping us busy, the release callback of v4l will take care
-of releasing it.  stv680.c does not relase its private
-data, so I don't do this here either.  Checking out the
-code I'd expect I better did that, but if there's a memory
-leak here it's tiny (~50 bytes per disconnect) */
-static void usb_dsbr100_disconnect(struct usb_interface *intf)
-{
-       dsbr100_device *radio = usb_get_intfdata(intf);
-
-       usb_set_intfdata (intf, NULL);
-       if (radio) {
-               video_unregister_device(radio->videodev);
-               radio->videodev = NULL;
-               if (radio->users) {
-                       kfree(radio);
-               } else {
-                       radio->removed = 1;
-               }
-       }
-}
-
-
-/* Video for Linux interface */
-
-static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file,
-                               unsigned int cmd, void *arg)
-{
-       dsbr100_device *radio=video_get_drvdata(video_devdata(file));
-
-       if (!radio)
-               return -EIO;
-
-       switch(cmd) {
-               case VIDIOCGCAP: {
-                       struct video_capability *v = arg;
-
-                       memset(v, 0, sizeof(*v));
-                       v->type = VID_TYPE_TUNER;
-                       v->channels = 1;
-                       v->audios = 1;
-                       strcpy(v->name, "D-Link R-100 USB FM Radio");
-                       return 0;
-               }
-               case VIDIOCGTUNER: {
-                       struct video_tuner *v = arg;
-
-                       dsbr100_getstat(radio);
-                       if(v->tuner)    /* Only 1 tuner */
-                               return -EINVAL;
-                       v->rangelow = FREQ_MIN*FREQ_MUL;
-                       v->rangehigh = FREQ_MAX*FREQ_MUL;
-                       v->flags = VIDEO_TUNER_LOW;
-                       v->mode = VIDEO_MODE_AUTO;
-                       v->signal = radio->stereo*0x7000;
-                               /* Don't know how to get signal strength */
-                       v->flags |= VIDEO_TUNER_STEREO_ON*radio->stereo;
-                       strcpy(v->name, "DSB R-100");
-                       return 0;
-               }
-               case VIDIOCSTUNER: {
-                       struct video_tuner *v = arg;
-
-                       if(v->tuner!=0)
-                               return -EINVAL;
-                       /* Only 1 tuner so no setting needed ! */
-                       return 0;
-               }
-               case VIDIOCGFREQ: {
-                       int *freq = arg;
-
-                       if (radio->curfreq==-1)
-                               return -EINVAL;
-                       *freq = radio->curfreq;
-                       return 0;
-               }
-               case VIDIOCSFREQ: {
-                       int *freq = arg;
-
-                       radio->curfreq = *freq;
-                       if (dsbr100_setfreq(radio, radio->curfreq)==-1)
-                               warn("Set frequency failed");
-                       return 0;
-               }
-               case VIDIOCGAUDIO: {
-                       struct video_audio *v = arg;
-
-                       memset(v, 0, sizeof(*v));
-                       v->flags |= VIDEO_AUDIO_MUTABLE;
-                       v->mode = VIDEO_SOUND_STEREO;
-                       v->volume = 1;
-                       v->step = 1;
-                       strcpy(v->name, "Radio");
-                       return 0;
-               }
-               case VIDIOCSAUDIO: {
-                       struct video_audio *v = arg;
-
-                       if (v->audio)
-                               return -EINVAL;
-                       if (v->flags&VIDEO_AUDIO_MUTE) {
-                               if (dsbr100_stop(radio)==-1)
-                                       warn("Radio did not respond properly");
-                       }
-                       else
-                               if (dsbr100_start(radio)==-1)
-                                       warn("Radio did not respond properly");
-                       return 0;
-               }
-               default:
-                       return -ENOIOCTLCMD;
-       }
-}
-
-static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
-                            unsigned int cmd, unsigned long arg)
-{
-       return video_usercopy(inode, file, cmd, arg, usb_dsbr100_do_ioctl);
-}
-
-static int usb_dsbr100_open(struct inode *inode, struct file *file)
-{
-       dsbr100_device *radio=video_get_drvdata(video_devdata(file));
-
-       radio->users = 1;
-       if (dsbr100_start(radio)<0) {
-               warn("Radio did not start up properly");
-               radio->users = 0;
-               return -EIO;
-       }
-       dsbr100_setfreq(radio, radio->curfreq);
-       return 0;
-}
-
-static int usb_dsbr100_close(struct inode *inode, struct file *file)
-{
-       dsbr100_device *radio=video_get_drvdata(video_devdata(file));
-
-       if (!radio)
-               return -ENODEV;
-       radio->users = 0;
-       if (radio->removed) {
-               kfree(radio);
-       }
-       return 0;
-}
-
-static int __init dsbr100_init(void)
-{
-       int retval = usb_register(&usb_dsbr100_driver);
-       info(DRIVER_VERSION ":" DRIVER_DESC);
-       return retval;
-}
-
-static void __exit dsbr100_exit(void)
-{
-       usb_deregister(&usb_dsbr100_driver);
-}
-
-module_init (dsbr100_init);
-module_exit (dsbr100_exit);
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
index f2fd9195b3ac6491468deec543c9c68fdf0af379..ed02ff81138865c27b7b28a80a455af34aae313d 100644 (file)
@@ -961,10 +961,10 @@ int msp34xxg_thread(void *data)
                /* setup the chip*/
                msp34xxg_reset(client);
                state->std = state->radio ? 0x40 : msp_standard;
-               if (state->std != 1)
-                       goto unmute;
                /* start autodetect */
                msp_write_dem(client, 0x20, state->std);
+               if (state->std != 1)
+                       goto unmute;
 
                /* watch autodetect */
                v4l_dbg(1, msp_debug, client, "started autodetect, waiting for result\n");
index 697145e0bf15b551c7073ef727a6c602fc2e0180..8fdf7101d3bfcabb31863d6f0a5622ed5071bb5e 100644 (file)
@@ -30,7 +30,7 @@ config USB_PWC
 
 config USB_PWC_DEBUG
        bool "USB Philips Cameras verbose debug"
-       depends USB_PWC
+       depends on USB_PWC
        help
          Say Y here in order to have the pwc driver generate verbose debugging
          messages.
index 47d0d83a0264445fd4f68b61b5e4b9d1f5906b23..d4703944df9c12c39bb719b311da043da60cb1d9 100644 (file)
@@ -160,6 +160,7 @@ static struct file_operations pwc_fops = {
        .poll =         pwc_video_poll,
        .mmap =         pwc_video_mmap,
        .ioctl =        pwc_video_ioctl,
+       .compat_ioctl = v4l_compat_ioctl32,
        .llseek =       no_llseek,
 };
 static struct video_device pwc_template = {
index 8656f2400e18c6d329252aa62c48f349009aeb41..2c171af9a9f2fb868f81ded74eb70fba0c6353f2 100644 (file)
@@ -2087,7 +2087,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
                struct v4l2_format *f = arg;
                return saa7134_try_fmt(dev,fh,f);
        }
-#ifdef CONFIG_V4L1_COMPAT
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
        case VIDIOCGMBUF:
        {
                struct video_mbuf *mbuf = arg;
index a167e17c6dcd030d3d773c922146a364dd3aea4e..d7eadc2c298da68f3b0ccc8ad8cdfa89f0d276c9 100644 (file)
@@ -1027,10 +1027,11 @@ static struct tuner_params tuner_tnf_5335mf_params[] = {
 /* 70-79 */
 /* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */
 
+/* '+ 4' turns on the Low Noise Amplifier */
 static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = {
-       { 16 * 130.00 /*MHz*/, 0xce, 0x01, },
-       { 16 * 364.50 /*MHz*/, 0xce, 0x02, },
-       { 16 * 999.99        , 0xce, 0x08, },
+       { 16 * 130.00 /*MHz*/, 0xce, 0x01 + 4, },
+       { 16 * 364.50 /*MHz*/, 0xce, 0x02 + 4, },
+       { 16 * 999.99        , 0xce, 0x08 + 4, },
 };
 
 static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = {
@@ -1060,10 +1061,11 @@ static struct tuner_params tuner_thomson_fe6600_params[] = {
 
 /* ------------ TUNER_SAMSUNG_TCPG_6121P30A - Samsung PAL ------------ */
 
+/* '+ 4' turns on the Low Noise Amplifier */
 static struct tuner_range tuner_samsung_tcpg_6121p30a_pal_ranges[] = {
-       { 16 * 146.25 /*MHz*/, 0xce, 0x01, },
-       { 16 * 428.50 /*MHz*/, 0xce, 0x02, },
-       { 16 * 999.99        , 0xce, 0x08, },
+       { 16 * 146.25 /*MHz*/, 0xce, 0x01 + 4, },
+       { 16 * 428.50 /*MHz*/, 0xce, 0x02 + 4, },
+       { 16 * 999.99        , 0xce, 0x08 + 4, },
 };
 
 static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = {
index d83a2c84d2334a279c7febcd070f6f7ef7a27899..d7c3fcbc80f7b5585d2a9463ece0f31695b566ee 100644 (file)
@@ -599,6 +599,10 @@ v4l_compat_translate_ioctl(struct inode         *inode,
                        dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err);
                        break;
                }
+
+               pict->depth   = ((fmt2->fmt.pix.bytesperline<<3)
+                                + (fmt2->fmt.pix.width-1) )
+                                /fmt2->fmt.pix.width;
                pict->palette = pixelformat_to_palette(
                        fmt2->fmt.pix.pixelformat);
                break;
index 2ecbeffb559e251a15400da69cce26292ccc4d1f..8d972ffdaf98782b3070713900faa245d308eec5 100644 (file)
@@ -202,7 +202,7 @@ static char *v4l2_memory_names[] = {
 /* ------------------------------------------------------------------ */
 /* debug help functions                                               */
 
-#ifdef CONFIG_V4L1_COMPAT
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 static const char *v4l1_ioctls[] = {
        [_IOC_NR(VIDIOCGCAP)]       = "VIDIOCGCAP",
        [_IOC_NR(VIDIOCGCHAN)]      = "VIDIOCGCHAN",
@@ -301,7 +301,7 @@ static const char *v4l2_ioctls[] = {
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
 static const char *v4l2_int_ioctls[] = {
-#ifdef CONFIG_V4L1_COMPAT
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
        [_IOC_NR(DECODER_GET_CAPABILITIES)]    = "DECODER_GET_CAPABILITIES",
        [_IOC_NR(DECODER_GET_STATUS)]          = "DECODER_GET_STATUS",
        [_IOC_NR(DECODER_SET_NORM)]            = "DECODER_SET_NORM",
@@ -367,7 +367,7 @@ void v4l_printk_ioctl(unsigned int cmd)
                       (_IOC_NR(cmd) < V4L2_INT_IOCTLS) ?
                       v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
                break;
-#ifdef CONFIG_V4L1_COMPAT
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
        case 'v':
                printk("v4l1 ioctl %s, dir=%s (0x%08x)\n",
                       (_IOC_NR(cmd) < V4L1_IOCTLS) ?
index 0fc90cd393f69f8331b19fd909271232ee0edf39..88bf2af2a0e715d575ca6614139d8becfc16fb05 100644 (file)
@@ -760,7 +760,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
                ret=vfd->vidioc_overlay(file, fh, *i);
                break;
        }
-#ifdef CONFIG_V4L1_COMPAT
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
        /* --- streaming capture ------------------------------------- */
        case VIDIOCGMBUF:
        {
index 38bd0c1018c28817fbc3bb830a9f8fc42fc779b4..841884af0cc03b56a992aa1084740dfa1937c3b6 100644 (file)
@@ -986,7 +986,7 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
                                file->f_flags & O_NONBLOCK));
 }
 
-#ifdef CONFIG_V4L1_COMPAT
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf)
 {
        struct vivi_fh  *fh=priv;
@@ -1328,7 +1328,7 @@ static struct video_device vivi = {
        .vidioc_s_ctrl        = vidioc_s_ctrl,
        .vidioc_streamon      = vidioc_streamon,
        .vidioc_streamoff     = vidioc_streamoff,
-#ifdef CONFIG_V4L1_COMPAT
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
        .vidiocgmbuf          = vidiocgmbuf,
 #endif
        .tvnorms              = tvnorms,
index 0b9682e9a357117edbe4cf439851134051b94d74..74f8cdeeff0f8501f379d01037144ecd404c6ff4 100644 (file)
@@ -79,7 +79,8 @@ static int mmc_queue_thread(void *d)
                spin_lock_irq(q->queue_lock);
                set_current_state(TASK_INTERRUPTIBLE);
                if (!blk_queue_plugged(q))
-                       mq->req = req = elv_next_request(q);
+                       req = elv_next_request(q);
+               mq->req = req;
                spin_unlock_irq(q->queue_lock);
 
                if (!req) {
index 8a30ef3ae4191d52320516ae72b93c75f47a6aac..c351c6d1a18a11ee8ed712c77248b4337c5729d5 100644 (file)
@@ -41,7 +41,7 @@
 #include "wbsd.h"
 
 #define DRIVER_NAME "wbsd"
-#define DRIVER_VERSION "1.5"
+#define DRIVER_VERSION "1.6"
 
 #define DBG(x...) \
        pr_debug(DRIVER_NAME ": " x)
@@ -1439,13 +1439,13 @@ static int __devinit wbsd_scan(struct wbsd_host *host)
 
 static int __devinit wbsd_request_region(struct wbsd_host *host, int base)
 {
-       if (io & 0x7)
+       if (base & 0x7)
                return -EINVAL;
 
        if (!request_region(base, 8, DRIVER_NAME))
                return -EIO;
 
-       host->base = io;
+       host->base = base;
 
        return 0;
 }
@@ -1773,7 +1773,7 @@ static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma,
        /*
         * Request resources.
         */
-       ret = wbsd_request_resources(host, io, irq, dma);
+       ret = wbsd_request_resources(host, base, irq, dma);
        if (ret) {
                wbsd_release_resources(host);
                wbsd_free_mmc(dev);
@@ -1861,6 +1861,7 @@ static void __devexit wbsd_shutdown(struct device *dev, int pnp)
 
 static int __devinit wbsd_probe(struct platform_device *dev)
 {
+       /* Use the module parameters for resources */
        return wbsd_init(&dev->dev, io, irq, dma, 0);
 }
 
index 07136ec423bd1bf0c5daa97f165a8f6ac1030b74..d7b115a35962413b1966b1c90b231bd813a2e848 100644 (file)
@@ -120,7 +120,6 @@ static const char version[] =
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
-#include <linux/config.h>      /* for CONFIG_IP_MULTICAST */
 #include <linux/spinlock.h>
 #include <linux/ethtool.h>
 #include <linux/delay.h>
index 4532b17e40ea04a9649baa2b197077a718dc8c04..aedfddf20cb32c77302903affa7e5584659003d4 100644 (file)
@@ -1003,7 +1003,8 @@ static int corkscrew_start_xmit(struct sk_buff *skb,
                /* Calculate the next Tx descriptor entry. */
                int entry = vp->cur_tx % TX_RING_SIZE;
                struct boom_tx_desc *prev_entry;
-               unsigned long flags, i;
+               unsigned long flags;
+               int i;
 
                if (vp->tx_full)        /* No room to transmit with */
                        return 1;
index 80e8ca013e448a96e54af66220810e80b3c794fb..7c23813bb097485c6199c646b3af933796aeaeb4 100644 (file)
@@ -3169,7 +3169,7 @@ static int __init vortex_init(void)
 {
        int pci_rc, eisa_rc;
 
-       pci_rc = pci_module_init(&vortex_driver);
+       pci_rc = pci_register_driver(&vortex_driver);
        eisa_rc = vortex_eisa_init();
 
        if (pci_rc == 0)
index 1428bb7715afd16a04fb6132cd560b420636d111..4c2e76326c4aecaaf361a5613ab168d0924dde57 100644 (file)
@@ -2098,7 +2098,7 @@ static int __init cp_init (void)
 #ifdef MODULE
        printk("%s", version);
 #endif
-       return pci_module_init (&cp_driver);
+       return pci_register_driver(&cp_driver);
 }
 
 static void __exit cp_exit (void)
index e4f4eaff76792292abe07865d7fcdbae34ac59de..2a707747ed8e2df375b6788941350f6c722bc76b 100644 (file)
@@ -2629,7 +2629,7 @@ static int __init rtl8139_init_module (void)
        printk (KERN_INFO RTL8139_DRIVER_NAME "\n");
 #endif
 
-       return pci_module_init (&rtl8139_pci_driver);
+       return pci_register_driver(&rtl8139_pci_driver);
 }
 
 
index 7e2ca9571467c8e4d9f441c0147537b69371ec35..257d3bce3993956b9c4fca79f5b086c65be776ff 100644 (file)
@@ -899,7 +899,7 @@ memory_squeeze:
 }
 
 
-static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
+static void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
 {
        struct i596_cmd *ptr;
 
@@ -932,7 +932,8 @@ static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private
        lp->scb.cmd = I596_NULL;
 }
 
-static inline void i596_reset(struct net_device *dev, struct i596_private *lp, int ioaddr)
+static void i596_reset(struct net_device *dev, struct i596_private *lp,
+                       int ioaddr)
 {
        unsigned long flags;
 
@@ -1578,7 +1579,7 @@ static int debug = -1;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "i82596 debug mask");
 
-int init_module(void)
+int __init init_module(void)
 {
        if (debug >= 0)
                i596_debug = debug;
@@ -1588,7 +1589,7 @@ int init_module(void)
        return 0;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        unregister_netdev(dev_82596);
 #ifdef __mc68000__
index d2935ae39814ae8e5dce9e4e66b7b2cba43d96ea..3eb7048684a682a7f6730d00630ecb4534e89ce0 100644 (file)
@@ -299,7 +299,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
         *      Slow phase with lock held.
         */
         
-       disable_irq_nosync(dev->irq);
+       disable_irq_nosync_lockdep(dev->irq);
        
        spin_lock(&ei_local->page_lock);
        
@@ -338,7 +338,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
                netif_stop_queue(dev);
                outb_p(ENISR_ALL, e8390_base + EN0_IMR);
                spin_unlock(&ei_local->page_lock);
-               enable_irq(dev->irq);
+               enable_irq_lockdep(dev->irq);
                ei_local->stat.tx_errors++;
                return 1;
        }
@@ -379,7 +379,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
        outb_p(ENISR_ALL, e8390_base + EN0_IMR);
        
        spin_unlock(&ei_local->page_lock);
-       enable_irq(dev->irq);
+       enable_irq_lockdep(dev->irq);
 
        dev_kfree_skb (skb);
        ei_local->stat.tx_bytes += send_length;
@@ -505,9 +505,9 @@ irqreturn_t ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 #ifdef CONFIG_NET_POLL_CONTROLLER
 void ei_poll(struct net_device *dev)
 {
-       disable_irq(dev->irq);
+       disable_irq_lockdep(dev->irq);
        ei_interrupt(dev->irq, dev, NULL);
-       enable_irq(dev->irq);
+       enable_irq_lockdep(dev->irq);
 }
 #endif
 
index 39189903e35579f921d51e8365f55dc43a22f809..6f388d9e9beabfed4b199d111656d14a524ce32c 100644 (file)
@@ -1411,6 +1411,22 @@ config FORCEDETH
          <file:Documentation/networking/net-modules.txt>.  The module will be
          called forcedeth.
 
+config FORCEDETH_NAPI
+       bool "Use Rx and Tx Polling (NAPI) (EXPERIMENTAL)"
+       depends on FORCEDETH && EXPERIMENTAL
+       help
+         NAPI is a new driver API designed to reduce CPU and interrupt load
+         when the driver is receiving lots of packets from the card. It is
+         still somewhat experimental and thus not yet enabled by default.
+
+         If your estimated Rx load is 10kpps or more, or if the card will be
+         deployed on potentially unfriendly networks (e.g. in a firewall),
+         then say Y here.
+
+         See <file:Documentation/networking/NAPI_HOWTO.txt> for more
+         information.
+
+         If in doubt, say N.
 
 config CS89x0
        tristate "CS89x0 support"
@@ -1724,6 +1740,20 @@ config VIA_RHINE_MMIO
 
          If unsure, say Y.
 
+config VIA_RHINE_NAPI
+       bool "Use Rx Polling (NAPI)"
+       depends on VIA_RHINE
+       help
+         NAPI is a new driver API designed to reduce CPU and interrupt load
+         when the driver is receiving lots of packets from the card.
+
+         If your estimated Rx load is 10kpps or more, or if the card will be
+         deployed on potentially unfriendly networks (e.g. in a firewall),
+         then say Y here.
+
+         See <file:Documentation/networking/NAPI_HOWTO.txt> for more
+         information.
+
 config LAN_SAA9730
        bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)"
        depends on NET_PCI && EXPERIMENTAL && MIPS
@@ -2219,6 +2249,33 @@ config GFAR_NAPI
        bool "NAPI Support"
        depends on GIANFAR
 
+config UCC_GETH
+       tristate "Freescale QE UCC GETH"
+       depends on QUICC_ENGINE && UCC_FAST
+       help
+         This driver supports the Gigabit Ethernet mode of QE UCC.
+         QE can be found on MPC836x CPUs.
+
+config UGETH_NAPI
+       bool "NAPI Support"
+       depends on UCC_GETH
+
+config UGETH_MAGIC_PACKET
+       bool "Magic Packet detection support"
+       depends on UCC_GETH
+
+config UGETH_FILTERING
+       bool "Mac address filtering support"
+       depends on UCC_GETH
+
+config UGETH_TX_ON_DEMOND
+       bool "Transmit on Demond support"
+       depends on UCC_GETH
+
+config UGETH_HAS_GIGA
+       bool
+       depends on UCC_GETH && MPC836x
+
 config MV643XX_ETH
        tristate "MV-643XX Ethernet support"
        depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MOMENCO_OCELOT_3 || PPC_MULTIPLATFORM
@@ -2249,6 +2306,15 @@ config MV643XX_ETH_2
          This enables support for Port 2 of the Marvell MV643XX Gigabit
          Ethernet.
 
+config QLA3XXX
+       tristate "QLogic QLA3XXX Network Driver Support"
+       depends on PCI
+       help
+         This driver supports QLogic ISP3XXX gigabit Ethernet cards.
+
+         To compile this driver as a module, choose M here: the module
+         will be called qla3xxx.
+
 endmenu
 
 #
@@ -2509,6 +2575,7 @@ config PLIP
 
 config PPP
        tristate "PPP (point-to-point protocol) support"
+       select SLHC
        ---help---
          PPP (Point to Point Protocol) is a newer and better SLIP.  It serves
          the same purpose: sending Internet traffic over telephone (and other
@@ -2689,6 +2756,7 @@ config SLIP
 config SLIP_COMPRESSED
        bool "CSLIP compressed headers"
        depends on SLIP
+       select SLHC
        ---help---
          This protocol is faster than SLIP because it uses compression on the
          TCP/IP headers (not on the data itself), but it has to be supported
@@ -2701,6 +2769,12 @@ config SLIP_COMPRESSED
          <http://www.tldp.org/docs.html#howto>, explains how to configure
          CSLIP. This won't enlarge your kernel.
 
+config SLHC
+       tristate
+       help
+         This option enables Van Jacobsen serial line header compression
+         routines.
+
 config SLIP_SMART
        bool "Keepalive and linefill"
        depends on SLIP
index c91e95126f78052eace67653aceef84c5fd50626..6ff17649c0fc47865e695f7a0940f571ff2d7adf 100644 (file)
@@ -2,10 +2,6 @@
 # Makefile for the Linux network (ethercard) device drivers.
 #
 
-ifeq ($(CONFIG_ISDN_PPP),y)
-  obj-$(CONFIG_ISDN) += slhc.o
-endif
-
 obj-$(CONFIG_E1000) += e1000/
 obj-$(CONFIG_IBM_EMAC) += ibm_emac/
 obj-$(CONFIG_IXGB) += ixgb/
@@ -18,6 +14,9 @@ gianfar_driver-objs := gianfar.o \
                gianfar_mii.o \
                gianfar_sysfs.o
 
+obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
+ucc_geth_driver-objs := ucc_geth.o ucc_geth_phy.o
+
 #
 # link order important here
 #
@@ -110,8 +109,9 @@ obj-$(CONFIG_FORCEDETH) += forcedeth.o
 obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
 
 obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
+obj-$(CONFIG_QLA3XXX) += qla3xxx.o
 
-obj-$(CONFIG_PPP) += ppp_generic.o slhc.o
+obj-$(CONFIG_PPP) += ppp_generic.o
 obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
 obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o
 obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o
@@ -120,9 +120,7 @@ obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o
 obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
 
 obj-$(CONFIG_SLIP) += slip.o
-ifeq ($(CONFIG_SLIP_COMPRESSED),y)
-  obj-$(CONFIG_SLIP) += slhc.o
-endif
+obj-$(CONFIG_SLHC) += slhc.o
 
 obj-$(CONFIG_DUMMY) += dummy.o
 obj-$(CONFIG_IFB) += ifb.o
index 7952dc6d77e3f3f7f03900b00fad0a767320eae2..0fbbcb75af69740fd07887727f8d79a8bb9d741c 100644 (file)
@@ -370,8 +370,7 @@ MODULE_PARM_DESC(mem, "Memory base address(es)");
 MODULE_DESCRIPTION("Ansel AC3200 EISA ethernet driver");
 MODULE_LICENSE("GPL");
 
-int
-init_module(void)
+int __init init_module(void)
 {
        struct net_device *dev;
        int this_dev, found = 0;
index 1c01e9b3d07c88cd2856232d268736ac77d87adc..c0f3574b470b9d718c7b766c01f7f8e9439ae214 100644 (file)
@@ -725,7 +725,7 @@ static struct pci_driver acenic_pci_driver = {
 
 static int __init acenic_init(void)
 {
-       return pci_module_init(&acenic_pci_driver);
+       return pci_register_driver(&acenic_pci_driver);
 }
 
 static void __exit acenic_exit(void)
index ed322a76980d760bd045630f0abdf2842d674a5b..2ef8e554263b59e8e5e3451e98f340d41599af95 100644 (file)
@@ -2158,7 +2158,7 @@ static struct pci_driver amd8111e_driver = {
 
 static int __init amd8111e_init(void)
 {
-       return pci_module_init(&amd8111e_driver);
+       return pci_register_driver(&amd8111e_driver);
 }
 
 static void __exit amd8111e_cleanup(void)
index 1d01ac0000e46c0fe79b73d3664d6ceb1c758e39..ae7f828344d9effa0d2a60f0254c9db0738f27a0 100644 (file)
@@ -1030,7 +1030,7 @@ module_param(io, int, 0);
 module_param(irq, int, 0);
 module_param(board_type, int, 0);
 
-int init_module(void)
+int __init init_module(void)
 {
        if (io == 0)
                printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n",
index 979a33df0a8c3d84dc4871188c465871b822b50f..fc256c197cd667286d8f46cf294f82aa0e4c7a1a 100644 (file)
@@ -177,7 +177,7 @@ static struct pci_driver com20020pci_driver = {
 static int __init com20020pci_init(void)
 {
        BUGLVL(D_NORMAL) printk(VERSION);
-       return pci_module_init(&com20020pci_driver);
+       return pci_register_driver(&com20020pci_driver);
 }
 
 static void __exit com20020pci_cleanup(void)
index 5d7929c79bce8743acf4cebdef6079358898d713..4ca061c2d5b26a869404b9bb9f26e40df62c6dab 100644 (file)
@@ -901,7 +901,7 @@ MODULE_PARM_DESC(io, "AT1700/FMV18X I/O base address");
 MODULE_PARM_DESC(irq, "AT1700/FMV18X IRQ number");
 MODULE_PARM_DESC(net_debug, "AT1700/FMV18X debug level (0-6)");
 
-int init_module(void)
+int __init init_module(void)
 {
        if (io == 0)
                printk("at1700: You should not use auto-probing with insmod!\n");
index bea0fc0ede2f6f50a32c0ad3baade45296dfad74..17eb2912971d4b9bc791bdf4d28af4c07f24773c 100644 (file)
@@ -2354,7 +2354,7 @@ static int __init b44_init(void)
        dma_desc_align_mask = ~(dma_desc_align_size - 1);
        dma_desc_sync_size = max_t(unsigned int, dma_desc_align_size, sizeof(struct dma_desc));
 
-       return pci_module_init(&b44_driver);
+       return pci_register_driver(&b44_driver);
 }
 
 static void __exit b44_cleanup(void)
index db73de0d25117339ede7074548003cec7986bddf..654b903985cd1c2aa270239b14bb8374a01d6de4 100644 (file)
@@ -56,8 +56,8 @@
 
 #define DRV_MODULE_NAME                "bnx2"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "1.4.43"
-#define DRV_MODULE_RELDATE     "June 28, 2006"
+#define DRV_MODULE_VERSION     "1.4.44"
+#define DRV_MODULE_RELDATE     "August 10, 2006"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -209,8 +209,10 @@ MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
 
 static inline u32 bnx2_tx_avail(struct bnx2 *bp)
 {
-       u32 diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons);
+       u32 diff;
 
+       smp_mb();
+       diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons);
        if (diff > MAX_TX_DESC_CNT)
                diff = (diff & MAX_TX_DESC_CNT) - 1;
        return (bp->tx_ring_size - diff);
@@ -1569,7 +1571,7 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index)
        struct rx_bd *rxbd = &bp->rx_desc_ring[RX_RING(index)][RX_IDX(index)];
        unsigned long align;
 
-       skb = dev_alloc_skb(bp->rx_buf_size);
+       skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size);
        if (skb == NULL) {
                return -ENOMEM;
        }
@@ -1578,7 +1580,6 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index)
                skb_reserve(skb, 8 - align);
        }
 
-       skb->dev = bp->dev;
        mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size,
                PCI_DMA_FROMDEVICE);
 
@@ -1686,15 +1687,20 @@ bnx2_tx_int(struct bnx2 *bp)
        }
 
        bp->tx_cons = sw_cons;
+       /* Need to make the tx_cons update visible to bnx2_start_xmit()
+        * before checking for netif_queue_stopped().  Without the
+        * memory barrier, there is a small possibility that bnx2_start_xmit()
+        * will miss it and cause the queue to be stopped forever.
+        */
+       smp_mb();
 
-       if (unlikely(netif_queue_stopped(bp->dev))) {
-               spin_lock(&bp->tx_lock);
+       if (unlikely(netif_queue_stopped(bp->dev)) &&
+                    (bnx2_tx_avail(bp) > bp->tx_wake_thresh)) {
+               netif_tx_lock(bp->dev);
                if ((netif_queue_stopped(bp->dev)) &&
-                   (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)) {
-
+                   (bnx2_tx_avail(bp) > bp->tx_wake_thresh))
                        netif_wake_queue(bp->dev);
-               }
-               spin_unlock(&bp->tx_lock);
+               netif_tx_unlock(bp->dev);
        }
 }
 
@@ -1786,7 +1792,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
                if ((bp->dev->mtu > 1500) && (len <= RX_COPY_THRESH)) {
                        struct sk_buff *new_skb;
 
-                       new_skb = dev_alloc_skb(len + 2);
+                       new_skb = netdev_alloc_skb(bp->dev, len + 2);
                        if (new_skb == NULL)
                                goto reuse_rx;
 
@@ -1797,7 +1803,6 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
 
                        skb_reserve(new_skb, 2);
                        skb_put(new_skb, len);
-                       new_skb->dev = bp->dev;
 
                        bnx2_reuse_rx_skb(bp, skb,
                                sw_ring_cons, sw_ring_prod);
@@ -3503,6 +3508,8 @@ bnx2_init_tx_ring(struct bnx2 *bp)
        struct tx_bd *txbd;
        u32 val;
 
+       bp->tx_wake_thresh = bp->tx_ring_size / 2;
+
        txbd = &bp->tx_desc_ring[MAX_TX_DESC_CNT];
                
        txbd->tx_bd_haddr_hi = (u64) bp->tx_desc_mapping >> 32;
@@ -3952,7 +3959,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
                return -EINVAL;
 
        pkt_size = 1514;
-       skb = dev_alloc_skb(pkt_size);
+       skb = netdev_alloc_skb(bp->dev, pkt_size);
        if (!skb)
                return -ENOMEM;
        packet = skb_put(skb, pkt_size);
@@ -4390,10 +4397,8 @@ bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
 #endif
 
 /* Called with netif_tx_lock.
- * hard_start_xmit is pseudo-lockless - a lock is only required when
- * the tx queue is full. This way, we get the benefit of lockless
- * operations most of the time without the complexities to handle
- * netif_stop_queue/wake_queue race conditions.
+ * bnx2_tx_int() runs without netif_tx_lock unless it needs to call
+ * netif_wake_queue().
  */
 static int
 bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -4512,12 +4517,9 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
        dev->trans_start = jiffies;
 
        if (unlikely(bnx2_tx_avail(bp) <= MAX_SKB_FRAGS)) {
-               spin_lock(&bp->tx_lock);
                netif_stop_queue(dev);
-               
-               if (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)
+               if (bnx2_tx_avail(bp) > bp->tx_wake_thresh)
                        netif_wake_queue(dev);
-               spin_unlock(&bp->tx_lock);
        }
 
        return NETDEV_TX_OK;
@@ -5628,7 +5630,6 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
        bp->pdev = pdev;
 
        spin_lock_init(&bp->phy_lock);
-       spin_lock_init(&bp->tx_lock);
        INIT_WORK(&bp->reset_task, bnx2_reset_task, bp);
 
        dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
@@ -5751,7 +5752,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
        bp->mac_addr[5] = (u8) reg;
 
        bp->tx_ring_size = MAX_TX_DESC_CNT;
-       bnx2_set_rx_ring_size(bp, 100);
+       bnx2_set_rx_ring_size(bp, 255);
 
        bp->rx_csum = 1;
 
@@ -6015,7 +6016,7 @@ static struct pci_driver bnx2_pci_driver = {
 
 static int __init bnx2_init(void)
 {
-       return pci_module_init(&bnx2_pci_driver);
+       return pci_register_driver(&bnx2_pci_driver);
 }
 
 static void __exit bnx2_cleanup(void)
index 658c5ee95c73ecdea4bd4c34c74e68e2b82b54bb..fe804763c60738b0d8c442175fa05d7816e1882c 100644 (file)
@@ -3890,10 +3890,6 @@ struct bnx2 {
        u32             tx_prod_bseq __attribute__((aligned(L1_CACHE_BYTES)));
        u16             tx_prod;
 
-       struct tx_bd    *tx_desc_ring;
-       struct sw_bd    *tx_buf_ring;
-       int             tx_ring_size;
-
        u16             tx_cons __attribute__((aligned(L1_CACHE_BYTES)));
        u16             hw_tx_cons;
 
@@ -3916,9 +3912,11 @@ struct bnx2 {
        struct sw_bd            *rx_buf_ring;
        struct rx_bd            *rx_desc_ring[MAX_RX_RINGS];
 
-       /* Only used to synchronize netif_stop_queue/wake_queue when tx */
-       /* ring is full */
-       spinlock_t              tx_lock;
+       /* TX constants */
+       struct tx_bd    *tx_desc_ring;
+       struct sw_bd    *tx_buf_ring;
+       int             tx_ring_size;
+       u32             tx_wake_thresh;
 
        /* End of fields used in the performance code paths. */
 
index a31544ccb3c494aed1e63cd01335aca8d2926583..26040abfef628954009a0835eb369a889974205d 100644 (file)
@@ -5245,7 +5245,7 @@ static int __init cas_init(void)
        else
                link_transition_timeout = 0;
 
-       return pci_module_init(&cas_driver);
+       return pci_register_driver(&cas_driver);
 }
 
 static void __exit cas_cleanup(void)
index e67872433e9277bd1e778c3d1532710b53915015..b6de184e469904c456e10be72c048624a00ba27a 100644 (file)
@@ -1243,7 +1243,7 @@ static struct pci_driver driver = {
 
 static int __init t1_init_module(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit t1_cleanup_module(void)
index 47eecce35fa446e3a2bb91fd279ca855598896ca..2dcca79b1f6ad800f9704efe35ad093e69618728 100644 (file)
@@ -1905,8 +1905,7 @@ MODULE_LICENSE("GPL");
 
 */
 
-int
-init_module(void)
+int __init init_module(void)
 {
        struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
        struct net_local *lp;
index 91cc8cbdd440dd8f2f7ce8da0c653e221f014e13..7d06dedbfb26f2fd0f6b9576ea00ca3215935736 100644 (file)
@@ -3444,7 +3444,7 @@ static int __init dfx_init(void)
 {
        int rc_pci, rc_eisa;
 
-       rc_pci = pci_module_init(&dfx_driver);
+       rc_pci = pci_register_driver(&dfx_driver);
        if (rc_pci >= 0) dfx_have_pci = 1;
        
        rc_eisa = dfx_eisa_init();
index 402961e68c89fca4223fc07503274367668c9117..a572c29705641e06e24f14af66f5f23e49cdf61e 100644 (file)
@@ -1815,7 +1815,7 @@ static struct pci_driver rio_driver = {
 static int __init
 rio_init (void)
 {
-       return pci_module_init (&rio_driver);
+       return pci_register_driver(&rio_driver);
 }
 
 static void __exit
index 1b758b70713486231d6f8593c559f0ced494801a..3d76fa144c4f8448eb0dc004a47d0fad3bcee3d5 100644 (file)
@@ -339,6 +339,17 @@ static void dm9000_timeout(struct net_device *dev)
        spin_unlock_irqrestore(&db->lock,flags);
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ *Used by netconsole
+ */
+static void dm9000_poll_controller(struct net_device *dev)
+{
+       disable_irq(dev->irq);
+       dm9000_interrupt(dev->irq,dev,NULL);
+       enable_irq(dev->irq);
+}
+#endif
 
 /* dm9000_release_board
  *
@@ -538,6 +549,9 @@ dm9000_probe(struct platform_device *pdev)
        ndev->stop               = &dm9000_stop;
        ndev->get_stats          = &dm9000_get_stats;
        ndev->set_multicast_list = &dm9000_hash_table;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       ndev->poll_controller    = &dm9000_poll_controller;
+#endif
 
 #ifdef DM9000_PROGRAM_EEPROM
        program_eeprom(db);
index e208c0905e6199b5f0148268141ac58b034123b8..b42ad76b1116a3e117b5f74a1cb7a20039ba2fdb 100644 (file)
@@ -2869,7 +2869,7 @@ static int __init e100_init_module(void)
                printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
                printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT);
        }
-       return pci_module_init(&e100_driver);
+       return pci_register_driver(&e100_driver);
 }
 
 static void __exit e100_cleanup_module(void)
index 8eddfdf62f556b04a1b8b812b7c9d9c2864c5308..f62d178483327601e2e4bc28b97e7bd2bf51dfb2 100644 (file)
@@ -105,6 +105,33 @@ static int32_t e1000_configure_kmrn_for_10_100(struct e1000_hw *hw,
                                                uint16_t duplex);
 static int32_t e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
 
+static int32_t e1000_erase_ich8_4k_segment(struct e1000_hw *hw,
+                                          uint32_t segment);
+static int32_t e1000_get_software_flag(struct e1000_hw *hw);
+static int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
+static int32_t e1000_init_lcd_from_nvm(struct e1000_hw *hw);
+static int32_t e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
+static int32_t e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
+                                     uint16_t words, uint16_t *data);
+static int32_t e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index,
+                                   uint8_t* data);
+static int32_t e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index,
+                                   uint16_t *data);
+static int32_t e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr,
+                                  uint16_t *data);
+static void e1000_release_software_flag(struct e1000_hw *hw);
+static void e1000_release_software_semaphore(struct e1000_hw *hw);
+static int32_t e1000_set_pci_ex_no_snoop(struct e1000_hw *hw,
+                                        uint32_t no_snoop);
+static int32_t e1000_verify_write_ich8_byte(struct e1000_hw *hw,
+                                           uint32_t index, uint8_t byte);
+static int32_t e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
+                                      uint16_t words, uint16_t *data);
+static int32_t e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index,
+                                    uint8_t data);
+static int32_t e1000_write_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr,
+                                   uint16_t data);
+
 /* IGP cable length table */
 static const
 uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
@@ -3247,7 +3274,7 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw)
     return data;
 }
 
-int32_t
+static int32_t
 e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
 {
     uint32_t swfw_sync = 0;
@@ -3291,7 +3318,7 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
     return E1000_SUCCESS;
 }
 
-void
+static void
 e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask)
 {
     uint32_t swfw_sync;
@@ -3589,7 +3616,7 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw,
     return E1000_SUCCESS;
 }
 
-int32_t
+static int32_t
 e1000_read_kmrn_reg(struct e1000_hw *hw,
                     uint32_t reg_addr,
                     uint16_t *data)
@@ -3622,7 +3649,7 @@ e1000_read_kmrn_reg(struct e1000_hw *hw,
     return E1000_SUCCESS;
 }
 
-int32_t
+static int32_t
 e1000_write_kmrn_reg(struct e1000_hw *hw,
                      uint32_t reg_addr,
                      uint16_t data)
@@ -3853,7 +3880,7 @@ e1000_phy_powerdown_workaround(struct e1000_hw *hw)
 *
 * hw - struct containing variables accessed by shared code
 ******************************************************************************/
-int32_t
+static int32_t
 e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
 {
     int32_t ret_val;
@@ -4100,7 +4127,7 @@ e1000_phy_igp_get_info(struct e1000_hw *hw,
 * hw - Struct containing variables accessed by shared code
 * phy_info - PHY information structure
 ******************************************************************************/
-int32_t
+static int32_t
 e1000_phy_ife_get_info(struct e1000_hw *hw,
                        struct e1000_phy_info *phy_info)
 {
@@ -5657,6 +5684,7 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
  * for the first 15 multicast addresses, and hashes the rest into the
  * multicast table.
  *****************************************************************************/
+#if 0
 void
 e1000_mc_addr_list_update(struct e1000_hw *hw,
                           uint8_t *mc_addr_list,
@@ -5733,6 +5761,7 @@ e1000_mc_addr_list_update(struct e1000_hw *hw,
     }
     DEBUGOUT("MC Update Complete\n");
 }
+#endif  /*  0  */
 
 /******************************************************************************
  * Hashes an address to determine its location in the multicast table
@@ -6601,6 +6630,7 @@ e1000_get_bus_info(struct e1000_hw *hw)
  * hw - Struct containing variables accessed by shared code
  * offset - offset to read from
  *****************************************************************************/
+#if 0
 uint32_t
 e1000_read_reg_io(struct e1000_hw *hw,
                   uint32_t offset)
@@ -6611,6 +6641,7 @@ e1000_read_reg_io(struct e1000_hw *hw,
     e1000_io_write(hw, io_addr, offset);
     return e1000_io_read(hw, io_data);
 }
+#endif  /*  0  */
 
 /******************************************************************************
  * Writes a value to one of the devices registers using port I/O (as opposed to
@@ -7923,6 +7954,7 @@ e1000_set_pci_express_master_disable(struct e1000_hw *hw)
  * returns: - none.
  *
  ***************************************************************************/
+#if 0
 void
 e1000_enable_pciex_master(struct e1000_hw *hw)
 {
@@ -7937,6 +7969,7 @@ e1000_enable_pciex_master(struct e1000_hw *hw)
     ctrl &= ~E1000_CTRL_GIO_MASTER_DISABLE;
     E1000_WRITE_REG(hw, CTRL, ctrl);
 }
+#endif  /*  0  */
 
 /*******************************************************************************
  *
@@ -8162,7 +8195,7 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
  *            E1000_SUCCESS at any other case.
  *
  ***************************************************************************/
-int32_t
+static int32_t
 e1000_get_software_semaphore(struct e1000_hw *hw)
 {
     int32_t timeout = hw->eeprom.word_size + 1;
@@ -8197,7 +8230,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
  * hw: Struct containing variables accessed by shared code
  *
  ***************************************************************************/
-void
+static void
 e1000_release_software_semaphore(struct e1000_hw *hw)
 {
     uint32_t swsm;
@@ -8279,7 +8312,7 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
  * returns: E1000_SUCCESS
  *
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop)
 {
     uint32_t gcr_reg = 0;
@@ -8320,7 +8353,7 @@ e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop)
  * hw: Struct containing variables accessed by shared code
  *
  ***************************************************************************/
-int32_t
+static int32_t
 e1000_get_software_flag(struct e1000_hw *hw)
 {
     int32_t timeout = PHY_CFG_TIMEOUT;
@@ -8359,7 +8392,7 @@ e1000_get_software_flag(struct e1000_hw *hw)
  * hw: Struct containing variables accessed by shared code
  *
  ***************************************************************************/
-void
+static void
 e1000_release_software_flag(struct e1000_hw *hw)
 {
     uint32_t extcnf_ctrl;
@@ -8383,6 +8416,7 @@ e1000_release_software_flag(struct e1000_hw *hw)
  * hw: Struct containing variables accessed by shared code
  *
  ***************************************************************************/
+#if 0
 int32_t
 e1000_ife_disable_dynamic_power_down(struct e1000_hw *hw)
 {
@@ -8402,6 +8436,7 @@ e1000_ife_disable_dynamic_power_down(struct e1000_hw *hw)
 
     return ret_val;
 }
+#endif  /*  0  */
 
 /***************************************************************************
  *
@@ -8411,6 +8446,7 @@ e1000_ife_disable_dynamic_power_down(struct e1000_hw *hw)
  * hw: Struct containing variables accessed by shared code
  *
  ***************************************************************************/
+#if 0
 int32_t
 e1000_ife_enable_dynamic_power_down(struct e1000_hw *hw)
 {
@@ -8430,6 +8466,7 @@ e1000_ife_enable_dynamic_power_down(struct e1000_hw *hw)
 
     return ret_val;
 }
+#endif  /*  0  */
 
 /******************************************************************************
  * Reads a 16 bit word or words from the EEPROM using the ICH8's flash access
@@ -8440,7 +8477,7 @@ e1000_ife_enable_dynamic_power_down(struct e1000_hw *hw)
  * data - word read from the EEPROM
  * words - number of words to read
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
                        uint16_t *data)
 {
@@ -8496,7 +8533,7 @@ e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
  * words - number of words to write
  * data - words to write to the EEPROM
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
                         uint16_t *data)
 {
@@ -8543,7 +8580,7 @@ e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
  *
  * hw - The pointer to the hw structure
  ****************************************************************************/
-int32_t
+static int32_t
 e1000_ich8_cycle_init(struct e1000_hw *hw)
 {
     union ich8_hws_flash_status hsfsts;
@@ -8610,7 +8647,7 @@ e1000_ich8_cycle_init(struct e1000_hw *hw)
  *
  * hw - The pointer to the hw structure
  ****************************************************************************/
-int32_t
+static int32_t
 e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout)
 {
     union ich8_hws_flash_ctrl hsflctl;
@@ -8645,7 +8682,7 @@ e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout)
  * size - Size of data to read, 1=byte 2=word
  * data - Pointer to the word to store the value read.
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
                      uint32_t size, uint16_t* data)
 {
@@ -8724,7 +8761,7 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
  * size - Size of data to read, 1=byte 2=word
  * data - The byte(s) to write to the NVM.
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
                       uint16_t data)
 {
@@ -8799,7 +8836,7 @@ e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
  * index - The index of the byte to read.
  * data - Pointer to a byte to store the value read.
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t* data)
 {
     int32_t status = E1000_SUCCESS;
@@ -8822,7 +8859,7 @@ e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t* data)
  * index - The index of the byte to write.
  * byte - The byte to write to the NVM.
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte)
 {
     int32_t error = E1000_SUCCESS;
@@ -8853,7 +8890,7 @@ e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte)
  * index - The index of the byte to read.
  * data - The byte to write to the NVM.
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t data)
 {
     int32_t status = E1000_SUCCESS;
@@ -8871,7 +8908,7 @@ e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t data)
  * index - The starting byte index of the word to read.
  * data - Pointer to a word to store the value read.
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data)
 {
     int32_t status = E1000_SUCCESS;
@@ -8886,6 +8923,7 @@ e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data)
  * index - The starting byte index of the word to read.
  * data - The word to write to the NVM.
  *****************************************************************************/
+#if 0
 int32_t
 e1000_write_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t data)
 {
@@ -8893,6 +8931,7 @@ e1000_write_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t data)
     status = e1000_write_ich8_data(hw, index, 2, data);
     return status;
 }
+#endif  /*  0  */
 
 /******************************************************************************
  * Erases the bank specified. Each bank is a 4k block. Segments are 0 based.
@@ -8901,7 +8940,7 @@ e1000_write_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t data)
  * hw - pointer to e1000_hw structure
  * segment - 0 for first segment, 1 for second segment, etc.
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t segment)
 {
     union ich8_hws_flash_status hsfsts;
@@ -8998,6 +9037,7 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t segment)
  * hw: Struct containing variables accessed by shared code
  *
  *****************************************************************************/
+#if 0
 int32_t
 e1000_duplex_reversal(struct e1000_hw *hw)
 {
@@ -9026,8 +9066,9 @@ e1000_duplex_reversal(struct e1000_hw *hw)
 
     return ret_val;
 }
+#endif  /*  0  */
 
-int32_t
+static int32_t
 e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
                                       uint32_t cnf_base_addr, uint32_t cnf_size)
 {
@@ -9061,7 +9102,7 @@ e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
 }
 
 
-int32_t
+static int32_t
 e1000_init_lcd_from_nvm(struct e1000_hw *hw)
 {
     uint32_t reg_data, cnf_base_addr, cnf_size, ret_val, loop;
index f9341e3276b314e324be6720c359f98dd6590d8c..375b95518c318ce820aee91d9464553088dde295 100644 (file)
@@ -323,13 +323,8 @@ int32_t e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t dat
 int32_t e1000_phy_hw_reset(struct e1000_hw *hw);
 int32_t e1000_phy_reset(struct e1000_hw *hw);
 void e1000_phy_powerdown_workaround(struct e1000_hw *hw);
-int32_t e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
-int32_t e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw, uint32_t cnf_base_addr, uint32_t cnf_size);
-int32_t e1000_init_lcd_from_nvm(struct e1000_hw *hw);
 int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
 int32_t e1000_validate_mdi_setting(struct e1000_hw *hw);
-int32_t e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *data);
-int32_t e1000_write_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data);
 
 /* EEPROM Functions */
 int32_t e1000_init_eeprom_params(struct e1000_hw *hw);
@@ -400,13 +395,8 @@ int32_t e1000_update_eeprom_checksum(struct e1000_hw *hw);
 int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
 int32_t e1000_read_part_num(struct e1000_hw *hw, uint32_t * part_num);
 int32_t e1000_read_mac_addr(struct e1000_hw * hw);
-int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask);
-void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask);
-void e1000_release_software_flag(struct e1000_hw *hw);
-int32_t e1000_get_software_flag(struct e1000_hw *hw);
 
 /* Filters (multicast, vlan, receive) */
-void e1000_mc_addr_list_update(struct e1000_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad, uint32_t rar_used_count);
 uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, uint8_t * mc_addr);
 void e1000_mta_set(struct e1000_hw *hw, uint32_t hash_value);
 void e1000_rar_set(struct e1000_hw *hw, uint8_t * mc_addr, uint32_t rar_index);
@@ -431,31 +421,9 @@ void e1000_pci_clear_mwi(struct e1000_hw *hw);
 void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
 void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
 /* Port I/O is only supported on 82544 and newer */
-uint32_t e1000_io_read(struct e1000_hw *hw, unsigned long port);
-uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset);
 void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value);
-void e1000_enable_pciex_master(struct e1000_hw *hw);
 int32_t e1000_disable_pciex_master(struct e1000_hw *hw);
-int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
-void e1000_release_software_semaphore(struct e1000_hw *hw);
 int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
-int32_t e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop);
-
-int32_t e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index,
-                             uint8_t *data);
-int32_t e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index,
-                                     uint8_t byte);
-int32_t e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index,
-                              uint8_t byte);
-int32_t e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index,
-                             uint16_t *data);
-int32_t e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
-                             uint32_t size, uint16_t *data);
-int32_t e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
-                               uint16_t words, uint16_t *data);
-int32_t e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
-                                uint16_t words, uint16_t *data);
-int32_t e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t segment);
 
 
 #define E1000_READ_REG_IO(a, reg) \
index 815abe559d992aae6d075310f4bfaff4f2b18709..0cf9ff2462ba7757d677a30fa7e0562aaeed7ed9 100644 (file)
@@ -244,7 +244,7 @@ e1000_init_module(void)
 
        printk(KERN_INFO "%s\n", e1000_copyright);
 
-       ret = pci_module_init(&e1000_driver);
+       ret = pci_register_driver(&e1000_driver);
 
        return ret;
 }
@@ -4383,11 +4383,13 @@ e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
        pci_write_config_word(adapter->pdev, reg, *value);
 }
 
+#if 0
 uint32_t
 e1000_io_read(struct e1000_hw *hw, unsigned long port)
 {
        return inl(port);
 }
+#endif  /*  0  */
 
 void
 e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value)
index e5c5cd2a271263c21e85c23bf96ec739c25f0db5..e4e733a380e3675733c9960519d453363f45eb95 100644 (file)
@@ -425,8 +425,8 @@ MODULE_LICENSE("GPL");
 
 /* This is set up so that only a single autoprobe takes place per call.
 ISA device autoprobes on a running machine are not recommended. */
-int
-init_module(void)
+
+int __init init_module(void)
 {
        struct net_device *dev;
        int this_dev, found = 0;
index 20d31430c74f9869ee29491f77cb03478f867f35..8dc61d65dd237643f923e30ef53684f1069e49a2 100644 (file)
@@ -1807,8 +1807,7 @@ MODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)");
 MODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)");
 MODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1)");
 
-int
-init_module(void)
+int __init init_module(void)
 {
        struct net_device *dev;
        int i;
index e445988c92eecb85e8ebea5c229bad6b408de4ff..a3d515def109f3839d3130df946a80afe18306e0 100644 (file)
@@ -2385,7 +2385,7 @@ static int __init eepro100_init_module(void)
 #ifdef MODULE
        printk(version);
 #endif
-       return pci_module_init(&eepro100_driver);
+       return pci_register_driver(&eepro100_driver);
 }
 
 static void __exit eepro100_cleanup_module(void)
index 33291bcf6d4cc917289184c73e77c4a15f6667ca..0701c1d810ca34df32cde5844dd5a8e661cb3605 100644 (file)
@@ -1698,7 +1698,7 @@ MODULE_LICENSE("GPL");
  * are specified, we verify and then use them.  If no parameters are given, we
  * autoprobe for one card only.
  */
-int init_module(void)
+int __init init_module(void)
 {
        struct net_device *dev;
        int this_dev, found = 0;
index a67650ccf084acb7c215a11524fef25d0220aff9..25c4619d842e680e2bda36d6d60e1af0203b03e3 100644 (file)
@@ -1604,7 +1604,7 @@ static int __init epic_init (void)
                version, version2, version3);
 #endif
 
-       return pci_module_init (&epic_driver);
+       return pci_register_driver(&epic_driver);
 }
 
 
index 6b0ab1eac3fb6179ddeafacb8a05ae8265be94bb..fd7b32a24ea4f33d9cf1461daff5433b2fcc5a36 100644 (file)
@@ -421,8 +421,7 @@ MODULE_PARM_DESC(mem, "memory base address(es)");
 MODULE_DESCRIPTION("Racal-Interlan ES3210 EISA ethernet driver");
 MODULE_LICENSE("GPL");
 
-int
-init_module(void)
+int __init init_module(void)
 {
        struct net_device *dev;
        int this_dev, found = 0;
index 4bf76f86d8e90081f8f796369daeaff0827cfc08..ca42efa9143c5f4ed7a805cfd19482c699cce01d 100644 (file)
@@ -1434,7 +1434,7 @@ MODULE_PARM_DESC(mediatype, "eth16i media type of interface(s) (bnc,tp,dix,auto,
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "eth16i debug level (0-6)");
 
-int init_module(void)
+int __init init_module(void)
 {
        int this_dev, found = 0;
        struct net_device *dev;
index 97d34fee8c1fc529d00c54deb0af842c8db2f3f1..a2121faa610ffe5b6991dd6f76f8219057bbc2c1 100644 (file)
@@ -92,7 +92,7 @@ static int full_duplex[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
 #include <asm/uaccess.h>
 
 /* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
+static char version[] =
 KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "\n";
 
 
@@ -1984,7 +1984,7 @@ static int __init fealnx_init(void)
        printk(version);
 #endif
 
-       return pci_module_init(&fealnx_driver);
+       return pci_register_driver(&fealnx_driver);
 }
 
 static void __exit fealnx_exit(void)
index 11b8f1b43dd5994a255c1b6613d0cfa868a4bdeb..8c8f7cf0e9526783a5762763c8438e2c472cf588 100644 (file)
  *     0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup.
  *     0.55: 22 Mar 2006: Add flow control (pause frame).
  *     0.56: 22 Mar 2006: Additional ethtool config and moduleparam support.
+ *     0.57: 14 May 2006: Mac address set in probe/remove and order corrections.
  *
  * 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.56"
+#ifdef CONFIG_FORCEDETH_NAPI
+#define DRIVERNAPI "-NAPI"
+#else
+#define DRIVERNAPI
+#endif
+#define FORCEDETH_VERSION              "0.57"
 #define DRV_NAME                       "forcedeth"
 
 #include <linux/module.h>
@@ -262,7 +268,8 @@ enum {
        NvRegRingSizes = 0x108,
 #define NVREG_RINGSZ_TXSHIFT 0
 #define NVREG_RINGSZ_RXSHIFT 16
-       NvRegUnknownTransmitterReg = 0x10c,
+       NvRegTransmitPoll = 0x10c,
+#define NVREG_TRANSMITPOLL_MAC_ADDR_REV        0x00008000
        NvRegLinkSpeed = 0x110,
 #define NVREG_LINKSPEED_FORCE 0x10000
 #define NVREG_LINKSPEED_10     1000
@@ -381,21 +388,21 @@ enum {
 
 /* Big endian: should work, but is untested */
 struct ring_desc {
-       u32 PacketBuffer;
-       u32 FlagLen;
+       __le32 buf;
+       __le32 flaglen;
 };
 
 struct ring_desc_ex {
-       u32 PacketBufferHigh;
-       u32 PacketBufferLow;
-       u32 TxVlan;
-       u32 FlagLen;
+       __le32 bufhigh;
+       __le32 buflow;
+       __le32 txvlan;
+       __le32 flaglen;
 };
 
-typedef union _ring_type {
+union ring_type {
        struct ring_desc* orig;
        struct ring_desc_ex* ex;
-} ring_type;
+};
 
 #define FLAG_MASK_V1 0xffff0000
 #define FLAG_MASK_V2 0xffffc000
@@ -653,8 +660,8 @@ static const struct nv_ethtool_str nv_etests_str[] = {
 };
 
 struct register_test {
-       u32 reg;
-       u32 mask;
+       __le32 reg;
+       __le32 mask;
 };
 
 static const struct register_test nv_registers_test[] = {
@@ -713,7 +720,7 @@ struct fe_priv {
        /* rx specific fields.
         * Locking: Within irq hander or disable_irq+spin_lock(&np->lock);
         */
-       ring_type rx_ring;
+       union ring_type rx_ring;
        unsigned int cur_rx, refill_rx;
        struct sk_buff **rx_skbuff;
        dma_addr_t *rx_dma;
@@ -733,7 +740,7 @@ struct fe_priv {
        /*
         * tx specific fields.
         */
-       ring_type tx_ring;
+       union ring_type tx_ring;
        unsigned int next_tx, nic_tx;
        struct sk_buff **tx_skbuff;
        dma_addr_t *tx_dma;
@@ -826,13 +833,13 @@ static inline void pci_push(u8 __iomem *base)
 
 static inline u32 nv_descr_getlength(struct ring_desc *prd, u32 v)
 {
-       return le32_to_cpu(prd->FlagLen)
+       return le32_to_cpu(prd->flaglen)
                & ((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;
+       return le32_to_cpu(prd->flaglen) & LEN_MASK_V2;
 }
 
 static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target,
@@ -885,7 +892,7 @@ static void free_rings(struct net_device *dev)
        struct fe_priv *np = get_nvpriv(dev);
 
        if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-               if(np->rx_ring.orig)
+               if (np->rx_ring.orig)
                        pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (np->rx_ring_size + np->tx_ring_size),
                                            np->rx_ring.orig, np->ring_addr);
        } else {
@@ -1178,7 +1185,7 @@ static void nv_stop_tx(struct net_device *dev)
                        KERN_INFO "nv_stop_tx: TransmitterStatus remained busy");
 
        udelay(NV_TXSTOP_DELAY2);
-       writel(0, base + NvRegUnknownTransmitterReg);
+       writel(readl(base + NvRegTransmitPoll) & NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll);
 }
 
 static void nv_txrx_reset(struct net_device *dev)
@@ -1258,14 +1265,14 @@ static int nv_alloc_rx(struct net_device *dev)
                np->rx_dma[nr] = pci_map_single(np->pci_dev, skb->data,
                                        skb->end-skb->data, PCI_DMA_FROMDEVICE);
                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]);
+                       np->rx_ring.orig[nr].buf = cpu_to_le32(np->rx_dma[nr]);
                        wmb();
-                       np->rx_ring.orig[nr].FlagLen = cpu_to_le32(np->rx_buf_sz | NV_RX_AVAIL);
+                       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;
+                       np->rx_ring.ex[nr].bufhigh = cpu_to_le64(np->rx_dma[nr]) >> 32;
+                       np->rx_ring.ex[nr].buflow = 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);
+                       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);
@@ -1277,6 +1284,16 @@ static int nv_alloc_rx(struct net_device *dev)
        return 0;
 }
 
+/* If rx bufs are exhausted called after 50ms to attempt to refresh */
+#ifdef CONFIG_FORCEDETH_NAPI
+static void nv_do_rx_refill(unsigned long data)
+{
+       struct net_device *dev = (struct net_device *) data;
+
+       /* Just reschedule NAPI rx processing */
+       netif_rx_schedule(dev);
+}
+#else
 static void nv_do_rx_refill(unsigned long data)
 {
        struct net_device *dev = (struct net_device *) data;
@@ -1305,6 +1322,7 @@ static void nv_do_rx_refill(unsigned long data)
                enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
        }
 }
+#endif
 
 static void nv_init_rx(struct net_device *dev)
 {
@@ -1315,9 +1333,9 @@ static void nv_init_rx(struct net_device *dev)
        np->refill_rx = 0;
        for (i = 0; i < np->rx_ring_size; i++)
                if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-                       np->rx_ring.orig[i].FlagLen = 0;
+                       np->rx_ring.orig[i].flaglen = 0;
                else
-                       np->rx_ring.ex[i].FlagLen = 0;
+                       np->rx_ring.ex[i].flaglen = 0;
 }
 
 static void nv_init_tx(struct net_device *dev)
@@ -1328,9 +1346,9 @@ static void nv_init_tx(struct net_device *dev)
        np->next_tx = np->nic_tx = 0;
        for (i = 0; i < np->tx_ring_size; i++) {
                if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-                       np->tx_ring.orig[i].FlagLen = 0;
+                       np->tx_ring.orig[i].flaglen = 0;
                else
-                       np->tx_ring.ex[i].FlagLen = 0;
+                       np->tx_ring.ex[i].flaglen = 0;
                np->tx_skbuff[i] = NULL;
                np->tx_dma[i] = 0;
        }
@@ -1373,9 +1391,9 @@ static void nv_drain_tx(struct net_device *dev)
 
        for (i = 0; i < np->tx_ring_size; i++) {
                if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-                       np->tx_ring.orig[i].FlagLen = 0;
+                       np->tx_ring.orig[i].flaglen = 0;
                else
-                       np->tx_ring.ex[i].FlagLen = 0;
+                       np->tx_ring.ex[i].flaglen = 0;
                if (nv_release_txskb(dev, i))
                        np->stats.tx_dropped++;
        }
@@ -1387,9 +1405,9 @@ static void nv_drain_rx(struct net_device *dev)
        int i;
        for (i = 0; i < np->rx_ring_size; i++) {
                if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-                       np->rx_ring.orig[i].FlagLen = 0;
+                       np->rx_ring.orig[i].flaglen = 0;
                else
-                       np->rx_ring.ex[i].FlagLen = 0;
+                       np->rx_ring.ex[i].flaglen = 0;
                wmb();
                if (np->rx_skbuff[i]) {
                        pci_unmap_single(np->pci_dev, np->rx_dma[i],
@@ -1450,17 +1468,17 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
                np->tx_dma_len[nr] = bcnt;
 
                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]);
-                       np->tx_ring.orig[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags);
+                       np->tx_ring.orig[nr].buf = cpu_to_le32(np->tx_dma[nr]);
+                       np->tx_ring.orig[nr].flaglen = cpu_to_le32((bcnt-1) | tx_flags);
                } 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;
-                       np->tx_ring.ex[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags);
+                       np->tx_ring.ex[nr].bufhigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
+                       np->tx_ring.ex[nr].buflow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
+                       np->tx_ring.ex[nr].flaglen = cpu_to_le32((bcnt-1) | tx_flags);
                }
                tx_flags = np->tx_flags;
                offset += bcnt;
                size -= bcnt;
-       } while(size);
+       } while (size);
 
        /* setup the fragments */
        for (i = 0; i < fragments; i++) {
@@ -1477,12 +1495,12 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        np->tx_dma_len[nr] = bcnt;
 
                        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]);
-                               np->tx_ring.orig[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags);
+                               np->tx_ring.orig[nr].buf = cpu_to_le32(np->tx_dma[nr]);
+                               np->tx_ring.orig[nr].flaglen = cpu_to_le32((bcnt-1) | tx_flags);
                        } 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;
-                               np->tx_ring.ex[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags);
+                               np->tx_ring.ex[nr].bufhigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
+                               np->tx_ring.ex[nr].buflow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
+                               np->tx_ring.ex[nr].flaglen = cpu_to_le32((bcnt-1) | tx_flags);
                        }
                        offset += bcnt;
                        size -= bcnt;
@@ -1491,9 +1509,9 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* set last fragment flag  */
        if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-               np->tx_ring.orig[nr].FlagLen |= cpu_to_le32(tx_flags_extra);
+               np->tx_ring.orig[nr].flaglen |= cpu_to_le32(tx_flags_extra);
        } else {
-               np->tx_ring.ex[nr].FlagLen |= cpu_to_le32(tx_flags_extra);
+               np->tx_ring.ex[nr].flaglen |= cpu_to_le32(tx_flags_extra);
        }
 
        np->tx_skbuff[nr] = skb;
@@ -1512,10 +1530,10 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* set tx flags */
        if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-               np->tx_ring.orig[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra);
+               np->tx_ring.orig[start_nr].flaglen |= cpu_to_le32(tx_flags | tx_flags_extra);
        } else {
-               np->tx_ring.ex[start_nr].TxVlan = cpu_to_le32(tx_flags_vlan);
-               np->tx_ring.ex[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra);
+               np->tx_ring.ex[start_nr].txvlan = cpu_to_le32(tx_flags_vlan);
+               np->tx_ring.ex[start_nr].flaglen |= cpu_to_le32(tx_flags | tx_flags_extra);
        }
 
        dprintk(KERN_DEBUG "%s: nv_start_xmit: packet %d (entries %d) queued for transmission. tx_flags_extra: %x\n",
@@ -1547,7 +1565,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
 static void nv_tx_done(struct net_device *dev)
 {
        struct fe_priv *np = netdev_priv(dev);
-       u32 Flags;
+       u32 flags;
        unsigned int i;
        struct sk_buff *skb;
 
@@ -1555,22 +1573,22 @@ static void nv_tx_done(struct net_device *dev)
                i = np->nic_tx % np->tx_ring_size;
 
                if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-                       Flags = le32_to_cpu(np->tx_ring.orig[i].FlagLen);
+                       flags = le32_to_cpu(np->tx_ring.orig[i].flaglen);
                else
-                       Flags = le32_to_cpu(np->tx_ring.ex[i].FlagLen);
+                       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);
-               if (Flags & NV_TX_VALID)
+               dprintk(KERN_DEBUG "%s: nv_tx_done: looking at packet %d, flags 0x%x.\n",
+                                       dev->name, np->nic_tx, flags);
+               if (flags & NV_TX_VALID)
                        break;
                if (np->desc_ver == DESC_VER_1) {
-                       if (Flags & NV_TX_LASTPACKET) {
+                       if (flags & NV_TX_LASTPACKET) {
                                skb = np->tx_skbuff[i];
-                               if (Flags & (NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION|
+                               if (flags & (NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION|
                                             NV_TX_UNDERFLOW|NV_TX_ERROR)) {
-                                       if (Flags & NV_TX_UNDERFLOW)
+                                       if (flags & NV_TX_UNDERFLOW)
                                                np->stats.tx_fifo_errors++;
-                                       if (Flags & NV_TX_CARRIERLOST)
+                                       if (flags & NV_TX_CARRIERLOST)
                                                np->stats.tx_carrier_errors++;
                                        np->stats.tx_errors++;
                                } else {
@@ -1579,13 +1597,13 @@ static void nv_tx_done(struct net_device *dev)
                                }
                        }
                } else {
-                       if (Flags & NV_TX2_LASTPACKET) {
+                       if (flags & NV_TX2_LASTPACKET) {
                                skb = np->tx_skbuff[i];
-                               if (Flags & (NV_TX2_RETRYERROR|NV_TX2_CARRIERLOST|NV_TX2_LATECOLLISION|
+                               if (flags & (NV_TX2_RETRYERROR|NV_TX2_CARRIERLOST|NV_TX2_LATECOLLISION|
                                             NV_TX2_UNDERFLOW|NV_TX2_ERROR)) {
-                                       if (Flags & NV_TX2_UNDERFLOW)
+                                       if (flags & NV_TX2_UNDERFLOW)
                                                np->stats.tx_fifo_errors++;
-                                       if (Flags & NV_TX2_CARRIERLOST)
+                                       if (flags & NV_TX2_CARRIERLOST)
                                                np->stats.tx_carrier_errors++;
                                        np->stats.tx_errors++;
                                } else {
@@ -1638,29 +1656,29 @@ static void nv_tx_timeout(struct net_device *dev)
                        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));
+                                      le32_to_cpu(np->tx_ring.orig[i].buf),
+                                      le32_to_cpu(np->tx_ring.orig[i].flaglen),
+                                      le32_to_cpu(np->tx_ring.orig[i+1].buf),
+                                      le32_to_cpu(np->tx_ring.orig[i+1].flaglen),
+                                      le32_to_cpu(np->tx_ring.orig[i+2].buf),
+                                      le32_to_cpu(np->tx_ring.orig[i+2].flaglen),
+                                      le32_to_cpu(np->tx_ring.orig[i+3].buf),
+                                      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));
+                                      le32_to_cpu(np->tx_ring.ex[i].bufhigh),
+                                      le32_to_cpu(np->tx_ring.ex[i].buflow),
+                                      le32_to_cpu(np->tx_ring.ex[i].flaglen),
+                                      le32_to_cpu(np->tx_ring.ex[i+1].bufhigh),
+                                      le32_to_cpu(np->tx_ring.ex[i+1].buflow),
+                                      le32_to_cpu(np->tx_ring.ex[i+1].flaglen),
+                                      le32_to_cpu(np->tx_ring.ex[i+2].bufhigh),
+                                      le32_to_cpu(np->tx_ring.ex[i+2].buflow),
+                                      le32_to_cpu(np->tx_ring.ex[i+2].flaglen),
+                                      le32_to_cpu(np->tx_ring.ex[i+3].bufhigh),
+                                      le32_to_cpu(np->tx_ring.ex[i+3].buflow),
+                                      le32_to_cpu(np->tx_ring.ex[i+3].flaglen));
                        }
                }
        }
@@ -1697,7 +1715,7 @@ static int nv_getlen(struct net_device *dev, void *packet, int datalen)
        int protolen;   /* length as stored in the proto field */
 
        /* 1) calculate len according to header */
-       if ( ((struct vlan_ethhdr *)packet)->h_vlan_proto == __constant_htons(ETH_P_8021Q)) {
+       if ( ((struct vlan_ethhdr *)packet)->h_vlan_proto == htons(ETH_P_8021Q)) {
                protolen = ntohs( ((struct vlan_ethhdr *)packet)->h_vlan_encapsulated_proto );
                hdrlen = VLAN_HLEN;
        } else {
@@ -1740,13 +1758,14 @@ static int nv_getlen(struct net_device *dev, void *packet, int datalen)
        }
 }
 
-static void nv_rx_process(struct net_device *dev)
+static int nv_rx_process(struct net_device *dev, int limit)
 {
        struct fe_priv *np = netdev_priv(dev);
-       u32 Flags;
+       u32 flags;
        u32 vlanflags = 0;
+       int count;
 
-       for (;;) {
+       for (count = 0; count < limit; ++count) {
                struct sk_buff *skb;
                int len;
                int i;
@@ -1755,18 +1774,18 @@ static void nv_rx_process(struct net_device *dev)
 
                i = np->cur_rx % np->rx_ring_size;
                if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-                       Flags = le32_to_cpu(np->rx_ring.orig[i].FlagLen);
+                       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);
+                       flags = le32_to_cpu(np->rx_ring.ex[i].flaglen);
                        len = nv_descr_getlength_ex(&np->rx_ring.ex[i], np->desc_ver);
-                       vlanflags = le32_to_cpu(np->rx_ring.ex[i].PacketBufferLow);
+                       vlanflags = le32_to_cpu(np->rx_ring.ex[i].buflow);
                }
 
-               dprintk(KERN_DEBUG "%s: nv_rx_process: looking at packet %d, Flags 0x%x.\n",
-                                       dev->name, np->cur_rx, Flags);
+               dprintk(KERN_DEBUG "%s: nv_rx_process: looking at packet %d, flags 0x%x.\n",
+                                       dev->name, np->cur_rx, flags);
 
-               if (Flags & NV_RX_AVAIL)
+               if (flags & NV_RX_AVAIL)
                        break;  /* still owned by hardware, */
 
                /*
@@ -1780,7 +1799,7 @@ static void nv_rx_process(struct net_device *dev)
 
                {
                        int j;
-                       dprintk(KERN_DEBUG "Dumping packet (flags 0x%x).",Flags);
+                       dprintk(KERN_DEBUG "Dumping packet (flags 0x%x).",flags);
                        for (j=0; j<64; j++) {
                                if ((j%16) == 0)
                                        dprintk("\n%03x:", j);
@@ -1790,30 +1809,30 @@ static void nv_rx_process(struct net_device *dev)
                }
                /* look at what we actually got: */
                if (np->desc_ver == DESC_VER_1) {
-                       if (!(Flags & NV_RX_DESCRIPTORVALID))
+                       if (!(flags & NV_RX_DESCRIPTORVALID))
                                goto next_pkt;
 
-                       if (Flags & NV_RX_ERROR) {
-                               if (Flags & NV_RX_MISSEDFRAME) {
+                       if (flags & NV_RX_ERROR) {
+                               if (flags & NV_RX_MISSEDFRAME) {
                                        np->stats.rx_missed_errors++;
                                        np->stats.rx_errors++;
                                        goto next_pkt;
                                }
-                               if (Flags & (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3)) {
+                               if (flags & (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3)) {
                                        np->stats.rx_errors++;
                                        goto next_pkt;
                                }
-                               if (Flags & NV_RX_CRCERR) {
+                               if (flags & NV_RX_CRCERR) {
                                        np->stats.rx_crc_errors++;
                                        np->stats.rx_errors++;
                                        goto next_pkt;
                                }
-                               if (Flags & NV_RX_OVERFLOW) {
+                               if (flags & NV_RX_OVERFLOW) {
                                        np->stats.rx_over_errors++;
                                        np->stats.rx_errors++;
                                        goto next_pkt;
                                }
-                               if (Flags & NV_RX_ERROR4) {
+                               if (flags & NV_RX_ERROR4) {
                                        len = nv_getlen(dev, np->rx_skbuff[i]->data, len);
                                        if (len < 0) {
                                                np->stats.rx_errors++;
@@ -1821,32 +1840,32 @@ static void nv_rx_process(struct net_device *dev)
                                        }
                                }
                                /* framing errors are soft errors. */
-                               if (Flags & NV_RX_FRAMINGERR) {
-                                       if (Flags & NV_RX_SUBSTRACT1) {
+                               if (flags & NV_RX_FRAMINGERR) {
+                                       if (flags & NV_RX_SUBSTRACT1) {
                                                len--;
                                        }
                                }
                        }
                } else {
-                       if (!(Flags & NV_RX2_DESCRIPTORVALID))
+                       if (!(flags & NV_RX2_DESCRIPTORVALID))
                                goto next_pkt;
 
-                       if (Flags & NV_RX2_ERROR) {
-                               if (Flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3)) {
+                       if (flags & NV_RX2_ERROR) {
+                               if (flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3)) {
                                        np->stats.rx_errors++;
                                        goto next_pkt;
                                }
-                               if (Flags & NV_RX2_CRCERR) {
+                               if (flags & NV_RX2_CRCERR) {
                                        np->stats.rx_crc_errors++;
                                        np->stats.rx_errors++;
                                        goto next_pkt;
                                }
-                               if (Flags & NV_RX2_OVERFLOW) {
+                               if (flags & NV_RX2_OVERFLOW) {
                                        np->stats.rx_over_errors++;
                                        np->stats.rx_errors++;
                                        goto next_pkt;
                                }
-                               if (Flags & NV_RX2_ERROR4) {
+                               if (flags & NV_RX2_ERROR4) {
                                        len = nv_getlen(dev, np->rx_skbuff[i]->data, len);
                                        if (len < 0) {
                                                np->stats.rx_errors++;
@@ -1854,17 +1873,17 @@ static void nv_rx_process(struct net_device *dev)
                                        }
                                }
                                /* framing errors are soft errors */
-                               if (Flags & NV_RX2_FRAMINGERR) {
-                                       if (Flags & NV_RX2_SUBSTRACT1) {
+                               if (flags & NV_RX2_FRAMINGERR) {
+                                       if (flags & NV_RX2_SUBSTRACT1) {
                                                len--;
                                        }
                                }
                        }
                        if (np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) {
-                               Flags &= NV_RX2_CHECKSUMMASK;
-                               if (Flags == NV_RX2_CHECKSUMOK1 ||
-                                   Flags == NV_RX2_CHECKSUMOK2 ||
-                                   Flags == NV_RX2_CHECKSUMOK3) {
+                               flags &= NV_RX2_CHECKSUMMASK;
+                               if (flags == NV_RX2_CHECKSUMOK1 ||
+                                   flags == NV_RX2_CHECKSUMOK2 ||
+                                   flags == NV_RX2_CHECKSUMOK3) {
                                        dprintk(KERN_DEBUG "%s: hw checksum hit!.\n", dev->name);
                                        np->rx_skbuff[i]->ip_summed = CHECKSUM_UNNECESSARY;
                                } else {
@@ -1880,17 +1899,27 @@ static void nv_rx_process(struct net_device *dev)
                skb->protocol = eth_type_trans(skb, dev);
                dprintk(KERN_DEBUG "%s: nv_rx_process: packet %d with %d bytes, proto %d accepted.\n",
                                        dev->name, np->cur_rx, len, skb->protocol);
-               if (np->vlangrp && (vlanflags & NV_RX3_VLAN_TAG_PRESENT)) {
-                       vlan_hwaccel_rx(skb, np->vlangrp, vlanflags & NV_RX3_VLAN_TAG_MASK);
-               } else {
+#ifdef CONFIG_FORCEDETH_NAPI
+               if (np->vlangrp && (vlanflags & NV_RX3_VLAN_TAG_PRESENT))
+                       vlan_hwaccel_receive_skb(skb, np->vlangrp,
+                                                vlanflags & NV_RX3_VLAN_TAG_MASK);
+               else
+                       netif_receive_skb(skb);
+#else
+               if (np->vlangrp && (vlanflags & NV_RX3_VLAN_TAG_PRESENT))
+                       vlan_hwaccel_rx(skb, np->vlangrp,
+                                       vlanflags & NV_RX3_VLAN_TAG_MASK);
+               else
                        netif_rx(skb);
-               }
+#endif
                dev->last_rx = jiffies;
                np->stats.rx_packets++;
                np->stats.rx_bytes += len;
 next_pkt:
                np->cur_rx++;
        }
+
+       return count;
 }
 
 static void set_bufsize(struct net_device *dev)
@@ -1990,7 +2019,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
        struct fe_priv *np = netdev_priv(dev);
        struct sockaddr *macaddr = (struct sockaddr*)addr;
 
-       if(!is_valid_ether_addr(macaddr->sa_data))
+       if (!is_valid_ether_addr(macaddr->sa_data))
                return -EADDRNOTAVAIL;
 
        /* synchronized against open : rtnl_lock() held by caller */
@@ -2283,20 +2312,20 @@ set_speed:
                        lpa_pause = lpa & (LPA_PAUSE_CAP| LPA_PAUSE_ASYM);
 
                        switch (adv_pause) {
-                       case (ADVERTISE_PAUSE_CAP):
+                       case ADVERTISE_PAUSE_CAP:
                                if (lpa_pause & LPA_PAUSE_CAP) {
                                        pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
                                        if (np->pause_flags & NV_PAUSEFRAME_TX_REQ)
                                                pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
                                }
                                break;
-                       case (ADVERTISE_PAUSE_ASYM):
+                       case ADVERTISE_PAUSE_ASYM:
                                if (lpa_pause == (LPA_PAUSE_CAP| LPA_PAUSE_ASYM))
                                {
                                        pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
                                }
                                break;
-                       case (ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM):
+                       case ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM:
                                if (lpa_pause & LPA_PAUSE_CAP)
                                {
                                        pause_flags |=  NV_PAUSEFRAME_RX_ENABLE;
@@ -2376,14 +2405,6 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
                nv_tx_done(dev);
                spin_unlock(&np->lock);
 
-               nv_rx_process(dev);
-               if (nv_alloc_rx(dev)) {
-                       spin_lock(&np->lock);
-                       if (!np->in_shutdown)
-                               mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
-                       spin_unlock(&np->lock);
-               }
-
                if (events & NVREG_IRQ_LINK) {
                        spin_lock(&np->lock);
                        nv_link_irq(dev);
@@ -2403,6 +2424,29 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
                        printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n",
                                                dev->name, events);
                }
+#ifdef CONFIG_FORCEDETH_NAPI
+               if (events & NVREG_IRQ_RX_ALL) {
+                       netif_rx_schedule(dev);
+
+                       /* Disable furthur receive irq's */
+                       spin_lock(&np->lock);
+                       np->irqmask &= ~NVREG_IRQ_RX_ALL;
+
+                       if (np->msi_flags & NV_MSI_X_ENABLED)
+                               writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
+                       else
+                               writel(np->irqmask, base + NvRegIrqMask);
+                       spin_unlock(&np->lock);
+               }
+#else
+               nv_rx_process(dev, dev->weight);
+               if (nv_alloc_rx(dev)) {
+                       spin_lock(&np->lock);
+                       if (!np->in_shutdown)
+                               mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
+                       spin_unlock(&np->lock);
+               }
+#endif
                if (i > max_interrupt_work) {
                        spin_lock(&np->lock);
                        /* disable interrupts on the nic */
@@ -2474,6 +2518,63 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs)
        return IRQ_RETVAL(i);
 }
 
+#ifdef CONFIG_FORCEDETH_NAPI
+static int nv_napi_poll(struct net_device *dev, int *budget)
+{
+       int pkts, limit = min(*budget, dev->quota);
+       struct fe_priv *np = netdev_priv(dev);
+       u8 __iomem *base = get_hwbase(dev);
+
+       pkts = nv_rx_process(dev, limit);
+
+       if (nv_alloc_rx(dev)) {
+               spin_lock_irq(&np->lock);
+               if (!np->in_shutdown)
+                       mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
+               spin_unlock_irq(&np->lock);
+       }
+
+       if (pkts < limit) {
+               /* all done, no more packets present */
+               netif_rx_complete(dev);
+
+               /* re-enable receive interrupts */
+               spin_lock_irq(&np->lock);
+               np->irqmask |= NVREG_IRQ_RX_ALL;
+               if (np->msi_flags & NV_MSI_X_ENABLED)
+                       writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
+               else
+                       writel(np->irqmask, base + NvRegIrqMask);
+               spin_unlock_irq(&np->lock);
+               return 0;
+       } else {
+               /* used up our quantum, so reschedule */
+               dev->quota -= pkts;
+               *budget -= pkts;
+               return 1;
+       }
+}
+#endif
+
+#ifdef CONFIG_FORCEDETH_NAPI
+static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *) data;
+       u8 __iomem *base = get_hwbase(dev);
+       u32 events;
+
+       events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_RX_ALL;
+       writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus);
+
+       if (events) {
+               netif_rx_schedule(dev);
+               /* disable receive interrupts on the nic */
+               writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
+               pci_push(base);
+       }
+       return IRQ_HANDLED;
+}
+#else
 static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
 {
        struct net_device *dev = (struct net_device *) data;
@@ -2492,7 +2593,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
                if (!(events & np->irqmask))
                        break;
 
-               nv_rx_process(dev);
+               nv_rx_process(dev, dev->weight);
                if (nv_alloc_rx(dev)) {
                        spin_lock_irq(&np->lock);
                        if (!np->in_shutdown)
@@ -2514,12 +2615,12 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
                        spin_unlock_irq(&np->lock);
                        break;
                }
-
        }
        dprintk(KERN_DEBUG "%s: nv_nic_irq_rx completed\n", dev->name);
 
        return IRQ_RETVAL(i);
 }
+#endif
 
 static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
 {
@@ -3245,7 +3346,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
        if (!rxtx_ring || !rx_skbuff || !rx_dma || !tx_skbuff || !tx_dma || !tx_dma_len) {
                /* fall back to old rings */
                if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-                       if(rxtx_ring)
+                       if (rxtx_ring)
                                pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (ring->rx_pending + ring->tx_pending),
                                                    rxtx_ring, ring_addr);
                } else {
@@ -3481,7 +3582,7 @@ static int nv_get_stats_count(struct net_device *dev)
        struct fe_priv *np = netdev_priv(dev);
 
        if (np->driver_data & DEV_HAS_STATISTICS)
-               return (sizeof(struct nv_ethtool_stats)/sizeof(u64));
+               return sizeof(struct nv_ethtool_stats)/sizeof(u64);
        else
                return 0;
 }
@@ -3619,7 +3720,7 @@ static int nv_loopback_test(struct net_device *dev)
        struct sk_buff *tx_skb, *rx_skb;
        dma_addr_t test_dma_addr;
        u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET);
-       u32 Flags;
+       u32 flags;
        int len, i, pkt_len;
        u8 *pkt_data;
        u32 filter_flags = 0;
@@ -3663,12 +3764,12 @@ static int nv_loopback_test(struct net_device *dev)
                                       tx_skb->end-tx_skb->data, PCI_DMA_FROMDEVICE);
 
        if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-               np->tx_ring.orig[0].PacketBuffer = cpu_to_le32(test_dma_addr);
-               np->tx_ring.orig[0].FlagLen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
+               np->tx_ring.orig[0].buf = cpu_to_le32(test_dma_addr);
+               np->tx_ring.orig[0].flaglen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
        } else {
-               np->tx_ring.ex[0].PacketBufferHigh = cpu_to_le64(test_dma_addr) >> 32;
-               np->tx_ring.ex[0].PacketBufferLow = cpu_to_le64(test_dma_addr) & 0x0FFFFFFFF;
-               np->tx_ring.ex[0].FlagLen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
+               np->tx_ring.ex[0].bufhigh = cpu_to_le64(test_dma_addr) >> 32;
+               np->tx_ring.ex[0].buflow = cpu_to_le64(test_dma_addr) & 0x0FFFFFFFF;
+               np->tx_ring.ex[0].flaglen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
        }
        writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
        pci_push(get_hwbase(dev));
@@ -3677,21 +3778,21 @@ static int nv_loopback_test(struct net_device *dev)
 
        /* check for rx of the packet */
        if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-               Flags = le32_to_cpu(np->rx_ring.orig[0].FlagLen);
+               flags = le32_to_cpu(np->rx_ring.orig[0].flaglen);
                len = nv_descr_getlength(&np->rx_ring.orig[0], np->desc_ver);
 
        } else {
-               Flags = le32_to_cpu(np->rx_ring.ex[0].FlagLen);
+               flags = le32_to_cpu(np->rx_ring.ex[0].flaglen);
                len = nv_descr_getlength_ex(&np->rx_ring.ex[0], np->desc_ver);
        }
 
-       if (Flags & NV_RX_AVAIL) {
+       if (flags & NV_RX_AVAIL) {
                ret = 0;
        } else if (np->desc_ver == DESC_VER_1) {
-               if (Flags & NV_RX_ERROR)
+               if (flags & NV_RX_ERROR)
                        ret = 0;
        } else {
-               if (Flags & NV_RX2_ERROR) {
+               if (flags & NV_RX2_ERROR) {
                        ret = 0;
                }
        }
@@ -3753,6 +3854,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
        if (test->flags & ETH_TEST_FL_OFFLINE) {
                if (netif_running(dev)) {
                        netif_stop_queue(dev);
+                       netif_poll_disable(dev);
                        netif_tx_lock_bh(dev);
                        spin_lock_irq(&np->lock);
                        nv_disable_hw_interrupts(dev, np->irqmask);
@@ -3811,6 +3913,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
                        nv_start_rx(dev);
                        nv_start_tx(dev);
                        netif_start_queue(dev);
+                       netif_poll_enable(dev);
                        nv_enable_hw_interrupts(dev, np->irqmask);
                }
        }
@@ -3895,10 +3998,9 @@ static int nv_open(struct net_device *dev)
 
        dprintk(KERN_DEBUG "nv_open: begin\n");
 
-       /* 1) erase previous misconfiguration */
+       /* erase previous misconfiguration */
        if (np->driver_data & DEV_HAS_POWER_CNTRL)
                nv_mac_reset(dev);
-       /* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */
        writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
        writel(0, base + NvRegMulticastAddrB);
        writel(0, base + NvRegMulticastMaskA);
@@ -3913,26 +4015,22 @@ static int nv_open(struct net_device *dev)
        if (np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE)
                writel(NVREG_TX_PAUSEFRAME_DISABLE,  base + NvRegTxPauseFrame);
 
-       /* 2) initialize descriptor rings */
+       /* initialize descriptor rings */
        set_bufsize(dev);
        oom = nv_init_ring(dev);
 
        writel(0, base + NvRegLinkSpeed);
-       writel(0, base + NvRegUnknownTransmitterReg);
+       writel(readl(base + NvRegTransmitPoll) & NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll);
        nv_txrx_reset(dev);
        writel(0, base + NvRegUnknownSetupReg6);
 
        np->in_shutdown = 0;
 
-       /* 3) set mac address */
-       nv_copy_mac_to_hw(dev);
-
-       /* 4) give hw rings */
+       /* give hw rings */
        setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
        writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
                base + NvRegRingSizes);
 
-       /* 5) continue setup */
        writel(np->linkspeed, base + NvRegLinkSpeed);
        if (np->desc_ver == DESC_VER_1)
                writel(NVREG_TX_WM_DESC1_DEFAULT, base + NvRegTxWatermark);
@@ -3950,7 +4048,6 @@ static int nv_open(struct net_device *dev)
        writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
        writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
 
-       /* 6) continue setup */
        writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1);
        writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus);
        writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags);
@@ -4020,6 +4117,8 @@ static int nv_open(struct net_device *dev)
        nv_start_rx(dev);
        nv_start_tx(dev);
        netif_start_queue(dev);
+       netif_poll_enable(dev);
+
        if (ret) {
                netif_carrier_on(dev);
        } else {
@@ -4049,6 +4148,7 @@ static int nv_close(struct net_device *dev)
        spin_lock_irq(&np->lock);
        np->in_shutdown = 1;
        spin_unlock_irq(&np->lock);
+       netif_poll_disable(dev);
        synchronize_irq(dev->irq);
 
        del_timer_sync(&np->oom_kick);
@@ -4076,12 +4176,6 @@ 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;
@@ -4094,7 +4188,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
        unsigned long addr;
        u8 __iomem *base;
        int err, i;
-       u32 powerstate;
+       u32 powerstate, txreg;
 
        dev = alloc_etherdev(sizeof(struct fe_priv));
        err = -ENOMEM;
@@ -4269,6 +4363,10 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
        dev->set_multicast_list = nv_set_multicast;
 #ifdef CONFIG_NET_POLL_CONTROLLER
        dev->poll_controller = nv_poll_controller;
+#endif
+       dev->weight = 64;
+#ifdef CONFIG_FORCEDETH_NAPI
+       dev->poll = nv_napi_poll;
 #endif
        SET_ETHTOOL_OPS(dev, &ops);
        dev->tx_timeout = nv_tx_timeout;
@@ -4281,12 +4379,30 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
        np->orig_mac[0] = readl(base + NvRegMacAddrA);
        np->orig_mac[1] = readl(base + NvRegMacAddrB);
 
-       dev->dev_addr[0] = (np->orig_mac[1] >>  8) & 0xff;
-       dev->dev_addr[1] = (np->orig_mac[1] >>  0) & 0xff;
-       dev->dev_addr[2] = (np->orig_mac[0] >> 24) & 0xff;
-       dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff;
-       dev->dev_addr[4] = (np->orig_mac[0] >>  8) & 0xff;
-       dev->dev_addr[5] = (np->orig_mac[0] >>  0) & 0xff;
+       /* check the workaround bit for correct mac address order */
+       txreg = readl(base + NvRegTransmitPoll);
+       if (txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) {
+               /* mac address is already in correct order */
+               dev->dev_addr[0] = (np->orig_mac[0] >>  0) & 0xff;
+               dev->dev_addr[1] = (np->orig_mac[0] >>  8) & 0xff;
+               dev->dev_addr[2] = (np->orig_mac[0] >> 16) & 0xff;
+               dev->dev_addr[3] = (np->orig_mac[0] >> 24) & 0xff;
+               dev->dev_addr[4] = (np->orig_mac[1] >>  0) & 0xff;
+               dev->dev_addr[5] = (np->orig_mac[1] >>  8) & 0xff;
+       } else {
+               /* need to reverse mac address to correct order */
+               dev->dev_addr[0] = (np->orig_mac[1] >>  8) & 0xff;
+               dev->dev_addr[1] = (np->orig_mac[1] >>  0) & 0xff;
+               dev->dev_addr[2] = (np->orig_mac[0] >> 24) & 0xff;
+               dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff;
+               dev->dev_addr[4] = (np->orig_mac[0] >>  8) & 0xff;
+               dev->dev_addr[5] = (np->orig_mac[0] >>  0) & 0xff;
+               /* set permanent address to be correct aswell */
+               np->orig_mac[0] = (dev->dev_addr[0] << 0) + (dev->dev_addr[1] << 8) +
+                       (dev->dev_addr[2] << 16) + (dev->dev_addr[3] << 24);
+               np->orig_mac[1] = (dev->dev_addr[4] << 0) + (dev->dev_addr[5] << 8);
+               writel(txreg|NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll);
+       }
        memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
        if (!is_valid_ether_addr(dev->perm_addr)) {
@@ -4309,6 +4425,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                        dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
                        dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
 
+       /* set mac address */
+       nv_copy_mac_to_hw(dev);
+
        /* disable WOL */
        writel(0, base + NvRegWakeUpFlags);
        np->wolenabled = 0;
@@ -4421,9 +4540,17 @@ out:
 static void __devexit nv_remove(struct pci_dev *pci_dev)
 {
        struct net_device *dev = pci_get_drvdata(pci_dev);
+       struct fe_priv *np = netdev_priv(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 */
        free_rings(dev);
        iounmap(get_hwbase(dev));
@@ -4540,7 +4667,7 @@ static struct pci_driver driver = {
 static int __init init_nic(void)
 {
        printk(KERN_INFO "forcedeth.c: Reverse Engineered nForce ethernet driver. Version %s.\n", FORCEDETH_VERSION);
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit exit_nic(void)
index d6dd3f2fb43e4c49bc52d216e740bb5762a52daf..02d4dc18ba693c0f7daa0c3d0a2edc478a0a5241 100644 (file)
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_FS_ENET) += fs_enet.o
 
-obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o
-obj-$(CONFIG_8260) += mac-fcc.o
+obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o mii-fec.o
+obj-$(CONFIG_CPM2) += mac-fcc.o mii-bitbang.o
 
-fs_enet-objs := fs_enet-main.o fs_enet-mii.o mii-bitbang.o mii-fixed.o
+fs_enet-objs := fs_enet-main.o
diff --git a/drivers/net/fs_enet/fec.h b/drivers/net/fs_enet/fec.h
new file mode 100644 (file)
index 0000000..e980527
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef FS_ENET_FEC_H
+#define FS_ENET_FEC_H
+
+/* CRC polynomium used by the FEC for the multicast group filtering */
+#define FEC_CRC_POLY   0x04C11DB7
+
+#define FEC_MAX_MULTICAST_ADDRS        64
+
+/* Interrupt events/masks.
+*/
+#define FEC_ENET_HBERR 0x80000000U     /* Heartbeat error          */
+#define FEC_ENET_BABR  0x40000000U     /* Babbling receiver        */
+#define FEC_ENET_BABT  0x20000000U     /* Babbling transmitter     */
+#define FEC_ENET_GRA   0x10000000U     /* Graceful stop complete   */
+#define FEC_ENET_TXF   0x08000000U     /* Full frame transmitted   */
+#define FEC_ENET_TXB   0x04000000U     /* A buffer was transmitted */
+#define FEC_ENET_RXF   0x02000000U     /* Full frame received      */
+#define FEC_ENET_RXB   0x01000000U     /* A buffer was received    */
+#define FEC_ENET_MII   0x00800000U     /* MII interrupt            */
+#define FEC_ENET_EBERR 0x00400000U     /* SDMA bus error           */
+
+#define FEC_ECNTRL_PINMUX      0x00000004
+#define FEC_ECNTRL_ETHER_EN    0x00000002
+#define FEC_ECNTRL_RESET       0x00000001
+
+#define FEC_RCNTRL_BC_REJ      0x00000010
+#define FEC_RCNTRL_PROM                0x00000008
+#define FEC_RCNTRL_MII_MODE    0x00000004
+#define FEC_RCNTRL_DRT         0x00000002
+#define FEC_RCNTRL_LOOP                0x00000001
+
+#define FEC_TCNTRL_FDEN                0x00000004
+#define FEC_TCNTRL_HBC         0x00000002
+#define FEC_TCNTRL_GTS         0x00000001
+
+
+
+/*
+ * Delay to wait for FEC reset command to complete (in us)
+ */
+#define FEC_RESET_DELAY                50
+#endif
index f6abff5846b35fd1ca5f3bccec6c62d639129bc6..df62506a178701eb30376f6f3f15cdd75a7dc289 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/bitops.h>
 #include <linux/fs.h>
 #include <linux/platform_device.h>
+#include <linux/phy.h>
 
 #include <linux/vmalloc.h>
 #include <asm/pgtable.h>
@@ -682,35 +683,6 @@ static void fs_free_irq(struct net_device *dev, int irq)
        (*fep->ops->post_free_irq)(dev, irq);
 }
 
-/**********************************************************************************/
-
-/* This interrupt occurs when the PHY detects a link change. */
-static irqreturn_t
-fs_mii_link_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       struct net_device *dev = dev_id;
-       struct fs_enet_private *fep;
-       const struct fs_platform_info *fpi;
-
-       fep = netdev_priv(dev);
-       fpi = fep->fpi;
-
-       /*
-        * Acknowledge the interrupt if possible. If we have not
-        * found the PHY yet we can't process or acknowledge the
-        * interrupt now. Instead we ignore this interrupt for now,
-        * which we can do since it is edge triggered. It will be
-        * acknowledged later by fs_enet_open().
-        */
-       if (!fep->phy)
-               return IRQ_NONE;
-
-       fs_mii_ack_int(dev);
-       fs_mii_link_status_change_check(dev, 0);
-
-       return IRQ_HANDLED;
-}
-
 static void fs_timeout(struct net_device *dev)
 {
        struct fs_enet_private *fep = netdev_priv(dev);
@@ -722,10 +694,13 @@ static void fs_timeout(struct net_device *dev)
        spin_lock_irqsave(&fep->lock, flags);
 
        if (dev->flags & IFF_UP) {
+               phy_stop(fep->phydev);
                (*fep->ops->stop)(dev);
                (*fep->ops->restart)(dev);
+               phy_start(fep->phydev);
        }
 
+       phy_start(fep->phydev);
        wake = fep->tx_free && !(CBDR_SC(fep->cur_tx) & BD_ENET_TX_READY);
        spin_unlock_irqrestore(&fep->lock, flags);
 
@@ -733,35 +708,112 @@ static void fs_timeout(struct net_device *dev)
                netif_wake_queue(dev);
 }
 
+/*-----------------------------------------------------------------------------
+ *  generic link-change handler - should be sufficient for most cases
+ *-----------------------------------------------------------------------------*/
+static void generic_adjust_link(struct  net_device *dev)
+{
+       struct fs_enet_private *fep = netdev_priv(dev);
+       struct phy_device *phydev = fep->phydev;
+       int new_state = 0;
+
+       if (phydev->link) {
+
+               /* adjust to duplex mode */
+               if (phydev->duplex != fep->oldduplex){
+                       new_state = 1;
+                       fep->oldduplex = phydev->duplex;
+               }
+
+               if (phydev->speed != fep->oldspeed) {
+                       new_state = 1;
+                       fep->oldspeed = phydev->speed;
+               }
+
+               if (!fep->oldlink) {
+                       new_state = 1;
+                       fep->oldlink = 1;
+                       netif_schedule(dev);
+                       netif_carrier_on(dev);
+                       netif_start_queue(dev);
+               }
+
+               if (new_state)
+                       fep->ops->restart(dev);
+
+       } else if (fep->oldlink) {
+               new_state = 1;
+               fep->oldlink = 0;
+               fep->oldspeed = 0;
+               fep->oldduplex = -1;
+               netif_carrier_off(dev);
+               netif_stop_queue(dev);
+       }
+
+       if (new_state && netif_msg_link(fep))
+               phy_print_status(phydev);
+}
+
+
+static void fs_adjust_link(struct net_device *dev)
+{
+       struct fs_enet_private *fep = netdev_priv(dev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&fep->lock, flags);
+
+       if(fep->ops->adjust_link)
+               fep->ops->adjust_link(dev);
+       else
+               generic_adjust_link(dev);
+
+       spin_unlock_irqrestore(&fep->lock, flags);
+}
+
+static int fs_init_phy(struct net_device *dev)
+{
+       struct fs_enet_private *fep = netdev_priv(dev);
+       struct phy_device *phydev;
+
+       fep->oldlink = 0;
+       fep->oldspeed = 0;
+       fep->oldduplex = -1;
+       if(fep->fpi->bus_id)
+               phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0);
+       else {
+               printk("No phy bus ID specified in BSP code\n");
+               return -EINVAL;
+       }
+       if (IS_ERR(phydev)) {
+               printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+               return PTR_ERR(phydev);
+       }
+
+       fep->phydev = phydev;
+
+       return 0;
+}
+
+
 static int fs_enet_open(struct net_device *dev)
 {
        struct fs_enet_private *fep = netdev_priv(dev);
-       const struct fs_platform_info *fpi = fep->fpi;
        int r;
+       int err;
 
        /* Install our interrupt handler. */
        r = fs_request_irq(dev, fep->interrupt, "fs_enet-mac", fs_enet_interrupt);
        if (r != 0) {
                printk(KERN_ERR DRV_MODULE_NAME
-                      ": %s Could not allocate FEC IRQ!", dev->name);
+                      ": %s Could not allocate FS_ENET IRQ!", dev->name);
                return -EINVAL;
        }
 
-       /* Install our phy interrupt handler */
-       if (fpi->phy_irq != -1) {
-
-               r = fs_request_irq(dev, fpi->phy_irq, "fs_enet-phy", fs_mii_link_interrupt);
-               if (r != 0) {
-                       printk(KERN_ERR DRV_MODULE_NAME
-                              ": %s Could not allocate PHY IRQ!", dev->name);
-                       fs_free_irq(dev, fep->interrupt);
-                       return -EINVAL;
-               }
-       }
+       err = fs_init_phy(dev);
+       if(err)
+               return err;
 
-       fs_mii_startup(dev);
-       netif_carrier_off(dev);
-       fs_mii_link_status_change_check(dev, 1);
+       phy_start(fep->phydev);
 
        return 0;
 }
@@ -769,20 +821,19 @@ static int fs_enet_open(struct net_device *dev)
 static int fs_enet_close(struct net_device *dev)
 {
        struct fs_enet_private *fep = netdev_priv(dev);
-       const struct fs_platform_info *fpi = fep->fpi;
        unsigned long flags;
 
        netif_stop_queue(dev);
        netif_carrier_off(dev);
-       fs_mii_shutdown(dev);
+       phy_stop(fep->phydev);
 
        spin_lock_irqsave(&fep->lock, flags);
        (*fep->ops->stop)(dev);
        spin_unlock_irqrestore(&fep->lock, flags);
 
        /* release any irqs */
-       if (fpi->phy_irq != -1)
-               fs_free_irq(dev, fpi->phy_irq);
+       phy_disconnect(fep->phydev);
+       fep->phydev = NULL;
        fs_free_irq(dev, fep->interrupt);
 
        return 0;
@@ -830,33 +881,19 @@ static void fs_get_regs(struct net_device *dev, struct ethtool_regs *regs,
 static int fs_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct fs_enet_private *fep = netdev_priv(dev);
-       unsigned long flags;
-       int rc;
-
-       spin_lock_irqsave(&fep->lock, flags);
-       rc = mii_ethtool_gset(&fep->mii_if, cmd);
-       spin_unlock_irqrestore(&fep->lock, flags);
-
-       return rc;
+       return phy_ethtool_gset(fep->phydev, cmd);
 }
 
 static int fs_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct fs_enet_private *fep = netdev_priv(dev);
-       unsigned long flags;
-       int rc;
-
-       spin_lock_irqsave(&fep->lock, flags);
-       rc = mii_ethtool_sset(&fep->mii_if, cmd);
-       spin_unlock_irqrestore(&fep->lock, flags);
-
-       return rc;
+       phy_ethtool_sset(fep->phydev, cmd);
+       return 0;
 }
 
 static int fs_nway_reset(struct net_device *dev)
 {
-       struct fs_enet_private *fep = netdev_priv(dev);
-       return mii_nway_restart(&fep->mii_if);
+       return 0;
 }
 
 static u32 fs_get_msglevel(struct net_device *dev)
@@ -898,7 +935,7 @@ static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                return -EINVAL;
 
        spin_lock_irqsave(&fep->lock, flags);
-       rc = generic_mii_ioctl(&fep->mii_if, mii, cmd, NULL);
+       rc = phy_mii_ioctl(fep->phydev, mii, cmd);
        spin_unlock_irqrestore(&fep->lock, flags);
        return rc;
 }
@@ -1030,12 +1067,6 @@ static struct net_device *fs_init_instance(struct device *dev,
        }
        registered = 1;
 
-       err = fs_mii_connect(ndev);
-       if (err != 0) {
-               printk(KERN_ERR DRV_MODULE_NAME
-                      ": %s fs_mii_connect failed.\n", ndev->name);
-               goto err;
-       }
 
        return ndev;
 
@@ -1073,8 +1104,6 @@ static int fs_cleanup_instance(struct net_device *ndev)
 
        fpi = fep->fpi;
 
-       fs_mii_disconnect(ndev);
-
        unregister_netdev(ndev);
 
        dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t),
@@ -1196,17 +1225,39 @@ static int __init fs_init(void)
        r = setup_immap();
        if (r != 0)
                return r;
-       r = driver_register(&fs_enet_fec_driver);
+
+#ifdef CONFIG_FS_ENET_HAS_FCC
+       /* let's insert mii stuff */
+       r = fs_enet_mdio_bb_init();
+
+       if (r != 0) {
+               printk(KERN_ERR DRV_MODULE_NAME
+                       "BB PHY init failed.\n");
+               return r;
+       }
+       r = driver_register(&fs_enet_fcc_driver);
        if (r != 0)
                goto err;
+#endif
 
-       r = driver_register(&fs_enet_fcc_driver);
+#ifdef CONFIG_FS_ENET_HAS_FEC
+       r =  fs_enet_mdio_fec_init();
+       if (r != 0) {
+               printk(KERN_ERR DRV_MODULE_NAME
+                       "FEC PHY init failed.\n");
+               return r;
+       }
+
+       r = driver_register(&fs_enet_fec_driver);
        if (r != 0)
                goto err;
+#endif
 
+#ifdef CONFIG_FS_ENET_HAS_SCC
        r = driver_register(&fs_enet_scc_driver);
        if (r != 0)
                goto err;
+#endif
 
        return 0;
 err:
diff --git a/drivers/net/fs_enet/fs_enet-mii.c b/drivers/net/fs_enet/fs_enet-mii.c
deleted file mode 100644 (file)
index b7e6e21..0000000
+++ /dev/null
@@ -1,505 +0,0 @@
-/*
- * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
- *
- * Copyright (c) 2003 Intracom S.A. 
- *  by Pantelis Antoniou <panto@intracom.gr>
- * 
- * 2005 (c) MontaVista Software, Inc. 
- * Vitaly Bordug <vbordug@ru.mvista.com>
- *
- * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
- * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
- *
- * This file is licensed under the terms of the GNU General Public License 
- * version 2. This program is licensed "as is" without any warranty of any 
- * kind, whether express or implied.
- */
-
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.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/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/bitops.h>
-
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-
-#include "fs_enet.h"
-
-/*************************************************/
-
-/*
- * Generic PHY support.
- * Should work for all PHYs, but link change is detected by polling
- */
-
-static void generic_timer_callback(unsigned long data)
-{
-       struct net_device *dev = (struct net_device *)data;
-       struct fs_enet_private *fep = netdev_priv(dev);
-
-       fep->phy_timer_list.expires = jiffies + HZ / 2;
-
-       add_timer(&fep->phy_timer_list);
-
-       fs_mii_link_status_change_check(dev, 0);
-}
-
-static void generic_startup(struct net_device *dev)
-{
-       struct fs_enet_private *fep = netdev_priv(dev);
-
-       fep->phy_timer_list.expires = jiffies + HZ / 2; /* every 500ms */
-       fep->phy_timer_list.data = (unsigned long)dev;
-       fep->phy_timer_list.function = generic_timer_callback;
-       add_timer(&fep->phy_timer_list);
-}
-
-static void generic_shutdown(struct net_device *dev)
-{
-       struct fs_enet_private *fep = netdev_priv(dev);
-
-       del_timer_sync(&fep->phy_timer_list);
-}
-
-/* ------------------------------------------------------------------------- */
-/* The Davicom DM9161 is used on the NETTA board                            */
-
-/* register definitions */
-
-#define MII_DM9161_ANAR                4       /* Aux. Config Register         */
-#define MII_DM9161_ACR         16      /* Aux. Config Register         */
-#define MII_DM9161_ACSR                17      /* Aux. Config/Status Register  */
-#define MII_DM9161_10TCSR      18      /* 10BaseT Config/Status Reg.   */
-#define MII_DM9161_INTR                21      /* Interrupt Register           */
-#define MII_DM9161_RECR                22      /* Receive Error Counter Reg.   */
-#define MII_DM9161_DISCR       23      /* Disconnect Counter Register  */
-
-static void dm9161_startup(struct net_device *dev)
-{
-       struct fs_enet_private *fep = netdev_priv(dev);
-
-       fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0000);
-       /* Start autonegotiation */
-       fs_mii_write(dev, fep->mii_if.phy_id, MII_BMCR, 0x1200);
-
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(HZ*8);
-}
-
-static void dm9161_ack_int(struct net_device *dev)
-{
-       struct fs_enet_private *fep = netdev_priv(dev);
-
-       fs_mii_read(dev, fep->mii_if.phy_id, MII_DM9161_INTR);
-}
-
-static void dm9161_shutdown(struct net_device *dev)
-{
-       struct fs_enet_private *fep = netdev_priv(dev);
-
-       fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0f00);
-}
-
-/**********************************************************************************/
-
-static const struct phy_info phy_info[] = {
-       {
-               .id = 0x00181b88,
-               .name = "DM9161",
-               .startup = dm9161_startup,
-               .ack_int = dm9161_ack_int,
-               .shutdown = dm9161_shutdown,
-       }, {
-               .id = 0,
-               .name = "GENERIC",
-               .startup = generic_startup,
-               .shutdown = generic_shutdown,
-       },
-};
-
-/**********************************************************************************/
-
-static int phy_id_detect(struct net_device *dev)
-{
-       struct fs_enet_private *fep = netdev_priv(dev);
-       const struct fs_platform_info *fpi = fep->fpi;
-       struct fs_enet_mii_bus *bus = fep->mii_bus;
-       int i, r, start, end, phytype, physubtype;
-       const struct phy_info *phy;
-       int phy_hwid, phy_id;
-
-       phy_hwid = -1;
-       fep->phy = NULL;
-
-       /* auto-detect? */
-       if (fpi->phy_addr == -1) {
-               start = 1;
-               end = 32;
-       } else {                /* direct */
-               start = fpi->phy_addr;
-               end = start + 1;
-       }
-
-       for (phy_id = start; phy_id < end; phy_id++) {
-               /* skip already used phy addresses on this bus */ 
-               if (bus->usage_map & (1 << phy_id))
-                       continue;
-               r = fs_mii_read(dev, phy_id, MII_PHYSID1);
-               if (r == -1 || (phytype = (r & 0xffff)) == 0xffff)
-                       continue;
-               r = fs_mii_read(dev, phy_id, MII_PHYSID2);
-               if (r == -1 || (physubtype = (r & 0xffff)) == 0xffff)
-                       continue;
-               phy_hwid = (phytype << 16) | physubtype;
-               if (phy_hwid != -1)
-                       break;
-       }
-
-       if (phy_hwid == -1) {
-               printk(KERN_ERR DRV_MODULE_NAME
-                      ": %s No PHY detected! range=0x%02x-0x%02x\n",
-                       dev->name, start, end);
-               return -1;
-       }
-
-       for (i = 0, phy = phy_info; i < ARRAY_SIZE(phy_info); i++, phy++)
-               if (phy->id == (phy_hwid >> 4) || phy->id == 0)
-                       break;
-
-       if (i >= ARRAY_SIZE(phy_info)) {
-               printk(KERN_ERR DRV_MODULE_NAME
-                      ": %s PHY id 0x%08x is not supported!\n",
-                      dev->name, phy_hwid);
-               return -1;
-       }
-
-       fep->phy = phy;
-
-       /* mark this address as used */
-       bus->usage_map |= (1 << phy_id);
-
-       printk(KERN_INFO DRV_MODULE_NAME
-              ": %s Phy @ 0x%x, type %s (0x%08x)%s\n",
-              dev->name, phy_id, fep->phy->name, phy_hwid,
-              fpi->phy_addr == -1 ? " (auto-detected)" : "");
-
-       return phy_id;
-}
-
-void fs_mii_startup(struct net_device *dev)
-{
-       struct fs_enet_private *fep = netdev_priv(dev);
-
-       if (fep->phy->startup)
-               (*fep->phy->startup) (dev);
-}
-
-void fs_mii_shutdown(struct net_device *dev)
-{
-       struct fs_enet_private *fep = netdev_priv(dev);
-
-       if (fep->phy->shutdown)
-               (*fep->phy->shutdown) (dev);
-}
-
-void fs_mii_ack_int(struct net_device *dev)
-{
-       struct fs_enet_private *fep = netdev_priv(dev);
-
-       if (fep->phy->ack_int)
-               (*fep->phy->ack_int) (dev);
-}
-
-#define MII_LINK       0x0001
-#define MII_HALF       0x0002
-#define MII_FULL       0x0004
-#define MII_BASE4      0x0008
-#define MII_10M                0x0010
-#define MII_100M       0x0020
-#define MII_1G         0x0040
-#define MII_10G                0x0080
-
-/* return full mii info at one gulp, with a usable form */
-static unsigned int mii_full_status(struct mii_if_info *mii)
-{
-       unsigned int status;
-       int bmsr, adv, lpa, neg;
-       struct fs_enet_private* fep = netdev_priv(mii->dev);
-       
-       /* first, a dummy read, needed to latch some MII phys */
-       (void)mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
-       bmsr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
-
-       /* no link */
-       if ((bmsr & BMSR_LSTATUS) == 0)
-               return 0;
-
-       status = MII_LINK;
-       
-       /* Lets look what ANEG says if it's supported - otherwize we shall
-          take the right values from the platform info*/
-       if(!mii->force_media) {
-               /* autoneg not completed; don't bother */
-               if ((bmsr & BMSR_ANEGCOMPLETE) == 0)
-                       return 0;
-
-               adv = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_ADVERTISE);
-               lpa = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_LPA);
-
-               neg = lpa & adv;
-       } else {
-               neg = fep->fpi->bus_info->lpa;
-       }
-
-       if (neg & LPA_100FULL)
-               status |= MII_FULL | MII_100M;
-       else if (neg & LPA_100BASE4)
-               status |= MII_FULL | MII_BASE4 | MII_100M;
-       else if (neg & LPA_100HALF)
-               status |= MII_HALF | MII_100M;
-       else if (neg & LPA_10FULL)
-               status |= MII_FULL | MII_10M;
-       else
-               status |= MII_HALF | MII_10M;
-       
-       return status;
-}
-
-void fs_mii_link_status_change_check(struct net_device *dev, int init_media)
-{
-       struct fs_enet_private *fep = netdev_priv(dev);
-       struct mii_if_info *mii = &fep->mii_if;
-       unsigned int mii_status;
-       int ok_to_print, link, duplex, speed;
-       unsigned long flags;
-
-       ok_to_print = netif_msg_link(fep);
-
-       mii_status = mii_full_status(mii);
-
-       if (!init_media && mii_status == fep->last_mii_status)
-               return;
-
-       fep->last_mii_status = mii_status;
-
-       link = !!(mii_status & MII_LINK);
-       duplex = !!(mii_status & MII_FULL);
-       speed = (mii_status & MII_100M) ? 100 : 10;
-
-       if (link == 0) {
-               netif_carrier_off(mii->dev);
-               netif_stop_queue(dev);
-               if (!init_media) {
-                       spin_lock_irqsave(&fep->lock, flags);
-                       (*fep->ops->stop)(dev);
-                       spin_unlock_irqrestore(&fep->lock, flags);
-               }
-
-               if (ok_to_print)
-                       printk(KERN_INFO "%s: link down\n", mii->dev->name);
-
-       } else {
-
-               mii->full_duplex = duplex;
-
-               netif_carrier_on(mii->dev);
-
-               spin_lock_irqsave(&fep->lock, flags);
-               fep->duplex = duplex;
-               fep->speed = speed;
-               (*fep->ops->restart)(dev);
-               spin_unlock_irqrestore(&fep->lock, flags);
-
-               netif_start_queue(dev);
-
-               if (ok_to_print)
-                       printk(KERN_INFO "%s: link up, %dMbps, %s-duplex\n",
-                              dev->name, speed, duplex ? "full" : "half");
-       }
-}
-
-/**********************************************************************************/
-
-int fs_mii_read(struct net_device *dev, int phy_id, int location)
-{
-       struct fs_enet_private *fep = netdev_priv(dev);
-       struct fs_enet_mii_bus *bus = fep->mii_bus;
-
-       unsigned long flags;
-       int ret;
-
-       spin_lock_irqsave(&bus->mii_lock, flags);
-       ret = (*bus->mii_read)(bus, phy_id, location);
-       spin_unlock_irqrestore(&bus->mii_lock, flags);
-
-       return ret;
-}
-
-void fs_mii_write(struct net_device *dev, int phy_id, int location, int value)
-{
-       struct fs_enet_private *fep = netdev_priv(dev);
-       struct fs_enet_mii_bus *bus = fep->mii_bus;
-       unsigned long flags;
-
-       spin_lock_irqsave(&bus->mii_lock, flags);
-       (*bus->mii_write)(bus, phy_id, location, value);
-       spin_unlock_irqrestore(&bus->mii_lock, flags);
-}
-
-/*****************************************************************************/
-
-/* list of all registered mii buses */
-static LIST_HEAD(fs_mii_bus_list);
-
-static struct fs_enet_mii_bus *lookup_bus(int method, int id)
-{
-       struct list_head *ptr;
-       struct fs_enet_mii_bus *bus;
-
-       list_for_each(ptr, &fs_mii_bus_list) {
-               bus = list_entry(ptr, struct fs_enet_mii_bus, list);
-               if (bus->bus_info->method == method &&
-                       bus->bus_info->id == id)
-                       return bus;
-       }
-       return NULL;
-}
-
-static struct fs_enet_mii_bus *create_bus(const struct fs_mii_bus_info *bi)
-{
-       struct fs_enet_mii_bus *bus;
-       int ret = 0;
-
-       bus = kmalloc(sizeof(*bus), GFP_KERNEL);
-       if (bus == NULL) {
-               ret = -ENOMEM;
-               goto err;
-       }
-       memset(bus, 0, sizeof(*bus));
-       spin_lock_init(&bus->mii_lock);
-       bus->bus_info = bi;
-       bus->refs = 0;
-       bus->usage_map = 0;
-
-       /* perform initialization */
-       switch (bi->method) {
-
-               case fsmii_fixed:
-                       ret = fs_mii_fixed_init(bus);
-                       if (ret != 0)
-                               goto err;
-                       break;
-
-               case fsmii_bitbang:
-                       ret = fs_mii_bitbang_init(bus);
-                       if (ret != 0)
-                               goto err;
-                       break;
-#ifdef CONFIG_FS_ENET_HAS_FEC
-               case fsmii_fec:
-                       ret = fs_mii_fec_init(bus);
-                       if (ret != 0)
-                               goto err;
-                       break;
-#endif
-               default:
-                       ret = -EINVAL;
-                       goto err;
-       }
-
-       list_add(&bus->list, &fs_mii_bus_list);
-
-       return bus;
-
-err:
-       kfree(bus);
-       return ERR_PTR(ret);
-}
-
-static void destroy_bus(struct fs_enet_mii_bus *bus)
-{
-       /* remove from bus list */
-       list_del(&bus->list);
-
-       /* nothing more needed */
-       kfree(bus);
-}
-
-int fs_mii_connect(struct net_device *dev)
-{
-       struct fs_enet_private *fep = netdev_priv(dev);
-       const struct fs_platform_info *fpi = fep->fpi;
-       struct fs_enet_mii_bus *bus = NULL;
-
-       /* check method validity */
-       switch (fpi->bus_info->method) {
-               case fsmii_fixed:
-               case fsmii_bitbang:
-                       break;
-#ifdef CONFIG_FS_ENET_HAS_FEC
-               case fsmii_fec:
-                       break;
-#endif
-               default:
-                       printk(KERN_ERR DRV_MODULE_NAME
-                              ": %s Unknown MII bus method (%d)!\n",
-                              dev->name, fpi->bus_info->method);
-                       return -EINVAL; 
-       }
-
-       bus = lookup_bus(fpi->bus_info->method, fpi->bus_info->id);
-
-       /* if not found create new bus */
-       if (bus == NULL) {
-               bus = create_bus(fpi->bus_info);
-               if (IS_ERR(bus)) {
-                       printk(KERN_ERR DRV_MODULE_NAME
-                              ": %s MII bus creation failure!\n", dev->name);
-                       return PTR_ERR(bus);
-               }
-       }
-
-       bus->refs++;
-
-       fep->mii_bus = bus;
-
-       fep->mii_if.dev = dev;
-       fep->mii_if.phy_id_mask = 0x1f;
-       fep->mii_if.reg_num_mask = 0x1f;
-       fep->mii_if.mdio_read = fs_mii_read;
-       fep->mii_if.mdio_write = fs_mii_write;
-       fep->mii_if.force_media = fpi->bus_info->disable_aneg;
-       fep->mii_if.phy_id = phy_id_detect(dev);
-
-       return 0;
-}
-
-void fs_mii_disconnect(struct net_device *dev)
-{
-       struct fs_enet_private *fep = netdev_priv(dev);
-       struct fs_enet_mii_bus *bus = NULL;
-
-       bus = fep->mii_bus;
-       fep->mii_bus = NULL;
-
-       if (--bus->refs <= 0)
-               destroy_bus(bus);
-}
index e7ec96c964a9fa0a3c2ee2a6f87a9badf46aef28..95022c005f75cb3497f269476b00657e87b4c493 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/netdevice.h>
 #include <linux/types.h>
 #include <linux/list.h>
+#include <linux/phy.h>
 
 #include <linux/fs_enet_pd.h>
 
 
 #ifdef CONFIG_CPM1
 #include <asm/commproc.h>
+
+struct fec_info {
+        fec_t*  fecp;
+       u32     mii_speed;
+};
 #endif
 
 #ifdef CONFIG_CPM2
 #include <asm/cpm2.h>
 #endif
 
+/* This is used to operate with pins.
+  Note that the actual port size may
+    be different; cpm(s) handle it OK  */
+struct bb_info {
+       u8 mdio_dat_msk;
+       u8 mdio_dir_msk;
+       u8 *mdio_dir;
+       u8 *mdio_dat;
+       u8 mdc_msk;
+       u8 *mdc_dat;
+       int delay;
+};
+
 /* hw driver ops */
 struct fs_ops {
        int (*setup_data)(struct net_device *dev);
@@ -25,6 +44,7 @@ struct fs_ops {
        void (*free_bd)(struct net_device *dev);
        void (*cleanup_data)(struct net_device *dev);
        void (*set_multicast_list)(struct net_device *dev);
+       void (*adjust_link)(struct net_device *dev);
        void (*restart)(struct net_device *dev);
        void (*stop)(struct net_device *dev);
        void (*pre_request_irq)(struct net_device *dev, int irq);
@@ -100,10 +120,6 @@ struct fs_enet_mii_bus {
        };
 };
 
-int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus);
-int fs_mii_fixed_init(struct fs_enet_mii_bus *bus);
-int fs_mii_fec_init(struct fs_enet_mii_bus *bus);
-
 struct fs_enet_private {
        struct device *dev;     /* pointer back to the device (must be initialized first) */
        spinlock_t lock;        /* during all ops except TX pckt processing */
@@ -130,7 +146,8 @@ struct fs_enet_private {
        struct fs_enet_mii_bus *mii_bus;
        int interrupt;
 
-       int duplex, speed;      /* current settings */
+       struct phy_device *phydev;
+       int oldduplex, oldspeed, oldlink;       /* current settings */
 
        /* event masks */
        u32 ev_napi_rx;         /* mask of NAPI rx events */
@@ -168,15 +185,9 @@ struct fs_enet_private {
 };
 
 /***************************************************************************/
-
-int fs_mii_read(struct net_device *dev, int phy_id, int location);
-void fs_mii_write(struct net_device *dev, int phy_id, int location, int value);
-
-void fs_mii_startup(struct net_device *dev);
-void fs_mii_shutdown(struct net_device *dev);
-void fs_mii_ack_int(struct net_device *dev);
-
-void fs_mii_link_status_change_check(struct net_device *dev, int init_media);
+int fs_enet_mdio_bb_init(void);
+int fs_mii_fixed_init(struct fs_enet_mii_bus *bus);
+int fs_enet_mdio_fec_init(void);
 
 void fs_init_bds(struct net_device *dev);
 void fs_cleanup_bds(struct net_device *dev);
@@ -194,7 +205,6 @@ int fs_enet_platform_init(void);
 void fs_enet_platform_cleanup(void);
 
 /***************************************************************************/
-
 /* buffer descriptor access macros */
 
 /* access macros */
index 64e20982c1fedc66a136eeb72893a1055cc0fa2c..1ff2597b8495b7fbd54d5a8d62a3ea11e7c1a623 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/bitops.h>
 #include <linux/fs.h>
 #include <linux/platform_device.h>
+#include <linux/phy.h>
 
 #include <asm/immap_cpm2.h>
 #include <asm/mpc8260.h>
@@ -122,22 +123,32 @@ static int do_pd_setup(struct fs_enet_private *fep)
 
        /* Attach the memory for the FCC Parameter RAM */
        r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_pram");
-       fep->fcc.ep = (void *)r->start;
-
+       fep->fcc.ep = (void *)ioremap(r->start, r->end - r->start + 1);
        if (fep->fcc.ep == NULL)
                return -EINVAL;
 
        r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_regs");
-       fep->fcc.fccp = (void *)r->start;
-
+       fep->fcc.fccp = (void *)ioremap(r->start, r->end - r->start + 1);
        if (fep->fcc.fccp == NULL)
                return -EINVAL;
 
-       fep->fcc.fcccp = (void *)fep->fpi->fcc_regs_c;
+       if (fep->fpi->fcc_regs_c) {
+
+               fep->fcc.fcccp = (void *)fep->fpi->fcc_regs_c;
+       } else {
+               r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                               "fcc_regs_c");
+               fep->fcc.fcccp = (void *)ioremap(r->start,
+                               r->end - r->start + 1);
+       }
 
        if (fep->fcc.fcccp == NULL)
                return -EINVAL;
 
+       fep->fcc.mem = (void *)fep->fpi->mem_offset;
+       if (fep->fcc.mem == NULL)
+               return -EINVAL;
+
        return 0;
 }
 
@@ -155,8 +166,6 @@ static int setup_data(struct net_device *dev)
        if ((unsigned int)fep->fcc.idx >= 3)    /* max 3 FCCs */
                return -EINVAL;
 
-       fep->fcc.mem = (void *)fpi->mem_offset;
-
        if (do_pd_setup(fep) != 0)
                return -EINVAL;
 
@@ -394,7 +403,7 @@ static void restart(struct net_device *dev)
 
        /* adjust to speed (for RMII mode) */
        if (fpi->use_rmii) {
-               if (fep->speed == 100)
+               if (fep->phydev->speed == 100)
                        C8(fcccp, fcc_gfemr, 0x20);
                else
                        S8(fcccp, fcc_gfemr, 0x20);
@@ -420,7 +429,7 @@ static void restart(struct net_device *dev)
                S32(fccp, fcc_fpsmr, FCC_PSMR_RMII);
 
        /* adjust to duplex mode */
-       if (fep->duplex)
+       if (fep->phydev->duplex)
                S32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
        else
                C32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
@@ -486,7 +495,10 @@ static void rx_bd_done(struct net_device *dev)
 
 static void tx_kickstart(struct net_device *dev)
 {
-       /* nothing */
+       struct fs_enet_private *fep = netdev_priv(dev);
+       fcc_t *fccp = fep->fcc.fccp;
+
+       S32(fccp, fcc_ftodr, 0x80);
 }
 
 static u32 get_int_events(struct net_device *dev)
index e09547077529c917bbdb318e0e455ddde363bb45..c2c5fd419bd0a3b642c5da5ac6d91dbe62942bd6 100644 (file)
@@ -46,6 +46,7 @@
 #endif
 
 #include "fs_enet.h"
+#include "fec.h"
 
 /*************************************************/
 
 /* clear bits */
 #define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v))
 
-
-/* CRC polynomium used by the FEC for the multicast group filtering */
-#define FEC_CRC_POLY   0x04C11DB7
-
-#define FEC_MAX_MULTICAST_ADDRS        64
-
-/* Interrupt events/masks.
-*/
-#define FEC_ENET_HBERR 0x80000000U     /* Heartbeat error          */
-#define FEC_ENET_BABR  0x40000000U     /* Babbling receiver        */
-#define FEC_ENET_BABT  0x20000000U     /* Babbling transmitter     */
-#define FEC_ENET_GRA   0x10000000U     /* Graceful stop complete   */
-#define FEC_ENET_TXF   0x08000000U     /* Full frame transmitted   */
-#define FEC_ENET_TXB   0x04000000U     /* A buffer was transmitted */
-#define FEC_ENET_RXF   0x02000000U     /* Full frame received      */
-#define FEC_ENET_RXB   0x01000000U     /* A buffer was received    */
-#define FEC_ENET_MII   0x00800000U     /* MII interrupt            */
-#define FEC_ENET_EBERR 0x00400000U     /* SDMA bus error           */
-
-#define FEC_ECNTRL_PINMUX      0x00000004
-#define FEC_ECNTRL_ETHER_EN    0x00000002
-#define FEC_ECNTRL_RESET       0x00000001
-
-#define FEC_RCNTRL_BC_REJ      0x00000010
-#define FEC_RCNTRL_PROM                0x00000008
-#define FEC_RCNTRL_MII_MODE    0x00000004
-#define FEC_RCNTRL_DRT         0x00000002
-#define FEC_RCNTRL_LOOP                0x00000001
-
-#define FEC_TCNTRL_FDEN                0x00000004
-#define FEC_TCNTRL_HBC         0x00000002
-#define FEC_TCNTRL_GTS         0x00000001
-
-
-/* Make MII read/write commands for the FEC.
-*/
-#define mk_mii_read(REG)       (0x60020000 | ((REG & 0x1f) << 18))
-#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
-#define mk_mii_end             0
-
-#define FEC_MII_LOOPS  10000
-
 /*
- * Delay to wait for FEC reset command to complete (in us) 
+ * Delay to wait for FEC reset command to complete (in us)
  */
 #define FEC_RESET_DELAY                50
 
@@ -303,13 +262,15 @@ static void restart(struct net_device *dev)
        int r;
        u32 addrhi, addrlo;
 
+       struct mii_bus* mii = fep->phydev->bus;
+       struct fec_info* fec_inf = mii->priv;
+
        r = whack_reset(fep->fec.fecp);
        if (r != 0)
                printk(KERN_ERR DRV_MODULE_NAME
                                ": %s FEC Reset FAILED!\n", dev->name);
-
        /*
-        * Set station address. 
+        * Set station address.
         */
        addrhi = ((u32) dev->dev_addr[0] << 24) |
                 ((u32) dev->dev_addr[1] << 16) |
@@ -350,12 +311,12 @@ static void restart(struct net_device *dev)
        FW(fecp, fun_code, 0x78000000);
 
        /*
-        * Set MII speed. 
+        * Set MII speed.
         */
-       FW(fecp, mii_speed, fep->mii_bus->fec.mii_speed);
+       FW(fecp, mii_speed, fec_inf->mii_speed);
 
        /*
-        * Clear any outstanding interrupt. 
+        * Clear any outstanding interrupt.
         */
        FW(fecp, ievent, 0xffc0);
        FW(fecp, ivec, (fep->interrupt / 2) << 29);
@@ -390,11 +351,12 @@ static void restart(struct net_device *dev)
        }
 #endif
 
+
        FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
        /*
-        * adjust to duplex mode 
+        * adjust to duplex mode
         */
-       if (fep->duplex) {
+       if (fep->phydev->duplex) {
                FC(fecp, r_cntrl, FEC_RCNTRL_DRT);
                FS(fecp, x_cntrl, FEC_TCNTRL_FDEN);     /* FD enable */
        } else {
@@ -418,9 +380,11 @@ static void restart(struct net_device *dev)
 static void stop(struct net_device *dev)
 {
        struct fs_enet_private *fep = netdev_priv(dev);
+       const struct fs_platform_info *fpi = fep->fpi;
        fec_t *fecp = fep->fec.fecp;
-       struct fs_enet_mii_bus *bus = fep->mii_bus;
-       const struct fs_mii_bus_info *bi = bus->bus_info;
+
+       struct fec_info* feci= fep->phydev->bus->priv;
+
        int i;
 
        if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0)
@@ -444,11 +408,11 @@ static void stop(struct net_device *dev)
        fs_cleanup_bds(dev);
 
        /* shut down FEC1? that's where the mii bus is */
-       if (fep->fec.idx == 0 && bus->refs > 1 && bi->method == fsmii_fec) {
+       if (fpi->has_phy) {
                FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
                FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
                FW(fecp, ievent, FEC_ENET_MII);
-               FW(fecp, mii_speed, bus->fec.mii_speed);
+               FW(fecp, mii_speed, feci->mii_speed);
        }
 }
 
@@ -583,73 +547,3 @@ const struct fs_ops fs_fec_ops = {
        .free_bd                = free_bd,
 };
 
-/***********************************************************************/
-
-static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
-{
-       fec_t *fecp = bus->fec.fecp;
-       int i, ret = -1;
-
-       if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
-               BUG();
-
-       /* Add PHY address to register command.  */
-       FW(fecp, mii_data, (phy_id << 23) | mk_mii_read(location));
-
-       for (i = 0; i < FEC_MII_LOOPS; i++)
-               if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
-                       break;
-
-       if (i < FEC_MII_LOOPS) {
-               FW(fecp, ievent, FEC_ENET_MII);
-               ret = FR(fecp, mii_data) & 0xffff;
-       }
-
-       return ret;
-}
-
-static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int value)
-{
-       fec_t *fecp = bus->fec.fecp;
-       int i;
-
-       /* this must never happen */
-       if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
-               BUG();
-
-       /* Add PHY address to register command.  */
-       FW(fecp, mii_data, (phy_id << 23) | mk_mii_write(location, value));
-
-       for (i = 0; i < FEC_MII_LOOPS; i++)
-               if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
-                       break;
-
-       if (i < FEC_MII_LOOPS)
-               FW(fecp, ievent, FEC_ENET_MII);
-}
-
-int fs_mii_fec_init(struct fs_enet_mii_bus *bus)
-{
-       bd_t *bd = (bd_t *)__res;
-       const struct fs_mii_bus_info *bi = bus->bus_info;
-       fec_t *fecp;
-
-       if (bi->id != 0)
-               return -1;
-
-       bus->fec.fecp = &((immap_t *)fs_enet_immap)->im_cpm.cp_fec;
-       bus->fec.mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2)
-                               & 0x3F) << 1;
-
-       fecp = bus->fec.fecp;
-
-       FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
-       FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
-       FW(fecp, ievent, FEC_ENET_MII);
-       FW(fecp, mii_speed, bus->fec.mii_speed);
-
-       bus->mii_read = mii_read;
-       bus->mii_write = mii_write;
-
-       return 0;
-}
index eaa24fab645fb5b3e906af00943fabd26005d6ec..95ec5872c5071bdb2d3b8bf25e8819249b93591e 100644 (file)
@@ -369,7 +369,7 @@ static void restart(struct net_device *dev)
        W16(sccp, scc_psmr, SCC_PSMR_ENCRC | SCC_PSMR_NIB22);
 
        /* Set full duplex mode if needed */
-       if (fep->duplex)
+       if (fep->phydev->duplex)
                S16(sccp, scc_psmr, SCC_PSMR_LPB | SCC_PSMR_FDE);
 
        S32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
@@ -500,6 +500,8 @@ static void tx_restart(struct net_device *dev)
        scc_cr_cmd(fep, CPM_CR_RESTART_TX);
 }
 
+
+
 /*************************************************************************/
 
 const struct fs_ops fs_scc_ops = {
index 48f9cf83ab6f4e857aa0fbf30daa47f8ace08898..0b9b8b5c847cee9597c31e4e9c3dfff9c54d5322 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/bitops.h>
+#include <linux/platform_device.h>
 
 #include <asm/pgtable.h>
 #include <asm/irq.h>
 
 #include "fs_enet.h"
 
-#ifdef CONFIG_8xx
-static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit)
+static int bitbang_prep_bit(u8 **datp, u8 *mskp,
+               struct fs_mii_bit *mii_bit)
 {
-       immap_t *im = (immap_t *)fs_enet_immap;
-       void *dir, *dat, *ppar;
+       void *dat;
        int adv;
        u8 msk;
 
-       switch (port) {
-               case fsiop_porta:
-                       dir = &im->im_ioport.iop_padir;
-                       dat = &im->im_ioport.iop_padat;
-                       ppar = &im->im_ioport.iop_papar;
-                       break;
-
-               case fsiop_portb:
-                       dir = &im->im_cpm.cp_pbdir;
-                       dat = &im->im_cpm.cp_pbdat;
-                       ppar = &im->im_cpm.cp_pbpar;
-                       break;
-
-               case fsiop_portc:
-                       dir = &im->im_ioport.iop_pcdir;
-                       dat = &im->im_ioport.iop_pcdat;
-                       ppar = &im->im_ioport.iop_pcpar;
-                       break;
-
-               case fsiop_portd:
-                       dir = &im->im_ioport.iop_pddir;
-                       dat = &im->im_ioport.iop_pddat;
-                       ppar = &im->im_ioport.iop_pdpar;
-                       break;
-
-               case fsiop_porte:
-                       dir = &im->im_cpm.cp_pedir;
-                       dat = &im->im_cpm.cp_pedat;
-                       ppar = &im->im_cpm.cp_pepar;
-                       break;
-
-               default:
-                       printk(KERN_ERR DRV_MODULE_NAME
-                              "Illegal port value %d!\n", port);
-                       return -EINVAL;
-       }
-
-       adv = bit >> 3;
-       dir = (char *)dir + adv;
-       dat = (char *)dat + adv;
-       ppar = (char *)ppar + adv;
-
-       msk = 1 << (7 - (bit & 7));
-       if ((in_8(ppar) & msk) != 0) {
-               printk(KERN_ERR DRV_MODULE_NAME
-                      "pin %d on port %d is not general purpose!\n", bit, port);
-               return -EINVAL;
-       }
-
-       *dirp = dir;
-       *datp = dat;
-       *mskp = msk;
-
-       return 0;
-}
-#endif
-
-#ifdef CONFIG_8260
-static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit)
-{
-       iop_cpm2_t *io = &((cpm2_map_t *)fs_enet_immap)->im_ioport;
-       void *dir, *dat, *ppar;
-       int adv;
-       u8 msk;
-
-       switch (port) {
-               case fsiop_porta:
-                       dir = &io->iop_pdira;
-                       dat = &io->iop_pdata;
-                       ppar = &io->iop_ppara;
-                       break;
-
-               case fsiop_portb:
-                       dir = &io->iop_pdirb;
-                       dat = &io->iop_pdatb;
-                       ppar = &io->iop_pparb;
-                       break;
-
-               case fsiop_portc:
-                       dir = &io->iop_pdirc;
-                       dat = &io->iop_pdatc;
-                       ppar = &io->iop_pparc;
-                       break;
-
-               case fsiop_portd:
-                       dir = &io->iop_pdird;
-                       dat = &io->iop_pdatd;
-                       ppar = &io->iop_ppard;
-                       break;
-
-               default:
-                       printk(KERN_ERR DRV_MODULE_NAME
-                              "Illegal port value %d!\n", port);
-                       return -EINVAL;
-       }
+       dat = (void*) mii_bit->offset;
 
-       adv = bit >> 3;
-       dir = (char *)dir + adv;
+       adv = mii_bit->bit >> 3;
        dat = (char *)dat + adv;
-       ppar = (char *)ppar + adv;
 
-       msk = 1 << (7 - (bit & 7));
-       if ((in_8(ppar) & msk) != 0) {
-               printk(KERN_ERR DRV_MODULE_NAME
-                      "pin %d on port %d is not general purpose!\n", bit, port);
-               return -EINVAL;
-       }
+       msk = 1 << (7 - (mii_bit->bit & 7));
 
-       *dirp = dir;
        *datp = dat;
        *mskp = msk;
 
        return 0;
 }
-#endif
 
 static inline void bb_set(u8 *p, u8 m)
 {
@@ -179,44 +76,44 @@ static inline int bb_read(u8 *p, u8 m)
        return (in_8(p) & m) != 0;
 }
 
-static inline void mdio_active(struct fs_enet_mii_bus *bus)
+static inline void mdio_active(struct bb_info *bitbang)
 {
-       bb_set(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
+       bb_set(bitbang->mdio_dir, bitbang->mdio_dir_msk);
 }
 
-static inline void mdio_tristate(struct fs_enet_mii_bus *bus)
+static inline void mdio_tristate(struct bb_info *bitbang )
 {
-       bb_clr(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
+       bb_clr(bitbang->mdio_dir, bitbang->mdio_dir_msk);
 }
 
-static inline int mdio_read(struct fs_enet_mii_bus *bus)
+static inline int mdio_read(struct bb_info *bitbang )
 {
-       return bb_read(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+       return bb_read(bitbang->mdio_dat, bitbang->mdio_dat_msk);
 }
 
-static inline void mdio(struct fs_enet_mii_bus *bus, int what)
+static inline void mdio(struct bb_info *bitbang , int what)
 {
        if (what)
-               bb_set(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+               bb_set(bitbang->mdio_dat, bitbang->mdio_dat_msk);
        else
-               bb_clr(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+               bb_clr(bitbang->mdio_dat, bitbang->mdio_dat_msk);
 }
 
-static inline void mdc(struct fs_enet_mii_bus *bus, int what)
+static inline void mdc(struct bb_info *bitbang , int what)
 {
        if (what)
-               bb_set(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
+               bb_set(bitbang->mdc_dat, bitbang->mdc_msk);
        else
-               bb_clr(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
+               bb_clr(bitbang->mdc_dat, bitbang->mdc_msk);
 }
 
-static inline void mii_delay(struct fs_enet_mii_bus *bus)
+static inline void mii_delay(struct bb_info *bitbang )
 {
-       udelay(bus->bus_info->i.bitbang.delay);
+       udelay(bitbang->delay);
 }
 
 /* Utility to send the preamble, address, and register (common to read and write). */
-static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg)
+static void bitbang_pre(struct bb_info *bitbang , int read, u8 addr, u8 reg)
 {
        int j;
 
@@ -228,177 +125,284 @@ static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg)
         * but it is safer and will be much more robust.
         */
 
-       mdio_active(bus);
-       mdio(bus, 1);
+       mdio_active(bitbang);
+       mdio(bitbang, 1);
        for (j = 0; j < 32; j++) {
-               mdc(bus, 0);
-               mii_delay(bus);
-               mdc(bus, 1);
-               mii_delay(bus);
+               mdc(bitbang, 0);
+               mii_delay(bitbang);
+               mdc(bitbang, 1);
+               mii_delay(bitbang);
        }
 
        /* send the start bit (01) and the read opcode (10) or write (10) */
-       mdc(bus, 0);
-       mdio(bus, 0);
-       mii_delay(bus);
-       mdc(bus, 1);
-       mii_delay(bus);
-       mdc(bus, 0);
-       mdio(bus, 1);
-       mii_delay(bus);
-       mdc(bus, 1);
-       mii_delay(bus);
-       mdc(bus, 0);
-       mdio(bus, read);
-       mii_delay(bus);
-       mdc(bus, 1);
-       mii_delay(bus);
-       mdc(bus, 0);
-       mdio(bus, !read);
-       mii_delay(bus);
-       mdc(bus, 1);
-       mii_delay(bus);
+       mdc(bitbang, 0);
+       mdio(bitbang, 0);
+       mii_delay(bitbang);
+       mdc(bitbang, 1);
+       mii_delay(bitbang);
+       mdc(bitbang, 0);
+       mdio(bitbang, 1);
+       mii_delay(bitbang);
+       mdc(bitbang, 1);
+       mii_delay(bitbang);
+       mdc(bitbang, 0);
+       mdio(bitbang, read);
+       mii_delay(bitbang);
+       mdc(bitbang, 1);
+       mii_delay(bitbang);
+       mdc(bitbang, 0);
+       mdio(bitbang, !read);
+       mii_delay(bitbang);
+       mdc(bitbang, 1);
+       mii_delay(bitbang);
 
        /* send the PHY address */
        for (j = 0; j < 5; j++) {
-               mdc(bus, 0);
-               mdio(bus, (addr & 0x10) != 0);
-               mii_delay(bus);
-               mdc(bus, 1);
-               mii_delay(bus);
+               mdc(bitbang, 0);
+               mdio(bitbang, (addr & 0x10) != 0);
+               mii_delay(bitbang);
+               mdc(bitbang, 1);
+               mii_delay(bitbang);
                addr <<= 1;
        }
 
        /* send the register address */
        for (j = 0; j < 5; j++) {
-               mdc(bus, 0);
-               mdio(bus, (reg & 0x10) != 0);
-               mii_delay(bus);
-               mdc(bus, 1);
-               mii_delay(bus);
+               mdc(bitbang, 0);
+               mdio(bitbang, (reg & 0x10) != 0);
+               mii_delay(bitbang);
+               mdc(bitbang, 1);
+               mii_delay(bitbang);
                reg <<= 1;
        }
 }
 
-static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
+static int fs_enet_mii_bb_read(struct mii_bus *bus , int phy_id, int location)
 {
        u16 rdreg;
        int ret, j;
        u8 addr = phy_id & 0xff;
        u8 reg = location & 0xff;
+       struct bb_info* bitbang = bus->priv;
 
-       bitbang_pre(bus, 1, addr, reg);
+       bitbang_pre(bitbang, 1, addr, reg);
 
        /* tri-state our MDIO I/O pin so we can read */
-       mdc(bus, 0);
-       mdio_tristate(bus);
-       mii_delay(bus);
-       mdc(bus, 1);
-       mii_delay(bus);
+       mdc(bitbang, 0);
+       mdio_tristate(bitbang);
+       mii_delay(bitbang);
+       mdc(bitbang, 1);
+       mii_delay(bitbang);
 
        /* check the turnaround bit: the PHY should be driving it to zero */
-       if (mdio_read(bus) != 0) {
+       if (mdio_read(bitbang) != 0) {
                /* PHY didn't drive TA low */
                for (j = 0; j < 32; j++) {
-                       mdc(bus, 0);
-                       mii_delay(bus);
-                       mdc(bus, 1);
-                       mii_delay(bus);
+                       mdc(bitbang, 0);
+                       mii_delay(bitbang);
+                       mdc(bitbang, 1);
+                       mii_delay(bitbang);
                }
                ret = -1;
                goto out;
        }
 
-       mdc(bus, 0);
-       mii_delay(bus);
+       mdc(bitbang, 0);
+       mii_delay(bitbang);
 
        /* read 16 bits of register data, MSB first */
        rdreg = 0;
        for (j = 0; j < 16; j++) {
-               mdc(bus, 1);
-               mii_delay(bus);
+               mdc(bitbang, 1);
+               mii_delay(bitbang);
                rdreg <<= 1;
-               rdreg |= mdio_read(bus);
-               mdc(bus, 0);
-               mii_delay(bus);
+               rdreg |= mdio_read(bitbang);
+               mdc(bitbang, 0);
+               mii_delay(bitbang);
        }
 
-       mdc(bus, 1);
-       mii_delay(bus);
-       mdc(bus, 0);
-       mii_delay(bus);
-       mdc(bus, 1);
-       mii_delay(bus);
+       mdc(bitbang, 1);
+       mii_delay(bitbang);
+       mdc(bitbang, 0);
+       mii_delay(bitbang);
+       mdc(bitbang, 1);
+       mii_delay(bitbang);
 
        ret = rdreg;
 out:
        return ret;
 }
 
-static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val)
+static int fs_enet_mii_bb_write(struct mii_bus *bus, int phy_id, int location, u16 val)
 {
        int j;
+       struct bb_info* bitbang = bus->priv;
+
        u8 addr = phy_id & 0xff;
        u8 reg = location & 0xff;
        u16 value = val & 0xffff;
 
-       bitbang_pre(bus, 0, addr, reg);
+       bitbang_pre(bitbang, 0, addr, reg);
 
        /* send the turnaround (10) */
-       mdc(bus, 0);
-       mdio(bus, 1);
-       mii_delay(bus);
-       mdc(bus, 1);
-       mii_delay(bus);
-       mdc(bus, 0);
-       mdio(bus, 0);
-       mii_delay(bus);
-       mdc(bus, 1);
-       mii_delay(bus);
+       mdc(bitbang, 0);
+       mdio(bitbang, 1);
+       mii_delay(bitbang);
+       mdc(bitbang, 1);
+       mii_delay(bitbang);
+       mdc(bitbang, 0);
+       mdio(bitbang, 0);
+       mii_delay(bitbang);
+       mdc(bitbang, 1);
+       mii_delay(bitbang);
 
        /* write 16 bits of register data, MSB first */
        for (j = 0; j < 16; j++) {
-               mdc(bus, 0);
-               mdio(bus, (value & 0x8000) != 0);
-               mii_delay(bus);
-               mdc(bus, 1);
-               mii_delay(bus);
+               mdc(bitbang, 0);
+               mdio(bitbang, (value & 0x8000) != 0);
+               mii_delay(bitbang);
+               mdc(bitbang, 1);
+               mii_delay(bitbang);
                value <<= 1;
        }
 
        /*
         * Tri-state the MDIO line.
         */
-       mdio_tristate(bus);
-       mdc(bus, 0);
-       mii_delay(bus);
-       mdc(bus, 1);
-       mii_delay(bus);
+       mdio_tristate(bitbang);
+       mdc(bitbang, 0);
+       mii_delay(bitbang);
+       mdc(bitbang, 1);
+       mii_delay(bitbang);
+       return 0;
 }
 
-int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus)
+static int fs_enet_mii_bb_reset(struct mii_bus *bus)
+{
+       /*nothing here - dunno how to reset it*/
+       return 0;
+}
+
+static int fs_mii_bitbang_init(struct bb_info *bitbang, struct fs_mii_bb_platform_info* fmpi)
 {
-       const struct fs_mii_bus_info *bi = bus->bus_info;
        int r;
 
-       r = bitbang_prep_bit(&bus->bitbang.mdio_dir,
-                        &bus->bitbang.mdio_dat,
-                        &bus->bitbang.mdio_msk,
-                        bi->i.bitbang.mdio_port,
-                        bi->i.bitbang.mdio_bit);
+       bitbang->delay = fmpi->delay;
+
+       r = bitbang_prep_bit(&bitbang->mdio_dir,
+                        &bitbang->mdio_dir_msk,
+                        &fmpi->mdio_dir);
        if (r != 0)
                return r;
 
-       r = bitbang_prep_bit(&bus->bitbang.mdc_dir,
-                        &bus->bitbang.mdc_dat,
-                        &bus->bitbang.mdc_msk,
-                        bi->i.bitbang.mdc_port,
-                        bi->i.bitbang.mdc_bit);
+       r = bitbang_prep_bit(&bitbang->mdio_dat,
+                        &bitbang->mdio_dat_msk,
+                        &fmpi->mdio_dat);
        if (r != 0)
                return r;
 
-       bus->mii_read = mii_read;
-       bus->mii_write = mii_write;
+       r = bitbang_prep_bit(&bitbang->mdc_dat,
+                        &bitbang->mdc_msk,
+                        &fmpi->mdc_dat);
+       if (r != 0)
+               return r;
 
        return 0;
 }
+
+
+static int __devinit fs_enet_mdio_probe(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct fs_mii_bb_platform_info *pdata;
+       struct mii_bus *new_bus;
+       struct bb_info *bitbang;
+       int err = 0;
+
+       if (NULL == dev)
+               return -EINVAL;
+
+       new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+       if (NULL == new_bus)
+               return -ENOMEM;
+
+       bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
+
+       if (NULL == bitbang)
+               return -ENOMEM;
+
+       new_bus->name = "BB MII Bus",
+       new_bus->read = &fs_enet_mii_bb_read,
+       new_bus->write = &fs_enet_mii_bb_write,
+       new_bus->reset = &fs_enet_mii_bb_reset,
+       new_bus->id = pdev->id;
+
+       new_bus->phy_mask = ~0x9;
+       pdata = (struct fs_mii_bb_platform_info *)pdev->dev.platform_data;
+
+       if (NULL == pdata) {
+               printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
+               return -ENODEV;
+       }
+
+       /*set up workspace*/
+       fs_mii_bitbang_init(bitbang, pdata);
+
+       new_bus->priv = bitbang;
+
+       new_bus->irq = pdata->irq;
+
+       new_bus->dev = dev;
+       dev_set_drvdata(dev, new_bus);
+
+       err = mdiobus_register(new_bus);
+
+       if (0 != err) {
+               printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
+                               new_bus->name);
+               goto bus_register_fail;
+       }
+
+       return 0;
+
+bus_register_fail:
+       kfree(bitbang);
+       kfree(new_bus);
+
+       return err;
+}
+
+
+static int fs_enet_mdio_remove(struct device *dev)
+{
+       struct mii_bus *bus = dev_get_drvdata(dev);
+
+       mdiobus_unregister(bus);
+
+       dev_set_drvdata(dev, NULL);
+
+       iounmap((void *) (&bus->priv));
+       bus->priv = NULL;
+       kfree(bus);
+
+       return 0;
+}
+
+static struct device_driver fs_enet_bb_mdio_driver = {
+       .name = "fsl-bb-mdio",
+       .bus = &platform_bus_type,
+       .probe = fs_enet_mdio_probe,
+       .remove = fs_enet_mdio_remove,
+};
+
+int fs_enet_mdio_bb_init(void)
+{
+       return driver_register(&fs_enet_bb_mdio_driver);
+}
+
+void fs_enet_mdio_bb_exit(void)
+{
+       driver_unregister(&fs_enet_bb_mdio_driver);
+}
+
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
new file mode 100644 (file)
index 0000000..1328e10
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
+ *
+ * Copyright (c) 2003 Intracom S.A.
+ *  by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.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/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+#include "fec.h"
+
+/* Make MII read/write commands for the FEC.
+*/
+#define mk_mii_read(REG)       (0x60020000 | ((REG & 0x1f) << 18))
+#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
+#define mk_mii_end             0
+
+#define FEC_MII_LOOPS  10000
+
+static int match_has_phy (struct device *dev, void* data)
+{
+       struct platform_device* pdev = container_of(dev, struct platform_device, dev);
+       struct fs_platform_info* fpi;
+       if(strcmp(pdev->name, (char*)data))
+       {
+           return 0;
+       }
+
+       fpi = pdev->dev.platform_data;
+       if((fpi)&&(fpi->has_phy))
+               return 1;
+       return 0;
+}
+
+static int fs_mii_fec_init(struct fec_info* fec, struct fs_mii_fec_platform_info *fmpi)
+{
+       struct resource *r;
+       fec_t *fecp;
+       char* name = "fsl-cpm-fec";
+
+       /* we need fec in order to be useful */
+       struct platform_device *fec_pdev =
+               container_of(bus_find_device(&platform_bus_type, NULL, name, match_has_phy),
+                               struct platform_device, dev);
+
+       if(fec_pdev == NULL) {
+               printk(KERN_ERR"Unable to find PHY for %s", name);
+               return -ENODEV;
+       }
+
+       r = platform_get_resource_byname(fec_pdev, IORESOURCE_MEM, "regs");
+
+       fec->fecp = fecp = (fec_t*)ioremap(r->start,sizeof(fec_t));
+       fec->mii_speed = fmpi->mii_speed;
+
+       setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);     /* MII enable */
+       setbits32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
+       out_be32(&fecp->fec_ievent, FEC_ENET_MII);
+       out_be32(&fecp->fec_mii_speed, fec->mii_speed);
+
+       return 0;
+}
+
+static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
+{
+       struct fec_info* fec = bus->priv;
+       fec_t *fecp = fec->fecp;
+       int i, ret = -1;
+
+       if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
+               BUG();
+
+       /* Add PHY address to register command.  */
+       out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_read(location));
+
+       for (i = 0; i < FEC_MII_LOOPS; i++)
+               if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0)
+                       break;
+
+       if (i < FEC_MII_LOOPS) {
+               out_be32(&fecp->fec_ievent, FEC_ENET_MII);
+               ret = in_be32(&fecp->fec_mii_data) & 0xffff;
+       }
+
+       return ret;
+
+}
+
+static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
+{
+       struct fec_info* fec = bus->priv;
+       fec_t *fecp = fec->fecp;
+       int i;
+
+       /* this must never happen */
+       if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
+               BUG();
+
+       /* Add PHY address to register command.  */
+       out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_write(location, val));
+
+       for (i = 0; i < FEC_MII_LOOPS; i++)
+               if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0)
+                       break;
+
+       if (i < FEC_MII_LOOPS)
+               out_be32(&fecp->fec_ievent, FEC_ENET_MII);
+
+       return 0;
+
+}
+
+static int fs_enet_fec_mii_reset(struct mii_bus *bus)
+{
+       /* nothing here - for now */
+       return 0;
+}
+
+static int __devinit fs_enet_fec_mdio_probe(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct fs_mii_fec_platform_info *pdata;
+       struct mii_bus *new_bus;
+       struct fec_info *fec;
+       int err = 0;
+       if (NULL == dev)
+               return -EINVAL;
+       new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+       if (NULL == new_bus)
+               return -ENOMEM;
+
+       fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL);
+
+       if (NULL == fec)
+               return -ENOMEM;
+
+       new_bus->name = "FEC MII Bus",
+       new_bus->read = &fs_enet_fec_mii_read,
+       new_bus->write = &fs_enet_fec_mii_write,
+       new_bus->reset = &fs_enet_fec_mii_reset,
+       new_bus->id = pdev->id;
+
+       pdata = (struct fs_mii_fec_platform_info *)pdev->dev.platform_data;
+
+       if (NULL == pdata) {
+               printk(KERN_ERR "fs_enet FEC mdio %d: Missing platform data!\n", pdev->id);
+               return -ENODEV;
+       }
+
+       /*set up workspace*/
+
+       fs_mii_fec_init(fec, pdata);
+       new_bus->priv = fec;
+
+       new_bus->irq = pdata->irq;
+
+       new_bus->dev = dev;
+       dev_set_drvdata(dev, new_bus);
+
+       err = mdiobus_register(new_bus);
+
+       if (0 != err) {
+               printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
+                               new_bus->name);
+               goto bus_register_fail;
+       }
+
+       return 0;
+
+bus_register_fail:
+       kfree(new_bus);
+
+       return err;
+}
+
+
+static int fs_enet_fec_mdio_remove(struct device *dev)
+{
+       struct mii_bus *bus = dev_get_drvdata(dev);
+
+       mdiobus_unregister(bus);
+
+       dev_set_drvdata(dev, NULL);
+       kfree(bus->priv);
+
+       bus->priv = NULL;
+       kfree(bus);
+
+       return 0;
+}
+
+static struct device_driver fs_enet_fec_mdio_driver = {
+       .name = "fsl-cpm-fec-mdio",
+       .bus = &platform_bus_type,
+       .probe = fs_enet_fec_mdio_probe,
+       .remove = fs_enet_fec_mdio_remove,
+};
+
+int fs_enet_mdio_fec_init(void)
+{
+       return driver_register(&fs_enet_fec_mdio_driver);
+}
+
+void fs_enet_mdio_fec_exit(void)
+{
+       driver_unregister(&fs_enet_fec_mdio_driver);
+}
+
diff --git a/drivers/net/fs_enet/mii-fixed.c b/drivers/net/fs_enet/mii-fixed.c
deleted file mode 100644 (file)
index ae4a9c3..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
- *
- * Copyright (c) 2003 Intracom S.A. 
- *  by Pantelis Antoniou <panto@intracom.gr>
- * 
- * 2005 (c) MontaVista Software, Inc. 
- * Vitaly Bordug <vbordug@ru.mvista.com>
- *
- * This file is licensed under the terms of the GNU General Public License 
- * version 2. This program is licensed "as is" without any warranty of any 
- * kind, whether express or implied.
- */
-
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.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/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/bitops.h>
-
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-
-#include "fs_enet.h"
-
-static const u16 mii_regs[7] = {
-       0x3100,
-       0x786d,
-       0x0fff,
-       0x0fff,
-       0x01e1,
-       0x45e1,
-       0x0003,
-};
-
-static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
-{
-       int ret = 0;
-
-       if ((unsigned int)location >= ARRAY_SIZE(mii_regs))
-               return -1;
-
-       if (location != 5)
-               ret = mii_regs[location];
-       else
-               ret = bus->fixed.lpa;
-
-       return ret;
-}
-
-static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val)
-{
-       /* do nothing */
-}
-
-int fs_mii_fixed_init(struct fs_enet_mii_bus *bus)
-{
-       const struct fs_mii_bus_info *bi = bus->bus_info;
-
-       bus->fixed.lpa = 0x45e1;        /* default 100Mb, full duplex */
-
-       /* if speed is fixed at 10Mb, remove 100Mb modes */
-       if (bi->i.fixed.speed == 10)
-               bus->fixed.lpa &= ~LPA_100;
-
-       /* if duplex is half, remove full duplex modes */
-       if (bi->i.fixed.duplex == 0)
-               bus->fixed.lpa &= ~LPA_DUPLEX;
-
-       bus->mii_read = mii_read;
-       bus->mii_write = mii_write;
-
-       return 0;
-}
index e7d9bf330287b504958b647e9e262440750c3a64..ff5a67d619bb210b63da2c10fe7b4986cb38af4a 100644 (file)
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/types.h>
-#include <linux/config.h>      /* for CONFIG_PCI */
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
index 47f6f64d604c980b2c5a553a5500a01fca4b1b78..415ba8dc94ceb87c04b075e7656e2c663049aa06 100644 (file)
@@ -45,7 +45,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/errno.h>
index 0ea65c4c6f8543b9972bd7b8d398f4aacd856563..b69776e0095151f7ffb0f87828620ec488310088 100644 (file)
@@ -40,7 +40,6 @@
  ********************************************************************/
 
 #include <linux/module.h>
-#include <linux/config.h> 
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/skbuff.h>
index b1cf8522d8fca82f81c57d42b6073c260bb3e5d1..346273d42f9742b9ab5fc3be91decf4e86e9a43b 100644 (file)
@@ -162,7 +162,7 @@ ixgb_init_module(void)
 
        printk(KERN_INFO "%s\n", ixgb_copyright);
 
-       return pci_module_init(&ixgb_driver);
+       return pci_register_driver(&ixgb_driver);
 }
 
 module_init(ixgb_init_module);
index c1c3452c90ca2696ac82edd8ccf865be33a1264b..5b4dbfe5fb7710ff0675b8834a6e014f42b66cf8 100644 (file)
@@ -326,7 +326,7 @@ MODULE_PARM_DESC(dma, "LANCE/PCnet ISA DMA channel (ignored for some devices)");
 MODULE_PARM_DESC(irq, "LANCE/PCnet IRQ number (ignored for some devices)");
 MODULE_PARM_DESC(lance_debug, "LANCE/PCnet debug level (0-7)");
 
-int init_module(void)
+int __init init_module(void)
 {
        struct net_device *dev;
        int this_dev, found = 0;
index 646e89fc3562f975848af257b45249491db0f673..c0ec7f6abcb29c17a339bbecc088f079f26a7b71 100644 (file)
@@ -406,7 +406,7 @@ MODULE_PARM_DESC(mem, "memory base address(es)");
 MODULE_DESCRIPTION("Mylex LNE390A/B EISA Ethernet driver");
 MODULE_LICENSE("GPL");
 
-int init_module(void)
+int __init init_module(void)
 {
        struct net_device *dev;
        int this_dev, found = 0;
index 9bdd43ab3573afb5981b456d9a50b0a7a7c6ce73..e2346e8a4d521d5d03f89f345a3a3801aa908167 100644 (file)
@@ -187,11 +187,14 @@ struct myri10ge_priv {
        u8 mac_addr[6];         /* eeprom mac address */
        unsigned long serial_number;
        int vendor_specific_offset;
+       int fw_multicast_support;
        u32 devctl;
        u16 msi_flags;
        u32 read_dma;
        u32 write_dma;
        u32 read_write_dma;
+       u32 link_changes;
+       u32 msg_enable;
 };
 
 static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat";
@@ -257,6 +260,12 @@ module_param(myri10ge_max_irq_loops, int, S_IRUGO);
 MODULE_PARM_DESC(myri10ge_max_irq_loops,
                 "Set stuck legacy IRQ detection threshold\n");
 
+#define MYRI10GE_MSG_DEFAULT NETIF_MSG_LINK
+
+static int myri10ge_debug = -1;        /* defaults above */
+module_param(myri10ge_debug, int, 0);
+MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)");
+
 #define MYRI10GE_FW_OFFSET 1024*1024
 #define MYRI10GE_HIGHPART_TO_U32(X) \
 (sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0)
@@ -271,7 +280,7 @@ myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
        struct mcp_cmd *buf;
        char buf_bytes[sizeof(*buf) + 8];
        struct mcp_cmd_response *response = mgp->cmd;
-       char __iomem *cmd_addr = mgp->sram + MXGEFW_CMD_OFFSET;
+       char __iomem *cmd_addr = mgp->sram + MXGEFW_ETH_CMD;
        u32 dma_low, dma_high, result, value;
        int sleep_total = 0;
 
@@ -320,6 +329,8 @@ myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
                if (result == 0) {
                        data->data0 = value;
                        return 0;
+               } else if (result == MXGEFW_CMD_UNKNOWN) {
+                       return -ENOSYS;
                } else {
                        dev_err(&mgp->pdev->dev,
                                "command %d failed, result = %d\n",
@@ -404,7 +415,7 @@ static void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable)
        buf[4] = htonl(dma_low);        /* dummy addr LSW */
        buf[5] = htonl(enable); /* enable? */
 
-       submit = mgp->sram + 0xfc01c0;
+       submit = mgp->sram + MXGEFW_BOOT_DUMMY_RDMA;
 
        myri10ge_pio_copy(submit, &buf, sizeof(buf));
        for (i = 0; mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 20; i++)
@@ -600,7 +611,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp)
        buf[5] = htonl(8);      /* where to copy to */
        buf[6] = htonl(0);      /* where to jump to */
 
-       submit = mgp->sram + 0xfc0000;
+       submit = mgp->sram + MXGEFW_BOOT_HANDOFF;
 
        myri10ge_pio_copy(submit, &buf, sizeof(buf));
        mb();
@@ -764,6 +775,7 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
        mgp->rx_small.cnt = 0;
        mgp->rx_done.idx = 0;
        mgp->rx_done.cnt = 0;
+       mgp->link_changes = 0;
        status = myri10ge_update_mac_address(mgp, mgp->dev->dev_addr);
        myri10ge_change_promisc(mgp, 0, 0);
        myri10ge_change_pause(mgp, mgp->pause);
@@ -798,12 +810,13 @@ myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst,
  * pages directly and building a fraglist in the near future.
  */
 
-static inline struct sk_buff *myri10ge_alloc_big(int bytes)
+static inline struct sk_buff *myri10ge_alloc_big(struct net_device *dev,
+                                                int bytes)
 {
        struct sk_buff *skb;
        unsigned long data, roundup;
 
-       skb = dev_alloc_skb(bytes + 4096 + MXGEFW_PAD);
+       skb = netdev_alloc_skb(dev, bytes + 4096 + MXGEFW_PAD);
        if (skb == NULL)
                return NULL;
 
@@ -821,12 +834,13 @@ static inline struct sk_buff *myri10ge_alloc_big(int bytes)
 
 /* Allocate 2x as much space as required and use whichever portion
  * does not cross a 4KB boundary */
-static inline struct sk_buff *myri10ge_alloc_small_safe(unsigned int bytes)
+static inline struct sk_buff *myri10ge_alloc_small_safe(struct net_device *dev,
+                                                       unsigned int bytes)
 {
        struct sk_buff *skb;
        unsigned long data, boundary;
 
-       skb = dev_alloc_skb(2 * (bytes + MXGEFW_PAD) - 1);
+       skb = netdev_alloc_skb(dev, 2 * (bytes + MXGEFW_PAD) - 1);
        if (unlikely(skb == NULL))
                return NULL;
 
@@ -847,12 +861,13 @@ static inline struct sk_buff *myri10ge_alloc_small_safe(unsigned int bytes)
 
 /* Allocate just enough space, and verify that the allocated
  * space does not cross a 4KB boundary */
-static inline struct sk_buff *myri10ge_alloc_small(int bytes)
+static inline struct sk_buff *myri10ge_alloc_small(struct net_device *dev,
+                                                  int bytes)
 {
        struct sk_buff *skb;
        unsigned long roundup, data, end;
 
-       skb = dev_alloc_skb(bytes + 16 + MXGEFW_PAD);
+       skb = netdev_alloc_skb(dev, bytes + 16 + MXGEFW_PAD);
        if (unlikely(skb == NULL))
                return NULL;
 
@@ -868,15 +883,17 @@ static inline struct sk_buff *myri10ge_alloc_small(int bytes)
                       "myri10ge_alloc_small: small skb crossed 4KB boundary\n");
                myri10ge_skb_cross_4k = 1;
                dev_kfree_skb_any(skb);
-               skb = myri10ge_alloc_small_safe(bytes);
+               skb = myri10ge_alloc_small_safe(dev, bytes);
        }
        return skb;
 }
 
 static inline int
-myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct pci_dev *pdev, int bytes,
-               int idx)
+myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct myri10ge_priv *mgp,
+               int bytes, int idx)
 {
+       struct net_device *dev = mgp->dev;
+       struct pci_dev *pdev = mgp->pdev;
        struct sk_buff *skb;
        dma_addr_t bus;
        int len, retval = 0;
@@ -884,11 +901,11 @@ myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct pci_dev *pdev, int bytes,
        bytes += VLAN_HLEN;     /* account for 802.1q vlan tag */
 
        if ((bytes + MXGEFW_PAD) > (4096 - 16) /* linux overhead */ )
-               skb = myri10ge_alloc_big(bytes);
+               skb = myri10ge_alloc_big(dev, bytes);
        else if (myri10ge_skb_cross_4k)
-               skb = myri10ge_alloc_small_safe(bytes);
+               skb = myri10ge_alloc_small_safe(dev, bytes);
        else
-               skb = myri10ge_alloc_small(bytes);
+               skb = myri10ge_alloc_small(dev, bytes);
 
        if (unlikely(skb == NULL)) {
                rx->alloc_fail++;
@@ -951,7 +968,7 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
        unmap_len = pci_unmap_len(&rx->info[idx], len);
 
        /* try to replace the received skb */
-       if (myri10ge_getbuf(rx, mgp->pdev, bytes, idx)) {
+       if (myri10ge_getbuf(rx, mgp, bytes, idx)) {
                /* drop the frame -- the old skbuf is re-cycled */
                mgp->stats.rx_dropped += 1;
                return 0;
@@ -968,7 +985,6 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
        skb_put(skb, len);
 
        skb->protocol = eth_type_trans(skb, mgp->dev);
-       skb->dev = mgp->dev;
        if (mgp->csum_flag) {
                if ((skb->protocol == ntohs(ETH_P_IP)) ||
                    (skb->protocol == ntohs(ETH_P_IPV6))) {
@@ -1081,13 +1097,19 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
                if (mgp->link_state != stats->link_up) {
                        mgp->link_state = stats->link_up;
                        if (mgp->link_state) {
-                               printk(KERN_INFO "myri10ge: %s: link up\n",
-                                      mgp->dev->name);
+                               if (netif_msg_link(mgp))
+                                       printk(KERN_INFO
+                                              "myri10ge: %s: link up\n",
+                                              mgp->dev->name);
                                netif_carrier_on(mgp->dev);
+                               mgp->link_changes++;
                        } else {
-                               printk(KERN_INFO "myri10ge: %s: link down\n",
-                                      mgp->dev->name);
+                               if (netif_msg_link(mgp))
+                                       printk(KERN_INFO
+                                              "myri10ge: %s: link down\n",
+                                              mgp->dev->name);
                                netif_carrier_off(mgp->dev);
+                               mgp->link_changes++;
                        }
                }
                if (mgp->rdma_tags_available !=
@@ -1289,7 +1311,8 @@ static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = {
        "serial_number", "tx_pkt_start", "tx_pkt_done",
        "tx_req", "tx_done", "rx_small_cnt", "rx_big_cnt",
        "wake_queue", "stop_queue", "watchdog_resets", "tx_linearized",
-       "link_up", "dropped_link_overflow", "dropped_link_error_or_filtered",
+       "link_changes", "link_up", "dropped_link_overflow",
+       "dropped_link_error_or_filtered", "dropped_multicast_filtered",
        "dropped_runt", "dropped_overrun", "dropped_no_small_buffer",
        "dropped_no_big_buffer"
 };
@@ -1341,16 +1364,31 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
        data[i++] = (unsigned int)mgp->stop_queue;
        data[i++] = (unsigned int)mgp->watchdog_resets;
        data[i++] = (unsigned int)mgp->tx_linearized;
+       data[i++] = (unsigned int)mgp->link_changes;
        data[i++] = (unsigned int)ntohl(mgp->fw_stats->link_up);
        data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_link_overflow);
        data[i++] =
            (unsigned int)ntohl(mgp->fw_stats->dropped_link_error_or_filtered);
+       data[i++] =
+           (unsigned int)ntohl(mgp->fw_stats->dropped_multicast_filtered);
        data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_runt);
        data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_overrun);
        data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_small_buffer);
        data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_big_buffer);
 }
 
+static void myri10ge_set_msglevel(struct net_device *netdev, u32 value)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+       mgp->msg_enable = value;
+}
+
+static u32 myri10ge_get_msglevel(struct net_device *netdev)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+       return mgp->msg_enable;
+}
+
 static struct ethtool_ops myri10ge_ethtool_ops = {
        .get_settings = myri10ge_get_settings,
        .get_drvinfo = myri10ge_get_drvinfo,
@@ -1371,7 +1409,9 @@ static struct ethtool_ops myri10ge_ethtool_ops = {
 #endif
        .get_strings = myri10ge_get_strings,
        .get_stats_count = myri10ge_get_stats_count,
-       .get_ethtool_stats = myri10ge_get_ethtool_stats
+       .get_ethtool_stats = myri10ge_get_ethtool_stats,
+       .set_msglevel = myri10ge_set_msglevel,
+       .get_msglevel = myri10ge_get_msglevel
 };
 
 static int myri10ge_allocate_rings(struct net_device *dev)
@@ -1439,7 +1479,7 @@ static int myri10ge_allocate_rings(struct net_device *dev)
        /* Fill the receive rings */
 
        for (i = 0; i <= mgp->rx_small.mask; i++) {
-               status = myri10ge_getbuf(&mgp->rx_small, mgp->pdev,
+               status = myri10ge_getbuf(&mgp->rx_small, mgp,
                                         mgp->small_bytes, i);
                if (status) {
                        printk(KERN_ERR
@@ -1451,8 +1491,7 @@ static int myri10ge_allocate_rings(struct net_device *dev)
 
        for (i = 0; i <= mgp->rx_big.mask; i++) {
                status =
-                   myri10ge_getbuf(&mgp->rx_big, mgp->pdev,
-                                   dev->mtu + ETH_HLEN, i);
+                   myri10ge_getbuf(&mgp->rx_big, mgp, dev->mtu + ETH_HLEN, i);
                if (status) {
                        printk(KERN_ERR
                               "myri10ge: %s: alloced only %d big bufs\n",
@@ -1648,9 +1687,11 @@ static int myri10ge_open(struct net_device *dev)
        }
 
        if (mgp->mtrr >= 0) {
-               mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + 0x200000;
-               mgp->rx_small.wc_fifo = (u8 __iomem *) mgp->sram + 0x300000;
-               mgp->rx_big.wc_fifo = (u8 __iomem *) mgp->sram + 0x340000;
+               mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + MXGEFW_ETH_SEND_4;
+               mgp->rx_small.wc_fifo =
+                   (u8 __iomem *) mgp->sram + MXGEFW_ETH_RECV_SMALL;
+               mgp->rx_big.wc_fifo =
+                   (u8 __iomem *) mgp->sram + MXGEFW_ETH_RECV_BIG;
        } else {
                mgp->tx.wc_fifo = NULL;
                mgp->rx_small.wc_fifo = NULL;
@@ -1686,7 +1727,21 @@ static int myri10ge_open(struct net_device *dev)
 
        cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->fw_stats_bus);
        cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->fw_stats_bus);
-       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA, &cmd, 0);
+       cmd.data2 = sizeof(struct mcp_irq_data);
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA_V2, &cmd, 0);
+       if (status == -ENOSYS) {
+               dma_addr_t bus = mgp->fw_stats_bus;
+               bus += offsetof(struct mcp_irq_data, send_done_count);
+               cmd.data0 = MYRI10GE_LOWPART_TO_U32(bus);
+               cmd.data1 = MYRI10GE_HIGHPART_TO_U32(bus);
+               status = myri10ge_send_cmd(mgp,
+                                          MXGEFW_CMD_SET_STATS_DMA_OBSOLETE,
+                                          &cmd, 0);
+               /* Firmware cannot support multicast without STATS_DMA_V2 */
+               mgp->fw_multicast_support = 0;
+       } else {
+               mgp->fw_multicast_support = 1;
+       }
        if (status) {
                printk(KERN_ERR "myri10ge: %s: Couldn't set stats DMA\n",
                       dev->name);
@@ -1841,7 +1896,8 @@ myri10ge_submit_req_wc(struct myri10ge_tx_buf *tx,
        if (cnt > 0) {
                /* pad it to 64 bytes.  The src is 64 bytes bigger than it
                 * needs to be so that we don't overrun it */
-               myri10ge_pio_copy(tx->wc_fifo + (cnt << 18), src, 64);
+               myri10ge_pio_copy(tx->wc_fifo + MXGEFW_ETH_SEND_OFFSET(cnt),
+                                 src, 64);
                mb();
        }
 }
@@ -2140,9 +2196,81 @@ static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
 
 static void myri10ge_set_multicast_list(struct net_device *dev)
 {
+       struct myri10ge_cmd cmd;
+       struct myri10ge_priv *mgp;
+       struct dev_mc_list *mc_list;
+       int err;
+
+       mgp = netdev_priv(dev);
        /* can be called from atomic contexts,
         * pass 1 to force atomicity in myri10ge_send_cmd() */
-       myri10ge_change_promisc(netdev_priv(dev), dev->flags & IFF_PROMISC, 1);
+       myri10ge_change_promisc(mgp, dev->flags & IFF_PROMISC, 1);
+
+       /* This firmware is known to not support multicast */
+       if (!mgp->fw_multicast_support)
+               return;
+
+       /* Disable multicast filtering */
+
+       err = myri10ge_send_cmd(mgp, MXGEFW_ENABLE_ALLMULTI, &cmd, 1);
+       if (err != 0) {
+               printk(KERN_ERR "myri10ge: %s: Failed MXGEFW_ENABLE_ALLMULTI,"
+                      " error status: %d\n", dev->name, err);
+               goto abort;
+       }
+
+       if (dev->flags & IFF_ALLMULTI) {
+               /* request to disable multicast filtering, so quit here */
+               return;
+       }
+
+       /* Flush the filters */
+
+       err = myri10ge_send_cmd(mgp, MXGEFW_LEAVE_ALL_MULTICAST_GROUPS,
+                               &cmd, 1);
+       if (err != 0) {
+               printk(KERN_ERR
+                      "myri10ge: %s: Failed MXGEFW_LEAVE_ALL_MULTICAST_GROUPS"
+                      ", error status: %d\n", dev->name, err);
+               goto abort;
+       }
+
+       /* Walk the multicast list, and add each address */
+       for (mc_list = dev->mc_list; mc_list != NULL; mc_list = mc_list->next) {
+               memcpy(&cmd.data0, &mc_list->dmi_addr, 4);
+               memcpy(&cmd.data1, ((char *)&mc_list->dmi_addr) + 4, 2);
+               cmd.data0 = htonl(cmd.data0);
+               cmd.data1 = htonl(cmd.data1);
+               err = myri10ge_send_cmd(mgp, MXGEFW_JOIN_MULTICAST_GROUP,
+                                       &cmd, 1);
+
+               if (err != 0) {
+                       printk(KERN_ERR "myri10ge: %s: Failed "
+                              "MXGEFW_JOIN_MULTICAST_GROUP, error status:"
+                              "%d\t", dev->name, err);
+                       printk(KERN_ERR "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+                              ((unsigned char *)&mc_list->dmi_addr)[0],
+                              ((unsigned char *)&mc_list->dmi_addr)[1],
+                              ((unsigned char *)&mc_list->dmi_addr)[2],
+                              ((unsigned char *)&mc_list->dmi_addr)[3],
+                              ((unsigned char *)&mc_list->dmi_addr)[4],
+                              ((unsigned char *)&mc_list->dmi_addr)[5]
+                           );
+                       goto abort;
+               }
+       }
+       /* Enable multicast filtering */
+       err = myri10ge_send_cmd(mgp, MXGEFW_DISABLE_ALLMULTI, &cmd, 1);
+       if (err != 0) {
+               printk(KERN_ERR "myri10ge: %s: Failed MXGEFW_DISABLE_ALLMULTI,"
+                      "error status: %d\n", dev->name, err);
+               goto abort;
+       }
+
+       return;
+
+abort:
+       return;
 }
 
 static int myri10ge_set_mac_address(struct net_device *dev, void *addr)
@@ -2581,6 +2709,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        mgp->csum_flag = MXGEFW_FLAGS_CKSUM;
        mgp->pause = myri10ge_flow_control;
        mgp->intr_coal_delay = myri10ge_intr_coal_delay;
+       mgp->msg_enable = netif_msg_init(myri10ge_debug, MYRI10GE_MSG_DEFAULT);
        init_waitqueue_head(&mgp->down_wq);
 
        if (pci_enable_device(pdev)) {
index 0a6cae6cb1869f08353bfeacbb5c05f55f12e72a..9519ae7cd5ec74f0dc9e64fca428b7b515c03ebe 100644 (file)
@@ -91,7 +91,19 @@ struct mcp_kreq_ether_recv {
 
 /* Commands */
 
-#define MXGEFW_CMD_OFFSET 0xf80000
+#define        MXGEFW_BOOT_HANDOFF     0xfc0000
+#define        MXGEFW_BOOT_DUMMY_RDMA  0xfc01c0
+
+#define        MXGEFW_ETH_CMD          0xf80000
+#define        MXGEFW_ETH_SEND_4       0x200000
+#define        MXGEFW_ETH_SEND_1       0x240000
+#define        MXGEFW_ETH_SEND_2       0x280000
+#define        MXGEFW_ETH_SEND_3       0x2c0000
+#define        MXGEFW_ETH_RECV_SMALL   0x300000
+#define        MXGEFW_ETH_RECV_BIG     0x340000
+
+#define        MXGEFW_ETH_SEND(n)              (0x200000 + (((n) & 0x03) * 0x40000))
+#define        MXGEFW_ETH_SEND_OFFSET(n)       (MXGEFW_ETH_SEND(n) - MXGEFW_ETH_SEND_4)
 
 enum myri10ge_mcp_cmd_type {
        MXGEFW_CMD_NONE = 0,
@@ -154,7 +166,7 @@ enum myri10ge_mcp_cmd_type {
        MXGEFW_CMD_SET_MTU,
        MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET,  /* in microseconds */
        MXGEFW_CMD_SET_STATS_INTERVAL,  /* in microseconds */
-       MXGEFW_CMD_SET_STATS_DMA,
+       MXGEFW_CMD_SET_STATS_DMA_OBSOLETE,      /* replaced by SET_STATS_DMA_V2 */
 
        MXGEFW_ENABLE_PROMISC,
        MXGEFW_DISABLE_PROMISC,
@@ -168,7 +180,26 @@ enum myri10ge_mcp_cmd_type {
         * data2       = RDMA length (MSH), WDMA length (LSH)
         * command return data = repetitions (MSH), 0.5-ms ticks (LSH)
         */
-       MXGEFW_DMA_TEST
+       MXGEFW_DMA_TEST,
+
+       MXGEFW_ENABLE_ALLMULTI,
+       MXGEFW_DISABLE_ALLMULTI,
+
+       /* returns MXGEFW_CMD_ERROR_MULTICAST
+        * if there is no room in the cache
+        * data0,MSH(data1) = multicast group address */
+       MXGEFW_JOIN_MULTICAST_GROUP,
+       /* returns MXGEFW_CMD_ERROR_MULTICAST
+        * if the address is not in the cache,
+        * or is equal to FF-FF-FF-FF-FF-FF
+        * data0,MSH(data1) = multicast group address */
+       MXGEFW_LEAVE_MULTICAST_GROUP,
+       MXGEFW_LEAVE_ALL_MULTICAST_GROUPS,
+
+       MXGEFW_CMD_SET_STATS_DMA_V2,
+       /* data0, data1 = bus addr,
+        * data2 = sizeof(struct mcp_irq_data) from driver point of view, allows
+        * adding new stuff to mcp_irq_data without changing the ABI */
 };
 
 enum myri10ge_mcp_cmd_status {
@@ -180,11 +211,17 @@ enum myri10ge_mcp_cmd_status {
        MXGEFW_CMD_ERROR_CLOSED,
        MXGEFW_CMD_ERROR_HASH_ERROR,
        MXGEFW_CMD_ERROR_BAD_PORT,
-       MXGEFW_CMD_ERROR_RESOURCES
+       MXGEFW_CMD_ERROR_RESOURCES,
+       MXGEFW_CMD_ERROR_MULTICAST
 };
 
-/* 40 Bytes */
+#define MXGEFW_OLD_IRQ_DATA_LEN 40
+
 struct mcp_irq_data {
+       /* add new counters at the beginning */
+       u32 future_use[5];
+       u32 dropped_multicast_filtered;
+       /* 40 Bytes */
        u32 send_done_count;
 
        u32 link_up;
index db0475a1102f858aa5f781ca667c951303981829..9510030feeb4e6ed23fb2b585db8bf42e06e69fb 100644 (file)
@@ -3246,7 +3246,7 @@ static int __init natsemi_init_mod (void)
        printk(version);
 #endif
 
-       return pci_module_init (&natsemi_driver);
+       return pci_register_driver(&natsemi_driver);
 }
 
 static void __exit natsemi_exit_mod (void)
index 34bdba9eec79c3374f1632cc50062d0540ae0997..654b477b570a24d926d8eff4d9db117c2fc0d6d3 100644 (file)
@@ -702,7 +702,7 @@ static int __init ne2k_pci_init(void)
 #ifdef MODULE
        printk(version);
 #endif
-       return pci_module_init (&ne2k_driver);
+       return pci_register_driver(&ne2k_driver);
 }
 
 
index b1311ae82675035a6725dece3f017be2b395dd4e..30ed9a5a40e06a2cb4cf94dffb92afb873a1bce3 100644 (file)
@@ -17,7 +17,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
index fa854c8fde75c18489009aa651628a7a2939e068..4d52ecf8af567a125ede66f68c7d4aadde80a1d2 100644 (file)
@@ -1323,7 +1323,7 @@ MODULE_PARM_DESC(irq, "NI5210 IRQ number,required");
 MODULE_PARM_DESC(memstart, "NI5210 memory base address,required");
 MODULE_PARM_DESC(memend, "NI5210 memory end address,required");
 
-int init_module(void)
+int __init init_module(void)
 {
        if(io <= 0x0 || !memend || !memstart || irq < 2) {
                printk("ni52: Autoprobing not allowed for modules.\nni52: Set symbols 'io' 'irq' 'memstart' and 'memend'\n");
index bb42ff2184848df705d61f6418f3471d05c2677f..810cc572f5f714a240e263d3ca3165787344aabb 100644 (file)
@@ -1253,7 +1253,7 @@ MODULE_PARM_DESC(irq, "ni6510 IRQ number (ignored for some cards)");
 MODULE_PARM_DESC(io, "ni6510 I/O base address");
 MODULE_PARM_DESC(dma, "ni6510 ISA DMA channel (ignored for some cards)");
 
-int init_module(void)
+int __init init_module(void)
 {
        dev_ni65 = ni65_probe(-1);
        return IS_ERR(dev_ni65) ? PTR_ERR(dev_ni65) : 0;
index 0e76859c90a2af03b3c967b4bf1bd1061b34d236..0dedd34804c3c13379184118b4be4c3ba6a152dd 100644 (file)
@@ -2178,7 +2178,7 @@ static struct pci_driver driver = {
 static int __init ns83820_init(void)
 {
        printk(KERN_INFO "ns83820.c: National Semiconductor DP83820 10/100/1000 driver.\n");
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit ns83820_exit(void)
index e0e2939640429267f065dff8290ed2dbc984416c..e6347620529e2cee9aca59a01036a4e0c6befbef 100644 (file)
@@ -1963,7 +1963,7 @@ static int __init netdrv_init_module (void)
 #ifdef MODULE
        printk(version);
 #endif
-       return pci_module_init (&netdrv_pci_driver);
+       return pci_register_driver(&netdrv_pci_driver);
 }
 
 
index 297e9f8053663e0efefda780c0d7978669ce5b64..c54f6a7ebf31d95aea1ec4269c56d9ed2d6cbdc7 100644 (file)
@@ -771,6 +771,7 @@ static struct pcmcia_device_id axnet_ids[] = {
        PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0309),
        PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1106),
        PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab),
+       PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202), 
        PCMCIA_DEVICE_PROD_ID12("AmbiCom,Inc.", "Fast Ethernet PC Card(AMB8110)", 0x49b020a7, 0x119cc9fc),
        PCMCIA_DEVICE_PROD_ID124("Fast Ethernet", "16-bit PC Card", "AX88190", 0xb4be14e3, 0x9a12eb6a, 0xab9be5ef),
        PCMCIA_DEVICE_PROD_ID12("ASIX", "AX88190", 0x0959823b, 0xab9be5ef),
@@ -786,8 +787,6 @@ static struct pcmcia_device_id axnet_ids[] = {
        PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEtherCard", 0x281f1c5d, 0x7ef26116),
        PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FEP501", 0x281f1c5d, 0x2e272058),
        PCMCIA_DEVICE_PROD_ID14("Network Everywhere", "AX88190", 0x820a67b6,  0xab9be5ef),
-       /* this is not specific enough */
-       /* PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202), */
        PCMCIA_DEVICE_NULL,
 };
 MODULE_DEVICE_TABLE(pcmcia, axnet_ids);
index 0ecebfc31f073be959ebf9ca646bd4c6a858b0f2..cc0dcc9bf63608a523cc1d377ddcdba53b215fa6 100644 (file)
@@ -654,11 +654,8 @@ static int pcnet_config(struct pcmcia_device *link)
     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 
     if (info->flags & (IS_DL10019|IS_DL10022)) {
-       u_char id = inb(dev->base_addr + 0x1a);
        dev->do_ioctl = &ei_ioctl;
        mii_phy_probe(dev);
-       if ((id == 0x30) && !info->pna_phy && (info->eth_phy == 4))
-           info->eth_phy = 0;
     }
 
     link->dev_node = &info->node;
@@ -821,15 +818,6 @@ static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value)
     }
 }
 
-static void mdio_reset(kio_addr_t addr, int phy_id)
-{
-    outb_p(0x08, addr);
-    outb_p(0x0c, addr);
-    outb_p(0x08, addr);
-    outb_p(0x0c, addr);
-    outb_p(0x00, addr);
-}
-
 /*======================================================================
 
     EEPROM access routines for DL10019 and DL10022 based cards
@@ -942,7 +930,8 @@ static void set_misc_reg(struct net_device *dev)
     }
     if (info->flags & IS_DL10022) {
        if (info->flags & HAS_MII) {
-           mdio_reset(nic_base + DLINK_GPIO, info->eth_phy);
+           /* Advertise 100F, 100H, 10F, 10H */
+           mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 4, 0x01e1);
            /* Restart MII autonegotiation */
            mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000);
            mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200);
index 9bae77ce13141d883a9f08ce9cc9d0ae38b39614..4122bb46f5ffbc7f9b7e6b61d4cbca18d2bce951 100644 (file)
@@ -345,6 +345,7 @@ typedef struct local_info_t {
     void __iomem *dingo_ccr; /* only used for CEM56 cards */
     unsigned last_ptr_value; /* last packets transmitted value */
     const char *manf_str;
+    struct work_struct tx_timeout_task;
 } local_info_t;
 
 /****************
@@ -352,6 +353,7 @@ typedef struct local_info_t {
  */
 static int do_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void do_tx_timeout(struct net_device *dev);
+static void xirc2ps_tx_timeout_task(void *data);
 static struct net_device_stats *do_get_stats(struct net_device *dev);
 static void set_addresses(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
@@ -589,6 +591,7 @@ xirc2ps_probe(struct pcmcia_device *link)
 #ifdef HAVE_TX_TIMEOUT
     dev->tx_timeout = do_tx_timeout;
     dev->watchdog_timeo = TX_TIMEOUT;
+    INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task, dev);
 #endif
 
     return xirc2ps_config(link);
@@ -1341,17 +1344,24 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 /*====================================================================*/
 
 static void
-do_tx_timeout(struct net_device *dev)
+xirc2ps_tx_timeout_task(void *data)
 {
-    local_info_t *lp = netdev_priv(dev);
-    printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);
-    lp->stats.tx_errors++;
+    struct net_device *dev = data;
     /* reset the card */
     do_reset(dev,1);
     dev->trans_start = jiffies;
     netif_wake_queue(dev);
 }
 
+static void
+do_tx_timeout(struct net_device *dev)
+{
+    local_info_t *lp = netdev_priv(dev);
+    lp->stats.tx_errors++;
+    printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);
+    schedule_work(&lp->tx_timeout_task);
+}
+
 static int
 do_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
index 4daafe3033589c49c6637baf95c004e20d5982fc..5e26fe806e21e347bf5dbac5c32ea27fa04f3ed3 100644 (file)
@@ -202,6 +202,8 @@ static int homepna[MAX_UNITS];
 #define CSR15          15
 #define PCNET32_MC_FILTER      8
 
+#define PCNET32_79C970A        0x2621
+
 /* The PCNET32 Rx and Tx ring descriptors. */
 struct pcnet32_rx_head {
        u32     base;
@@ -289,6 +291,7 @@ struct pcnet32_private {
 
        /* each bit indicates an available PHY */
        u32                     phymask;
+       unsigned short          chip_version;   /* which variant this is */
 };
 
 static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *);
@@ -724,9 +727,11 @@ static u32 pcnet32_get_link(struct net_device *dev)
        spin_lock_irqsave(&lp->lock, flags);
        if (lp->mii) {
                r = mii_link_ok(&lp->mii_if);
-       } else {
+       } else if (lp->chip_version >= PCNET32_79C970A) {
                ulong ioaddr = dev->base_addr;  /* card base I/O address */
                r = (lp->a.read_bcr(ioaddr, 4) != 0xc0);
+       } else {        /* can not detect link on really old chips */
+               r = 1;
        }
        spin_unlock_irqrestore(&lp->lock, flags);
 
@@ -1091,6 +1096,10 @@ static int pcnet32_suspend(struct net_device *dev, unsigned long *flags,
        ulong ioaddr = dev->base_addr;
        int ticks;
 
+       /* really old chips have to be stopped. */
+       if (lp->chip_version < PCNET32_79C970A)
+               return 0;
+
        /* set SUSPEND (SPND) - CSR5 bit 0 */
        csr5 = a->read_csr(ioaddr, CSR5);
        a->write_csr(ioaddr, CSR5, csr5 | CSR5_SUSPEND);
@@ -1529,6 +1538,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
        lp->mii_if.reg_num_mask = 0x1f;
        lp->dxsuflo = dxsuflo;
        lp->mii = mii;
+       lp->chip_version = chip_version;
        lp->msg_enable = pcnet32_debug;
        if ((cards_found >= MAX_UNITS)
            || (options[cards_found] > sizeof(options_mapping)))
@@ -1839,10 +1849,7 @@ static int pcnet32_open(struct net_device *dev)
                                val |= 2;
                } else if (lp->options & PCNET32_PORT_ASEL) {
                        /* workaround of xSeries250, turn on for 79C975 only */
-                       i = ((lp->a.read_csr(ioaddr, 88) |
-                             (lp->a.
-                              read_csr(ioaddr, 89) << 16)) >> 12) & 0xffff;
-                       if (i == 0x2627)
+                       if (lp->chip_version == 0x2627)
                                val |= 3;
                }
                lp->a.write_bcr(ioaddr, 9, val);
@@ -1986,9 +1993,11 @@ static int pcnet32_open(struct net_device *dev)
 
        netif_start_queue(dev);
 
-       /* Print the link status and start the watchdog */
-       pcnet32_check_media(dev, 1);
-       mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
+       if (lp->chip_version >= PCNET32_79C970A) {
+               /* Print the link status and start the watchdog */
+               pcnet32_check_media(dev, 1);
+               mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
+       }
 
        i = 0;
        while (i++ < 100)
@@ -2969,7 +2978,7 @@ static int __init pcnet32_init_module(void)
                tx_start = tx_start_pt;
 
        /* find the PCI devices */
-       if (!pci_module_init(&pcnet32_driver))
+       if (!pci_register_driver(&pcnet32_driver))
                pcnet32_have_pci = 1;
 
        /* should we find any remaining VLbus devices ? */
index 2ba6d3a40e2ee5b2caf4347324a93a74a6665b44..b79ec0d7480fa9c411fd723cb93b13c5a47f344b 100644 (file)
@@ -56,5 +56,22 @@ config SMSC_PHY
        ---help---
          Currently supports the LAN83C185 PHY
 
+config FIXED_PHY
+       tristate "Drivers for PHY emulation on fixed speed/link"
+       depends on PHYLIB
+       ---help---
+         Adds the driver to PHY layer to cover the boards that do not have any PHY bound,
+         but with the ability to manipulate with speed/link in software. The relavant MII
+         speed/duplex parameters could be effectively handled in user-specified  fuction.
+         Currently tested with mpc866ads.
+
+config FIXED_MII_10_FDX
+       bool "Emulation for 10M Fdx fixed PHY behavior"
+       depends on FIXED_PHY
+
+config FIXED_MII_100_FDX
+       bool "Emulation for 100M Fdx fixed PHY behavior"
+       depends on FIXED_PHY
+
 endmenu
 
index a00e61942525aa0d8eed8b02552b31efa38fa27f..320f8323123fbb291c280575ecb4c403ef8476b5 100644 (file)
@@ -10,3 +10,4 @@ obj-$(CONFIG_LXT_PHY)         += lxt.o
 obj-$(CONFIG_QSEMI_PHY)                += qsemi.o
 obj-$(CONFIG_SMSC_PHY)         += smsc.o
 obj-$(CONFIG_VITESSE_PHY)      += vitesse.o
+obj-$(CONFIG_FIXED_PHY)                += fixed.o
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
new file mode 100644 (file)
index 0000000..341036d
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * drivers/net/phy/fixed.c
+ *
+ * Driver for fixed PHYs, when transceiver is able to operate in one fixed mode.
+ *
+ * Author: Vitaly Bordug
+ *
+ * Copyright (c) 2006 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/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/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#define MII_REGS_NUM   7
+
+/*
+    The idea is to emulate normal phy behavior by responding with
+    pre-defined values to mii BMCR read, so that read_status hook could
+    take all the needed info.
+*/
+
+struct fixed_phy_status {
+       u8      link;
+       u16     speed;
+       u8      duplex;
+};
+
+/*-----------------------------------------------------------------------------
+ *  Private information hoder for mii_bus
+ *-----------------------------------------------------------------------------*/
+struct fixed_info {
+       u16 *regs;
+       u8 regs_num;
+       struct fixed_phy_status phy_status;
+       struct phy_device *phydev; /* pointer to the container */
+       /* link & speed cb */
+       int(*link_update)(struct net_device*, struct fixed_phy_status*);
+
+};
+
+/*-----------------------------------------------------------------------------
+ *  If something weird is required to be done with link/speed,
+ * network driver is able to assign a function to implement this.
+ * May be useful for PHY's that need to be software-driven.
+ *-----------------------------------------------------------------------------*/
+int fixed_mdio_set_link_update(struct phy_device* phydev,
+               int(*link_update)(struct net_device*, struct fixed_phy_status*))
+{
+       struct fixed_info *fixed;
+
+       if(link_update == NULL)
+               return -EINVAL;
+
+       if(phydev) {
+               if(phydev->bus) {
+                       fixed = phydev->bus->priv;
+                       fixed->link_update = link_update;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+EXPORT_SYMBOL(fixed_mdio_set_link_update);
+
+/*-----------------------------------------------------------------------------
+ *  This is used for updating internal mii regs from the status
+ *-----------------------------------------------------------------------------*/
+static int fixed_mdio_update_regs(struct fixed_info *fixed)
+{
+       u16 *regs = fixed->regs;
+       u16 bmsr = 0;
+       u16 bmcr = 0;
+
+       if(!regs) {
+               printk(KERN_ERR "%s: regs not set up", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       if(fixed->phy_status.link)
+               bmsr |= BMSR_LSTATUS;
+
+       if(fixed->phy_status.duplex) {
+               bmcr |= BMCR_FULLDPLX;
+
+               switch ( fixed->phy_status.speed ) {
+               case 100:
+                       bmsr |= BMSR_100FULL;
+                       bmcr |= BMCR_SPEED100;
+               break;
+
+               case 10:
+                       bmsr |= BMSR_10FULL;
+               break;
+               }
+       } else {
+               switch ( fixed->phy_status.speed ) {
+               case 100:
+                       bmsr |= BMSR_100HALF;
+                       bmcr |= BMCR_SPEED100;
+               break;
+
+               case 10:
+                       bmsr |= BMSR_100HALF;
+               break;
+               }
+       }
+
+       regs[MII_BMCR] =  bmcr;
+       regs[MII_BMSR] =  bmsr | 0x800; /*we are always capable of 10 hdx*/
+
+       return 0;
+}
+
+static int fixed_mii_read(struct mii_bus *bus, int phy_id, int location)
+{
+       struct fixed_info *fixed = bus->priv;
+
+       /* if user has registered link update callback, use it */
+       if(fixed->phydev)
+               if(fixed->phydev->attached_dev) {
+                       if(fixed->link_update) {
+                               fixed->link_update(fixed->phydev->attached_dev,
+                                               &fixed->phy_status);
+                               fixed_mdio_update_regs(fixed);
+                       }
+       }
+
+       if ((unsigned int)location >= fixed->regs_num)
+               return -1;
+       return fixed->regs[location];
+}
+
+static int fixed_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
+{
+       /* do nothing for now*/
+       return 0;
+}
+
+static int fixed_mii_reset(struct mii_bus *bus)
+{
+       /*nothing here - no way/need to reset it*/
+       return 0;
+}
+
+static int fixed_config_aneg(struct phy_device *phydev)
+{
+       /* :TODO:03/13/2006 09:45:37 PM::
+        The full autoneg funcionality can be emulated,
+        but no need to have anything here for now
+        */
+       return 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * the manual bind will do the magic - with phy_id_mask == 0
+ * match will never return true...
+ *-----------------------------------------------------------------------------*/
+static struct phy_driver fixed_mdio_driver = {
+       .name           = "Fixed PHY",
+       .features       = PHY_BASIC_FEATURES,
+       .config_aneg    = fixed_config_aneg,
+       .read_status    = genphy_read_status,
+       .driver         = { .owner = THIS_MODULE,},
+};
+
+/*-----------------------------------------------------------------------------
+ *  This func is used to create all the necessary stuff, bind
+ * the fixed phy driver and register all it on the mdio_bus_type.
+ * speed is either 10 or 100, duplex is boolean.
+ * number is used to create multiple fixed PHYs, so that several devices can
+ * utilize them simultaneously.
+ *-----------------------------------------------------------------------------*/
+static int fixed_mdio_register_device(int number, int speed, int duplex)
+{
+       struct mii_bus *new_bus;
+       struct fixed_info *fixed;
+       struct phy_device *phydev;
+       int err = 0;
+
+       struct device* dev = kzalloc(sizeof(struct device), GFP_KERNEL);
+
+       if (NULL == dev)
+               return -ENOMEM;
+
+       new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+       if (NULL == new_bus) {
+               kfree(dev);
+               return -ENOMEM;
+       }
+       fixed = kzalloc(sizeof(struct fixed_info), GFP_KERNEL);
+
+       if (NULL == fixed) {
+               kfree(dev);
+               kfree(new_bus);
+               return -ENOMEM;
+       }
+
+       fixed->regs = kzalloc(MII_REGS_NUM*sizeof(int), GFP_KERNEL);
+       fixed->regs_num = MII_REGS_NUM;
+       fixed->phy_status.speed = speed;
+       fixed->phy_status.duplex = duplex;
+       fixed->phy_status.link = 1;
+
+       new_bus->name = "Fixed MII Bus",
+       new_bus->read = &fixed_mii_read,
+       new_bus->write = &fixed_mii_write,
+       new_bus->reset = &fixed_mii_reset,
+
+       /*set up workspace*/
+       fixed_mdio_update_regs(fixed);
+       new_bus->priv = fixed;
+
+       new_bus->dev = dev;
+       dev_set_drvdata(dev, new_bus);
+
+       /* create phy_device and register it on the mdio bus */
+       phydev = phy_device_create(new_bus, 0, 0);
+
+       /*
+        Put the phydev pointer into the fixed pack so that bus read/write code could
+        be able to access for instance attached netdev. Well it doesn't have to do
+        so, only in case of utilizing user-specified link-update...
+        */
+       fixed->phydev = phydev;
+
+       if(NULL == phydev) {
+               err = -ENOMEM;
+               goto device_create_fail;
+       }
+
+       phydev->irq = -1;
+       phydev->dev.bus = &mdio_bus_type;
+
+       if(number)
+               snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
+                               "fixed_%d@%d:%d", number, speed, duplex);
+       else
+               snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
+                               "fixed@%d:%d", speed, duplex);
+       phydev->bus = new_bus;
+
+       err = device_register(&phydev->dev);
+       if(err) {
+               printk(KERN_ERR "Phy %s failed to register\n",
+                               phydev->dev.bus_id);
+               goto bus_register_fail;
+       }
+
+       /*
+          the mdio bus has phy_id match... In order not to do it
+          artificially, we are binding the driver here by hand;
+          it will be the same for all the fixed phys anyway.
+        */
+       down_write(&phydev->dev.bus->subsys.rwsem);
+
+       phydev->dev.driver = &fixed_mdio_driver.driver;
+
+       err = phydev->dev.driver->probe(&phydev->dev);
+       if(err < 0) {
+               printk(KERN_ERR "Phy %s: problems with fixed driver\n",phydev->dev.bus_id);
+               up_write(&phydev->dev.bus->subsys.rwsem);
+               goto probe_fail;
+       }
+
+       device_bind_driver(&phydev->dev);
+       up_write(&phydev->dev.bus->subsys.rwsem);
+
+       return 0;
+
+probe_fail:
+       device_unregister(&phydev->dev);
+bus_register_fail:
+       kfree(phydev);
+device_create_fail:
+       kfree(dev);
+       kfree(new_bus);
+       kfree(fixed);
+
+       return err;
+}
+
+
+MODULE_DESCRIPTION("Fixed PHY device & driver for PAL");
+MODULE_AUTHOR("Vitaly Bordug");
+MODULE_LICENSE("GPL");
+
+static int __init fixed_init(void)
+{
+       int ret;
+       int duplex = 0;
+
+       /* register on the bus... Not expected to be matched with anything there... */
+       phy_driver_register(&fixed_mdio_driver);
+
+       /* So let the fun begin...
+          We will create several mdio devices here, and will bound the upper
+          driver to them.
+
+          Then the external software can lookup the phy bus by searching
+          fixed@speed:duplex, e.g. fixed@100:1, to be connected to the
+          virtual 100M Fdx phy.
+
+          In case several virtual PHYs required, the bus_id will be in form
+          fixed_<num>@<speed>:<duplex>, which make it able even to define
+          driver-specific link control callback, if for instance PHY is completely
+          SW-driven.
+
+       */
+
+#ifdef CONFIG_FIXED_MII_DUPLEX
+       duplex = 1;
+#endif
+
+#ifdef CONFIG_FIXED_MII_100_FDX
+       fixed_mdio_register_device(0, 100, 1);
+#endif
+
+#ifdef CONFIX_FIXED_MII_10_FDX
+       fixed_mdio_register_device(0, 10, 1);
+#endif
+       return 0;
+}
+
+static void __exit fixed_exit(void)
+{
+       phy_driver_unregister(&fixed_mdio_driver);
+       /* :WARNING:02/18/2006 04:32:40 AM:: Cleanup all the created stuff */
+}
+
+module_init(fixed_init);
+module_exit(fixed_exit);
index 1dde390c164d9952e0324582a1f5e6c80bd64b6d..cf6660c93ffa57aeca305f53abe0a500ca38a0f4 100644 (file)
@@ -159,6 +159,7 @@ struct bus_type mdio_bus_type = {
        .suspend        = mdio_bus_suspend,
        .resume         = mdio_bus_resume,
 };
+EXPORT_SYMBOL(mdio_bus_type);
 
 int __init mdio_bus_init(void)
 {
index 1bc1e032c5d6c9654912b8b6cdef51658b88cb7d..2d1ecfdc80dbecbc5e345d4524803ecf49bba114 100644 (file)
@@ -45,6 +45,35 @@ static struct phy_driver genphy_driver;
 extern int mdio_bus_init(void);
 extern void mdio_bus_exit(void);
 
+struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
+{
+       struct phy_device *dev;
+       /* We allocate the device, and initialize the
+        * default values */
+       dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
+
+       if (NULL == dev)
+               return (struct phy_device*) PTR_ERR((void*)-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;
+}
+EXPORT_SYMBOL(phy_device_create);
+
 /* get_phy_device
  *
  * description: Reads the ID registers of the PHY at addr on the
@@ -78,27 +107,7 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
        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);
+       dev = phy_device_create(bus, addr, phy_id);
 
        return dev;
 }
index 25e31fb5cb316334a0d4aa3595c8719c120ca903..b1d8ed40ad98e541120c6c1e00ff87741b4d8040 100644 (file)
@@ -14,7 +14,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mii.h>
index ffd215d9a9be4f6c82b1acd2919c107003ede6c8..792716beb052ad44b143dbb253375ebdb706b566 100644 (file)
@@ -12,7 +12,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mii.h>
index 0ec6e9d57b9499d438c9cf1838a212238e261a09..c872f7c6cce39392e7490cb2437ea62bd8fcc53f 100644 (file)
@@ -192,7 +192,7 @@ struct cardmap {
        void *ptr[CARDMAP_WIDTH];
 };
 static void *cardmap_get(struct cardmap *map, unsigned int nr);
-static void cardmap_set(struct cardmap **map, unsigned int nr, void *ptr);
+static int cardmap_set(struct cardmap **map, unsigned int nr, void *ptr);
 static unsigned int cardmap_find_first_free(struct cardmap *map);
 static void cardmap_destroy(struct cardmap **map);
 
@@ -1995,10 +1995,9 @@ ppp_register_channel(struct ppp_channel *chan)
 {
        struct channel *pch;
 
-       pch = kmalloc(sizeof(struct channel), GFP_KERNEL);
+       pch = kzalloc(sizeof(struct channel), GFP_KERNEL);
        if (pch == 0)
                return -ENOMEM;
-       memset(pch, 0, sizeof(struct channel));
        pch->ppp = NULL;
        pch->chan = chan;
        chan->ppp = pch;
@@ -2408,13 +2407,12 @@ ppp_create_interface(int unit, int *retp)
        int ret = -ENOMEM;
        int i;
 
-       ppp = kmalloc(sizeof(struct ppp), GFP_KERNEL);
+       ppp = kzalloc(sizeof(struct ppp), GFP_KERNEL);
        if (!ppp)
                goto out;
        dev = alloc_netdev(0, "", ppp_setup);
        if (!dev)
                goto out1;
-       memset(ppp, 0, sizeof(struct ppp));
 
        ppp->mru = PPP_MRU;
        init_ppp_file(&ppp->file, INTERFACE);
@@ -2454,11 +2452,16 @@ ppp_create_interface(int unit, int *retp)
        }
 
        atomic_inc(&ppp_unit_count);
-       cardmap_set(&all_ppp_units, unit, ppp);
+       ret = cardmap_set(&all_ppp_units, unit, ppp);
+       if (ret != 0)
+               goto out3;
+
        mutex_unlock(&all_ppp_mutex);
        *retp = 0;
        return ppp;
 
+out3:
+       atomic_dec(&ppp_unit_count);
 out2:
        mutex_unlock(&all_ppp_mutex);
        free_netdev(dev);
@@ -2695,7 +2698,7 @@ static void *cardmap_get(struct cardmap *map, unsigned int nr)
        return NULL;
 }
 
-static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
+static int cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
 {
        struct cardmap *p;
        int i;
@@ -2704,8 +2707,9 @@ static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
        if (p == NULL || (nr >> p->shift) >= CARDMAP_WIDTH) {
                do {
                        /* need a new top level */
-                       struct cardmap *np = kmalloc(sizeof(*np), GFP_KERNEL);
-                       memset(np, 0, sizeof(*np));
+                       struct cardmap *np = kzalloc(sizeof(*np), GFP_KERNEL);
+                       if (!np)
+                               goto enomem;
                        np->ptr[0] = p;
                        if (p != NULL) {
                                np->shift = p->shift + CARDMAP_ORDER;
@@ -2719,8 +2723,9 @@ static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
        while (p->shift > 0) {
                i = (nr >> p->shift) & CARDMAP_MASK;
                if (p->ptr[i] == NULL) {
-                       struct cardmap *np = kmalloc(sizeof(*np), GFP_KERNEL);
-                       memset(np, 0, sizeof(*np));
+                       struct cardmap *np = kzalloc(sizeof(*np), GFP_KERNEL);
+                       if (!np)
+                               goto enomem;
                        np->shift = p->shift - CARDMAP_ORDER;
                        np->parent = p;
                        p->ptr[i] = np;
@@ -2735,6 +2740,9 @@ static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
                set_bit(i, &p->inuse);
        else
                clear_bit(i, &p->inuse);
+       return 0;
+ enomem:
+       return -ENOMEM;
 }
 
 static unsigned int cardmap_find_first_free(struct cardmap *map)
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
new file mode 100644 (file)
index 0000000..c729aee
--- /dev/null
@@ -0,0 +1,3537 @@
+/*
+ * QLogic QLA3xxx NIC HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla3xxx for copyright and licensing details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/dmapool.h>
+#include <linux/mempool.h>
+#include <linux/spinlock.h>
+#include <linux/kthread.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/ip.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_vlan.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+
+#include "qla3xxx.h"
+
+#define DRV_NAME       "qla3xxx"
+#define DRV_STRING     "QLogic ISP3XXX Network Driver"
+#define DRV_VERSION    "v2.02.00-k36"
+#define PFX            DRV_NAME " "
+
+static const char ql3xxx_driver_name[] = DRV_NAME;
+static const char ql3xxx_driver_version[] = DRV_VERSION;
+
+MODULE_AUTHOR("QLogic Corporation");
+MODULE_DESCRIPTION("QLogic ISP3XXX Network Driver " DRV_VERSION " ");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+static const u32 default_msg
+    = NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
+    | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN;
+
+static int debug = -1;         /* defaults above */
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
+static int msi;
+module_param(msi, int, 0);
+MODULE_PARM_DESC(msi, "Turn on Message Signaled Interrupts.");
+
+static struct pci_device_id ql3xxx_pci_tbl[] __devinitdata = {
+       {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QL3022_DEVICE_ID)},
+       /* required last entry */
+       {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, ql3xxx_pci_tbl);
+
+/*
+ * Caller must take hw_lock.
+ */
+static int ql_sem_spinlock(struct ql3_adapter *qdev,
+                           u32 sem_mask, u32 sem_bits)
+{
+       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+       u32 value;
+       unsigned int seconds = 3;
+
+       do {
+               writel((sem_mask | sem_bits),
+                      &port_regs->CommonRegs.semaphoreReg);
+               value = readl(&port_regs->CommonRegs.semaphoreReg);
+               if ((value & (sem_mask >> 16)) == sem_bits)
+                       return 0;
+               ssleep(1);
+       } while(--seconds);
+       return -1;
+}
+
+static void ql_sem_unlock(struct ql3_adapter *qdev, u32 sem_mask)
+{
+       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+       writel(sem_mask, &port_regs->CommonRegs.semaphoreReg);
+       readl(&port_regs->CommonRegs.semaphoreReg);
+}
+
+static int ql_sem_lock(struct ql3_adapter *qdev, u32 sem_mask, u32 sem_bits)
+{
+       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+       u32 value;
+
+       writel((sem_mask | sem_bits), &port_regs->CommonRegs.semaphoreReg);
+       value = readl(&port_regs->CommonRegs.semaphoreReg);
+       return ((value & (sem_mask >> 16)) == sem_bits);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static int ql_wait_for_drvr_lock(struct ql3_adapter *qdev)
+{
+       int i = 0;
+
+       while (1) {
+               if (!ql_sem_lock(qdev,
+                                QL_DRVR_SEM_MASK,
+                                (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index)
+                                 * 2) << 1)) {
+                       if (i < 10) {
+                               ssleep(1);
+                               i++;
+                       } else {
+                               printk(KERN_ERR PFX "%s: Timed out waiting for "
+                                      "driver lock...\n",
+                                      qdev->ndev->name);
+                               return 0;
+                       }
+               } else {
+                       printk(KERN_DEBUG PFX
+                              "%s: driver lock acquired.\n",
+                              qdev->ndev->name);
+                       return 1;
+               }
+       }
+}
+
+static void ql_set_register_page(struct ql3_adapter *qdev, u32 page)
+{
+       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+
+       writel(((ISP_CONTROL_NP_MASK << 16) | page),
+                       &port_regs->CommonRegs.ispControlStatus);
+       readl(&port_regs->CommonRegs.ispControlStatus);
+       qdev->current_page = page;
+}
+
+static u32 ql_read_common_reg_l(struct ql3_adapter *qdev,
+                             u32 __iomem * reg)
+{
+       u32 value;
+       unsigned long hw_flags;
+
+       spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+       value = readl(reg);
+       spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
+       return value;
+}
+
+static u32 ql_read_common_reg(struct ql3_adapter *qdev,
+                             u32 __iomem * reg)
+{
+       return readl(reg);
+}
+
+static u32 ql_read_page0_reg_l(struct ql3_adapter *qdev, u32 __iomem *reg)
+{
+       u32 value;
+       unsigned long hw_flags;
+
+       spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+
+       if (qdev->current_page != 0)
+               ql_set_register_page(qdev,0);
+       value = readl(reg);
+
+       spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+       return value;
+}
+
+static u32 ql_read_page0_reg(struct ql3_adapter *qdev, u32 __iomem *reg)
+{
+       if (qdev->current_page != 0)
+               ql_set_register_page(qdev,0);
+       return readl(reg);
+}
+
+static void ql_write_common_reg_l(struct ql3_adapter *qdev,
+                               u32 * reg, u32 value)
+{
+       unsigned long hw_flags;
+
+       spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+       writel(value, (u32 *) reg);
+       readl(reg);
+       spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+       return;
+}
+
+static void ql_write_common_reg(struct ql3_adapter *qdev,
+                               u32 * reg, u32 value)
+{
+       writel(value, (u32 *) reg);
+       readl(reg);
+       return;
+}
+
+static void ql_write_page0_reg(struct ql3_adapter *qdev,
+                              u32 * reg, u32 value)
+{
+       if (qdev->current_page != 0)
+               ql_set_register_page(qdev,0);
+       writel(value, (u32 *) reg);
+       readl(reg);
+       return;
+}
+
+/*
+ * Caller holds hw_lock. Only called during init.
+ */
+static void ql_write_page1_reg(struct ql3_adapter *qdev,
+                              u32 * reg, u32 value)
+{
+       if (qdev->current_page != 1)
+               ql_set_register_page(qdev,1);
+       writel(value, (u32 *) reg);
+       readl(reg);
+       return;
+}
+
+/*
+ * Caller holds hw_lock. Only called during init.
+ */
+static void ql_write_page2_reg(struct ql3_adapter *qdev,
+                              u32 * reg, u32 value)
+{
+       if (qdev->current_page != 2)
+               ql_set_register_page(qdev,2);
+       writel(value, (u32 *) reg);
+       readl(reg);
+       return;
+}
+
+static void ql_disable_interrupts(struct ql3_adapter *qdev)
+{
+       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+
+       ql_write_common_reg_l(qdev, &port_regs->CommonRegs.ispInterruptMaskReg,
+                           (ISP_IMR_ENABLE_INT << 16));
+
+}
+
+static void ql_enable_interrupts(struct ql3_adapter *qdev)
+{
+       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+
+       ql_write_common_reg_l(qdev, &port_regs->CommonRegs.ispInterruptMaskReg,
+                           ((0xff << 16) | ISP_IMR_ENABLE_INT));
+
+}
+
+static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev,
+                                           struct ql_rcv_buf_cb *lrg_buf_cb)
+{
+       u64 map;
+       lrg_buf_cb->next = NULL;
+
+       if (qdev->lrg_buf_free_tail == NULL) {  /* The list is empty  */
+               qdev->lrg_buf_free_head = qdev->lrg_buf_free_tail = lrg_buf_cb;
+       } else {
+               qdev->lrg_buf_free_tail->next = lrg_buf_cb;
+               qdev->lrg_buf_free_tail = lrg_buf_cb;
+       }
+
+       if (!lrg_buf_cb->skb) {
+               lrg_buf_cb->skb = dev_alloc_skb(qdev->lrg_buffer_len);
+               if (unlikely(!lrg_buf_cb->skb)) {
+                       printk(KERN_ERR PFX "%s: failed dev_alloc_skb().\n",
+                              qdev->ndev->name);
+                       qdev->lrg_buf_skb_check++;
+               } else {
+                       /*
+                        * We save some space to copy the ethhdr from first
+                        * buffer
+                        */
+                       skb_reserve(lrg_buf_cb->skb, QL_HEADER_SPACE);
+                       map = pci_map_single(qdev->pdev,
+                                            lrg_buf_cb->skb->data,
+                                            qdev->lrg_buffer_len -
+                                            QL_HEADER_SPACE,
+                                            PCI_DMA_FROMDEVICE);
+                       lrg_buf_cb->buf_phy_addr_low =
+                           cpu_to_le32(LS_64BITS(map));
+                       lrg_buf_cb->buf_phy_addr_high =
+                           cpu_to_le32(MS_64BITS(map));
+                       pci_unmap_addr_set(lrg_buf_cb, mapaddr, map);
+                       pci_unmap_len_set(lrg_buf_cb, maplen,
+                                         qdev->lrg_buffer_len -
+                                         QL_HEADER_SPACE);
+               }
+       }
+
+       qdev->lrg_buf_free_count++;
+}
+
+static struct ql_rcv_buf_cb *ql_get_from_lrg_buf_free_list(struct ql3_adapter
+                                                          *qdev)
+{
+       struct ql_rcv_buf_cb *lrg_buf_cb;
+
+       if ((lrg_buf_cb = qdev->lrg_buf_free_head) != NULL) {
+               if ((qdev->lrg_buf_free_head = lrg_buf_cb->next) == NULL)
+                       qdev->lrg_buf_free_tail = NULL;
+               qdev->lrg_buf_free_count--;
+       }
+
+       return lrg_buf_cb;
+}
+
+static u32 addrBits = EEPROM_NO_ADDR_BITS;
+static u32 dataBits = EEPROM_NO_DATA_BITS;
+
+static void fm93c56a_deselect(struct ql3_adapter *qdev);
+static void eeprom_readword(struct ql3_adapter *qdev, u32 eepromAddr,
+                           unsigned short *value);
+
+/*
+ * Caller holds hw_lock.
+ */
+static void fm93c56a_select(struct ql3_adapter *qdev)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+
+       qdev->eeprom_cmd_data = AUBURN_EEPROM_CS_1;
+       ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+                           ISP_NVRAM_MASK | qdev->eeprom_cmd_data);
+       ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+                           ((ISP_NVRAM_MASK << 16) | qdev->eeprom_cmd_data));
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void fm93c56a_cmd(struct ql3_adapter *qdev, u32 cmd, u32 eepromAddr)
+{
+       int i;
+       u32 mask;
+       u32 dataBit;
+       u32 previousBit;
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+
+       /* Clock in a zero, then do the start bit */
+       ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+                           ISP_NVRAM_MASK | qdev->eeprom_cmd_data |
+                           AUBURN_EEPROM_DO_1);
+       ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+                           ISP_NVRAM_MASK | qdev->
+                           eeprom_cmd_data | AUBURN_EEPROM_DO_1 |
+                           AUBURN_EEPROM_CLK_RISE);
+       ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+                           ISP_NVRAM_MASK | qdev->
+                           eeprom_cmd_data | AUBURN_EEPROM_DO_1 |
+                           AUBURN_EEPROM_CLK_FALL);
+
+       mask = 1 << (FM93C56A_CMD_BITS - 1);
+       /* Force the previous data bit to be different */
+       previousBit = 0xffff;
+       for (i = 0; i < FM93C56A_CMD_BITS; i++) {
+               dataBit =
+                   (cmd & mask) ? AUBURN_EEPROM_DO_1 : AUBURN_EEPROM_DO_0;
+               if (previousBit != dataBit) {
+                       /*
+                        * If the bit changed, then change the DO state to
+                        * match
+                        */
+                       ql_write_common_reg(qdev,
+                                           &port_regs->CommonRegs.
+                                           serialPortInterfaceReg,
+                                           ISP_NVRAM_MASK | qdev->
+                                           eeprom_cmd_data | dataBit);
+                       previousBit = dataBit;
+               }
+               ql_write_common_reg(qdev,
+                                   &port_regs->CommonRegs.
+                                   serialPortInterfaceReg,
+                                   ISP_NVRAM_MASK | qdev->
+                                   eeprom_cmd_data | dataBit |
+                                   AUBURN_EEPROM_CLK_RISE);
+               ql_write_common_reg(qdev,
+                                   &port_regs->CommonRegs.
+                                   serialPortInterfaceReg,
+                                   ISP_NVRAM_MASK | qdev->
+                                   eeprom_cmd_data | dataBit |
+                                   AUBURN_EEPROM_CLK_FALL);
+               cmd = cmd << 1;
+       }
+
+       mask = 1 << (addrBits - 1);
+       /* Force the previous data bit to be different */
+       previousBit = 0xffff;
+       for (i = 0; i < addrBits; i++) {
+               dataBit =
+                   (eepromAddr & mask) ? AUBURN_EEPROM_DO_1 :
+                   AUBURN_EEPROM_DO_0;
+               if (previousBit != dataBit) {
+                       /*
+                        * If the bit changed, then change the DO state to
+                        * match
+                        */
+                       ql_write_common_reg(qdev,
+                                           &port_regs->CommonRegs.
+                                           serialPortInterfaceReg,
+                                           ISP_NVRAM_MASK | qdev->
+                                           eeprom_cmd_data | dataBit);
+                       previousBit = dataBit;
+               }
+               ql_write_common_reg(qdev,
+                                   &port_regs->CommonRegs.
+                                   serialPortInterfaceReg,
+                                   ISP_NVRAM_MASK | qdev->
+                                   eeprom_cmd_data | dataBit |
+                                   AUBURN_EEPROM_CLK_RISE);
+               ql_write_common_reg(qdev,
+                                   &port_regs->CommonRegs.
+                                   serialPortInterfaceReg,
+                                   ISP_NVRAM_MASK | qdev->
+                                   eeprom_cmd_data | dataBit |
+                                   AUBURN_EEPROM_CLK_FALL);
+               eepromAddr = eepromAddr << 1;
+       }
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void fm93c56a_deselect(struct ql3_adapter *qdev)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+       qdev->eeprom_cmd_data = AUBURN_EEPROM_CS_0;
+       ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+                           ISP_NVRAM_MASK | qdev->eeprom_cmd_data);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void fm93c56a_datain(struct ql3_adapter *qdev, unsigned short *value)
+{
+       int i;
+       u32 data = 0;
+       u32 dataBit;
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+
+       /* Read the data bits */
+       /* The first bit is a dummy.  Clock right over it. */
+       for (i = 0; i < dataBits; i++) {
+               ql_write_common_reg(qdev,
+                                   &port_regs->CommonRegs.
+                                   serialPortInterfaceReg,
+                                   ISP_NVRAM_MASK | qdev->eeprom_cmd_data |
+                                   AUBURN_EEPROM_CLK_RISE);
+               ql_write_common_reg(qdev,
+                                   &port_regs->CommonRegs.
+                                   serialPortInterfaceReg,
+                                   ISP_NVRAM_MASK | qdev->eeprom_cmd_data |
+                                   AUBURN_EEPROM_CLK_FALL);
+               dataBit =
+                   (ql_read_common_reg
+                    (qdev,
+                     &port_regs->CommonRegs.
+                     serialPortInterfaceReg) & AUBURN_EEPROM_DI_1) ? 1 : 0;
+               data = (data << 1) | dataBit;
+       }
+       *value = (u16) data;
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void eeprom_readword(struct ql3_adapter *qdev,
+                           u32 eepromAddr, unsigned short *value)
+{
+       fm93c56a_select(qdev);
+       fm93c56a_cmd(qdev, (int)FM93C56A_READ, eepromAddr);
+       fm93c56a_datain(qdev, value);
+       fm93c56a_deselect(qdev);
+}
+
+static void ql_swap_mac_addr(u8 * macAddress)
+{
+#ifdef __BIG_ENDIAN
+       u8 temp;
+       temp = macAddress[0];
+       macAddress[0] = macAddress[1];
+       macAddress[1] = temp;
+       temp = macAddress[2];
+       macAddress[2] = macAddress[3];
+       macAddress[3] = temp;
+       temp = macAddress[4];
+       macAddress[4] = macAddress[5];
+       macAddress[5] = temp;
+#endif
+}
+
+static int ql_get_nvram_params(struct ql3_adapter *qdev)
+{
+       u16 *pEEPROMData;
+       u16 checksum = 0;
+       u32 index;
+       unsigned long hw_flags;
+
+       spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+
+       pEEPROMData = (u16 *) & qdev->nvram_data;
+       qdev->eeprom_cmd_data = 0;
+       if(ql_sem_spinlock(qdev, QL_NVRAM_SEM_MASK,
+                       (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+                        2) << 10)) {
+               printk(KERN_ERR PFX"%s: Failed ql_sem_spinlock().\n",
+                       __func__);
+               spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+               return -1;
+       }
+
+       for (index = 0; index < EEPROM_SIZE; index++) {
+               eeprom_readword(qdev, index, pEEPROMData);
+               checksum += *pEEPROMData;
+               pEEPROMData++;
+       }
+       ql_sem_unlock(qdev, QL_NVRAM_SEM_MASK);
+
+       if (checksum != 0) {
+               printk(KERN_ERR PFX "%s: checksum should be zero, is %x!!\n",
+                      qdev->ndev->name, checksum);
+               spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+               return -1;
+       }
+
+       /*
+        * We have a problem with endianness for the MAC addresses
+        * and the two 8-bit values version, and numPorts.  We
+        * have to swap them on big endian systems.
+        */
+       ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn0.macAddress);
+       ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn1.macAddress);
+       ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn2.macAddress);
+       ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn3.macAddress);
+       pEEPROMData = (u16 *) & qdev->nvram_data.version;
+       *pEEPROMData = le16_to_cpu(*pEEPROMData);
+
+       spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+       return checksum;
+}
+
+static const u32 PHYAddr[2] = {
+       PORT0_PHY_ADDRESS, PORT1_PHY_ADDRESS
+};
+
+static int ql_wait_for_mii_ready(struct ql3_adapter *qdev)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+       u32 temp;
+       int count = 1000;
+
+       while (count) {
+               temp = ql_read_page0_reg(qdev, &port_regs->macMIIStatusReg);
+               if (!(temp & MAC_MII_STATUS_BSY))
+                       return 0;
+               udelay(10);
+               count--;
+       }
+       return -1;
+}
+
+static void ql_mii_enable_scan_mode(struct ql3_adapter *qdev)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+       u32 scanControl;
+
+       if (qdev->numPorts > 1) {
+               /* Auto scan will cycle through multiple ports */
+               scanControl = MAC_MII_CONTROL_AS | MAC_MII_CONTROL_SC;
+       } else {
+               scanControl = MAC_MII_CONTROL_SC;
+       }
+
+       /*
+        * Scan register 1 of PHY/PETBI,
+        * Set up to scan both devices
+        * The autoscan starts from the first register, completes
+        * the last one before rolling over to the first
+        */
+       ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,
+                          PHYAddr[0] | MII_SCAN_REGISTER);
+
+       ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,
+                          (scanControl) |
+                          ((MAC_MII_CONTROL_SC | MAC_MII_CONTROL_AS) << 16));
+}
+
+static u8 ql_mii_disable_scan_mode(struct ql3_adapter *qdev)
+{
+       u8 ret;
+       struct ql3xxx_port_registers __iomem *port_regs =
+                                       qdev->mem_map_registers;
+
+       /* See if scan mode is enabled before we turn it off */
+       if (ql_read_page0_reg(qdev, &port_regs->macMIIMgmtControlReg) &
+           (MAC_MII_CONTROL_AS | MAC_MII_CONTROL_SC)) {
+               /* Scan is enabled */
+               ret = 1;
+       } else {
+               /* Scan is disabled */
+               ret = 0;
+       }
+
+       /*
+        * When disabling scan mode you must first change the MII register
+        * address
+        */
+       ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,
+                          PHYAddr[0] | MII_SCAN_REGISTER);
+
+       ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,
+                          ((MAC_MII_CONTROL_SC | MAC_MII_CONTROL_AS |
+                            MAC_MII_CONTROL_RC) << 16));
+
+       return ret;
+}
+
+static int ql_mii_write_reg_ex(struct ql3_adapter *qdev,
+                              u16 regAddr, u16 value, u32 mac_index)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+       u8 scanWasEnabled;
+
+       scanWasEnabled = ql_mii_disable_scan_mode(qdev);
+
+       if (ql_wait_for_mii_ready(qdev)) {
+               if (netif_msg_link(qdev))
+                       printk(KERN_WARNING PFX
+                              "%s Timed out waiting for management port to "
+                              "get free before issuing command.\n",
+                              qdev->ndev->name);
+               return -1;
+       }
+
+       ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,
+                          PHYAddr[mac_index] | regAddr);
+
+       ql_write_page0_reg(qdev, &port_regs->macMIIMgmtDataReg, value);
+
+       /* Wait for write to complete 9/10/04 SJP */
+       if (ql_wait_for_mii_ready(qdev)) {
+               if (netif_msg_link(qdev))
+                       printk(KERN_WARNING PFX
+                              "%s: Timed out waiting for management port to"
+                              "get free before issuing command.\n",
+                              qdev->ndev->name);
+               return -1;
+       }
+
+       if (scanWasEnabled)
+               ql_mii_enable_scan_mode(qdev);
+
+       return 0;
+}
+
+static int ql_mii_read_reg_ex(struct ql3_adapter *qdev, u16 regAddr,
+                             u16 * value, u32 mac_index)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+       u8 scanWasEnabled;
+       u32 temp;
+
+       scanWasEnabled = ql_mii_disable_scan_mode(qdev);
+
+       if (ql_wait_for_mii_ready(qdev)) {
+               if (netif_msg_link(qdev))
+                       printk(KERN_WARNING PFX
+                              "%s: Timed out waiting for management port to "
+                              "get free before issuing command.\n",
+                              qdev->ndev->name);
+               return -1;
+       }
+
+       ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,
+                          PHYAddr[mac_index] | regAddr);
+
+       ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,
+                          (MAC_MII_CONTROL_RC << 16));
+
+       ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,
+                          (MAC_MII_CONTROL_RC << 16) | MAC_MII_CONTROL_RC);
+
+       /* Wait for the read to complete */
+       if (ql_wait_for_mii_ready(qdev)) {
+               if (netif_msg_link(qdev))
+                       printk(KERN_WARNING PFX
+                              "%s: Timed out waiting for management port to "
+                              "get free after issuing command.\n",
+                              qdev->ndev->name);
+               return -1;
+       }
+
+       temp = ql_read_page0_reg(qdev, &port_regs->macMIIMgmtDataReg);
+       *value = (u16) temp;
+
+       if (scanWasEnabled)
+               ql_mii_enable_scan_mode(qdev);
+
+       return 0;
+}
+
+static int ql_mii_write_reg(struct ql3_adapter *qdev, u16 regAddr, u16 value)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+
+       ql_mii_disable_scan_mode(qdev);
+
+       if (ql_wait_for_mii_ready(qdev)) {
+               if (netif_msg_link(qdev))
+                       printk(KERN_WARNING PFX
+                              "%s: Timed out waiting for management port to "
+                              "get free before issuing command.\n",
+                              qdev->ndev->name);
+               return -1;
+       }
+
+       ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,
+                          qdev->PHYAddr | regAddr);
+
+       ql_write_page0_reg(qdev, &port_regs->macMIIMgmtDataReg, value);
+
+       /* Wait for write to complete. */
+       if (ql_wait_for_mii_ready(qdev)) {
+               if (netif_msg_link(qdev))
+                       printk(KERN_WARNING PFX
+                              "%s: Timed out waiting for management port to "
+                              "get free before issuing command.\n",
+                              qdev->ndev->name);
+               return -1;
+       }
+
+       ql_mii_enable_scan_mode(qdev);
+
+       return 0;
+}
+
+static int ql_mii_read_reg(struct ql3_adapter *qdev, u16 regAddr, u16 *value)
+{
+       u32 temp;
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+
+       ql_mii_disable_scan_mode(qdev);
+
+       if (ql_wait_for_mii_ready(qdev)) {
+               if (netif_msg_link(qdev))
+                       printk(KERN_WARNING PFX
+                              "%s: Timed out waiting for management port to "
+                              "get free before issuing command.\n",
+                              qdev->ndev->name);
+               return -1;
+       }
+
+       ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,
+                          qdev->PHYAddr | regAddr);
+
+       ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,
+                          (MAC_MII_CONTROL_RC << 16));
+
+       ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,
+                          (MAC_MII_CONTROL_RC << 16) | MAC_MII_CONTROL_RC);
+
+       /* Wait for the read to complete */
+       if (ql_wait_for_mii_ready(qdev)) {
+               if (netif_msg_link(qdev))
+                       printk(KERN_WARNING PFX
+                              "%s: Timed out waiting for management port to "
+                              "get free before issuing command.\n",
+                              qdev->ndev->name);
+               return -1;
+       }
+
+       temp = ql_read_page0_reg(qdev, &port_regs->macMIIMgmtDataReg);
+       *value = (u16) temp;
+
+       ql_mii_enable_scan_mode(qdev);
+
+       return 0;
+}
+
+static void ql_petbi_reset(struct ql3_adapter *qdev)
+{
+       ql_mii_write_reg(qdev, PETBI_CONTROL_REG, PETBI_CTRL_SOFT_RESET);
+}
+
+static void ql_petbi_start_neg(struct ql3_adapter *qdev)
+{
+       u16 reg;
+
+       /* Enable Auto-negotiation sense */
+       ql_mii_read_reg(qdev, PETBI_TBI_CTRL, &reg);
+       reg |= PETBI_TBI_AUTO_SENSE;
+       ql_mii_write_reg(qdev, PETBI_TBI_CTRL, reg);
+
+       ql_mii_write_reg(qdev, PETBI_NEG_ADVER,
+                        PETBI_NEG_PAUSE | PETBI_NEG_DUPLEX);
+
+       ql_mii_write_reg(qdev, PETBI_CONTROL_REG,
+                        PETBI_CTRL_AUTO_NEG | PETBI_CTRL_RESTART_NEG |
+                        PETBI_CTRL_FULL_DUPLEX | PETBI_CTRL_SPEED_1000);
+
+}
+
+static void ql_petbi_reset_ex(struct ql3_adapter *qdev, u32 mac_index)
+{
+       ql_mii_write_reg_ex(qdev, PETBI_CONTROL_REG, PETBI_CTRL_SOFT_RESET,
+                           mac_index);
+}
+
+static void ql_petbi_start_neg_ex(struct ql3_adapter *qdev, u32 mac_index)
+{
+       u16 reg;
+
+       /* Enable Auto-negotiation sense */
+       ql_mii_read_reg_ex(qdev, PETBI_TBI_CTRL, &reg, mac_index);
+       reg |= PETBI_TBI_AUTO_SENSE;
+       ql_mii_write_reg_ex(qdev, PETBI_TBI_CTRL, reg, mac_index);
+
+       ql_mii_write_reg_ex(qdev, PETBI_NEG_ADVER,
+                           PETBI_NEG_PAUSE | PETBI_NEG_DUPLEX, mac_index);
+
+       ql_mii_write_reg_ex(qdev, PETBI_CONTROL_REG,
+                           PETBI_CTRL_AUTO_NEG | PETBI_CTRL_RESTART_NEG |
+                           PETBI_CTRL_FULL_DUPLEX | PETBI_CTRL_SPEED_1000,
+                           mac_index);
+}
+
+static void ql_petbi_init(struct ql3_adapter *qdev)
+{
+       ql_petbi_reset(qdev);
+       ql_petbi_start_neg(qdev);
+}
+
+static void ql_petbi_init_ex(struct ql3_adapter *qdev, u32 mac_index)
+{
+       ql_petbi_reset_ex(qdev, mac_index);
+       ql_petbi_start_neg_ex(qdev, mac_index);
+}
+
+static int ql_is_petbi_neg_pause(struct ql3_adapter *qdev)
+{
+       u16 reg;
+
+       if (ql_mii_read_reg(qdev, PETBI_NEG_PARTNER, &reg) < 0)
+               return 0;
+
+       return (reg & PETBI_NEG_PAUSE_MASK) == PETBI_NEG_PAUSE;
+}
+
+static int ql_phy_get_speed(struct ql3_adapter *qdev)
+{
+       u16 reg;
+
+       if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, &reg) < 0)
+               return 0;
+
+       reg = (((reg & 0x18) >> 3) & 3);
+
+       if (reg == 2)
+               return SPEED_1000;
+       else if (reg == 1)
+               return SPEED_100;
+       else if (reg == 0)
+               return SPEED_10;
+       else
+               return -1;
+}
+
+static int ql_is_full_dup(struct ql3_adapter *qdev)
+{
+       u16 reg;
+
+       if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, &reg) < 0)
+               return 0;
+
+       return (reg & PHY_AUX_DUPLEX_STAT) != 0;
+}
+
+static int ql_is_phy_neg_pause(struct ql3_adapter *qdev)
+{
+       u16 reg;
+
+       if (ql_mii_read_reg(qdev, PHY_NEG_PARTNER, &reg) < 0)
+               return 0;
+
+       return (reg & PHY_NEG_PAUSE) != 0;
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void ql_mac_enable(struct ql3_adapter *qdev, u32 enable)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+       u32 value;
+
+       if (enable)
+               value = (MAC_CONFIG_REG_PE | (MAC_CONFIG_REG_PE << 16));
+       else
+               value = (MAC_CONFIG_REG_PE << 16);
+
+       if (qdev->mac_index)
+               ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value);
+       else
+               ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void ql_mac_cfg_soft_reset(struct ql3_adapter *qdev, u32 enable)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+       u32 value;
+
+       if (enable)
+               value = (MAC_CONFIG_REG_SR | (MAC_CONFIG_REG_SR << 16));
+       else
+               value = (MAC_CONFIG_REG_SR << 16);
+
+       if (qdev->mac_index)
+               ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value);
+       else
+               ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void ql_mac_cfg_gig(struct ql3_adapter *qdev, u32 enable)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+       u32 value;
+
+       if (enable)
+               value = (MAC_CONFIG_REG_GM | (MAC_CONFIG_REG_GM << 16));
+       else
+               value = (MAC_CONFIG_REG_GM << 16);
+
+       if (qdev->mac_index)
+               ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value);
+       else
+               ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void ql_mac_cfg_full_dup(struct ql3_adapter *qdev, u32 enable)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+       u32 value;
+
+       if (enable)
+               value = (MAC_CONFIG_REG_FD | (MAC_CONFIG_REG_FD << 16));
+       else
+               value = (MAC_CONFIG_REG_FD << 16);
+
+       if (qdev->mac_index)
+               ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value);
+       else
+               ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void ql_mac_cfg_pause(struct ql3_adapter *qdev, u32 enable)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+       u32 value;
+
+       if (enable)
+               value =
+                   ((MAC_CONFIG_REG_TF | MAC_CONFIG_REG_RF) |
+                    ((MAC_CONFIG_REG_TF | MAC_CONFIG_REG_RF) << 16));
+       else
+               value = ((MAC_CONFIG_REG_TF | MAC_CONFIG_REG_RF) << 16);
+
+       if (qdev->mac_index)
+               ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value);
+       else
+               ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static int ql_is_fiber(struct ql3_adapter *qdev)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+       u32 bitToCheck = 0;
+       u32 temp;
+
+       switch (qdev->mac_index) {
+       case 0:
+               bitToCheck = PORT_STATUS_SM0;
+               break;
+       case 1:
+               bitToCheck = PORT_STATUS_SM1;
+               break;
+       }
+
+       temp = ql_read_page0_reg(qdev, &port_regs->portStatus);
+       return (temp & bitToCheck) != 0;
+}
+
+static int ql_is_auto_cfg(struct ql3_adapter *qdev)
+{
+       u16 reg;
+       ql_mii_read_reg(qdev, 0x00, &reg);
+       return (reg & 0x1000) != 0;
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static int ql_is_auto_neg_complete(struct ql3_adapter *qdev)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+       u32 bitToCheck = 0;
+       u32 temp;
+
+       switch (qdev->mac_index) {
+       case 0:
+               bitToCheck = PORT_STATUS_AC0;
+               break;
+       case 1:
+               bitToCheck = PORT_STATUS_AC1;
+               break;
+       }
+
+       temp = ql_read_page0_reg(qdev, &port_regs->portStatus);
+       if (temp & bitToCheck) {
+               if (netif_msg_link(qdev))
+                       printk(KERN_INFO PFX
+                              "%s: Auto-Negotiate complete.\n",
+                              qdev->ndev->name);
+               return 1;
+       } else {
+               if (netif_msg_link(qdev))
+                       printk(KERN_WARNING PFX
+                              "%s: Auto-Negotiate incomplete.\n",
+                              qdev->ndev->name);
+               return 0;
+       }
+}
+
+/*
+ *  ql_is_neg_pause() returns 1 if pause was negotiated to be on
+ */
+static int ql_is_neg_pause(struct ql3_adapter *qdev)
+{
+       if (ql_is_fiber(qdev))
+               return ql_is_petbi_neg_pause(qdev);
+       else
+               return ql_is_phy_neg_pause(qdev);
+}
+
+static int ql_auto_neg_error(struct ql3_adapter *qdev)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+       u32 bitToCheck = 0;
+       u32 temp;
+
+       switch (qdev->mac_index) {
+       case 0:
+               bitToCheck = PORT_STATUS_AE0;
+               break;
+       case 1:
+               bitToCheck = PORT_STATUS_AE1;
+               break;
+       }
+       temp = ql_read_page0_reg(qdev, &port_regs->portStatus);
+       return (temp & bitToCheck) != 0;
+}
+
+static u32 ql_get_link_speed(struct ql3_adapter *qdev)
+{
+       if (ql_is_fiber(qdev))
+               return SPEED_1000;
+       else
+               return ql_phy_get_speed(qdev);
+}
+
+static int ql_is_link_full_dup(struct ql3_adapter *qdev)
+{
+       if (ql_is_fiber(qdev))
+               return 1;
+       else
+               return ql_is_full_dup(qdev);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static int ql_link_down_detect(struct ql3_adapter *qdev)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+       u32 bitToCheck = 0;
+       u32 temp;
+
+       switch (qdev->mac_index) {
+       case 0:
+               bitToCheck = ISP_CONTROL_LINK_DN_0;
+               break;
+       case 1:
+               bitToCheck = ISP_CONTROL_LINK_DN_1;
+               break;
+       }
+
+       temp =
+           ql_read_common_reg(qdev, &port_regs->CommonRegs.ispControlStatus);
+       return (temp & bitToCheck) != 0;
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static int ql_link_down_detect_clear(struct ql3_adapter *qdev)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+
+       switch (qdev->mac_index) {
+       case 0:
+               ql_write_common_reg(qdev,
+                                   &port_regs->CommonRegs.ispControlStatus,
+                                   (ISP_CONTROL_LINK_DN_0) |
+                                   (ISP_CONTROL_LINK_DN_0 << 16));
+               break;
+
+       case 1:
+               ql_write_common_reg(qdev,
+                                   &port_regs->CommonRegs.ispControlStatus,
+                                   (ISP_CONTROL_LINK_DN_1) |
+                                   (ISP_CONTROL_LINK_DN_1 << 16));
+               break;
+
+       default:
+               return 1;
+       }
+
+       return 0;
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static int ql_this_adapter_controls_port(struct ql3_adapter *qdev,
+                                        u32 mac_index)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+       u32 bitToCheck = 0;
+       u32 temp;
+
+       switch (mac_index) {
+       case 0:
+               bitToCheck = PORT_STATUS_F1_ENABLED;
+               break;
+       case 1:
+               bitToCheck = PORT_STATUS_F3_ENABLED;
+               break;
+       default:
+               break;
+       }
+
+       temp = ql_read_page0_reg(qdev, &port_regs->portStatus);
+       if (temp & bitToCheck) {
+               if (netif_msg_link(qdev))
+                       printk(KERN_DEBUG PFX
+                              "%s: is not link master.\n", qdev->ndev->name);
+               return 0;
+       } else {
+               if (netif_msg_link(qdev))
+                       printk(KERN_DEBUG PFX
+                              "%s: is link master.\n", qdev->ndev->name);
+               return 1;
+       }
+}
+
+static void ql_phy_reset_ex(struct ql3_adapter *qdev, u32 mac_index)
+{
+       ql_mii_write_reg_ex(qdev, CONTROL_REG, PHY_CTRL_SOFT_RESET, mac_index);
+}
+
+static void ql_phy_start_neg_ex(struct ql3_adapter *qdev, u32 mac_index)
+{
+       u16 reg;
+
+       ql_mii_write_reg_ex(qdev, PHY_NEG_ADVER,
+                           PHY_NEG_PAUSE | PHY_NEG_ADV_SPEED | 1, mac_index);
+
+       ql_mii_read_reg_ex(qdev, CONTROL_REG, &reg, mac_index);
+       ql_mii_write_reg_ex(qdev, CONTROL_REG, reg | PHY_CTRL_RESTART_NEG,
+                           mac_index);
+}
+
+static void ql_phy_init_ex(struct ql3_adapter *qdev, u32 mac_index)
+{
+       ql_phy_reset_ex(qdev, mac_index);
+       ql_phy_start_neg_ex(qdev, mac_index);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static u32 ql_get_link_state(struct ql3_adapter *qdev)
+{
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+       u32 bitToCheck = 0;
+       u32 temp, linkState;
+
+       switch (qdev->mac_index) {
+       case 0:
+               bitToCheck = PORT_STATUS_UP0;
+               break;
+       case 1:
+               bitToCheck = PORT_STATUS_UP1;
+               break;
+       }
+       temp = ql_read_page0_reg(qdev, &port_regs->portStatus);
+       if (temp & bitToCheck) {
+               linkState = LS_UP;
+       } else {
+               linkState = LS_DOWN;
+               if (netif_msg_link(qdev))
+                       printk(KERN_WARNING PFX
+                              "%s: Link is down.\n", qdev->ndev->name);
+       }
+       return linkState;
+}
+
+static int ql_port_start(struct ql3_adapter *qdev)
+{
+       if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
+               (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+                        2) << 7))
+               return -1;
+
+       if (ql_is_fiber(qdev)) {
+               ql_petbi_init(qdev);
+       } else {
+               /* Copper port */
+               ql_phy_init_ex(qdev, qdev->mac_index);
+       }
+
+       ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
+       return 0;
+}
+
+static int ql_finish_auto_neg(struct ql3_adapter *qdev)
+{
+
+       if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
+               (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+                        2) << 7))
+               return -1;
+
+       if (!ql_auto_neg_error(qdev)) {
+               if (test_bit(QL_LINK_MASTER,&qdev->flags)) {
+                       /* configure the MAC */
+                       if (netif_msg_link(qdev))
+                               printk(KERN_DEBUG PFX
+                                      "%s: Configuring link.\n",
+                                      qdev->ndev->
+                                      name);
+                       ql_mac_cfg_soft_reset(qdev, 1);
+                       ql_mac_cfg_gig(qdev,
+                                      (ql_get_link_speed
+                                       (qdev) ==
+                                       SPEED_1000));
+                       ql_mac_cfg_full_dup(qdev,
+                                           ql_is_link_full_dup
+                                           (qdev));
+                       ql_mac_cfg_pause(qdev,
+                                        ql_is_neg_pause
+                                        (qdev));
+                       ql_mac_cfg_soft_reset(qdev, 0);
+
+                       /* enable the MAC */
+                       if (netif_msg_link(qdev))
+                               printk(KERN_DEBUG PFX
+                                      "%s: Enabling mac.\n",
+                                      qdev->ndev->
+                                              name);
+                       ql_mac_enable(qdev, 1);
+               }
+
+               if (netif_msg_link(qdev))
+                       printk(KERN_DEBUG PFX
+                              "%s: Change port_link_state LS_DOWN to LS_UP.\n",
+                              qdev->ndev->name);
+               qdev->port_link_state = LS_UP;
+               netif_start_queue(qdev->ndev);
+               netif_carrier_on(qdev->ndev);
+               if (netif_msg_link(qdev))
+                       printk(KERN_INFO PFX
+                              "%s: Link is up at %d Mbps, %s duplex.\n",
+                              qdev->ndev->name,
+                              ql_get_link_speed(qdev),
+                              ql_is_link_full_dup(qdev)
+                              ? "full" : "half");
+
+       } else {        /* Remote error detected */
+
+               if (test_bit(QL_LINK_MASTER,&qdev->flags)) {
+                       if (netif_msg_link(qdev))
+                               printk(KERN_DEBUG PFX
+                                      "%s: Remote error detected. "
+                                      "Calling ql_port_start().\n",
+                                      qdev->ndev->
+                                      name);
+                       /*
+                        * ql_port_start() is shared code and needs
+                        * to lock the PHY on it's own.
+                        */
+                       ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
+                       if(ql_port_start(qdev)) {/* Restart port */
+                               return -1;
+                       } else
+                               return 0;
+               }
+       }
+       ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
+       return 0;
+}
+
+static void ql_link_state_machine(struct ql3_adapter *qdev)
+{
+       u32 curr_link_state;
+       unsigned long hw_flags;
+
+       spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+
+       curr_link_state = ql_get_link_state(qdev);
+
+       if (test_bit(QL_RESET_ACTIVE,&qdev->flags)) {
+               if (netif_msg_link(qdev))
+                       printk(KERN_INFO PFX
+                              "%s: Reset in progress, skip processing link "
+                              "state.\n", qdev->ndev->name);
+               return;
+       }
+
+       switch (qdev->port_link_state) {
+       default:
+               if (test_bit(QL_LINK_MASTER,&qdev->flags)) {
+                       ql_port_start(qdev);
+               }
+               qdev->port_link_state = LS_DOWN;
+               /* Fall Through */
+
+       case LS_DOWN:
+               if (netif_msg_link(qdev))
+                       printk(KERN_DEBUG PFX
+                              "%s: port_link_state = LS_DOWN.\n",
+                              qdev->ndev->name);
+               if (curr_link_state == LS_UP) {
+                       if (netif_msg_link(qdev))
+                               printk(KERN_DEBUG PFX
+                                      "%s: curr_link_state = LS_UP.\n",
+                                      qdev->ndev->name);
+                       if (ql_is_auto_neg_complete(qdev))
+                               ql_finish_auto_neg(qdev);
+
+                       if (qdev->port_link_state == LS_UP)
+                               ql_link_down_detect_clear(qdev);
+
+               }
+               break;
+
+       case LS_UP:
+               /*
+                * See if the link is currently down or went down and came
+                * back up
+                */
+               if ((curr_link_state == LS_DOWN) || ql_link_down_detect(qdev)) {
+                       if (netif_msg_link(qdev))
+                               printk(KERN_INFO PFX "%s: Link is down.\n",
+                                      qdev->ndev->name);
+                       qdev->port_link_state = LS_DOWN;
+               }
+               break;
+       }
+       spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+}
+
+/*
+ * Caller must take hw_lock and QL_PHY_GIO_SEM.
+ */
+static void ql_get_phy_owner(struct ql3_adapter *qdev)
+{
+       if (ql_this_adapter_controls_port(qdev, qdev->mac_index))
+               set_bit(QL_LINK_MASTER,&qdev->flags);
+       else
+               clear_bit(QL_LINK_MASTER,&qdev->flags);
+}
+
+/*
+ * Caller must take hw_lock and QL_PHY_GIO_SEM.
+ */
+static void ql_init_scan_mode(struct ql3_adapter *qdev)
+{
+       ql_mii_enable_scan_mode(qdev);
+
+       if (test_bit(QL_LINK_OPTICAL,&qdev->flags)) {
+               if (ql_this_adapter_controls_port(qdev, qdev->mac_index))
+                       ql_petbi_init_ex(qdev, qdev->mac_index);
+       } else {
+               if (ql_this_adapter_controls_port(qdev, qdev->mac_index))
+                       ql_phy_init_ex(qdev, qdev->mac_index);
+       }
+}
+
+/*
+ * MII_Setup needs to be called before taking the PHY out of reset so that the
+ * management interface clock speed can be set properly.  It would be better if
+ * we had a way to disable MDC until after the PHY is out of reset, but we
+ * don't have that capability.
+ */
+static int ql_mii_setup(struct ql3_adapter *qdev)
+{
+       u32 reg;
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+
+       if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
+                       (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+                        2) << 7))
+               return -1;
+
+       /* Divide 125MHz clock by 28 to meet PHY timing requirements */
+       reg = MAC_MII_CONTROL_CLK_SEL_DIV28;
+
+       ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,
+                          reg | ((MAC_MII_CONTROL_CLK_SEL_MASK) << 16));
+
+       ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
+       return 0;
+}
+
+static u32 ql_supported_modes(struct ql3_adapter *qdev)
+{
+       u32 supported;
+
+       if (test_bit(QL_LINK_OPTICAL,&qdev->flags)) {
+               supported = SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE
+                   | SUPPORTED_Autoneg;
+       } else {
+               supported = SUPPORTED_10baseT_Half
+                   | SUPPORTED_10baseT_Full
+                   | SUPPORTED_100baseT_Half
+                   | SUPPORTED_100baseT_Full
+                   | SUPPORTED_1000baseT_Half
+                   | SUPPORTED_1000baseT_Full
+                   | SUPPORTED_Autoneg | SUPPORTED_TP;
+       }
+
+       return supported;
+}
+
+static int ql_get_auto_cfg_status(struct ql3_adapter *qdev)
+{
+       int status;
+       unsigned long hw_flags;
+       spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+       if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
+               (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+                        2) << 7))
+               return 0;
+       status = ql_is_auto_cfg(qdev);
+       ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
+       spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+       return status;
+}
+
+static u32 ql_get_speed(struct ql3_adapter *qdev)
+{
+       u32 status;
+       unsigned long hw_flags;
+       spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+       if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
+               (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+                        2) << 7))
+               return 0;
+       status = ql_get_link_speed(qdev);
+       ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
+       spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+       return status;
+}
+
+static int ql_get_full_dup(struct ql3_adapter *qdev)
+{
+       int status;
+       unsigned long hw_flags;
+       spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+       if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
+               (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+                        2) << 7))
+               return 0;
+       status = ql_is_link_full_dup(qdev);
+       ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
+       spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+       return status;
+}
+
+
+static int ql_get_settings(struct net_device *ndev, struct ethtool_cmd *ecmd)
+{
+       struct ql3_adapter *qdev = netdev_priv(ndev);
+
+       ecmd->transceiver = XCVR_INTERNAL;
+       ecmd->supported = ql_supported_modes(qdev);
+
+       if (test_bit(QL_LINK_OPTICAL,&qdev->flags)) {
+               ecmd->port = PORT_FIBRE;
+       } else {
+               ecmd->port = PORT_TP;
+               ecmd->phy_address = qdev->PHYAddr;
+       }
+       ecmd->advertising = ql_supported_modes(qdev);
+       ecmd->autoneg = ql_get_auto_cfg_status(qdev);
+       ecmd->speed = ql_get_speed(qdev);
+       ecmd->duplex = ql_get_full_dup(qdev);
+       return 0;
+}
+
+static void ql_get_drvinfo(struct net_device *ndev,
+                          struct ethtool_drvinfo *drvinfo)
+{
+       struct ql3_adapter *qdev = netdev_priv(ndev);
+       strncpy(drvinfo->driver, ql3xxx_driver_name, 32);
+       strncpy(drvinfo->version, ql3xxx_driver_version, 32);
+       strncpy(drvinfo->fw_version, "N/A", 32);
+       strncpy(drvinfo->bus_info, pci_name(qdev->pdev), 32);
+       drvinfo->n_stats = 0;
+       drvinfo->testinfo_len = 0;
+       drvinfo->regdump_len = 0;
+       drvinfo->eedump_len = 0;
+}
+
+static u32 ql_get_msglevel(struct net_device *ndev)
+{
+       struct ql3_adapter *qdev = netdev_priv(ndev);
+       return qdev->msg_enable;
+}
+
+static void ql_set_msglevel(struct net_device *ndev, u32 value)
+{
+       struct ql3_adapter *qdev = netdev_priv(ndev);
+       qdev->msg_enable = value;
+}
+
+static struct ethtool_ops ql3xxx_ethtool_ops = {
+       .get_settings = ql_get_settings,
+       .get_drvinfo = ql_get_drvinfo,
+       .get_perm_addr = ethtool_op_get_perm_addr,
+       .get_link = ethtool_op_get_link,
+       .get_msglevel = ql_get_msglevel,
+       .set_msglevel = ql_set_msglevel,
+};
+
+static int ql_populate_free_queue(struct ql3_adapter *qdev)
+{
+       struct ql_rcv_buf_cb *lrg_buf_cb = qdev->lrg_buf_free_head;
+       u64 map;
+
+       while (lrg_buf_cb) {
+               if (!lrg_buf_cb->skb) {
+                       lrg_buf_cb->skb = dev_alloc_skb(qdev->lrg_buffer_len);
+                       if (unlikely(!lrg_buf_cb->skb)) {
+                               printk(KERN_DEBUG PFX
+                                      "%s: Failed dev_alloc_skb().\n",
+                                      qdev->ndev->name);
+                               break;
+                       } else {
+                               /*
+                                * We save some space to copy the ethhdr from
+                                * first buffer
+                                */
+                               skb_reserve(lrg_buf_cb->skb, QL_HEADER_SPACE);
+                               map = pci_map_single(qdev->pdev,
+                                                    lrg_buf_cb->skb->data,
+                                                    qdev->lrg_buffer_len -
+                                                    QL_HEADER_SPACE,
+                                                    PCI_DMA_FROMDEVICE);
+                               lrg_buf_cb->buf_phy_addr_low =
+                                   cpu_to_le32(LS_64BITS(map));
+                               lrg_buf_cb->buf_phy_addr_high =
+                                   cpu_to_le32(MS_64BITS(map));
+                               pci_unmap_addr_set(lrg_buf_cb, mapaddr, map);
+                               pci_unmap_len_set(lrg_buf_cb, maplen,
+                                                 qdev->lrg_buffer_len -
+                                                 QL_HEADER_SPACE);
+                               --qdev->lrg_buf_skb_check;
+                               if (!qdev->lrg_buf_skb_check)
+                                       return 1;
+                       }
+               }
+               lrg_buf_cb = lrg_buf_cb->next;
+       }
+       return 0;
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void ql_update_lrg_bufq_prod_index(struct ql3_adapter *qdev)
+{
+       struct bufq_addr_element *lrg_buf_q_ele;
+       int i;
+       struct ql_rcv_buf_cb *lrg_buf_cb;
+       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+
+       if ((qdev->lrg_buf_free_count >= 8)
+           && (qdev->lrg_buf_release_cnt >= 16)) {
+
+               if (qdev->lrg_buf_skb_check)
+                       if (!ql_populate_free_queue(qdev))
+                               return;
+
+               lrg_buf_q_ele = qdev->lrg_buf_next_free;
+
+               while ((qdev->lrg_buf_release_cnt >= 16)
+                      && (qdev->lrg_buf_free_count >= 8)) {
+
+                       for (i = 0; i < 8; i++) {
+                               lrg_buf_cb =
+                                   ql_get_from_lrg_buf_free_list(qdev);
+                               lrg_buf_q_ele->addr_high =
+                                   lrg_buf_cb->buf_phy_addr_high;
+                               lrg_buf_q_ele->addr_low =
+                                   lrg_buf_cb->buf_phy_addr_low;
+                               lrg_buf_q_ele++;
+
+                               qdev->lrg_buf_release_cnt--;
+                       }
+
+                       qdev->lrg_buf_q_producer_index++;
+
+                       if (qdev->lrg_buf_q_producer_index == NUM_LBUFQ_ENTRIES)
+                               qdev->lrg_buf_q_producer_index = 0;
+
+                       if (qdev->lrg_buf_q_producer_index ==
+                           (NUM_LBUFQ_ENTRIES - 1)) {
+                               lrg_buf_q_ele = qdev->lrg_buf_q_virt_addr;
+                       }
+               }
+
+               qdev->lrg_buf_next_free = lrg_buf_q_ele;
+
+               ql_write_common_reg(qdev,
+                                   (u32 *) & port_regs->CommonRegs.
+                                   rxLargeQProducerIndex,
+                                   qdev->lrg_buf_q_producer_index);
+       }
+}
+
+static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
+                                  struct ob_mac_iocb_rsp *mac_rsp)
+{
+       struct ql_tx_buf_cb *tx_cb;
+
+       tx_cb = &qdev->tx_buf[mac_rsp->transaction_id];
+       pci_unmap_single(qdev->pdev,
+                        pci_unmap_addr(tx_cb, mapaddr),
+                        pci_unmap_len(tx_cb, maplen), PCI_DMA_TODEVICE);
+       dev_kfree_skb_irq(tx_cb->skb);
+       qdev->stats.tx_packets++;
+       qdev->stats.tx_bytes += tx_cb->skb->len;
+       tx_cb->skb = NULL;
+       atomic_inc(&qdev->tx_count);
+}
+
+static void ql_process_mac_rx_intr(struct ql3_adapter *qdev,
+                                  struct ib_mac_iocb_rsp *ib_mac_rsp_ptr)
+{
+       long int offset;
+       u32 lrg_buf_phy_addr_low = 0;
+       struct ql_rcv_buf_cb *lrg_buf_cb1 = NULL;
+       struct ql_rcv_buf_cb *lrg_buf_cb2 = NULL;
+       u32 *curr_ial_ptr;
+       struct sk_buff *skb;
+       u16 length = le16_to_cpu(ib_mac_rsp_ptr->length);
+
+       /*
+        * Get the inbound address list (small buffer).
+        */
+       offset = qdev->small_buf_index * QL_SMALL_BUFFER_SIZE;
+       if (++qdev->small_buf_index == NUM_SMALL_BUFFERS)
+               qdev->small_buf_index = 0;
+
+       curr_ial_ptr = (u32 *) (qdev->small_buf_virt_addr + offset);
+       qdev->last_rsp_offset = qdev->small_buf_phy_addr_low + offset;
+       qdev->small_buf_release_cnt++;
+
+       /* start of first buffer */
+       lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
+       lrg_buf_cb1 = &qdev->lrg_buf[qdev->lrg_buf_index];
+       qdev->lrg_buf_release_cnt++;
+       if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS)
+               qdev->lrg_buf_index = 0;
+       curr_ial_ptr++;         /* 64-bit pointers require two incs. */
+       curr_ial_ptr++;
+
+       /* start of second buffer */
+       lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
+       lrg_buf_cb2 = &qdev->lrg_buf[qdev->lrg_buf_index];
+
+       /*
+        * Second buffer gets sent up the stack.
+        */
+       qdev->lrg_buf_release_cnt++;
+       if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS)
+               qdev->lrg_buf_index = 0;
+       skb = lrg_buf_cb2->skb;
+
+       qdev->stats.rx_packets++;
+       qdev->stats.rx_bytes += length;
+
+       skb_put(skb, length);
+       pci_unmap_single(qdev->pdev,
+                        pci_unmap_addr(lrg_buf_cb2, mapaddr),
+                        pci_unmap_len(lrg_buf_cb2, maplen),
+                        PCI_DMA_FROMDEVICE);
+       prefetch(skb->data);
+       skb->dev = qdev->ndev;
+       skb->ip_summed = CHECKSUM_NONE;
+       skb->protocol = eth_type_trans(skb, qdev->ndev);
+
+       netif_receive_skb(skb);
+       qdev->ndev->last_rx = jiffies;
+       lrg_buf_cb2->skb = NULL;
+
+       ql_release_to_lrg_buf_free_list(qdev, lrg_buf_cb1);
+       ql_release_to_lrg_buf_free_list(qdev, lrg_buf_cb2);
+}
+
+static void ql_process_macip_rx_intr(struct ql3_adapter *qdev,
+                                    struct ib_ip_iocb_rsp *ib_ip_rsp_ptr)
+{
+       long int offset;
+       u32 lrg_buf_phy_addr_low = 0;
+       struct ql_rcv_buf_cb *lrg_buf_cb1 = NULL;
+       struct ql_rcv_buf_cb *lrg_buf_cb2 = NULL;
+       u32 *curr_ial_ptr;
+       struct sk_buff *skb1, *skb2;
+       struct net_device *ndev = qdev->ndev;
+       u16 length = le16_to_cpu(ib_ip_rsp_ptr->length);
+       u16 size = 0;
+
+       /*
+        * Get the inbound address list (small buffer).
+        */
+
+       offset = qdev->small_buf_index * QL_SMALL_BUFFER_SIZE;
+       if (++qdev->small_buf_index == NUM_SMALL_BUFFERS)
+               qdev->small_buf_index = 0;
+       curr_ial_ptr = (u32 *) (qdev->small_buf_virt_addr + offset);
+       qdev->last_rsp_offset = qdev->small_buf_phy_addr_low + offset;
+       qdev->small_buf_release_cnt++;
+
+       /* start of first buffer */
+       lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
+       lrg_buf_cb1 = &qdev->lrg_buf[qdev->lrg_buf_index];
+
+       qdev->lrg_buf_release_cnt++;
+       if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS)
+               qdev->lrg_buf_index = 0;
+       skb1 = lrg_buf_cb1->skb;
+       curr_ial_ptr++;         /* 64-bit pointers require two incs. */
+       curr_ial_ptr++;
+
+       /* start of second buffer */
+       lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
+       lrg_buf_cb2 = &qdev->lrg_buf[qdev->lrg_buf_index];
+       skb2 = lrg_buf_cb2->skb;
+       qdev->lrg_buf_release_cnt++;
+       if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS)
+               qdev->lrg_buf_index = 0;
+
+       qdev->stats.rx_packets++;
+       qdev->stats.rx_bytes += length;
+
+       /*
+        * Copy the ethhdr from first buffer to second. This
+        * is necessary for IP completions.
+        */
+       if (*((u16 *) skb1->data) != 0xFFFF)
+               size = VLAN_ETH_HLEN;
+       else
+               size = ETH_HLEN;
+
+       skb_put(skb2, length);  /* Just the second buffer length here. */
+       pci_unmap_single(qdev->pdev,
+                        pci_unmap_addr(lrg_buf_cb2, mapaddr),
+                        pci_unmap_len(lrg_buf_cb2, maplen),
+                        PCI_DMA_FROMDEVICE);
+       prefetch(skb2->data);
+
+       memcpy(skb_push(skb2, size), skb1->data + VLAN_ID_LEN, size);
+       skb2->dev = qdev->ndev;
+       skb2->ip_summed = CHECKSUM_NONE;
+       skb2->protocol = eth_type_trans(skb2, qdev->ndev);
+
+       netif_receive_skb(skb2);
+       ndev->last_rx = jiffies;
+       lrg_buf_cb2->skb = NULL;
+
+       ql_release_to_lrg_buf_free_list(qdev, lrg_buf_cb1);
+       ql_release_to_lrg_buf_free_list(qdev, lrg_buf_cb2);
+}
+
+static int ql_tx_rx_clean(struct ql3_adapter *qdev,
+                         int *tx_cleaned, int *rx_cleaned, int work_to_do)
+{
+       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+       struct net_rsp_iocb *net_rsp;
+       struct net_device *ndev = qdev->ndev;
+       unsigned long hw_flags;
+
+       /* While there are entries in the completion queue. */
+       while ((cpu_to_le32(*(qdev->prsp_producer_index)) !=
+               qdev->rsp_consumer_index) && (*rx_cleaned < work_to_do)) {
+
+               net_rsp = qdev->rsp_current;
+               switch (net_rsp->opcode) {
+
+               case OPCODE_OB_MAC_IOCB_FN0:
+               case OPCODE_OB_MAC_IOCB_FN2:
+                       ql_process_mac_tx_intr(qdev, (struct ob_mac_iocb_rsp *)
+                                              net_rsp);
+                       (*tx_cleaned)++;
+                       break;
+
+               case OPCODE_IB_MAC_IOCB:
+                       ql_process_mac_rx_intr(qdev, (struct ib_mac_iocb_rsp *)
+                                              net_rsp);
+                       (*rx_cleaned)++;
+                       break;
+
+               case OPCODE_IB_IP_IOCB:
+                       ql_process_macip_rx_intr(qdev, (struct ib_ip_iocb_rsp *)
+                                                net_rsp);
+                       (*rx_cleaned)++;
+                       break;
+               default:
+                       {
+                               u32 *tmp = (u32 *) net_rsp;
+                               printk(KERN_ERR PFX
+                                      "%s: Hit default case, not "
+                                      "handled!\n"
+                                      "        dropping the packet, opcode = "
+                                      "%x.\n",
+                                      ndev->name, net_rsp->opcode);
+                               printk(KERN_ERR PFX
+                                      "0x%08lx 0x%08lx 0x%08lx 0x%08lx \n",
+                                      (unsigned long int)tmp[0],
+                                      (unsigned long int)tmp[1],
+                                      (unsigned long int)tmp[2],
+                                      (unsigned long int)tmp[3]);
+                       }
+               }
+
+               qdev->rsp_consumer_index++;
+
+               if (qdev->rsp_consumer_index == NUM_RSP_Q_ENTRIES) {
+                       qdev->rsp_consumer_index = 0;
+                       qdev->rsp_current = qdev->rsp_q_virt_addr;
+               } else {
+                       qdev->rsp_current++;
+               }
+       }
+
+       spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+
+       ql_update_lrg_bufq_prod_index(qdev);
+
+       if (qdev->small_buf_release_cnt >= 16) {
+               while (qdev->small_buf_release_cnt >= 16) {
+                       qdev->small_buf_q_producer_index++;
+
+                       if (qdev->small_buf_q_producer_index ==
+                           NUM_SBUFQ_ENTRIES)
+                               qdev->small_buf_q_producer_index = 0;
+                       qdev->small_buf_release_cnt -= 8;
+               }
+
+               ql_write_common_reg(qdev,
+                                   (u32 *) & port_regs->CommonRegs.
+                                   rxSmallQProducerIndex,
+                                   qdev->small_buf_q_producer_index);
+       }
+
+       ql_write_common_reg(qdev,
+                           (u32 *) & port_regs->CommonRegs.rspQConsumerIndex,
+                           qdev->rsp_consumer_index);
+       spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
+       if (unlikely(netif_queue_stopped(qdev->ndev))) {
+               if (netif_queue_stopped(qdev->ndev) &&
+                   (atomic_read(&qdev->tx_count) > (NUM_REQ_Q_ENTRIES / 4)))
+                       netif_wake_queue(qdev->ndev);
+       }
+
+       return *tx_cleaned + *rx_cleaned;
+}
+
+static int ql_poll(struct net_device *ndev, int *budget)
+{
+       struct ql3_adapter *qdev = netdev_priv(ndev);
+       int work_to_do = min(*budget, ndev->quota);
+       int rx_cleaned = 0, tx_cleaned = 0;
+
+       if (!netif_carrier_ok(ndev))
+               goto quit_polling;
+
+       ql_tx_rx_clean(qdev, &tx_cleaned, &rx_cleaned, work_to_do);
+       *budget -= rx_cleaned;
+       ndev->quota -= rx_cleaned;
+
+       if ((!tx_cleaned && !rx_cleaned) || !netif_running(ndev)) {
+quit_polling:
+               netif_rx_complete(ndev);
+               ql_enable_interrupts(qdev);
+               return 0;
+       }
+       return 1;
+}
+
+static irqreturn_t ql3xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+
+       struct net_device *ndev = dev_id;
+       struct ql3_adapter *qdev = netdev_priv(ndev);
+       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+       u32 value;
+       int handled = 1;
+       u32 var;
+
+       port_regs = qdev->mem_map_registers;
+
+       value =
+           ql_read_common_reg_l(qdev, &port_regs->CommonRegs.ispControlStatus);
+
+       if (value & (ISP_CONTROL_FE | ISP_CONTROL_RI)) {
+               spin_lock(&qdev->adapter_lock);
+               netif_stop_queue(qdev->ndev);
+               netif_carrier_off(qdev->ndev);
+               ql_disable_interrupts(qdev);
+               qdev->port_link_state = LS_DOWN;
+               set_bit(QL_RESET_ACTIVE,&qdev->flags) ;
+
+               if (value & ISP_CONTROL_FE) {
+                       /*
+                        * Chip Fatal Error.
+                        */
+                       var =
+                           ql_read_page0_reg_l(qdev,
+                                             &port_regs->PortFatalErrStatus);
+                       printk(KERN_WARNING PFX
+                              "%s: Resetting chip. PortFatalErrStatus "
+                              "register = 0x%x\n", ndev->name, var);
+                       set_bit(QL_RESET_START,&qdev->flags) ;
+               } else {
+                       /*
+                        * Soft Reset Requested.
+                        */
+                       set_bit(QL_RESET_PER_SCSI,&qdev->flags) ;
+                       printk(KERN_ERR PFX
+                              "%s: Another function issued a reset to the "
+                              "chip. ISR value = %x.\n", ndev->name, value);
+               }
+               queue_work(qdev->workqueue, &qdev->reset_work);
+               spin_unlock(&qdev->adapter_lock);
+       } else if (value & ISP_IMR_DISABLE_CMPL_INT) {
+               ql_disable_interrupts(qdev);
+               if (likely(netif_rx_schedule_prep(ndev)))
+                       __netif_rx_schedule(ndev);
+               else
+                       ql_enable_interrupts(qdev);
+       } else {
+               return IRQ_NONE;
+       }
+
+       return IRQ_RETVAL(handled);
+}
+
+static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
+{
+       struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
+       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+       struct ql_tx_buf_cb *tx_cb;
+       struct ob_mac_iocb_req *mac_iocb_ptr;
+       u64 map;
+
+       if (unlikely(atomic_read(&qdev->tx_count) < 2)) {
+               if (!netif_queue_stopped(ndev))
+                       netif_stop_queue(ndev);
+               return NETDEV_TX_BUSY;
+       }
+       tx_cb = &qdev->tx_buf[qdev->req_producer_index] ;
+       mac_iocb_ptr = tx_cb->queue_entry;
+       memset((void *)mac_iocb_ptr, 0, sizeof(struct ob_mac_iocb_req));
+       mac_iocb_ptr->opcode = qdev->mac_ob_opcode;
+       mac_iocb_ptr->flags |= qdev->mb_bit_mask;
+       mac_iocb_ptr->transaction_id = qdev->req_producer_index;
+       mac_iocb_ptr->data_len = cpu_to_le16((u16) skb->len);
+       tx_cb->skb = skb;
+       map = pci_map_single(qdev->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
+       mac_iocb_ptr->buf_addr0_low = cpu_to_le32(LS_64BITS(map));
+       mac_iocb_ptr->buf_addr0_high = cpu_to_le32(MS_64BITS(map));
+       mac_iocb_ptr->buf_0_len = cpu_to_le32(skb->len | OB_MAC_IOCB_REQ_E);
+       pci_unmap_addr_set(tx_cb, mapaddr, map);
+       pci_unmap_len_set(tx_cb, maplen, skb->len);
+       atomic_dec(&qdev->tx_count);
+
+       qdev->req_producer_index++;
+       if (qdev->req_producer_index == NUM_REQ_Q_ENTRIES)
+               qdev->req_producer_index = 0;
+       wmb();
+       ql_write_common_reg_l(qdev,
+                           (u32 *) & port_regs->CommonRegs.reqQProducerIndex,
+                           qdev->req_producer_index);
+
+       ndev->trans_start = jiffies;
+       if (netif_msg_tx_queued(qdev))
+               printk(KERN_DEBUG PFX "%s: tx queued, slot %d, len %d\n",
+                      ndev->name, qdev->req_producer_index, skb->len);
+
+       return NETDEV_TX_OK;
+}
+static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)
+{
+       qdev->req_q_size =
+           (u32) (NUM_REQ_Q_ENTRIES * sizeof(struct ob_mac_iocb_req));
+
+       qdev->req_q_virt_addr =
+           pci_alloc_consistent(qdev->pdev,
+                                (size_t) qdev->req_q_size,
+                                &qdev->req_q_phy_addr);
+
+       if ((qdev->req_q_virt_addr == NULL) ||
+           LS_64BITS(qdev->req_q_phy_addr) & (qdev->req_q_size - 1)) {
+               printk(KERN_ERR PFX "%s: reqQ failed.\n",
+                      qdev->ndev->name);
+               return -ENOMEM;
+       }
+
+       qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb);
+
+       qdev->rsp_q_virt_addr =
+           pci_alloc_consistent(qdev->pdev,
+                                (size_t) qdev->rsp_q_size,
+                                &qdev->rsp_q_phy_addr);
+
+       if ((qdev->rsp_q_virt_addr == NULL) ||
+           LS_64BITS(qdev->rsp_q_phy_addr) & (qdev->rsp_q_size - 1)) {
+               printk(KERN_ERR PFX
+                      "%s: rspQ allocation failed\n",
+                      qdev->ndev->name);
+               pci_free_consistent(qdev->pdev, (size_t) qdev->req_q_size,
+                                   qdev->req_q_virt_addr,
+                                   qdev->req_q_phy_addr);
+               return -ENOMEM;
+       }
+
+       set_bit(QL_ALLOC_REQ_RSP_Q_DONE,&qdev->flags);
+
+       return 0;
+}
+
+static void ql_free_net_req_rsp_queues(struct ql3_adapter *qdev)
+{
+       if (!test_bit(QL_ALLOC_REQ_RSP_Q_DONE,&qdev->flags)) {
+               printk(KERN_INFO PFX
+                      "%s: Already done.\n", qdev->ndev->name);
+               return;
+       }
+
+       pci_free_consistent(qdev->pdev,
+                           qdev->req_q_size,
+                           qdev->req_q_virt_addr, qdev->req_q_phy_addr);
+
+       qdev->req_q_virt_addr = NULL;
+
+       pci_free_consistent(qdev->pdev,
+                           qdev->rsp_q_size,
+                           qdev->rsp_q_virt_addr, qdev->rsp_q_phy_addr);
+
+       qdev->rsp_q_virt_addr = NULL;
+
+       clear_bit(QL_ALLOC_REQ_RSP_Q_DONE,&qdev->flags);
+}
+
+static int ql_alloc_buffer_queues(struct ql3_adapter *qdev)
+{
+       /* Create Large Buffer Queue */
+       qdev->lrg_buf_q_size =
+           NUM_LBUFQ_ENTRIES * sizeof(struct lrg_buf_q_entry);
+       if (qdev->lrg_buf_q_size < PAGE_SIZE)
+               qdev->lrg_buf_q_alloc_size = PAGE_SIZE;
+       else
+               qdev->lrg_buf_q_alloc_size = qdev->lrg_buf_q_size * 2;
+
+       qdev->lrg_buf_q_alloc_virt_addr =
+           pci_alloc_consistent(qdev->pdev,
+                                qdev->lrg_buf_q_alloc_size,
+                                &qdev->lrg_buf_q_alloc_phy_addr);
+
+       if (qdev->lrg_buf_q_alloc_virt_addr == NULL) {
+               printk(KERN_ERR PFX
+                      "%s: lBufQ failed\n", qdev->ndev->name);
+               return -ENOMEM;
+       }
+       qdev->lrg_buf_q_virt_addr = qdev->lrg_buf_q_alloc_virt_addr;
+       qdev->lrg_buf_q_phy_addr = qdev->lrg_buf_q_alloc_phy_addr;
+
+       /* Create Small Buffer Queue */
+       qdev->small_buf_q_size =
+           NUM_SBUFQ_ENTRIES * sizeof(struct lrg_buf_q_entry);
+       if (qdev->small_buf_q_size < PAGE_SIZE)
+               qdev->small_buf_q_alloc_size = PAGE_SIZE;
+       else
+               qdev->small_buf_q_alloc_size = qdev->small_buf_q_size * 2;
+
+       qdev->small_buf_q_alloc_virt_addr =
+           pci_alloc_consistent(qdev->pdev,
+                                qdev->small_buf_q_alloc_size,
+                                &qdev->small_buf_q_alloc_phy_addr);
+
+       if (qdev->small_buf_q_alloc_virt_addr == NULL) {
+               printk(KERN_ERR PFX
+                      "%s: Small Buffer Queue allocation failed.\n",
+                      qdev->ndev->name);
+               pci_free_consistent(qdev->pdev, qdev->lrg_buf_q_alloc_size,
+                                   qdev->lrg_buf_q_alloc_virt_addr,
+                                   qdev->lrg_buf_q_alloc_phy_addr);
+               return -ENOMEM;
+       }
+
+       qdev->small_buf_q_virt_addr = qdev->small_buf_q_alloc_virt_addr;
+       qdev->small_buf_q_phy_addr = qdev->small_buf_q_alloc_phy_addr;
+       set_bit(QL_ALLOC_BUFQS_DONE,&qdev->flags);
+       return 0;
+}
+
+static void ql_free_buffer_queues(struct ql3_adapter *qdev)
+{
+       if (!test_bit(QL_ALLOC_BUFQS_DONE,&qdev->flags)) {
+               printk(KERN_INFO PFX
+                      "%s: Already done.\n", qdev->ndev->name);
+               return;
+       }
+
+       pci_free_consistent(qdev->pdev,
+                           qdev->lrg_buf_q_alloc_size,
+                           qdev->lrg_buf_q_alloc_virt_addr,
+                           qdev->lrg_buf_q_alloc_phy_addr);
+
+       qdev->lrg_buf_q_virt_addr = NULL;
+
+       pci_free_consistent(qdev->pdev,
+                           qdev->small_buf_q_alloc_size,
+                           qdev->small_buf_q_alloc_virt_addr,
+                           qdev->small_buf_q_alloc_phy_addr);
+
+       qdev->small_buf_q_virt_addr = NULL;
+
+       clear_bit(QL_ALLOC_BUFQS_DONE,&qdev->flags);
+}
+
+static int ql_alloc_small_buffers(struct ql3_adapter *qdev)
+{
+       int i;
+       struct bufq_addr_element *small_buf_q_entry;
+
+       /* Currently we allocate on one of memory and use it for smallbuffers */
+       qdev->small_buf_total_size =
+           (QL_ADDR_ELE_PER_BUFQ_ENTRY * NUM_SBUFQ_ENTRIES *
+            QL_SMALL_BUFFER_SIZE);
+
+       qdev->small_buf_virt_addr =
+           pci_alloc_consistent(qdev->pdev,
+                                qdev->small_buf_total_size,
+                                &qdev->small_buf_phy_addr);
+
+       if (qdev->small_buf_virt_addr == NULL) {
+               printk(KERN_ERR PFX
+                      "%s: Failed to get small buffer memory.\n",
+                      qdev->ndev->name);
+               return -ENOMEM;
+       }
+
+       qdev->small_buf_phy_addr_low = LS_64BITS(qdev->small_buf_phy_addr);
+       qdev->small_buf_phy_addr_high = MS_64BITS(qdev->small_buf_phy_addr);
+
+       small_buf_q_entry = qdev->small_buf_q_virt_addr;
+
+       qdev->last_rsp_offset = qdev->small_buf_phy_addr_low;
+
+       /* Initialize the small buffer queue. */
+       for (i = 0; i < (QL_ADDR_ELE_PER_BUFQ_ENTRY * NUM_SBUFQ_ENTRIES); i++) {
+               small_buf_q_entry->addr_high =
+                   cpu_to_le32(qdev->small_buf_phy_addr_high);
+               small_buf_q_entry->addr_low =
+                   cpu_to_le32(qdev->small_buf_phy_addr_low +
+                               (i * QL_SMALL_BUFFER_SIZE));
+               small_buf_q_entry++;
+       }
+       qdev->small_buf_index = 0;
+       set_bit(QL_ALLOC_SMALL_BUF_DONE,&qdev->flags);
+       return 0;
+}
+
+static void ql_free_small_buffers(struct ql3_adapter *qdev)
+{
+       if (!test_bit(QL_ALLOC_SMALL_BUF_DONE,&qdev->flags)) {
+               printk(KERN_INFO PFX
+                      "%s: Already done.\n", qdev->ndev->name);
+               return;
+       }
+       if (qdev->small_buf_virt_addr != NULL) {
+               pci_free_consistent(qdev->pdev,
+                                   qdev->small_buf_total_size,
+                                   qdev->small_buf_virt_addr,
+                                   qdev->small_buf_phy_addr);
+
+               qdev->small_buf_virt_addr = NULL;
+       }
+}
+
+static void ql_free_large_buffers(struct ql3_adapter *qdev)
+{
+       int i = 0;
+       struct ql_rcv_buf_cb *lrg_buf_cb;
+
+       for (i = 0; i < NUM_LARGE_BUFFERS; i++) {
+               lrg_buf_cb = &qdev->lrg_buf[i];
+               if (lrg_buf_cb->skb) {
+                       dev_kfree_skb(lrg_buf_cb->skb);
+                       pci_unmap_single(qdev->pdev,
+                                        pci_unmap_addr(lrg_buf_cb, mapaddr),
+                                        pci_unmap_len(lrg_buf_cb, maplen),
+                                        PCI_DMA_FROMDEVICE);
+                       memset(lrg_buf_cb, 0, sizeof(struct ql_rcv_buf_cb));
+               } else {
+                       break;
+               }
+       }
+}
+
+static void ql_init_large_buffers(struct ql3_adapter *qdev)
+{
+       int i;
+       struct ql_rcv_buf_cb *lrg_buf_cb;
+       struct bufq_addr_element *buf_addr_ele = qdev->lrg_buf_q_virt_addr;
+
+       for (i = 0; i < NUM_LARGE_BUFFERS; i++) {
+               lrg_buf_cb = &qdev->lrg_buf[i];
+               buf_addr_ele->addr_high = lrg_buf_cb->buf_phy_addr_high;
+               buf_addr_ele->addr_low = lrg_buf_cb->buf_phy_addr_low;
+               buf_addr_ele++;
+       }
+       qdev->lrg_buf_index = 0;
+       qdev->lrg_buf_skb_check = 0;
+}
+
+static int ql_alloc_large_buffers(struct ql3_adapter *qdev)
+{
+       int i;
+       struct ql_rcv_buf_cb *lrg_buf_cb;
+       struct sk_buff *skb;
+       u64 map;
+
+       for (i = 0; i < NUM_LARGE_BUFFERS; i++) {
+               skb = dev_alloc_skb(qdev->lrg_buffer_len);
+               if (unlikely(!skb)) {
+                       /* Better luck next round */
+                       printk(KERN_ERR PFX
+                              "%s: large buff alloc failed, "
+                              "for %d bytes at index %d.\n",
+                              qdev->ndev->name,
+                              qdev->lrg_buffer_len * 2, i);
+                       ql_free_large_buffers(qdev);
+                       return -ENOMEM;
+               } else {
+
+                       lrg_buf_cb = &qdev->lrg_buf[i];
+                       memset(lrg_buf_cb, 0, sizeof(struct ql_rcv_buf_cb));
+                       lrg_buf_cb->index = i;
+                       lrg_buf_cb->skb = skb;
+                       /*
+                        * We save some space to copy the ethhdr from first
+                        * buffer
+                        */
+                       skb_reserve(skb, QL_HEADER_SPACE);
+                       map = pci_map_single(qdev->pdev,
+                                            skb->data,
+                                            qdev->lrg_buffer_len -
+                                            QL_HEADER_SPACE,
+                                            PCI_DMA_FROMDEVICE);
+                       pci_unmap_addr_set(lrg_buf_cb, mapaddr, map);
+                       pci_unmap_len_set(lrg_buf_cb, maplen,
+                                         qdev->lrg_buffer_len -
+                                         QL_HEADER_SPACE);
+                       lrg_buf_cb->buf_phy_addr_low =
+                           cpu_to_le32(LS_64BITS(map));
+                       lrg_buf_cb->buf_phy_addr_high =
+                           cpu_to_le32(MS_64BITS(map));
+               }
+       }
+       return 0;
+}
+
+static void ql_create_send_free_list(struct ql3_adapter *qdev)
+{
+       struct ql_tx_buf_cb *tx_cb;
+       int i;
+       struct ob_mac_iocb_req *req_q_curr =
+                                       qdev->req_q_virt_addr;
+
+       /* Create free list of transmit buffers */
+       for (i = 0; i < NUM_REQ_Q_ENTRIES; i++) {
+               tx_cb = &qdev->tx_buf[i];
+               tx_cb->skb = NULL;
+               tx_cb->queue_entry = req_q_curr;
+               req_q_curr++;
+       }
+}
+
+static int ql_alloc_mem_resources(struct ql3_adapter *qdev)
+{
+       if (qdev->ndev->mtu == NORMAL_MTU_SIZE)
+               qdev->lrg_buffer_len = NORMAL_MTU_SIZE;
+       else if (qdev->ndev->mtu == JUMBO_MTU_SIZE) {
+               qdev->lrg_buffer_len = JUMBO_MTU_SIZE;
+       } else {
+               printk(KERN_ERR PFX
+                      "%s: Invalid mtu size.  Only 1500 and 9000 are accepted.\n",
+                      qdev->ndev->name);
+               return -ENOMEM;
+       }
+       qdev->lrg_buffer_len += VLAN_ETH_HLEN + VLAN_ID_LEN + QL_HEADER_SPACE;
+       qdev->max_frame_size =
+           (qdev->lrg_buffer_len - QL_HEADER_SPACE) + ETHERNET_CRC_SIZE;
+
+       /*
+        * First allocate a page of shared memory and use it for shadow
+        * locations of Network Request Queue Consumer Address Register and
+        * Network Completion Queue Producer Index Register
+        */
+       qdev->shadow_reg_virt_addr =
+           pci_alloc_consistent(qdev->pdev,
+                                PAGE_SIZE, &qdev->shadow_reg_phy_addr);
+
+       if (qdev->shadow_reg_virt_addr != NULL) {
+               qdev->preq_consumer_index = (u16 *) qdev->shadow_reg_virt_addr;
+               qdev->req_consumer_index_phy_addr_high =
+                   MS_64BITS(qdev->shadow_reg_phy_addr);
+               qdev->req_consumer_index_phy_addr_low =
+                   LS_64BITS(qdev->shadow_reg_phy_addr);
+
+               qdev->prsp_producer_index =
+                   (u32 *) (((u8 *) qdev->preq_consumer_index) + 8);
+               qdev->rsp_producer_index_phy_addr_high =
+                   qdev->req_consumer_index_phy_addr_high;
+               qdev->rsp_producer_index_phy_addr_low =
+                   qdev->req_consumer_index_phy_addr_low + 8;
+       } else {
+               printk(KERN_ERR PFX
+                      "%s: shadowReg Alloc failed.\n", qdev->ndev->name);
+               return -ENOMEM;
+       }
+
+       if (ql_alloc_net_req_rsp_queues(qdev) != 0) {
+               printk(KERN_ERR PFX
+                      "%s: ql_alloc_net_req_rsp_queues failed.\n",
+                      qdev->ndev->name);
+               goto err_req_rsp;
+       }
+
+       if (ql_alloc_buffer_queues(qdev) != 0) {
+               printk(KERN_ERR PFX
+                      "%s: ql_alloc_buffer_queues failed.\n",
+                      qdev->ndev->name);
+               goto err_buffer_queues;
+       }
+
+       if (ql_alloc_small_buffers(qdev) != 0) {
+               printk(KERN_ERR PFX
+                      "%s: ql_alloc_small_buffers failed\n", qdev->ndev->name);
+               goto err_small_buffers;
+       }
+
+       if (ql_alloc_large_buffers(qdev) != 0) {
+               printk(KERN_ERR PFX
+                      "%s: ql_alloc_large_buffers failed\n", qdev->ndev->name);
+               goto err_small_buffers;
+       }
+
+       /* Initialize the large buffer queue. */
+       ql_init_large_buffers(qdev);
+       ql_create_send_free_list(qdev);
+
+       qdev->rsp_current = qdev->rsp_q_virt_addr;
+
+       return 0;
+
+err_small_buffers:
+       ql_free_buffer_queues(qdev);
+err_buffer_queues:
+       ql_free_net_req_rsp_queues(qdev);
+err_req_rsp:
+       pci_free_consistent(qdev->pdev,
+                           PAGE_SIZE,
+                           qdev->shadow_reg_virt_addr,
+                           qdev->shadow_reg_phy_addr);
+
+       return -ENOMEM;
+}
+
+static void ql_free_mem_resources(struct ql3_adapter *qdev)
+{
+       ql_free_large_buffers(qdev);
+       ql_free_small_buffers(qdev);
+       ql_free_buffer_queues(qdev);
+       ql_free_net_req_rsp_queues(qdev);
+       if (qdev->shadow_reg_virt_addr != NULL) {
+               pci_free_consistent(qdev->pdev,
+                                   PAGE_SIZE,
+                                   qdev->shadow_reg_virt_addr,
+                                   qdev->shadow_reg_phy_addr);
+               qdev->shadow_reg_virt_addr = NULL;
+       }
+}
+
+static int ql_init_misc_registers(struct ql3_adapter *qdev)
+{
+       struct ql3xxx_local_ram_registers *local_ram =
+           (struct ql3xxx_local_ram_registers *)qdev->mem_map_registers;
+
+       if(ql_sem_spinlock(qdev, QL_DDR_RAM_SEM_MASK,
+                       (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+                        2) << 4))
+               return -1;
+
+       ql_write_page2_reg(qdev,
+                          &local_ram->bufletSize, qdev->nvram_data.bufletSize);
+
+       ql_write_page2_reg(qdev,
+                          &local_ram->maxBufletCount,
+                          qdev->nvram_data.bufletCount);
+
+       ql_write_page2_reg(qdev,
+                          &local_ram->freeBufletThresholdLow,
+                          (qdev->nvram_data.tcpWindowThreshold25 << 16) |
+                          (qdev->nvram_data.tcpWindowThreshold0));
+
+       ql_write_page2_reg(qdev,
+                          &local_ram->freeBufletThresholdHigh,
+                          qdev->nvram_data.tcpWindowThreshold50);
+
+       ql_write_page2_reg(qdev,
+                          &local_ram->ipHashTableBase,
+                          (qdev->nvram_data.ipHashTableBaseHi << 16) |
+                          qdev->nvram_data.ipHashTableBaseLo);
+       ql_write_page2_reg(qdev,
+                          &local_ram->ipHashTableCount,
+                          qdev->nvram_data.ipHashTableSize);
+       ql_write_page2_reg(qdev,
+                          &local_ram->tcpHashTableBase,
+                          (qdev->nvram_data.tcpHashTableBaseHi << 16) |
+                          qdev->nvram_data.tcpHashTableBaseLo);
+       ql_write_page2_reg(qdev,
+                          &local_ram->tcpHashTableCount,
+                          qdev->nvram_data.tcpHashTableSize);
+       ql_write_page2_reg(qdev,
+                          &local_ram->ncbBase,
+                          (qdev->nvram_data.ncbTableBaseHi << 16) |
+                          qdev->nvram_data.ncbTableBaseLo);
+       ql_write_page2_reg(qdev,
+                          &local_ram->maxNcbCount,
+                          qdev->nvram_data.ncbTableSize);
+       ql_write_page2_reg(qdev,
+                          &local_ram->drbBase,
+                          (qdev->nvram_data.drbTableBaseHi << 16) |
+                          qdev->nvram_data.drbTableBaseLo);
+       ql_write_page2_reg(qdev,
+                          &local_ram->maxDrbCount,
+                          qdev->nvram_data.drbTableSize);
+       ql_sem_unlock(qdev, QL_DDR_RAM_SEM_MASK);
+       return 0;
+}
+
+static int ql_adapter_initialize(struct ql3_adapter *qdev)
+{
+       u32 value;
+       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+       struct ql3xxx_host_memory_registers __iomem *hmem_regs =
+           (struct ql3xxx_host_memory_registers *)port_regs;
+       u32 delay = 10;
+       int status = 0;
+
+       if(ql_mii_setup(qdev))
+               return -1;
+
+       /* Bring out PHY out of reset */
+       ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+                           (ISP_SERIAL_PORT_IF_WE |
+                            (ISP_SERIAL_PORT_IF_WE << 16)));
+
+       qdev->port_link_state = LS_DOWN;
+       netif_carrier_off(qdev->ndev);
+
+       /* V2 chip fix for ARS-39168. */
+       ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+                           (ISP_SERIAL_PORT_IF_SDE |
+                            (ISP_SERIAL_PORT_IF_SDE << 16)));
+
+       /* Request Queue Registers */
+       *((u32 *) (qdev->preq_consumer_index)) = 0;
+       atomic_set(&qdev->tx_count,NUM_REQ_Q_ENTRIES);
+       qdev->req_producer_index = 0;
+
+       ql_write_page1_reg(qdev,
+                          &hmem_regs->reqConsumerIndexAddrHigh,
+                          qdev->req_consumer_index_phy_addr_high);
+       ql_write_page1_reg(qdev,
+                          &hmem_regs->reqConsumerIndexAddrLow,
+                          qdev->req_consumer_index_phy_addr_low);
+
+       ql_write_page1_reg(qdev,
+                          &hmem_regs->reqBaseAddrHigh,
+                          MS_64BITS(qdev->req_q_phy_addr));
+       ql_write_page1_reg(qdev,
+                          &hmem_regs->reqBaseAddrLow,
+                          LS_64BITS(qdev->req_q_phy_addr));
+       ql_write_page1_reg(qdev, &hmem_regs->reqLength, NUM_REQ_Q_ENTRIES);
+
+       /* Response Queue Registers */
+       *((u16 *) (qdev->prsp_producer_index)) = 0;
+       qdev->rsp_consumer_index = 0;
+       qdev->rsp_current = qdev->rsp_q_virt_addr;
+
+       ql_write_page1_reg(qdev,
+                          &hmem_regs->rspProducerIndexAddrHigh,
+                          qdev->rsp_producer_index_phy_addr_high);
+
+       ql_write_page1_reg(qdev,
+                          &hmem_regs->rspProducerIndexAddrLow,
+                          qdev->rsp_producer_index_phy_addr_low);
+
+       ql_write_page1_reg(qdev,
+                          &hmem_regs->rspBaseAddrHigh,
+                          MS_64BITS(qdev->rsp_q_phy_addr));
+
+       ql_write_page1_reg(qdev,
+                          &hmem_regs->rspBaseAddrLow,
+                          LS_64BITS(qdev->rsp_q_phy_addr));
+
+       ql_write_page1_reg(qdev, &hmem_regs->rspLength, NUM_RSP_Q_ENTRIES);
+
+       /* Large Buffer Queue */
+       ql_write_page1_reg(qdev,
+                          &hmem_regs->rxLargeQBaseAddrHigh,
+                          MS_64BITS(qdev->lrg_buf_q_phy_addr));
+
+       ql_write_page1_reg(qdev,
+                          &hmem_regs->rxLargeQBaseAddrLow,
+                          LS_64BITS(qdev->lrg_buf_q_phy_addr));
+
+       ql_write_page1_reg(qdev, &hmem_regs->rxLargeQLength, NUM_LBUFQ_ENTRIES);
+
+       ql_write_page1_reg(qdev,
+                          &hmem_regs->rxLargeBufferLength,
+                          qdev->lrg_buffer_len);
+
+       /* Small Buffer Queue */
+       ql_write_page1_reg(qdev,
+                          &hmem_regs->rxSmallQBaseAddrHigh,
+                          MS_64BITS(qdev->small_buf_q_phy_addr));
+
+       ql_write_page1_reg(qdev,
+                          &hmem_regs->rxSmallQBaseAddrLow,
+                          LS_64BITS(qdev->small_buf_q_phy_addr));
+
+       ql_write_page1_reg(qdev, &hmem_regs->rxSmallQLength, NUM_SBUFQ_ENTRIES);
+       ql_write_page1_reg(qdev,
+                          &hmem_regs->rxSmallBufferLength,
+                          QL_SMALL_BUFFER_SIZE);
+
+       qdev->small_buf_q_producer_index = NUM_SBUFQ_ENTRIES - 1;
+       qdev->small_buf_release_cnt = 8;
+       qdev->lrg_buf_q_producer_index = NUM_LBUFQ_ENTRIES - 1;
+       qdev->lrg_buf_release_cnt = 8;
+       qdev->lrg_buf_next_free =
+           (struct bufq_addr_element *)qdev->lrg_buf_q_virt_addr;
+       qdev->small_buf_index = 0;
+       qdev->lrg_buf_index = 0;
+       qdev->lrg_buf_free_count = 0;
+       qdev->lrg_buf_free_head = NULL;
+       qdev->lrg_buf_free_tail = NULL;
+
+       ql_write_common_reg(qdev,
+                           (u32 *) & port_regs->CommonRegs.
+                           rxSmallQProducerIndex,
+                           qdev->small_buf_q_producer_index);
+       ql_write_common_reg(qdev,
+                           (u32 *) & port_regs->CommonRegs.
+                           rxLargeQProducerIndex,
+                           qdev->lrg_buf_q_producer_index);
+
+       /*
+        * Find out if the chip has already been initialized.  If it has, then
+        * we skip some of the initialization.
+        */
+       clear_bit(QL_LINK_MASTER, &qdev->flags);
+       value = ql_read_page0_reg(qdev, &port_regs->portStatus);
+       if ((value & PORT_STATUS_IC) == 0) {
+
+               /* Chip has not been configured yet, so let it rip. */
+               if(ql_init_misc_registers(qdev)) {
+                       status = -1;
+                       goto out;
+               }
+
+               if (qdev->mac_index)
+                       ql_write_page0_reg(qdev,
+                                          &port_regs->mac1MaxFrameLengthReg,
+                                          qdev->max_frame_size);
+               else
+                       ql_write_page0_reg(qdev,
+                                          &port_regs->mac0MaxFrameLengthReg,
+                                          qdev->max_frame_size);
+
+               value = qdev->nvram_data.tcpMaxWindowSize;
+               ql_write_page0_reg(qdev, &port_regs->tcpMaxWindow, value);
+
+               value = (0xFFFF << 16) | qdev->nvram_data.extHwConfig;
+
+               if(ql_sem_spinlock(qdev, QL_FLASH_SEM_MASK,
+                               (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index)
+                                * 2) << 13)) {
+                       status = -1;
+                       goto out;
+               }
+               ql_write_page0_reg(qdev, &port_regs->ExternalHWConfig, value);
+               ql_write_page0_reg(qdev, &port_regs->InternalChipConfig,
+                                  (((INTERNAL_CHIP_SD | INTERNAL_CHIP_WE) <<
+                                    16) | (INTERNAL_CHIP_SD |
+                                           INTERNAL_CHIP_WE)));
+               ql_sem_unlock(qdev, QL_FLASH_SEM_MASK);
+       }
+
+
+       if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
+                       (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+                        2) << 7)) {
+               status = -1;
+               goto out;
+       }
+
+       ql_init_scan_mode(qdev);
+       ql_get_phy_owner(qdev);
+
+       /* Load the MAC Configuration */
+
+       /* Program lower 32 bits of the MAC address */
+       ql_write_page0_reg(qdev, &port_regs->macAddrIndirectPtrReg,
+                          (MAC_ADDR_INDIRECT_PTR_REG_RP_MASK << 16));
+       ql_write_page0_reg(qdev, &port_regs->macAddrDataReg,
+                          ((qdev->ndev->dev_addr[2] << 24)
+                           | (qdev->ndev->dev_addr[3] << 16)
+                           | (qdev->ndev->dev_addr[4] << 8)
+                           | qdev->ndev->dev_addr[5]));
+
+       /* Program top 16 bits of the MAC address */
+       ql_write_page0_reg(qdev, &port_regs->macAddrIndirectPtrReg,
+                          ((MAC_ADDR_INDIRECT_PTR_REG_RP_MASK << 16) | 1));
+       ql_write_page0_reg(qdev, &port_regs->macAddrDataReg,
+                          ((qdev->ndev->dev_addr[0] << 8)
+                           | qdev->ndev->dev_addr[1]));
+
+       /* Enable Primary MAC */
+       ql_write_page0_reg(qdev, &port_regs->macAddrIndirectPtrReg,
+                          ((MAC_ADDR_INDIRECT_PTR_REG_PE << 16) |
+                           MAC_ADDR_INDIRECT_PTR_REG_PE));
+
+       /* Clear Primary and Secondary IP addresses */
+       ql_write_page0_reg(qdev, &port_regs->ipAddrIndexReg,
+                          ((IP_ADDR_INDEX_REG_MASK << 16) |
+                           (qdev->mac_index << 2)));
+       ql_write_page0_reg(qdev, &port_regs->ipAddrDataReg, 0);
+
+       ql_write_page0_reg(qdev, &port_regs->ipAddrIndexReg,
+                          ((IP_ADDR_INDEX_REG_MASK << 16) |
+                           ((qdev->mac_index << 2) + 1)));
+       ql_write_page0_reg(qdev, &port_regs->ipAddrDataReg, 0);
+
+       ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
+
+       /* Indicate Configuration Complete */
+       ql_write_page0_reg(qdev,
+                          &port_regs->portControl,
+                          ((PORT_CONTROL_CC << 16) | PORT_CONTROL_CC));
+
+       do {
+               value = ql_read_page0_reg(qdev, &port_regs->portStatus);
+               if (value & PORT_STATUS_IC)
+                       break;
+               msleep(500);
+       } while (--delay);
+
+       if (delay == 0) {
+               printk(KERN_ERR PFX
+                      "%s: Hw Initialization timeout.\n", qdev->ndev->name);
+               status = -1;
+               goto out;
+       }
+
+       /* Enable Ethernet Function */
+       value =
+           (PORT_CONTROL_EF | PORT_CONTROL_ET | PORT_CONTROL_EI |
+            PORT_CONTROL_HH);
+       ql_write_page0_reg(qdev, &port_regs->portControl,
+                          ((value << 16) | value));
+
+out:
+       return status;
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static int ql_adapter_reset(struct ql3_adapter *qdev)
+{
+       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+       int status = 0;
+       u16 value;
+       int max_wait_time;
+
+       set_bit(QL_RESET_ACTIVE, &qdev->flags);
+       clear_bit(QL_RESET_DONE, &qdev->flags);
+
+       /*
+        * Issue soft reset to chip.
+        */
+       printk(KERN_DEBUG PFX
+              "%s: Issue soft reset to chip.\n",
+              qdev->ndev->name);
+       ql_write_common_reg(qdev,
+                           (u32 *) & port_regs->CommonRegs.ispControlStatus,
+                           ((ISP_CONTROL_SR << 16) | ISP_CONTROL_SR));
+
+       /* Wait 3 seconds for reset to complete. */
+       printk(KERN_DEBUG PFX
+              "%s: Wait 10 milliseconds for reset to complete.\n",
+              qdev->ndev->name);
+
+       /* Wait until the firmware tells us the Soft Reset is done */
+       max_wait_time = 5;
+       do {
+               value =
+                   ql_read_common_reg(qdev,
+                                      &port_regs->CommonRegs.ispControlStatus);
+               if ((value & ISP_CONTROL_SR) == 0)
+                       break;
+
+               ssleep(1);
+       } while ((--max_wait_time));
+
+       /*
+        * Also, make sure that the Network Reset Interrupt bit has been
+        * cleared after the soft reset has taken place.
+        */
+       value =
+           ql_read_common_reg(qdev, &port_regs->CommonRegs.ispControlStatus);
+       if (value & ISP_CONTROL_RI) {
+               printk(KERN_DEBUG PFX
+                      "ql_adapter_reset: clearing RI after reset.\n");
+               ql_write_common_reg(qdev,
+                                   (u32 *) & port_regs->CommonRegs.
+                                   ispControlStatus,
+                                   ((ISP_CONTROL_RI << 16) | ISP_CONTROL_RI));
+       }
+
+       if (max_wait_time == 0) {
+               /* Issue Force Soft Reset */
+               ql_write_common_reg(qdev,
+                                   (u32 *) & port_regs->CommonRegs.
+                                   ispControlStatus,
+                                   ((ISP_CONTROL_FSR << 16) |
+                                    ISP_CONTROL_FSR));
+               /*
+                * Wait until the firmware tells us the Force Soft Reset is
+                * done
+                */
+               max_wait_time = 5;
+               do {
+                       value =
+                           ql_read_common_reg(qdev,
+                                              &port_regs->CommonRegs.
+                                              ispControlStatus);
+                       if ((value & ISP_CONTROL_FSR) == 0) {
+                               break;
+                       }
+                       ssleep(1);
+               } while ((--max_wait_time));
+       }
+       if (max_wait_time == 0)
+               status = 1;
+
+       clear_bit(QL_RESET_ACTIVE, &qdev->flags);
+       set_bit(QL_RESET_DONE, &qdev->flags);
+       return status;
+}
+
+static void ql_set_mac_info(struct ql3_adapter *qdev)
+{
+       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+       u32 value, port_status;
+       u8 func_number;
+
+       /* Get the function number */
+       value =
+           ql_read_common_reg_l(qdev, &port_regs->CommonRegs.ispControlStatus);
+       func_number = (u8) ((value >> 4) & OPCODE_FUNC_ID_MASK);
+       port_status = ql_read_page0_reg(qdev, &port_regs->portStatus);
+       switch (value & ISP_CONTROL_FN_MASK) {
+       case ISP_CONTROL_FN0_NET:
+               qdev->mac_index = 0;
+               qdev->mac_ob_opcode = OUTBOUND_MAC_IOCB | func_number;
+               qdev->tcp_ob_opcode = OUTBOUND_TCP_IOCB | func_number;
+               qdev->update_ob_opcode = UPDATE_NCB_IOCB | func_number;
+               qdev->mb_bit_mask = FN0_MA_BITS_MASK;
+               qdev->PHYAddr = PORT0_PHY_ADDRESS;
+               if (port_status & PORT_STATUS_SM0)
+                       set_bit(QL_LINK_OPTICAL,&qdev->flags);
+               else
+                       clear_bit(QL_LINK_OPTICAL,&qdev->flags);
+               break;
+
+       case ISP_CONTROL_FN1_NET:
+               qdev->mac_index = 1;
+               qdev->mac_ob_opcode = OUTBOUND_MAC_IOCB | func_number;
+               qdev->tcp_ob_opcode = OUTBOUND_TCP_IOCB | func_number;
+               qdev->update_ob_opcode = UPDATE_NCB_IOCB | func_number;
+               qdev->mb_bit_mask = FN1_MA_BITS_MASK;
+               qdev->PHYAddr = PORT1_PHY_ADDRESS;
+               if (port_status & PORT_STATUS_SM1)
+                       set_bit(QL_LINK_OPTICAL,&qdev->flags);
+               else
+                       clear_bit(QL_LINK_OPTICAL,&qdev->flags);
+               break;
+
+       case ISP_CONTROL_FN0_SCSI:
+       case ISP_CONTROL_FN1_SCSI:
+       default:
+               printk(KERN_DEBUG PFX
+                      "%s: Invalid function number, ispControlStatus = 0x%x\n",
+                      qdev->ndev->name,value);
+               break;
+       }
+       qdev->numPorts = qdev->nvram_data.numPorts;
+}
+
+static void ql_display_dev_info(struct net_device *ndev)
+{
+       struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
+       struct pci_dev *pdev = qdev->pdev;
+
+       printk(KERN_INFO PFX
+              "\n%s Adapter %d RevisionID %d found on PCI slot %d.\n",
+              DRV_NAME, qdev->index, qdev->chip_rev_id, qdev->pci_slot);
+       printk(KERN_INFO PFX
+              "%s Interface.\n",
+              test_bit(QL_LINK_OPTICAL,&qdev->flags) ? "OPTICAL" : "COPPER");
+
+       /*
+        * Print PCI bus width/type.
+        */
+       printk(KERN_INFO PFX
+              "Bus interface is %s %s.\n",
+              ((qdev->pci_width == 64) ? "64-bit" : "32-bit"),
+              ((qdev->pci_x) ? "PCI-X" : "PCI"));
+
+       printk(KERN_INFO PFX
+              "mem  IO base address adjusted = 0x%p\n",
+              qdev->mem_map_registers);
+       printk(KERN_INFO PFX "Interrupt number = %d\n", pdev->irq);
+
+       if (netif_msg_probe(qdev))
+               printk(KERN_INFO PFX
+                      "%s: MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
+                      ndev->name, ndev->dev_addr[0], ndev->dev_addr[1],
+                      ndev->dev_addr[2], ndev->dev_addr[3], ndev->dev_addr[4],
+                      ndev->dev_addr[5]);
+}
+
+static int ql_adapter_down(struct ql3_adapter *qdev, int do_reset)
+{
+       struct net_device *ndev = qdev->ndev;
+       int retval = 0;
+
+       netif_stop_queue(ndev);
+       netif_carrier_off(ndev);
+
+       clear_bit(QL_ADAPTER_UP,&qdev->flags);
+       clear_bit(QL_LINK_MASTER,&qdev->flags);
+
+       ql_disable_interrupts(qdev);
+
+       free_irq(qdev->pdev->irq, ndev);
+
+       if (qdev->msi && test_bit(QL_MSI_ENABLED,&qdev->flags)) {
+               printk(KERN_INFO PFX
+                      "%s: calling pci_disable_msi().\n", qdev->ndev->name);
+               clear_bit(QL_MSI_ENABLED,&qdev->flags);
+               pci_disable_msi(qdev->pdev);
+       }
+
+       del_timer_sync(&qdev->adapter_timer);
+
+       netif_poll_disable(ndev);
+
+       if (do_reset) {
+               int soft_reset;
+               unsigned long hw_flags;
+
+               spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+               if (ql_wait_for_drvr_lock(qdev)) {
+                       if ((soft_reset = ql_adapter_reset(qdev))) {
+                               printk(KERN_ERR PFX
+                                      "%s: ql_adapter_reset(%d) FAILED!\n",
+                                      ndev->name, qdev->index);
+                       }
+                       printk(KERN_ERR PFX
+                               "%s: Releaseing driver lock via chip reset.\n",ndev->name);
+               } else {
+                       printk(KERN_ERR PFX
+                              "%s: Could not acquire driver lock to do "
+                              "reset!\n", ndev->name);
+                       retval = -1;
+               }
+               spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+       }
+       ql_free_mem_resources(qdev);
+       return retval;
+}
+
+static int ql_adapter_up(struct ql3_adapter *qdev)
+{
+       struct net_device *ndev = qdev->ndev;
+       int err;
+       unsigned long irq_flags = SA_SAMPLE_RANDOM | SA_SHIRQ;
+       unsigned long hw_flags;
+
+       if (ql_alloc_mem_resources(qdev)) {
+               printk(KERN_ERR PFX
+                      "%s Unable to  allocate buffers.\n", ndev->name);
+               return -ENOMEM;
+       }
+
+       if (qdev->msi) {
+               if (pci_enable_msi(qdev->pdev)) {
+                       printk(KERN_ERR PFX
+                              "%s: User requested MSI, but MSI failed to "
+                              "initialize.  Continuing without MSI.\n",
+                              qdev->ndev->name);
+                       qdev->msi = 0;
+               } else {
+                       printk(KERN_INFO PFX "%s: MSI Enabled...\n", qdev->ndev->name);
+                       set_bit(QL_MSI_ENABLED,&qdev->flags);
+                       irq_flags &= ~SA_SHIRQ;
+               }
+       }
+
+       if ((err = request_irq(qdev->pdev->irq,
+                              ql3xxx_isr,
+                              irq_flags, ndev->name, ndev))) {
+               printk(KERN_ERR PFX
+                      "%s: Failed to reserve interrupt %d already in use.\n",
+                      ndev->name, qdev->pdev->irq);
+               goto err_irq;
+       }
+
+       spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+
+       if ((err = ql_wait_for_drvr_lock(qdev))) {
+               if ((err = ql_adapter_initialize(qdev))) {
+                       printk(KERN_ERR PFX
+                              "%s: Unable to initialize adapter.\n",
+                              ndev->name);
+                       goto err_init;
+               }
+               printk(KERN_ERR PFX
+                               "%s: Releaseing driver lock.\n",ndev->name);
+               ql_sem_unlock(qdev, QL_DRVR_SEM_MASK);
+       } else {
+               printk(KERN_ERR PFX
+                      "%s: Could not aquire driver lock.\n",
+                      ndev->name);
+               goto err_lock;
+       }
+
+       spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
+       set_bit(QL_ADAPTER_UP,&qdev->flags);
+
+       mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);
+
+       netif_poll_enable(ndev);
+       ql_enable_interrupts(qdev);
+       return 0;
+
+err_init:
+       ql_sem_unlock(qdev, QL_DRVR_SEM_MASK);
+err_lock:
+       free_irq(qdev->pdev->irq, ndev);
+err_irq:
+       if (qdev->msi && test_bit(QL_MSI_ENABLED,&qdev->flags)) {
+               printk(KERN_INFO PFX
+                      "%s: calling pci_disable_msi().\n",
+                      qdev->ndev->name);
+               clear_bit(QL_MSI_ENABLED,&qdev->flags);
+               pci_disable_msi(qdev->pdev);
+       }
+       return err;
+}
+
+static int ql_cycle_adapter(struct ql3_adapter *qdev, int reset)
+{
+       if( ql_adapter_down(qdev,reset) || ql_adapter_up(qdev)) {
+               printk(KERN_ERR PFX
+                               "%s: Driver up/down cycle failed, "
+                               "closing device\n",qdev->ndev->name);
+               dev_close(qdev->ndev);
+               return -1;
+       }
+       return 0;
+}
+
+static int ql3xxx_close(struct net_device *ndev)
+{
+       struct ql3_adapter *qdev = netdev_priv(ndev);
+
+       /*
+        * Wait for device to recover from a reset.
+        * (Rarely happens, but possible.)
+        */
+       while (!test_bit(QL_ADAPTER_UP,&qdev->flags))
+               msleep(50);
+
+       ql_adapter_down(qdev,QL_DO_RESET);
+       return 0;
+}
+
+static int ql3xxx_open(struct net_device *ndev)
+{
+       struct ql3_adapter *qdev = netdev_priv(ndev);
+       return (ql_adapter_up(qdev));
+}
+
+static struct net_device_stats *ql3xxx_get_stats(struct net_device *dev)
+{
+       struct ql3_adapter *qdev = (struct ql3_adapter *)dev->priv;
+       return &qdev->stats;
+}
+
+static int ql3xxx_change_mtu(struct net_device *ndev, int new_mtu)
+{
+       struct ql3_adapter *qdev = netdev_priv(ndev);
+       printk(KERN_ERR PFX "%s:  new mtu size = %d.\n", ndev->name, new_mtu);
+       if (new_mtu != NORMAL_MTU_SIZE && new_mtu != JUMBO_MTU_SIZE) {
+               printk(KERN_ERR PFX
+                      "%s: mtu size of %d is not valid.  Use exactly %d or "
+                      "%d.\n", ndev->name, new_mtu, NORMAL_MTU_SIZE,
+                      JUMBO_MTU_SIZE);
+               return -EINVAL;
+       }
+
+       if (!netif_running(ndev)) {
+               ndev->mtu = new_mtu;
+               return 0;
+       }
+
+       ndev->mtu = new_mtu;
+       return ql_cycle_adapter(qdev,QL_DO_RESET);
+}
+
+static void ql3xxx_set_multicast_list(struct net_device *ndev)
+{
+       /*
+        * We are manually parsing the list in the net_device structure.
+        */
+       return;
+}
+
+static int ql3xxx_set_mac_address(struct net_device *ndev, void *p)
+{
+       struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
+       struct ql3xxx_port_registers __iomem *port_regs =
+                       qdev->mem_map_registers;
+       struct sockaddr *addr = p;
+       unsigned long hw_flags;
+
+       if (netif_running(ndev))
+               return -EBUSY;
+
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EADDRNOTAVAIL;
+
+       memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
+
+       spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+       /* Program lower 32 bits of the MAC address */
+       ql_write_page0_reg(qdev, &port_regs->macAddrIndirectPtrReg,
+                          (MAC_ADDR_INDIRECT_PTR_REG_RP_MASK << 16));
+       ql_write_page0_reg(qdev, &port_regs->macAddrDataReg,
+                          ((ndev->dev_addr[2] << 24) | (ndev->
+                                                        dev_addr[3] << 16) |
+                           (ndev->dev_addr[4] << 8) | ndev->dev_addr[5]));
+
+       /* Program top 16 bits of the MAC address */
+       ql_write_page0_reg(qdev, &port_regs->macAddrIndirectPtrReg,
+                          ((MAC_ADDR_INDIRECT_PTR_REG_RP_MASK << 16) | 1));
+       ql_write_page0_reg(qdev, &port_regs->macAddrDataReg,
+                          ((ndev->dev_addr[0] << 8) | ndev->dev_addr[1]));
+       spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
+       return 0;
+}
+
+static void ql3xxx_tx_timeout(struct net_device *ndev)
+{
+       struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
+
+       printk(KERN_ERR PFX "%s: Resetting...\n", ndev->name);
+       /*
+        * Stop the queues, we've got a problem.
+        */
+       netif_stop_queue(ndev);
+
+       /*
+        * Wake up the worker to process this event.
+        */
+       queue_work(qdev->workqueue, &qdev->tx_timeout_work);
+}
+
+static void ql_reset_work(struct ql3_adapter *qdev)
+{
+       struct net_device *ndev = qdev->ndev;
+       u32 value;
+       struct ql_tx_buf_cb *tx_cb;
+       int max_wait_time, i;
+       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+       unsigned long hw_flags;
+
+       if (test_bit((QL_RESET_PER_SCSI | QL_RESET_START),&qdev->flags)) {
+               clear_bit(QL_LINK_MASTER,&qdev->flags);
+
+               /*
+                * Loop through the active list and return the skb.
+                */
+               for (i = 0; i < NUM_REQ_Q_ENTRIES; i++) {
+                       tx_cb = &qdev->tx_buf[i];
+                       if (tx_cb->skb) {
+
+                               printk(KERN_DEBUG PFX
+                                      "%s: Freeing lost SKB.\n",
+                                      qdev->ndev->name);
+                               pci_unmap_single(qdev->pdev,
+                                       pci_unmap_addr(tx_cb, mapaddr),
+                                       pci_unmap_len(tx_cb, maplen), PCI_DMA_TODEVICE);
+                               dev_kfree_skb(tx_cb->skb);
+                               tx_cb->skb = NULL;
+                       }
+               }
+
+               printk(KERN_ERR PFX
+                      "%s: Clearing NRI after reset.\n", qdev->ndev->name);
+               spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+               ql_write_common_reg(qdev,
+                                   &port_regs->CommonRegs.
+                                   ispControlStatus,
+                                   ((ISP_CONTROL_RI << 16) | ISP_CONTROL_RI));
+               /*
+                * Wait the for Soft Reset to Complete.
+                */
+               max_wait_time = 10;
+               do {
+                       value = ql_read_common_reg(qdev,
+                                                  &port_regs->CommonRegs.
+
+                                                  ispControlStatus);
+                       if ((value & ISP_CONTROL_SR) == 0) {
+                               printk(KERN_DEBUG PFX
+                                      "%s: reset completed.\n",
+                                      qdev->ndev->name);
+                               break;
+                       }
+
+                       if (value & ISP_CONTROL_RI) {
+                               printk(KERN_DEBUG PFX
+                                      "%s: clearing NRI after reset.\n",
+                                      qdev->ndev->name);
+                               ql_write_common_reg(qdev,
+                                                   (u32 *) &
+                                                   port_regs->
+                                                   CommonRegs.
+                                                   ispControlStatus,
+                                                   ((ISP_CONTROL_RI <<
+                                                     16) | ISP_CONTROL_RI));
+                       }
+
+                       ssleep(1);
+               } while (--max_wait_time);
+               spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
+               if (value & ISP_CONTROL_SR) {
+
+                       /*
+                        * Set the reset flags and clear the board again.
+                        * Nothing else to do...
+                        */
+                       printk(KERN_ERR PFX
+                              "%s: Timed out waiting for reset to "
+                              "complete.\n", ndev->name);
+                       printk(KERN_ERR PFX
+                              "%s: Do a reset.\n", ndev->name);
+                       clear_bit(QL_RESET_PER_SCSI,&qdev->flags);
+                       clear_bit(QL_RESET_START,&qdev->flags);
+                       ql_cycle_adapter(qdev,QL_DO_RESET);
+                       return;
+               }
+
+               clear_bit(QL_RESET_ACTIVE,&qdev->flags);
+               clear_bit(QL_RESET_PER_SCSI,&qdev->flags);
+               clear_bit(QL_RESET_START,&qdev->flags);
+               ql_cycle_adapter(qdev,QL_NO_RESET);
+       }
+}
+
+static void ql_tx_timeout_work(struct ql3_adapter *qdev)
+{
+       ql_cycle_adapter(qdev,QL_DO_RESET);
+}
+
+static void ql_get_board_info(struct ql3_adapter *qdev)
+{
+       struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+       u32 value;
+
+       value = ql_read_page0_reg_l(qdev, &port_regs->portStatus);
+
+       qdev->chip_rev_id = ((value & PORT_STATUS_REV_ID_MASK) >> 12);
+       if (value & PORT_STATUS_64)
+               qdev->pci_width = 64;
+       else
+               qdev->pci_width = 32;
+       if (value & PORT_STATUS_X)
+               qdev->pci_x = 1;
+       else
+               qdev->pci_x = 0;
+       qdev->pci_slot = (u8) PCI_SLOT(qdev->pdev->devfn);
+}
+
+static void ql3xxx_timer(unsigned long ptr)
+{
+       struct ql3_adapter *qdev = (struct ql3_adapter *)ptr;
+
+       if (test_bit(QL_RESET_ACTIVE,&qdev->flags)) {
+               printk(KERN_DEBUG PFX
+                      "%s: Reset in progress.\n",
+                      qdev->ndev->name);
+               goto end;
+       }
+
+       ql_link_state_machine(qdev);
+
+       /* Restart timer on 2 second interval. */
+end:
+       mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);
+}
+
+static int __devinit ql3xxx_probe(struct pci_dev *pdev,
+                                 const struct pci_device_id *pci_entry)
+{
+       struct net_device *ndev = NULL;
+       struct ql3_adapter *qdev = NULL;
+       static int cards_found = 0;
+       int pci_using_dac, err;
+
+       err = pci_enable_device(pdev);
+       if (err) {
+               printk(KERN_ERR PFX "%s cannot enable PCI device\n",
+                      pci_name(pdev));
+               goto err_out;
+       }
+
+       err = pci_request_regions(pdev, DRV_NAME);
+       if (err) {
+               printk(KERN_ERR PFX "%s cannot obtain PCI resources\n",
+                      pci_name(pdev));
+               goto err_out_disable_pdev;
+       }
+
+       pci_set_master(pdev);
+
+       if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+               pci_using_dac = 1;
+               err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+       } else if (!(err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+               pci_using_dac = 0;
+               err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+       }
+
+       if (err) {
+               printk(KERN_ERR PFX "%s no usable DMA configuration\n",
+                      pci_name(pdev));
+               goto err_out_free_regions;
+       }
+
+       ndev = alloc_etherdev(sizeof(struct ql3_adapter));
+       if (!ndev)
+               goto err_out_free_regions;
+
+       SET_MODULE_OWNER(ndev);
+       SET_NETDEV_DEV(ndev, &pdev->dev);
+
+       ndev->features = NETIF_F_LLTX;
+       if (pci_using_dac)
+               ndev->features |= NETIF_F_HIGHDMA;
+
+       pci_set_drvdata(pdev, ndev);
+
+       qdev = netdev_priv(ndev);
+       qdev->index = cards_found;
+       qdev->ndev = ndev;
+       qdev->pdev = pdev;
+       qdev->port_link_state = LS_DOWN;
+       if (msi)
+               qdev->msi = 1;
+
+       qdev->msg_enable = netif_msg_init(debug, default_msg);
+
+       qdev->mem_map_registers =
+           ioremap_nocache(pci_resource_start(pdev, 1),
+                           pci_resource_len(qdev->pdev, 1));
+       if (!qdev->mem_map_registers) {
+               printk(KERN_ERR PFX "%s: cannot map device registers\n",
+                      pci_name(pdev));
+               goto err_out_free_ndev;
+       }
+
+       spin_lock_init(&qdev->adapter_lock);
+       spin_lock_init(&qdev->hw_lock);
+
+       /* Set driver entry points */
+       ndev->open = ql3xxx_open;
+       ndev->hard_start_xmit = ql3xxx_send;
+       ndev->stop = ql3xxx_close;
+       ndev->get_stats = ql3xxx_get_stats;
+       ndev->change_mtu = ql3xxx_change_mtu;
+       ndev->set_multicast_list = ql3xxx_set_multicast_list;
+       SET_ETHTOOL_OPS(ndev, &ql3xxx_ethtool_ops);
+       ndev->set_mac_address = ql3xxx_set_mac_address;
+       ndev->tx_timeout = ql3xxx_tx_timeout;
+       ndev->watchdog_timeo = 5 * HZ;
+
+       ndev->poll = &ql_poll;
+       ndev->weight = 64;
+
+       ndev->irq = pdev->irq;
+
+       /* make sure the EEPROM is good */
+       if (ql_get_nvram_params(qdev)) {
+               printk(KERN_ALERT PFX
+                      "ql3xxx_probe: Adapter #%d, Invalid NVRAM parameters.\n",
+                      qdev->index);
+               goto err_out_iounmap;
+       }
+
+       ql_set_mac_info(qdev);
+
+       /* Validate and set parameters */
+       if (qdev->mac_index) {
+               memcpy(ndev->dev_addr, &qdev->nvram_data.funcCfg_fn2.macAddress,
+                      ETH_ALEN);
+       } else {
+               memcpy(ndev->dev_addr, &qdev->nvram_data.funcCfg_fn0.macAddress,
+                      ETH_ALEN);
+       }
+       memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
+
+       ndev->tx_queue_len = NUM_REQ_Q_ENTRIES;
+
+       /* Turn off support for multicasting */
+       ndev->flags &= ~IFF_MULTICAST;
+
+       /* Record PCI bus information. */
+       ql_get_board_info(qdev);
+
+       /*
+        * Set the Maximum Memory Read Byte Count value. We do this to handle
+        * jumbo frames.
+        */
+       if (qdev->pci_x) {
+               pci_write_config_word(pdev, (int)0x4e, (u16) 0x0036);
+       }
+
+       err = register_netdev(ndev);
+       if (err) {
+               printk(KERN_ERR PFX "%s: cannot register net device\n",
+                      pci_name(pdev));
+               goto err_out_iounmap;
+       }
+
+       /* we're going to reset, so assume we have no link for now */
+
+       netif_carrier_off(ndev);
+       netif_stop_queue(ndev);
+
+       qdev->workqueue = create_singlethread_workqueue(ndev->name);
+       INIT_WORK(&qdev->reset_work, (void (*)(void *))ql_reset_work, qdev);
+       INIT_WORK(&qdev->tx_timeout_work,
+                 (void (*)(void *))ql_tx_timeout_work, qdev);
+
+       init_timer(&qdev->adapter_timer);
+       qdev->adapter_timer.function = ql3xxx_timer;
+       qdev->adapter_timer.expires = jiffies + HZ * 2; /* two second delay */
+       qdev->adapter_timer.data = (unsigned long)qdev;
+
+       if(!cards_found) {
+               printk(KERN_ALERT PFX "%s\n", DRV_STRING);
+               printk(KERN_ALERT PFX "Driver name: %s, Version: %s.\n",
+                  DRV_NAME, DRV_VERSION);
+       }
+       ql_display_dev_info(ndev);
+
+       cards_found++;
+       return 0;
+
+err_out_iounmap:
+       iounmap(qdev->mem_map_registers);
+err_out_free_ndev:
+       free_netdev(ndev);
+err_out_free_regions:
+       pci_release_regions(pdev);
+err_out_disable_pdev:
+       pci_disable_device(pdev);
+       pci_set_drvdata(pdev, NULL);
+err_out:
+       return err;
+}
+
+static void __devexit ql3xxx_remove(struct pci_dev *pdev)
+{
+       struct net_device *ndev = pci_get_drvdata(pdev);
+       struct ql3_adapter *qdev = netdev_priv(ndev);
+
+       unregister_netdev(ndev);
+       qdev = netdev_priv(ndev);
+
+       ql_disable_interrupts(qdev);
+
+       if (qdev->workqueue) {
+               cancel_delayed_work(&qdev->reset_work);
+               cancel_delayed_work(&qdev->tx_timeout_work);
+               destroy_workqueue(qdev->workqueue);
+               qdev->workqueue = NULL;
+       }
+
+       iounmap((void *)qdev->mmap_virt_base);
+       pci_release_regions(pdev);
+       pci_set_drvdata(pdev, NULL);
+       free_netdev(ndev);
+}
+
+static struct pci_driver ql3xxx_driver = {
+
+       .name = DRV_NAME,
+       .id_table = ql3xxx_pci_tbl,
+       .probe = ql3xxx_probe,
+       .remove = __devexit_p(ql3xxx_remove),
+};
+
+static int __init ql3xxx_init_module(void)
+{
+       return pci_register_driver(&ql3xxx_driver);
+}
+
+static void __exit ql3xxx_exit(void)
+{
+       pci_unregister_driver(&ql3xxx_driver);
+}
+
+module_init(ql3xxx_init_module);
+module_exit(ql3xxx_exit);
diff --git a/drivers/net/qla3xxx.h b/drivers/net/qla3xxx.h
new file mode 100644 (file)
index 0000000..9492cee
--- /dev/null
@@ -0,0 +1,1194 @@
+/*
+ * QLogic QLA3xxx NIC HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla3xxx for copyright and licensing details.
+ */
+#ifndef _QLA3XXX_H_
+#define _QLA3XXX_H_
+
+/*
+ * IOCB Definitions...
+ */
+#pragma pack(1)
+
+#define OPCODE_OB_MAC_IOCB_FN0          0x01
+#define OPCODE_OB_MAC_IOCB_FN2          0x21
+#define OPCODE_OB_TCP_IOCB_FN0          0x03
+#define OPCODE_OB_TCP_IOCB_FN2          0x23
+#define OPCODE_UPDATE_NCB_IOCB_FN0      0x00
+#define OPCODE_UPDATE_NCB_IOCB_FN2      0x20
+
+#define OPCODE_UPDATE_NCB_IOCB      0xF0
+#define OPCODE_IB_MAC_IOCB          0xF9
+#define OPCODE_IB_IP_IOCB           0xFA
+#define OPCODE_IB_TCP_IOCB          0xFB
+#define OPCODE_DUMP_PROTO_IOCB      0xFE
+#define OPCODE_BUFFER_ALERT_IOCB    0xFB
+
+#define OPCODE_FUNC_ID_MASK                 0x30
+#define OUTBOUND_MAC_IOCB                   0x01       /* plus function bits */
+#define OUTBOUND_TCP_IOCB                   0x03       /* plus function bits */
+#define UPDATE_NCB_IOCB                     0x00       /* plus function bits */
+
+#define FN0_MA_BITS_MASK    0x00
+#define FN1_MA_BITS_MASK    0x80
+
+struct ob_mac_iocb_req {
+       u8 opcode;
+       u8 flags;
+#define OB_MAC_IOCB_REQ_MA  0xC0
+#define OB_MAC_IOCB_REQ_F   0x20
+#define OB_MAC_IOCB_REQ_X   0x10
+#define OB_MAC_IOCB_REQ_D   0x02
+#define OB_MAC_IOCB_REQ_I   0x01
+       __le16 reserved0;
+
+       __le32 transaction_id;
+       __le16 data_len;
+       __le16 reserved1;
+       __le32 reserved2;
+       __le32 reserved3;
+       __le32 buf_addr0_low;
+       __le32 buf_addr0_high;
+       __le32 buf_0_len;
+       __le32 buf_addr1_low;
+       __le32 buf_addr1_high;
+       __le32 buf_1_len;
+       __le32 buf_addr2_low;
+       __le32 buf_addr2_high;
+       __le32 buf_2_len;
+       __le32 reserved4;
+       __le32 reserved5;
+};
+/*
+ * The following constants define control bits for buffer
+ * length fields for all IOCB's.
+ */
+#define OB_MAC_IOCB_REQ_E   0x80000000 /* Last valid buffer in list. */
+#define OB_MAC_IOCB_REQ_C   0x40000000 /* points to an OAL. (continuation) */
+#define OB_MAC_IOCB_REQ_L   0x20000000 /* Auburn local address pointer. */
+#define OB_MAC_IOCB_REQ_R   0x10000000 /* 32-bit address pointer. */
+
+struct ob_mac_iocb_rsp {
+       u8 opcode;
+       u8 flags;
+#define OB_MAC_IOCB_RSP_P   0x08
+#define OB_MAC_IOCB_RSP_S   0x02
+#define OB_MAC_IOCB_RSP_I   0x01
+
+       __le16 reserved0;
+       __le32 transaction_id;
+       __le32 reserved1;
+       __le32 reserved2;
+};
+
+struct ib_mac_iocb_rsp {
+       u8 opcode;
+       u8 flags;
+#define IB_MAC_IOCB_RSP_S   0x80
+#define IB_MAC_IOCB_RSP_H1  0x40
+#define IB_MAC_IOCB_RSP_H0  0x20
+#define IB_MAC_IOCB_RSP_B   0x10
+#define IB_MAC_IOCB_RSP_M   0x08
+#define IB_MAC_IOCB_RSP_MA  0x07
+
+       __le16 length;
+       __le32 reserved;
+       __le32 ial_low;
+       __le32 ial_high;
+
+};
+
+struct ob_ip_iocb_req {
+       u8 opcode;
+       __le16 flags;
+#define OB_IP_IOCB_REQ_O        0x100
+#define OB_IP_IOCB_REQ_H        0x008
+#define OB_IP_IOCB_REQ_U        0x004
+#define OB_IP_IOCB_REQ_D        0x002
+#define OB_IP_IOCB_REQ_I        0x001
+
+       u8 reserved0;
+
+       __le32 transaction_id;
+       __le16 data_len;
+       __le16 reserved1;
+       __le32 hncb_ptr_low;
+       __le32 hncb_ptr_high;
+       __le32 buf_addr0_low;
+       __le32 buf_addr0_high;
+       __le32 buf_0_len;
+       __le32 buf_addr1_low;
+       __le32 buf_addr1_high;
+       __le32 buf_1_len;
+       __le32 buf_addr2_low;
+       __le32 buf_addr2_high;
+       __le32 buf_2_len;
+       __le32 reserved2;
+       __le32 reserved3;
+};
+
+/* defines for BufferLength fields above */
+#define OB_IP_IOCB_REQ_E    0x80000000
+#define OB_IP_IOCB_REQ_C    0x40000000
+#define OB_IP_IOCB_REQ_L    0x20000000
+#define OB_IP_IOCB_REQ_R    0x10000000
+
+struct ob_ip_iocb_rsp {
+       u8 opcode;
+       u8 flags;
+#define OB_MAC_IOCB_RSP_E       0x08
+#define OB_MAC_IOCB_RSP_L       0x04
+#define OB_MAC_IOCB_RSP_S       0x02
+#define OB_MAC_IOCB_RSP_I       0x01
+
+       __le16 reserved0;
+       __le32 transaction_id;
+       __le32 reserved1;
+       __le32 reserved2;
+};
+
+struct ob_tcp_iocb_req {
+       u8 opcode;
+
+       u8 flags0;
+#define OB_TCP_IOCB_REQ_P       0x80
+#define OB_TCP_IOCB_REQ_CI      0x20
+#define OB_TCP_IOCB_REQ_H       0x10
+#define OB_TCP_IOCB_REQ_LN      0x08
+#define OB_TCP_IOCB_REQ_K       0x04
+#define OB_TCP_IOCB_REQ_D       0x02
+#define OB_TCP_IOCB_REQ_I       0x01
+
+       u8 flags1;
+#define OB_TCP_IOCB_REQ_OSM     0x40
+#define OB_TCP_IOCB_REQ_URG     0x20
+#define OB_TCP_IOCB_REQ_ACK     0x10
+#define OB_TCP_IOCB_REQ_PSH     0x08
+#define OB_TCP_IOCB_REQ_RST     0x04
+#define OB_TCP_IOCB_REQ_SYN     0x02
+#define OB_TCP_IOCB_REQ_FIN     0x01
+
+       u8 options_len;
+#define OB_TCP_IOCB_REQ_OMASK   0xF0
+#define OB_TCP_IOCB_REQ_SHIFT   4
+
+       __le32 transaction_id;
+       __le32 data_len;
+       __le32 hncb_ptr_low;
+       __le32 hncb_ptr_high;
+       __le32 buf_addr0_low;
+       __le32 buf_addr0_high;
+       __le32 buf_0_len;
+       __le32 buf_addr1_low;
+       __le32 buf_addr1_high;
+       __le32 buf_1_len;
+       __le32 buf_addr2_low;
+       __le32 buf_addr2_high;
+       __le32 buf_2_len;
+       __le32 time_stamp;
+       __le32 reserved1;
+};
+
+struct ob_tcp_iocb_rsp {
+       u8 opcode;
+
+       u8 flags0;
+#define OB_TCP_IOCB_RSP_C       0x20
+#define OB_TCP_IOCB_RSP_H       0x10
+#define OB_TCP_IOCB_RSP_LN      0x08
+#define OB_TCP_IOCB_RSP_K       0x04
+#define OB_TCP_IOCB_RSP_D       0x02
+#define OB_TCP_IOCB_RSP_I       0x01
+
+       u8 flags1;
+#define OB_TCP_IOCB_RSP_E       0x10
+#define OB_TCP_IOCB_RSP_W       0x08
+#define OB_TCP_IOCB_RSP_P       0x04
+#define OB_TCP_IOCB_RSP_T       0x02
+#define OB_TCP_IOCB_RSP_F       0x01
+
+       u8 state;
+#define OB_TCP_IOCB_RSP_SMASK   0xF0
+#define OB_TCP_IOCB_RSP_SHIFT   4
+
+       __le32 transaction_id;
+       __le32 local_ncb_ptr;
+       __le32 reserved0;
+};
+
+struct ib_ip_iocb_rsp {
+       u8 opcode;
+       u8 flags;
+#define IB_IP_IOCB_RSP_S        0x80
+#define IB_IP_IOCB_RSP_H1       0x40
+#define IB_IP_IOCB_RSP_H0       0x20
+#define IB_IP_IOCB_RSP_B        0x10
+#define IB_IP_IOCB_RSP_M        0x08
+#define IB_IP_IOCB_RSP_MA       0x07
+
+       __le16 length;
+       __le16 checksum;
+       __le16 reserved;
+#define IB_IP_IOCB_RSP_R        0x01
+       __le32 ial_low;
+       __le32 ial_high;
+};
+
+struct ib_tcp_iocb_rsp {
+       u8 opcode;
+       u8 flags;
+#define IB_TCP_IOCB_RSP_P       0x80
+#define IB_TCP_IOCB_RSP_T       0x40
+#define IB_TCP_IOCB_RSP_D       0x20
+#define IB_TCP_IOCB_RSP_N       0x10
+#define IB_TCP_IOCB_RSP_IP      0x03
+#define IB_TCP_FLAG_MASK        0xf0
+#define IB_TCP_FLAG_IOCB_SYN    0x00
+
+#define TCP_IB_RSP_FLAGS(x) (x->flags & ~IB_TCP_FLAG_MASK)
+
+       __le16 length;
+       __le32 hncb_ref_num;
+       __le32 ial_low;
+       __le32 ial_high;
+};
+
+struct net_rsp_iocb {
+       u8 opcode;
+       u8 flags;
+       __le16 reserved0;
+       __le32 reserved[3];
+};
+#pragma pack()
+
+/*
+ * Register Definitions...
+ */
+#define PORT0_PHY_ADDRESS   0x1e00
+#define PORT1_PHY_ADDRESS   0x1f00
+
+#define ETHERNET_CRC_SIZE   4
+
+#define MII_SCAN_REGISTER 0x00000001
+
+/* 32-bit ispControlStatus */
+enum {
+       ISP_CONTROL_NP_MASK = 0x0003,
+       ISP_CONTROL_NP_PCSR = 0x0000,
+       ISP_CONTROL_NP_HMCR = 0x0001,
+       ISP_CONTROL_NP_LRAMCR = 0x0002,
+       ISP_CONTROL_NP_PSR = 0x0003,
+       ISP_CONTROL_RI = 0x0008,
+       ISP_CONTROL_CI = 0x0010,
+       ISP_CONTROL_PI = 0x0020,
+       ISP_CONTROL_IN = 0x0040,
+       ISP_CONTROL_BE = 0x0080,
+       ISP_CONTROL_FN_MASK = 0x0700,
+       ISP_CONTROL_FN0_NET = 0x0400,
+       ISP_CONTROL_FN0_SCSI = 0x0500,
+       ISP_CONTROL_FN1_NET = 0x0600,
+       ISP_CONTROL_FN1_SCSI = 0x0700,
+       ISP_CONTROL_LINK_DN_0 = 0x0800,
+       ISP_CONTROL_LINK_DN_1 = 0x1000,
+       ISP_CONTROL_FSR = 0x2000,
+       ISP_CONTROL_FE = 0x4000,
+       ISP_CONTROL_SR = 0x8000,
+};
+
+/* 32-bit ispInterruptMaskReg */
+enum {
+       ISP_IMR_ENABLE_INT = 0x0004,
+       ISP_IMR_DISABLE_RESET_INT = 0x0008,
+       ISP_IMR_DISABLE_CMPL_INT = 0x0010,
+       ISP_IMR_DISABLE_PROC_INT = 0x0020,
+};
+
+/* 32-bit serialPortInterfaceReg */
+enum {
+       ISP_SERIAL_PORT_IF_CLK = 0x0001,
+       ISP_SERIAL_PORT_IF_CS = 0x0002,
+       ISP_SERIAL_PORT_IF_D0 = 0x0004,
+       ISP_SERIAL_PORT_IF_DI = 0x0008,
+       ISP_NVRAM_MASK = (0x000F << 16),
+       ISP_SERIAL_PORT_IF_WE = 0x0010,
+       ISP_SERIAL_PORT_IF_NVR_MASK = 0x001F,
+       ISP_SERIAL_PORT_IF_SCI = 0x0400,
+       ISP_SERIAL_PORT_IF_SC0 = 0x0800,
+       ISP_SERIAL_PORT_IF_SCE = 0x1000,
+       ISP_SERIAL_PORT_IF_SDI = 0x2000,
+       ISP_SERIAL_PORT_IF_SDO = 0x4000,
+       ISP_SERIAL_PORT_IF_SDE = 0x8000,
+       ISP_SERIAL_PORT_IF_I2C_MASK = 0xFC00,
+};
+
+/* semaphoreReg */
+enum {
+       QL_RESOURCE_MASK_BASE_CODE = 0x7,
+       QL_RESOURCE_BITS_BASE_CODE = 0x4,
+       QL_DRVR_SEM_BITS = (QL_RESOURCE_BITS_BASE_CODE << 1),
+       QL_DDR_RAM_SEM_BITS = (QL_RESOURCE_BITS_BASE_CODE << 4),
+       QL_PHY_GIO_SEM_BITS = (QL_RESOURCE_BITS_BASE_CODE << 7),
+       QL_NVRAM_SEM_BITS = (QL_RESOURCE_BITS_BASE_CODE << 10),
+       QL_FLASH_SEM_BITS = (QL_RESOURCE_BITS_BASE_CODE << 13),
+       QL_DRVR_SEM_MASK = (QL_RESOURCE_MASK_BASE_CODE << (1 + 16)),
+       QL_DDR_RAM_SEM_MASK = (QL_RESOURCE_MASK_BASE_CODE << (4 + 16)),
+       QL_PHY_GIO_SEM_MASK = (QL_RESOURCE_MASK_BASE_CODE << (7 + 16)),
+       QL_NVRAM_SEM_MASK = (QL_RESOURCE_MASK_BASE_CODE << (10 + 16)),
+       QL_FLASH_SEM_MASK = (QL_RESOURCE_MASK_BASE_CODE << (13 + 16)),
+};
+
+ /*
+  * QL3XXX memory-mapped registers
+  * QL3XXX has 4 "pages" of registers, each page occupying
+  * 256 bytes.  Each page has a "common" area at the start and then
+  * page-specific registers after that.
+  */
+struct ql3xxx_common_registers {
+       u32 MB0;                /* Offset 0x00 */
+       u32 MB1;                /* Offset 0x04 */
+       u32 MB2;                /* Offset 0x08 */
+       u32 MB3;                /* Offset 0x0c */
+       u32 MB4;                /* Offset 0x10 */
+       u32 MB5;                /* Offset 0x14 */
+       u32 MB6;                /* Offset 0x18 */
+       u32 MB7;                /* Offset 0x1c */
+       u32 flashBiosAddr;
+       u32 flashBiosData;
+       u32 ispControlStatus;
+       u32 ispInterruptMaskReg;
+       u32 serialPortInterfaceReg;
+       u32 semaphoreReg;
+       u32 reqQProducerIndex;
+       u32 rspQConsumerIndex;
+
+       u32 rxLargeQProducerIndex;
+       u32 rxSmallQProducerIndex;
+       u32 arcMadiCommand;
+       u32 arcMadiData;
+};
+
+enum {
+       EXT_HW_CONFIG_SP_MASK = 0x0006,
+       EXT_HW_CONFIG_SP_NONE = 0x0000,
+       EXT_HW_CONFIG_SP_BYTE_PARITY = 0x0002,
+       EXT_HW_CONFIG_SP_ECC = 0x0004,
+       EXT_HW_CONFIG_SP_ECCx = 0x0006,
+       EXT_HW_CONFIG_SIZE_MASK = 0x0060,
+       EXT_HW_CONFIG_SIZE_128M = 0x0000,
+       EXT_HW_CONFIG_SIZE_256M = 0x0020,
+       EXT_HW_CONFIG_SIZE_512M = 0x0040,
+       EXT_HW_CONFIG_SIZE_INVALID = 0x0060,
+       EXT_HW_CONFIG_PD = 0x0080,
+       EXT_HW_CONFIG_FW = 0x0200,
+       EXT_HW_CONFIG_US = 0x0400,
+       EXT_HW_CONFIG_DCS_MASK = 0x1800,
+       EXT_HW_CONFIG_DCS_9MA = 0x0000,
+       EXT_HW_CONFIG_DCS_15MA = 0x0800,
+       EXT_HW_CONFIG_DCS_18MA = 0x1000,
+       EXT_HW_CONFIG_DCS_24MA = 0x1800,
+       EXT_HW_CONFIG_DDS_MASK = 0x6000,
+       EXT_HW_CONFIG_DDS_9MA = 0x0000,
+       EXT_HW_CONFIG_DDS_15MA = 0x2000,
+       EXT_HW_CONFIG_DDS_18MA = 0x4000,
+       EXT_HW_CONFIG_DDS_24MA = 0x6000,
+};
+
+/* InternalChipConfig */
+enum {
+       INTERNAL_CHIP_DM = 0x0001,
+       INTERNAL_CHIP_SD = 0x0002,
+       INTERNAL_CHIP_RAP_MASK = 0x000C,
+       INTERNAL_CHIP_RAP_RR = 0x0000,
+       INTERNAL_CHIP_RAP_NRM = 0x0004,
+       INTERNAL_CHIP_RAP_ERM = 0x0008,
+       INTERNAL_CHIP_RAP_ERMx = 0x000C,
+       INTERNAL_CHIP_WE = 0x0010,
+       INTERNAL_CHIP_EF = 0x0020,
+       INTERNAL_CHIP_FR = 0x0040,
+       INTERNAL_CHIP_FW = 0x0080,
+       INTERNAL_CHIP_FI = 0x0100,
+       INTERNAL_CHIP_FT = 0x0200,
+};
+
+/* portControl */
+enum {
+       PORT_CONTROL_DS = 0x0001,
+       PORT_CONTROL_HH = 0x0002,
+       PORT_CONTROL_EI = 0x0004,
+       PORT_CONTROL_ET = 0x0008,
+       PORT_CONTROL_EF = 0x0010,
+       PORT_CONTROL_DRM = 0x0020,
+       PORT_CONTROL_RLB = 0x0040,
+       PORT_CONTROL_RCB = 0x0080,
+       PORT_CONTROL_MAC = 0x0100,
+       PORT_CONTROL_IPV = 0x0200,
+       PORT_CONTROL_IFP = 0x0400,
+       PORT_CONTROL_ITP = 0x0800,
+       PORT_CONTROL_FI = 0x1000,
+       PORT_CONTROL_DFP = 0x2000,
+       PORT_CONTROL_OI = 0x4000,
+       PORT_CONTROL_CC = 0x8000,
+};
+
+/* portStatus */
+enum {
+       PORT_STATUS_SM0 = 0x0001,
+       PORT_STATUS_SM1 = 0x0002,
+       PORT_STATUS_X = 0x0008,
+       PORT_STATUS_DL = 0x0080,
+       PORT_STATUS_IC = 0x0200,
+       PORT_STATUS_MRC = 0x0400,
+       PORT_STATUS_NL = 0x0800,
+       PORT_STATUS_REV_ID_MASK = 0x7000,
+       PORT_STATUS_REV_ID_1 = 0x1000,
+       PORT_STATUS_REV_ID_2 = 0x2000,
+       PORT_STATUS_REV_ID_3 = 0x3000,
+       PORT_STATUS_64 = 0x8000,
+       PORT_STATUS_UP0 = 0x10000,
+       PORT_STATUS_AC0 = 0x20000,
+       PORT_STATUS_AE0 = 0x40000,
+       PORT_STATUS_UP1 = 0x100000,
+       PORT_STATUS_AC1 = 0x200000,
+       PORT_STATUS_AE1 = 0x400000,
+       PORT_STATUS_F0_ENABLED = 0x1000000,
+       PORT_STATUS_F1_ENABLED = 0x2000000,
+       PORT_STATUS_F2_ENABLED = 0x4000000,
+       PORT_STATUS_F3_ENABLED = 0x8000000,
+};
+
+/* macMIIMgmtControlReg */
+enum {
+       MAC_ADDR_INDIRECT_PTR_REG_RP_MASK = 0x0003,
+       MAC_ADDR_INDIRECT_PTR_REG_RP_PRI_LWR = 0x0000,
+       MAC_ADDR_INDIRECT_PTR_REG_RP_PRI_UPR = 0x0001,
+       MAC_ADDR_INDIRECT_PTR_REG_RP_SEC_LWR = 0x0002,
+       MAC_ADDR_INDIRECT_PTR_REG_RP_SEC_UPR = 0x0003,
+       MAC_ADDR_INDIRECT_PTR_REG_PR = 0x0008,
+       MAC_ADDR_INDIRECT_PTR_REG_SS = 0x0010,
+       MAC_ADDR_INDIRECT_PTR_REG_SE = 0x0020,
+       MAC_ADDR_INDIRECT_PTR_REG_SP = 0x0040,
+       MAC_ADDR_INDIRECT_PTR_REG_PE = 0x0080,
+};
+
+/* macMIIMgmtControlReg */
+enum {
+       MAC_MII_CONTROL_RC = 0x0001,
+       MAC_MII_CONTROL_SC = 0x0002,
+       MAC_MII_CONTROL_AS = 0x0004,
+       MAC_MII_CONTROL_NP = 0x0008,
+       MAC_MII_CONTROL_CLK_SEL_MASK = 0x0070,
+       MAC_MII_CONTROL_CLK_SEL_DIV2 = 0x0000,
+       MAC_MII_CONTROL_CLK_SEL_DIV4 = 0x0010,
+       MAC_MII_CONTROL_CLK_SEL_DIV6 = 0x0020,
+       MAC_MII_CONTROL_CLK_SEL_DIV8 = 0x0030,
+       MAC_MII_CONTROL_CLK_SEL_DIV10 = 0x0040,
+       MAC_MII_CONTROL_CLK_SEL_DIV14 = 0x0050,
+       MAC_MII_CONTROL_CLK_SEL_DIV20 = 0x0060,
+       MAC_MII_CONTROL_CLK_SEL_DIV28 = 0x0070,
+       MAC_MII_CONTROL_RM = 0x8000,
+};
+
+/* macMIIStatusReg */
+enum {
+       MAC_MII_STATUS_BSY = 0x0001,
+       MAC_MII_STATUS_SC = 0x0002,
+       MAC_MII_STATUS_NV = 0x0004,
+};
+
+enum {
+       MAC_CONFIG_REG_PE = 0x0001,
+       MAC_CONFIG_REG_TF = 0x0002,
+       MAC_CONFIG_REG_RF = 0x0004,
+       MAC_CONFIG_REG_FD = 0x0008,
+       MAC_CONFIG_REG_GM = 0x0010,
+       MAC_CONFIG_REG_LB = 0x0020,
+       MAC_CONFIG_REG_SR = 0x8000,
+};
+
+enum {
+       MAC_HALF_DUPLEX_REG_ED = 0x10000,
+       MAC_HALF_DUPLEX_REG_NB = 0x20000,
+       MAC_HALF_DUPLEX_REG_BNB = 0x40000,
+       MAC_HALF_DUPLEX_REG_ALT = 0x80000,
+};
+
+enum {
+       IP_ADDR_INDEX_REG_MASK = 0x000f,
+       IP_ADDR_INDEX_REG_FUNC_0_PRI = 0x0000,
+       IP_ADDR_INDEX_REG_FUNC_0_SEC = 0x0001,
+       IP_ADDR_INDEX_REG_FUNC_1_PRI = 0x0002,
+       IP_ADDR_INDEX_REG_FUNC_1_SEC = 0x0003,
+       IP_ADDR_INDEX_REG_FUNC_2_PRI = 0x0004,
+       IP_ADDR_INDEX_REG_FUNC_2_SEC = 0x0005,
+       IP_ADDR_INDEX_REG_FUNC_3_PRI = 0x0006,
+       IP_ADDR_INDEX_REG_FUNC_3_SEC = 0x0007,
+};
+
+enum {
+       PROBE_MUX_ADDR_REG_MUX_SEL_MASK = 0x003f,
+       PROBE_MUX_ADDR_REG_SYSCLK = 0x0000,
+       PROBE_MUX_ADDR_REG_PCICLK = 0x0040,
+       PROBE_MUX_ADDR_REG_NRXCLK = 0x0080,
+       PROBE_MUX_ADDR_REG_CPUCLK = 0x00C0,
+       PROBE_MUX_ADDR_REG_MODULE_SEL_MASK = 0x3f00,
+       PROBE_MUX_ADDR_REG_UP = 0x4000,
+       PROBE_MUX_ADDR_REG_RE = 0x8000,
+};
+
+enum {
+       STATISTICS_INDEX_REG_MASK = 0x01ff,
+       STATISTICS_INDEX_REG_MAC0_TX_FRAME = 0x0000,
+       STATISTICS_INDEX_REG_MAC0_TX_BYTES = 0x0001,
+       STATISTICS_INDEX_REG_MAC0_TX_STAT1 = 0x0002,
+       STATISTICS_INDEX_REG_MAC0_TX_STAT2 = 0x0003,
+       STATISTICS_INDEX_REG_MAC0_TX_STAT3 = 0x0004,
+       STATISTICS_INDEX_REG_MAC0_TX_STAT4 = 0x0005,
+       STATISTICS_INDEX_REG_MAC0_TX_STAT5 = 0x0006,
+       STATISTICS_INDEX_REG_MAC0_RX_FRAME = 0x0007,
+       STATISTICS_INDEX_REG_MAC0_RX_BYTES = 0x0008,
+       STATISTICS_INDEX_REG_MAC0_RX_STAT1 = 0x0009,
+       STATISTICS_INDEX_REG_MAC0_RX_STAT2 = 0x000a,
+       STATISTICS_INDEX_REG_MAC0_RX_STAT3 = 0x000b,
+       STATISTICS_INDEX_REG_MAC0_RX_ERR_CRC = 0x000c,
+       STATISTICS_INDEX_REG_MAC0_RX_ERR_ENC = 0x000d,
+       STATISTICS_INDEX_REG_MAC0_RX_ERR_LEN = 0x000e,
+       STATISTICS_INDEX_REG_MAC0_RX_STAT4 = 0x000f,
+       STATISTICS_INDEX_REG_MAC1_TX_FRAME = 0x0010,
+       STATISTICS_INDEX_REG_MAC1_TX_BYTES = 0x0011,
+       STATISTICS_INDEX_REG_MAC1_TX_STAT1 = 0x0012,
+       STATISTICS_INDEX_REG_MAC1_TX_STAT2 = 0x0013,
+       STATISTICS_INDEX_REG_MAC1_TX_STAT3 = 0x0014,
+       STATISTICS_INDEX_REG_MAC1_TX_STAT4 = 0x0015,
+       STATISTICS_INDEX_REG_MAC1_TX_STAT5 = 0x0016,
+       STATISTICS_INDEX_REG_MAC1_RX_FRAME = 0x0017,
+       STATISTICS_INDEX_REG_MAC1_RX_BYTES = 0x0018,
+       STATISTICS_INDEX_REG_MAC1_RX_STAT1 = 0x0019,
+       STATISTICS_INDEX_REG_MAC1_RX_STAT2 = 0x001a,
+       STATISTICS_INDEX_REG_MAC1_RX_STAT3 = 0x001b,
+       STATISTICS_INDEX_REG_MAC1_RX_ERR_CRC = 0x001c,
+       STATISTICS_INDEX_REG_MAC1_RX_ERR_ENC = 0x001d,
+       STATISTICS_INDEX_REG_MAC1_RX_ERR_LEN = 0x001e,
+       STATISTICS_INDEX_REG_MAC1_RX_STAT4 = 0x001f,
+       STATISTICS_INDEX_REG_IP_TX_PKTS = 0x0020,
+       STATISTICS_INDEX_REG_IP_TX_BYTES = 0x0021,
+       STATISTICS_INDEX_REG_IP_TX_FRAG = 0x0022,
+       STATISTICS_INDEX_REG_IP_RX_PKTS = 0x0023,
+       STATISTICS_INDEX_REG_IP_RX_BYTES = 0x0024,
+       STATISTICS_INDEX_REG_IP_RX_FRAG = 0x0025,
+       STATISTICS_INDEX_REG_IP_DGRM_REASSEMBLY = 0x0026,
+       STATISTICS_INDEX_REG_IP_V6_RX_PKTS = 0x0027,
+       STATISTICS_INDEX_REG_IP_RX_PKTERR = 0x0028,
+       STATISTICS_INDEX_REG_IP_REASSEMBLY_ERR = 0x0029,
+       STATISTICS_INDEX_REG_TCP_TX_SEG = 0x0030,
+       STATISTICS_INDEX_REG_TCP_TX_BYTES = 0x0031,
+       STATISTICS_INDEX_REG_TCP_RX_SEG = 0x0032,
+       STATISTICS_INDEX_REG_TCP_RX_BYTES = 0x0033,
+       STATISTICS_INDEX_REG_TCP_TIMER_EXP = 0x0034,
+       STATISTICS_INDEX_REG_TCP_RX_ACK = 0x0035,
+       STATISTICS_INDEX_REG_TCP_TX_ACK = 0x0036,
+       STATISTICS_INDEX_REG_TCP_RX_ERR = 0x0037,
+       STATISTICS_INDEX_REG_TCP_RX_WIN_PROBE = 0x0038,
+       STATISTICS_INDEX_REG_TCP_ECC_ERR_CORR = 0x003f,
+};
+
+enum {
+       PORT_FATAL_ERROR_STATUS_OFB_RE_MAC0 = 0x00000001,
+       PORT_FATAL_ERROR_STATUS_OFB_RE_MAC1 = 0x00000002,
+       PORT_FATAL_ERROR_STATUS_OFB_WE = 0x00000004,
+       PORT_FATAL_ERROR_STATUS_IFB_RE = 0x00000008,
+       PORT_FATAL_ERROR_STATUS_IFB_WE_MAC0 = 0x00000010,
+       PORT_FATAL_ERROR_STATUS_IFB_WE_MAC1 = 0x00000020,
+       PORT_FATAL_ERROR_STATUS_ODE_RE = 0x00000040,
+       PORT_FATAL_ERROR_STATUS_ODE_WE = 0x00000080,
+       PORT_FATAL_ERROR_STATUS_IDE_RE = 0x00000100,
+       PORT_FATAL_ERROR_STATUS_IDE_WE = 0x00000200,
+       PORT_FATAL_ERROR_STATUS_SDE_RE = 0x00000400,
+       PORT_FATAL_ERROR_STATUS_SDE_WE = 0x00000800,
+       PORT_FATAL_ERROR_STATUS_BLE = 0x00001000,
+       PORT_FATAL_ERROR_STATUS_SPE = 0x00002000,
+       PORT_FATAL_ERROR_STATUS_EP0 = 0x00004000,
+       PORT_FATAL_ERROR_STATUS_EP1 = 0x00008000,
+       PORT_FATAL_ERROR_STATUS_ICE = 0x00010000,
+       PORT_FATAL_ERROR_STATUS_ILE = 0x00020000,
+       PORT_FATAL_ERROR_STATUS_OPE = 0x00040000,
+       PORT_FATAL_ERROR_STATUS_TA = 0x00080000,
+       PORT_FATAL_ERROR_STATUS_MA = 0x00100000,
+       PORT_FATAL_ERROR_STATUS_SCE = 0x00200000,
+       PORT_FATAL_ERROR_STATUS_RPE = 0x00400000,
+       PORT_FATAL_ERROR_STATUS_MPE = 0x00800000,
+       PORT_FATAL_ERROR_STATUS_OCE = 0x01000000,
+};
+
+/*
+ *  port control and status page - page 0
+ */
+
+struct ql3xxx_port_registers {
+       struct ql3xxx_common_registers CommonRegs;
+
+       u32 ExternalHWConfig;
+       u32 InternalChipConfig;
+       u32 portControl;
+       u32 portStatus;
+       u32 macAddrIndirectPtrReg;
+       u32 macAddrDataReg;
+       u32 macMIIMgmtControlReg;
+       u32 macMIIMgmtAddrReg;
+       u32 macMIIMgmtDataReg;
+       u32 macMIIStatusReg;
+       u32 mac0ConfigReg;
+       u32 mac0IpgIfgReg;
+       u32 mac0HalfDuplexReg;
+       u32 mac0MaxFrameLengthReg;
+       u32 mac0PauseThresholdReg;
+       u32 mac1ConfigReg;
+       u32 mac1IpgIfgReg;
+       u32 mac1HalfDuplexReg;
+       u32 mac1MaxFrameLengthReg;
+       u32 mac1PauseThresholdReg;
+       u32 ipAddrIndexReg;
+       u32 ipAddrDataReg;
+       u32 ipReassemblyTimeout;
+       u32 tcpMaxWindow;
+       u32 currentTcpTimestamp[2];
+       u32 internalRamRWAddrReg;
+       u32 internalRamWDataReg;
+       u32 reclaimedBufferAddrRegLow;
+       u32 reclaimedBufferAddrRegHigh;
+       u32 reserved[2];
+       u32 fpgaRevID;
+       u32 localRamAddr;
+       u32 localRamDataAutoIncr;
+       u32 localRamDataNonIncr;
+       u32 gpOutput;
+       u32 gpInput;
+       u32 probeMuxAddr;
+       u32 probeMuxData;
+       u32 statisticsIndexReg;
+       u32 statisticsReadDataRegAutoIncr;
+       u32 statisticsReadDataRegNoIncr;
+       u32 PortFatalErrStatus;
+};
+
+/*
+ * port host memory config page - page 1
+ */
+struct ql3xxx_host_memory_registers {
+       struct ql3xxx_common_registers CommonRegs;
+
+       u32 reserved[12];
+
+       /* Network Request Queue */
+       u32 reqConsumerIndex;
+       u32 reqConsumerIndexAddrLow;
+       u32 reqConsumerIndexAddrHigh;
+       u32 reqBaseAddrLow;
+       u32 reqBaseAddrHigh;
+       u32 reqLength;
+
+       /* Network Completion Queue */
+       u32 rspProducerIndex;
+       u32 rspProducerIndexAddrLow;
+       u32 rspProducerIndexAddrHigh;
+       u32 rspBaseAddrLow;
+       u32 rspBaseAddrHigh;
+       u32 rspLength;
+
+       /* RX Large Buffer Queue */
+       u32 rxLargeQConsumerIndex;
+       u32 rxLargeQBaseAddrLow;
+       u32 rxLargeQBaseAddrHigh;
+       u32 rxLargeQLength;
+       u32 rxLargeBufferLength;
+
+       /* RX Small Buffer Queue */
+       u32 rxSmallQConsumerIndex;
+       u32 rxSmallQBaseAddrLow;
+       u32 rxSmallQBaseAddrHigh;
+       u32 rxSmallQLength;
+       u32 rxSmallBufferLength;
+
+};
+
+/*
+ *  port local RAM page - page 2
+ */
+struct ql3xxx_local_ram_registers {
+       struct ql3xxx_common_registers CommonRegs;
+       u32 bufletSize;
+       u32 maxBufletCount;
+       u32 currentBufletCount;
+       u32 reserved;
+       u32 freeBufletThresholdLow;
+       u32 freeBufletThresholdHigh;
+       u32 ipHashTableBase;
+       u32 ipHashTableCount;
+       u32 tcpHashTableBase;
+       u32 tcpHashTableCount;
+       u32 ncbBase;
+       u32 maxNcbCount;
+       u32 currentNcbCount;
+       u32 drbBase;
+       u32 maxDrbCount;
+       u32 currentDrbCount;
+};
+
+/*
+ * definitions for Semaphore bits in Semaphore/Serial NVRAM interface register
+ */
+
+#define LS_64BITS(x)    (u32)(0xffffffff & ((u64)x))
+#define MS_64BITS(x)    (u32)(0xffffffff & (((u64)x)>>16>>16) )
+
+/*
+ * I/O register
+ */
+
+enum {
+       CONTROL_REG = 0,
+       STATUS_REG = 1,
+       PHY_STAT_LINK_UP = 0x0004,
+       PHY_CTRL_LOOPBACK = 0x4000,
+
+       PETBI_CONTROL_REG = 0x00,
+       PETBI_CTRL_SOFT_RESET = 0x8000,
+       PETBI_CTRL_AUTO_NEG = 0x1000,
+       PETBI_CTRL_RESTART_NEG = 0x0200,
+       PETBI_CTRL_FULL_DUPLEX = 0x0100,
+       PETBI_CTRL_SPEED_1000 = 0x0040,
+
+       PETBI_STATUS_REG = 0x01,
+       PETBI_STAT_NEG_DONE = 0x0020,
+       PETBI_STAT_LINK_UP = 0x0004,
+
+       PETBI_NEG_ADVER = 0x04,
+       PETBI_NEG_PAUSE = 0x0080,
+       PETBI_NEG_PAUSE_MASK = 0x0180,
+       PETBI_NEG_DUPLEX = 0x0020,
+       PETBI_NEG_DUPLEX_MASK = 0x0060,
+
+       PETBI_NEG_PARTNER = 0x05,
+       PETBI_NEG_ERROR_MASK = 0x3000,
+
+       PETBI_EXPANSION_REG = 0x06,
+       PETBI_EXP_PAGE_RX = 0x0002,
+
+       PETBI_TBI_CTRL = 0x11,
+       PETBI_TBI_RESET = 0x8000,
+       PETBI_TBI_AUTO_SENSE = 0x0100,
+       PETBI_TBI_SERDES_MODE = 0x0010,
+       PETBI_TBI_SERDES_WRAP = 0x0002,
+
+       AUX_CONTROL_STATUS = 0x1c,
+       PHY_AUX_NEG_DONE = 0x8000,
+       PHY_NEG_PARTNER = 5,
+       PHY_AUX_DUPLEX_STAT = 0x0020,
+       PHY_AUX_SPEED_STAT = 0x0018,
+       PHY_AUX_NO_HW_STRAP = 0x0004,
+       PHY_AUX_RESET_STICK = 0x0002,
+       PHY_NEG_PAUSE = 0x0400,
+       PHY_CTRL_SOFT_RESET = 0x8000,
+       PHY_NEG_ADVER = 4,
+       PHY_NEG_ADV_SPEED = 0x01e0,
+       PHY_CTRL_RESTART_NEG = 0x0200,
+};
+enum {
+/* AM29LV Flash definitions    */
+       FM93C56A_START = 0x1,
+/* Commands */
+       FM93C56A_READ = 0x2,
+       FM93C56A_WEN = 0x0,
+       FM93C56A_WRITE = 0x1,
+       FM93C56A_WRITE_ALL = 0x0,
+       FM93C56A_WDS = 0x0,
+       FM93C56A_ERASE = 0x3,
+       FM93C56A_ERASE_ALL = 0x0,
+/* Command Extentions */
+       FM93C56A_WEN_EXT = 0x3,
+       FM93C56A_WRITE_ALL_EXT = 0x1,
+       FM93C56A_WDS_EXT = 0x0,
+       FM93C56A_ERASE_ALL_EXT = 0x2,
+/* Special Bits */
+       FM93C56A_READ_DUMMY_BITS = 1,
+       FM93C56A_READY = 0,
+       FM93C56A_BUSY = 1,
+       FM93C56A_CMD_BITS = 2,
+/* AM29LV Flash definitions    */
+       FM93C56A_SIZE_8 = 0x100,
+       FM93C56A_SIZE_16 = 0x80,
+       FM93C66A_SIZE_8 = 0x200,
+       FM93C66A_SIZE_16 = 0x100,
+       FM93C86A_SIZE_16 = 0x400,
+/* Address Bits */
+       FM93C56A_NO_ADDR_BITS_16 = 8,
+       FM93C56A_NO_ADDR_BITS_8 = 9,
+       FM93C86A_NO_ADDR_BITS_16 = 10,
+/* Data Bits */
+       FM93C56A_DATA_BITS_16 = 16,
+       FM93C56A_DATA_BITS_8 = 8,
+};
+enum {
+/* Auburn Bits */
+           AUBURN_EEPROM_DI = 0x8,
+       AUBURN_EEPROM_DI_0 = 0x0,
+       AUBURN_EEPROM_DI_1 = 0x8,
+       AUBURN_EEPROM_DO = 0x4,
+       AUBURN_EEPROM_DO_0 = 0x0,
+       AUBURN_EEPROM_DO_1 = 0x4,
+       AUBURN_EEPROM_CS = 0x2,
+       AUBURN_EEPROM_CS_0 = 0x0,
+       AUBURN_EEPROM_CS_1 = 0x2,
+       AUBURN_EEPROM_CLK_RISE = 0x1,
+       AUBURN_EEPROM_CLK_FALL = 0x0,
+};
+enum {EEPROM_SIZE = FM93C86A_SIZE_16,
+       EEPROM_NO_ADDR_BITS = FM93C86A_NO_ADDR_BITS_16,
+       EEPROM_NO_DATA_BITS = FM93C56A_DATA_BITS_16,
+};
+
+/*
+ *  MAC Config data structure
+ */
+    struct eeprom_port_cfg {
+       u16 etherMtu_mac;
+       u16 pauseThreshold_mac;
+       u16 resumeThreshold_mac;
+       u16 portConfiguration;
+#define PORT_CONFIG_AUTO_NEG_ENABLED        0x8000
+#define PORT_CONFIG_SYM_PAUSE_ENABLED       0x4000
+#define PORT_CONFIG_FULL_DUPLEX_ENABLED     0x2000
+#define PORT_CONFIG_HALF_DUPLEX_ENABLED     0x1000
+#define PORT_CONFIG_1000MB_SPEED            0x0400
+#define PORT_CONFIG_100MB_SPEED             0x0200
+#define PORT_CONFIG_10MB_SPEED              0x0100
+#define PORT_CONFIG_LINK_SPEED_MASK         0x0F00
+       u16 reserved[12];
+
+};
+
+/*
+ * BIOS data structure
+ */
+struct eeprom_bios_cfg {
+       u16 SpinDlyEn:1, disBios:1, EnMemMap:1, EnSelectBoot:1, Reserved:12;
+
+       u8 bootID0:7, boodID0Valid:1;
+       u8 bootLun0[8];
+
+       u8 bootID1:7, boodID1Valid:1;
+       u8 bootLun1[8];
+
+       u16 MaxLunsTrgt;
+       u8 reserved[10];
+};
+
+/*
+ *  Function Specific Data structure
+ */
+struct eeprom_function_cfg {
+       u8 reserved[30];
+       u8 macAddress[6];
+       u8 macAddressSecondary[6];
+
+       u16 subsysVendorId;
+       u16 subsysDeviceId;
+};
+
+/*
+ *  EEPROM format
+ */
+struct eeprom_data {
+       u8 asicId[4];
+       u8 version;
+       u8 numPorts;
+       u16 boardId;
+
+#define EEPROM_BOARDID_STR_SIZE   16
+#define EEPROM_SERIAL_NUM_SIZE    16
+
+       u8 boardIdStr[16];
+       u8 serialNumber[16];
+       u16 extHwConfig;
+       struct eeprom_port_cfg macCfg_port0;
+       struct eeprom_port_cfg macCfg_port1;
+       u16 bufletSize;
+       u16 bufletCount;
+       u16 tcpWindowThreshold50;
+       u16 tcpWindowThreshold25;
+       u16 tcpWindowThreshold0;
+       u16 ipHashTableBaseHi;
+       u16 ipHashTableBaseLo;
+       u16 ipHashTableSize;
+       u16 tcpHashTableBaseHi;
+       u16 tcpHashTableBaseLo;
+       u16 tcpHashTableSize;
+       u16 ncbTableBaseHi;
+       u16 ncbTableBaseLo;
+       u16 ncbTableSize;
+       u16 drbTableBaseHi;
+       u16 drbTableBaseLo;
+       u16 drbTableSize;
+       u16 reserved_142[4];
+       u16 ipReassemblyTimeout;
+       u16 tcpMaxWindowSize;
+       u16 ipSecurity;
+#define IPSEC_CONFIG_PRESENT 0x0001
+       u8 reserved_156[294];
+       u16 qDebug[8];
+       struct eeprom_function_cfg funcCfg_fn0;
+       u16 reserved_510;
+       u8 oemSpace[432];
+       struct eeprom_bios_cfg biosCfg_fn1;
+       struct eeprom_function_cfg funcCfg_fn1;
+       u16 reserved_1022;
+       u8 reserved_1024[464];
+       struct eeprom_function_cfg funcCfg_fn2;
+       u16 reserved_1534;
+       u8 reserved_1536[432];
+       struct eeprom_bios_cfg biosCfg_fn3;
+       struct eeprom_function_cfg funcCfg_fn3;
+       u16 checksum;
+};
+
+/*
+ * General definitions...
+ */
+
+/*
+ * Below are a number compiler switches for controlling driver behavior.
+ * Some are not supported under certain conditions and are notated as such.
+ */
+
+#define QL3XXX_VENDOR_ID    0x1077
+#define QL3022_DEVICE_ID    0x3022
+
+/* MTU & Frame Size stuff */
+#define NORMAL_MTU_SIZE                ETH_DATA_LEN
+#define JUMBO_MTU_SIZE                         9000
+#define VLAN_ID_LEN                        2
+
+/* Request Queue Related Definitions */
+#define NUM_REQ_Q_ENTRIES   256        /* so that 64 * 64  = 4096 (1 page) */
+
+/* Response Queue Related Definitions */
+#define NUM_RSP_Q_ENTRIES   256        /* so that 256 * 16  = 4096 (1 page) */
+
+/* Transmit and Receive Buffers */
+#define NUM_LBUFQ_ENTRIES      128
+#define NUM_SBUFQ_ENTRIES      64
+#define QL_SMALL_BUFFER_SIZE    32
+#define QL_ADDR_ELE_PER_BUFQ_ENTRY \
+(sizeof(struct lrg_buf_q_entry) / sizeof(struct bufq_addr_element))
+    /* Each send has at least control block.  This is how many we keep. */
+#define NUM_SMALL_BUFFERS      NUM_SBUFQ_ENTRIES * QL_ADDR_ELE_PER_BUFQ_ENTRY
+#define NUM_LARGE_BUFFERS      NUM_LBUFQ_ENTRIES * QL_ADDR_ELE_PER_BUFQ_ENTRY
+#define QL_HEADER_SPACE 32     /* make header space at top of skb. */
+/*
+ * Large & Small Buffers for Receives
+ */
+struct lrg_buf_q_entry {
+
+       u32 addr0_lower;
+#define IAL_LAST_ENTRY 0x00000001
+#define IAL_CONT_ENTRY 0x00000002
+#define IAL_FLAG_MASK  0x00000003
+       u32 addr0_upper;
+       u32 addr1_lower;
+       u32 addr1_upper;
+       u32 addr2_lower;
+       u32 addr2_upper;
+       u32 addr3_lower;
+       u32 addr3_upper;
+       u32 addr4_lower;
+       u32 addr4_upper;
+       u32 addr5_lower;
+       u32 addr5_upper;
+       u32 addr6_lower;
+       u32 addr6_upper;
+       u32 addr7_lower;
+       u32 addr7_upper;
+
+};
+
+struct bufq_addr_element {
+       u32 addr_low;
+       u32 addr_high;
+};
+
+#define QL_NO_RESET                    0
+#define QL_DO_RESET                    1
+
+enum link_state_t {
+       LS_UNKNOWN = 0,
+       LS_DOWN,
+       LS_DEGRADE,
+       LS_RECOVER,
+       LS_UP,
+};
+
+struct ql_rcv_buf_cb {
+       struct ql_rcv_buf_cb *next;
+       struct sk_buff *skb;
+        DECLARE_PCI_UNMAP_ADDR(mapaddr);
+        DECLARE_PCI_UNMAP_LEN(maplen);
+       __le32 buf_phy_addr_low;
+       __le32 buf_phy_addr_high;
+       int index;
+};
+
+struct ql_tx_buf_cb {
+       struct sk_buff *skb;
+       struct ob_mac_iocb_req *queue_entry ;
+        DECLARE_PCI_UNMAP_ADDR(mapaddr);
+        DECLARE_PCI_UNMAP_LEN(maplen);
+};
+
+/* definitions for type field */
+#define QL_BUF_TYPE_MACIOCB 0x01
+#define QL_BUF_TYPE_IPIOCB  0x02
+#define QL_BUF_TYPE_TCPIOCB 0x03
+
+/* qdev->flags definitions. */
+enum { QL_RESET_DONE = 1,      /* Reset finished. */
+       QL_RESET_ACTIVE = 2,    /* Waiting for reset to finish. */
+       QL_RESET_START = 3,     /* Please reset the chip. */
+       QL_RESET_PER_SCSI = 4,  /* SCSI driver requests reset. */
+       QL_TX_TIMEOUT = 5,      /* Timeout in progress. */
+       QL_LINK_MASTER = 6,     /* This driver controls the link. */
+       QL_ADAPTER_UP = 7,      /* Adapter has been brought up. */
+       QL_THREAD_UP = 8,       /* This flag is available. */
+       QL_LINK_UP = 9, /* Link Status. */
+       QL_ALLOC_REQ_RSP_Q_DONE = 10,
+       QL_ALLOC_BUFQS_DONE = 11,
+       QL_ALLOC_SMALL_BUF_DONE = 12,
+       QL_LINK_OPTICAL = 13,
+       QL_MSI_ENABLED = 14,
+};
+
+/*
+ * ql3_adapter - The main Adapter structure definition.
+ * This structure has all fields relevant to the hardware.
+ */
+
+struct ql3_adapter {
+       u32 reserved_00;
+       unsigned long flags;
+
+       /* PCI Configuration information for this device */
+       struct pci_dev *pdev;
+       struct net_device *ndev;        /* Parent NET device */
+
+       /* Hardware information */
+       u8 chip_rev_id;
+       u8 pci_slot;
+       u8 pci_width;
+       u8 pci_x;
+       u32 msi;
+       int index;
+       struct timer_list adapter_timer;        /* timer used for various functions */
+
+       spinlock_t adapter_lock;
+       spinlock_t hw_lock;
+
+       /* PCI Bus Relative Register Addresses */
+       u8 *mmap_virt_base;     /* stores return value from ioremap() */
+       struct ql3xxx_port_registers __iomem *mem_map_registers;
+       u32 current_page;       /* tracks current register page */
+
+       u32 msg_enable;
+       u8 reserved_01[2];
+       u8 reserved_02[2];
+
+       /* Page for Shadow Registers */
+       void *shadow_reg_virt_addr;
+       dma_addr_t shadow_reg_phy_addr;
+
+       /* Net Request Queue */
+       u32 req_q_size;
+       u32 reserved_03;
+       struct ob_mac_iocb_req *req_q_virt_addr;
+       dma_addr_t req_q_phy_addr;
+       u16 req_producer_index;
+       u16 reserved_04;
+       u16 *preq_consumer_index;
+       u32 req_consumer_index_phy_addr_high;
+       u32 req_consumer_index_phy_addr_low;
+       atomic_t tx_count;
+       struct ql_tx_buf_cb tx_buf[NUM_REQ_Q_ENTRIES];
+
+       /* Net Response Queue */
+       u32 rsp_q_size;
+       u32 eeprom_cmd_data;
+       struct net_rsp_iocb *rsp_q_virt_addr;
+       dma_addr_t rsp_q_phy_addr;
+       struct net_rsp_iocb *rsp_current;
+       u16 rsp_consumer_index;
+       u16 reserved_06;
+       u32 *prsp_producer_index;
+       u32 rsp_producer_index_phy_addr_high;
+       u32 rsp_producer_index_phy_addr_low;
+
+       /* Large Buffer Queue */
+       u32 lrg_buf_q_alloc_size;
+       u32 lrg_buf_q_size;
+       void *lrg_buf_q_alloc_virt_addr;
+       void *lrg_buf_q_virt_addr;
+       dma_addr_t lrg_buf_q_alloc_phy_addr;
+       dma_addr_t lrg_buf_q_phy_addr;
+       u32 lrg_buf_q_producer_index;
+       u32 lrg_buf_release_cnt;
+       struct bufq_addr_element *lrg_buf_next_free;
+
+       /* Large (Receive) Buffers */
+       struct ql_rcv_buf_cb lrg_buf[NUM_LARGE_BUFFERS];
+       struct ql_rcv_buf_cb *lrg_buf_free_head;
+       struct ql_rcv_buf_cb *lrg_buf_free_tail;
+       u32 lrg_buf_free_count;
+       u32 lrg_buffer_len;
+       u32 lrg_buf_index;
+       u32 lrg_buf_skb_check;
+
+       /* Small Buffer Queue */
+       u32 small_buf_q_alloc_size;
+       u32 small_buf_q_size;
+       u32 small_buf_q_producer_index;
+       void *small_buf_q_alloc_virt_addr;
+       void *small_buf_q_virt_addr;
+       dma_addr_t small_buf_q_alloc_phy_addr;
+       dma_addr_t small_buf_q_phy_addr;
+       u32 small_buf_index;
+
+       /* Small (Receive) Buffers */
+       void *small_buf_virt_addr;
+       dma_addr_t small_buf_phy_addr;
+       u32 small_buf_phy_addr_low;
+       u32 small_buf_phy_addr_high;
+       u32 small_buf_release_cnt;
+       u32 small_buf_total_size;
+
+       /* ISR related, saves status for DPC. */
+       u32 control_status;
+
+       struct eeprom_data nvram_data;
+       struct timer_list ioctl_timer;
+       u32 port_link_state;
+       u32 last_rsp_offset;
+
+       /* 4022 specific */
+       u32 mac_index;          /* Driver's MAC number can be 0 or 1 for first and second networking functions respectively */
+       u32 PHYAddr;            /* Address of PHY 0x1e00 Port 0 and 0x1f00 Port 1 */
+       u32 mac_ob_opcode;      /* Opcode to use on mac transmission */
+       u32 tcp_ob_opcode;      /* Opcode to use on tcp transmission */
+       u32 update_ob_opcode;   /* Opcode to use for updating NCB */
+       u32 mb_bit_mask;        /* MA Bits mask to use on transmission */
+       u32 numPorts;
+       struct net_device_stats stats;
+       struct workqueue_struct *workqueue;
+       struct work_struct reset_work;
+       struct work_struct tx_timeout_work;
+       u32 max_frame_size;
+};
+
+#endif                         /* _QLA3XXX_H_ */
index 4c2f575faad709db506ce5c250ab81eefacd2e79..5722a5638ffc94e8b8e516be043268535a42de5b 100644 (file)
@@ -2809,7 +2809,7 @@ static struct pci_driver rtl8169_pci_driver = {
 static int __init
 rtl8169_init_module(void)
 {
-       return pci_module_init(&rtl8169_pci_driver);
+       return pci_register_driver(&rtl8169_pci_driver);
 }
 
 static void __exit
index c3ed734cbe39cdabd5713c5c1e2214e9827b9513..31bcdad5471685fc3ccb121f3c054e69badef3a3 100644 (file)
@@ -1736,7 +1736,7 @@ static struct pci_driver rr_driver = {
 
 static int __init rr_init_module(void)
 {
-       return pci_module_init(&rr_driver);
+       return pci_register_driver(&rr_driver);
 }
 
 static void __exit rr_cleanup_module(void)
index 132ed32bce1ae819c8112a2d644c1de895d1370c..c16f9156c98a2944007d0d55a4edcad4c5201049 100644 (file)
@@ -71,6 +71,7 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/div64.h>
+#include <asm/irq.h>
 
 /* local include */
 #include "s2io.h"
@@ -7232,7 +7233,7 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
 
 int __init s2io_starter(void)
 {
-       return pci_module_init(&s2io_driver);
+       return pci_register_driver(&s2io_driver);
 }
 
 /**
index b2acedbefa8ffb2b63413e1d097ce29c8ca085c2..c479b07be788a129b4bac08abf19a141d8e2f945 100644 (file)
@@ -1131,7 +1131,7 @@ static struct pci_driver saa9730_driver = {
 
 static int __init saa9730_init(void)
 {
-       return pci_module_init(&saa9730_driver);
+       return pci_register_driver(&saa9730_driver);
 }
 
 static void __exit saa9730_cleanup(void)
index efd0f235020fb4e7099174d70232aece63581c0d..01392bca0223ea5ffcd55b0e1ac819d4c22bea03 100644 (file)
@@ -742,7 +742,7 @@ module_param(irq, int, 0);
 MODULE_PARM_DESC(io, "SEEQ 8005 I/O base address");
 MODULE_PARM_DESC(irq, "SEEQ 8005 IRQ number");
 
-int init_module(void)
+int __init init_module(void)
 {
        dev_seeq = seeq8005_probe(-1);
        if (IS_ERR(dev_seeq))
index df0cbebb3277ac69a167ef62154ab2ccf00a33ce..16e30d523fc5a96d7ec9029eb104d0da969bdbdf 100644 (file)
@@ -1871,7 +1871,7 @@ static struct pci_driver sis190_pci_driver = {
 
 static int __init sis190_init_module(void)
 {
-       return pci_module_init(&sis190_pci_driver);
+       return pci_register_driver(&sis190_pci_driver);
 }
 
 static void __exit sis190_cleanup_module(void)
index 29ee7ffedfff0f060dd3dfd8b3423d8af71ba7b1..6af50286349de02374a8a217797dd9e75cd543c8 100644 (file)
@@ -134,6 +134,7 @@ static const struct mii_chip_info {
        { "AMD 79C901 10BASE-T PHY",            0x0000, 0x6B70, LAN },
        { "AMD 79C901 HomePNA PHY",             0x0000, 0x6B90, HOME},
        { "ICS LAN PHY",                        0x0015, 0xF440, LAN },
+       { "ICS LAN PHY",                        0x0143, 0xBC70, LAN },
        { "NS 83851 PHY",                       0x2000, 0x5C20, MIX },
        { "NS 83847 PHY",                       0x2000, 0x5C30, MIX },
        { "Realtek RTL8201 PHY",                0x0000, 0x8200, LAN },
@@ -2495,7 +2496,7 @@ static int __init sis900_init_module(void)
        printk(version);
 #endif
 
-       return pci_module_init(&sis900_pci_driver);
+       return pci_register_driver(&sis900_pci_driver);
 }
 
 static void __exit sis900_cleanup_module(void)
index ee62845d3ac9d9140eea0e2a8c0e801ce75a9682..49e76c7f10da041f26237fd391e91a87c25a3ada 100644 (file)
@@ -5133,7 +5133,7 @@ static struct pci_driver skge_driver = {
 
 static int __init skge_init(void)
 {
-       return pci_module_init(&skge_driver);
+       return pci_register_driver(&skge_driver);
 }
 
 static void __exit skge_exit(void)
index b5714a60237d91ea37b874878d6835d60ade2fd5..8e4d18440a5695ebe17acd66f1052cf0b6683739 100644 (file)
@@ -2280,7 +2280,7 @@ static struct pci_driver skfddi_pci_driver = {
 
 static int __init skfd_init(void)
 {
-       return pci_module_init(&skfddi_pci_driver);
+       return pci_register_driver(&skfddi_pci_driver);
 }
 
 static void __exit skfd_exit(void)
index 7de9a07b2ac2defb1c45311c21b5348952bb82f5..1b752141a4f39133fc76e763fbff1be481bc508f 100644 (file)
@@ -2211,6 +2211,7 @@ static int skge_up(struct net_device *dev)
        skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
        skge_led(skge, LED_MODE_ON);
 
+       netif_poll_enable(dev);
        return 0;
 
  free_rx_ring:
@@ -2279,6 +2280,7 @@ static int skge_down(struct net_device *dev)
 
        skge_led(skge, LED_MODE_OFF);
 
+       netif_poll_disable(dev);
        skge_tx_clean(skge);
        skge_rx_clean(skge);
 
@@ -3508,7 +3510,7 @@ static struct pci_driver skge_driver = {
 
 static int __init skge_init_module(void)
 {
-       return pci_module_init(&skge_driver);
+       return pci_register_driver(&skge_driver);
 }
 
 static void __exit skge_cleanup_module(void)
index 933e87f1cc687dc6c8c300af83f6725dde79c7d9..805a7dcf5508596662cf88e8463018468b9ab8e1 100644 (file)
@@ -50,7 +50,7 @@
 #include "sky2.h"
 
 #define DRV_NAME               "sky2"
-#define DRV_VERSION            "1.5"
+#define DRV_VERSION            "1.6"
 #define PFX                    DRV_NAME " "
 
 /*
@@ -121,6 +121,11 @@ static const struct pci_device_id sky2_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4365) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) },
        { 0 }
 };
 
@@ -1926,12 +1931,6 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
        }
 }
 
-/* Is status ring empty or is there more to do? */
-static inline int sky2_more_work(const struct sky2_hw *hw)
-{
-       return (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX));
-}
-
 /* Process status response ring */
 static int sky2_status_intr(struct sky2_hw *hw, int to_do)
 {
@@ -2022,6 +2021,9 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
                }
        }
 
+       /* Fully processed status ring so clear irq */
+       sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
+
 exit_loop:
        if (buf_write[0]) {
                sky2 = netdev_priv(hw->dev[0]);
@@ -2231,19 +2233,16 @@ static int sky2_poll(struct net_device *dev0, int *budget)
                sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2);
 
        work_done = sky2_status_intr(hw, work_limit);
-       *budget -= work_done;
-       dev0->quota -= work_done;
-
-       if (status & Y2_IS_STAT_BMU)
-               sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
+       if (work_done < work_limit) {
+               netif_rx_complete(dev0);
 
-       if (sky2_more_work(hw))
+               sky2_read32(hw, B0_Y2_SP_LISR);
+               return 0;
+       } else {
+               *budget -= work_done;
+               dev0->quota -= work_done;
                return 1;
-
-       netif_rx_complete(dev0);
-
-       sky2_read32(hw, B0_Y2_SP_LISR);
-       return 0;
+       }
 }
 
 static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs)
index 3a1b7131681cd5fa5c9313cdde005d0b0faa76fa..9a540e2092b9a658f7b6ba6234e3675bd87d68aa 100644 (file)
@@ -94,27 +94,23 @@ slhc_init(int rslots, int tslots)
        register struct cstate *ts;
        struct slcompress *comp;
 
-       comp = (struct slcompress *)kmalloc(sizeof(struct slcompress),
-                                           GFP_KERNEL);
+       comp = kzalloc(sizeof(struct slcompress), GFP_KERNEL);
        if (! comp)
                goto out_fail;
-       memset(comp, 0, sizeof(struct slcompress));
 
        if ( rslots > 0  &&  rslots < 256 ) {
                size_t rsize = rslots * sizeof(struct cstate);
-               comp->rstate = (struct cstate *) kmalloc(rsize, GFP_KERNEL);
+               comp->rstate = kzalloc(rsize, GFP_KERNEL);
                if (! comp->rstate)
                        goto out_free;
-               memset(comp->rstate, 0, rsize);
                comp->rslot_limit = rslots - 1;
        }
 
        if ( tslots > 0  &&  tslots < 256 ) {
                size_t tsize = tslots * sizeof(struct cstate);
-               comp->tstate = (struct cstate *) kmalloc(tsize, GFP_KERNEL);
+               comp->tstate = kzalloc(tsize, GFP_KERNEL);
                if (! comp->tstate)
                        goto out_free2;
-               memset(comp->tstate, 0, tsize);
                comp->tslot_limit = tslots - 1;
        }
 
@@ -141,9 +137,9 @@ slhc_init(int rslots, int tslots)
        return comp;
 
 out_free2:
-       kfree((unsigned char *)comp->rstate);
+       kfree(comp->rstate);
 out_free:
-       kfree((unsigned char *)comp);
+       kfree(comp);
 out_fail:
        return NULL;
 }
@@ -700,20 +696,6 @@ EXPORT_SYMBOL(slhc_compress);
 EXPORT_SYMBOL(slhc_uncompress);
 EXPORT_SYMBOL(slhc_toss);
 
-#ifdef MODULE
-
-int init_module(void)
-{
-       printk(KERN_INFO "CSLIP: code copyright 1989 Regents of the University of California\n");
-       return 0;
-}
-
-void cleanup_module(void)
-{
-       return;
-}
-
-#endif /* MODULE */
 #else /* CONFIG_INET */
 
 
index d37bd860b336937c8f50645efec075a581283673..4438fe8c9499068041808b28fb599247c09055de 100644 (file)
@@ -55,8 +55,6 @@ static const char version[] =
                         )
 #endif
 
-
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -1092,6 +1090,7 @@ static irqreturn_t smc911x_interrupt(int irq, void *dev_id, struct pt_regs *regs
        /* Spurious interrupt check */
        if ((SMC_GET_IRQ_CFG() & (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) !=
                (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) {
+               spin_unlock_irqrestore(&lp->lock, flags);
                return IRQ_NONE;
        }
 
index 3d8dcb6c8758f32eff96fcaf905374a6105d6427..cf62373b808b6eaf81b6f36888026da82b27c38b 100644 (file)
@@ -321,12 +321,12 @@ static void smc_reset(struct net_device *dev)
        DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
 
        /* Disable all interrupts, block TX tasklet */
-       spin_lock(&lp->lock);
+       spin_lock_irq(&lp->lock);
        SMC_SELECT_BANK(2);
        SMC_SET_INT_MASK(0);
        pending_skb = lp->pending_tx_skb;
        lp->pending_tx_skb = NULL;
-       spin_unlock(&lp->lock);
+       spin_unlock_irq(&lp->lock);
 
        /* free any pending tx skb */
        if (pending_skb) {
@@ -448,12 +448,12 @@ static void smc_shutdown(struct net_device *dev)
        DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
 
        /* no more interrupts for me */
-       spin_lock(&lp->lock);
+       spin_lock_irq(&lp->lock);
        SMC_SELECT_BANK(2);
        SMC_SET_INT_MASK(0);
        pending_skb = lp->pending_tx_skb;
        lp->pending_tx_skb = NULL;
-       spin_unlock(&lp->lock);
+       spin_unlock_irq(&lp->lock);
        if (pending_skb)
                dev_kfree_skb(pending_skb);
 
index 9f9f8f2d533877e6e97740fda9ed69d5e6ca064a..7aa7fbac8224a385f91c8fd696daeab35d1aba58 100644 (file)
@@ -184,16 +184,10 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define SMC_IO_SHIFT           0
 #define SMC_NOWAIT             1
 
-#define SMC_inb(a, r)          readb((a) + (r))
-#define SMC_outb(v, a, r)      writeb(v, (a) + (r))
 #define SMC_inw(a, r)          readw((a) + (r))
 #define SMC_outw(v, a, r)      writew(v, (a) + (r))
 #define SMC_insw(a, r, p, l)   readsw((a) + (r), p, l)
 #define SMC_outsw(a, r, p, l)  writesw((a) + (r), p, l)
-#define SMC_inl(a, r)          readl((a) + (r))
-#define SMC_outl(v, a, r)      writel(v, (a) + (r))
-#define SMC_insl(a, r, p, l)   readsl((a) + (r), p, l)
-#define SMC_outsl(a, r, p, l)  writesl((a) + (r), p, l)
 
 #include <asm/mach-types.h>
 #include <asm/arch/cpu.h>
@@ -367,6 +361,24 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r,
 
 #define SMC_IRQ_FLAGS          (0)
 
+#elif  defined(CONFIG_ARCH_VERSATILE)
+
+#define SMC_CAN_USE_8BIT       1
+#define SMC_CAN_USE_16BIT      1
+#define SMC_CAN_USE_32BIT      1
+#define SMC_NOWAIT             1
+
+#define SMC_inb(a, r)          readb((a) + (r))
+#define SMC_inw(a, r)          readw((a) + (r))
+#define SMC_inl(a, r)          readl((a) + (r))
+#define SMC_outb(v, a, r)      writeb(v, (a) + (r))
+#define SMC_outw(v, a, r)      writew(v, (a) + (r))
+#define SMC_outl(v, a, r)      writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l)   readsl((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l)  writesl((a) + (r), p, l)
+
+#define SMC_IRQ_FLAGS          (0)
+
 #else
 
 #define SMC_CAN_USE_8BIT       1
index 647f62e9707dd3ac701bdf3f7c2c31e99765452f..88907218457a639d95a313b580631f8fc7e35b1a 100644 (file)
@@ -1611,13 +1611,12 @@ spider_net_open(struct net_device *netdev)
        int result;
 
        result = -ENOMEM;
-       if (spider_net_init_chain(card, &card->tx_chain,
-                       card->descr,
-                       PCI_DMA_TODEVICE, tx_descriptors))
+       if (spider_net_init_chain(card, &card->tx_chain, card->descr,
+                       PCI_DMA_TODEVICE, card->tx_desc))
                goto alloc_tx_failed;
        if (spider_net_init_chain(card, &card->rx_chain,
-                       card->descr + tx_descriptors,
-                       PCI_DMA_FROMDEVICE, rx_descriptors))
+                       card->descr + card->rx_desc,
+                       PCI_DMA_FROMDEVICE, card->rx_desc))
                goto alloc_rx_failed;
 
        /* allocate rx skbs */
@@ -2005,6 +2004,9 @@ spider_net_setup_netdev(struct spider_net_card *card)
 
        card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT;
 
+       card->tx_desc = tx_descriptors;
+       card->rx_desc = rx_descriptors;
+
        spider_net_setup_netdev_ops(netdev);
 
        netdev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX;
index f6dcf180ae3d280b49c0d434fcdf503b4fc8321b..30407cdf0892bf0017ea7b72bd21e0a20421f301 100644 (file)
@@ -440,6 +440,9 @@ struct spider_net_card {
        /* for ethtool */
        int msg_enable;
 
+       int rx_desc;
+       int tx_desc;
+
        struct spider_net_descr descr[0];
 };
 
index a5bb0b7633af2576db48f9a347962b9394506db5..02209222b8c94d6f200745c578b6406addadfe9d 100644 (file)
@@ -130,6 +130,18 @@ spider_net_ethtool_set_tx_csum(struct net_device *netdev, uint32_t data)
         return 0;
 }
 
+static void
+spider_net_ethtool_get_ringparam(struct net_device *netdev,
+                                struct ethtool_ringparam *ering)
+{
+       struct spider_net_card *card = netdev->priv;
+
+       ering->tx_max_pending = SPIDER_NET_TX_DESCRIPTORS_MAX;
+       ering->tx_pending = card->tx_desc;
+       ering->rx_max_pending = SPIDER_NET_RX_DESCRIPTORS_MAX;
+       ering->rx_pending = card->rx_desc;
+}
+
 struct ethtool_ops spider_net_ethtool_ops = {
        .get_settings           = spider_net_ethtool_get_settings,
        .get_drvinfo            = spider_net_ethtool_get_drvinfo,
@@ -141,5 +153,6 @@ struct ethtool_ops spider_net_ethtool_ops = {
        .set_rx_csum            = spider_net_ethtool_set_rx_csum,
        .get_tx_csum            = spider_net_ethtool_get_tx_csum,
        .set_tx_csum            = spider_net_ethtool_set_tx_csum,
+       .get_ringparam          = spider_net_ethtool_get_ringparam,
 };
 
index c0a62b00ffc896879be84b96fbca0572692d46e3..8e1f6206b7d0da7c49e1b487a925ecb2b6f42faa 100644 (file)
@@ -2053,7 +2053,7 @@ static int __init starfire_init (void)
                return -ENODEV;
        }
 
-       return pci_module_init (&starfire_driver);
+       return pci_register_driver(&starfire_driver);
 }
 
 
index ac17377b3e9fd4aa8cde1af0b85e0b0b594570ce..c243a80f4006e4a8d7def429202cce2885456964 100644 (file)
@@ -17,6 +17,8 @@
        Support and updates available at
        http://www.scyld.com/network/sundance.html
        [link no longer provides useful info -jgarzik]
+       Archives of the mailing list are still available at
+       http://www.beowulf.org/pipermail/netdrivers/
 
 */
 
@@ -107,7 +109,7 @@ static char *media[MAX_UNITS];
 #endif
 
 /* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
+static char version[] =
 KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "  Written by Donald Becker\n"
 KERN_INFO "  http://www.scyld.com/network/sundance.html\n";
 
@@ -646,7 +648,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
        /* Reset the chip to erase previous misconfiguration. */
        if (netif_msg_hw(np))
                printk("ASIC Control is %x.\n", ioread32(ioaddr + ASICCtrl));
-       iowrite16(0x00ff, ioaddr + ASICCtrl + 2);
+       sundance_reset(dev, 0x00ff << 16);
        if (netif_msg_hw(np))
                printk("ASIC Control is now %x.\n", ioread32(ioaddr + ASICCtrl));
 
@@ -1075,13 +1077,8 @@ reset_tx (struct net_device *dev)
        
        /* Reset tx logic, TxListPtr will be cleaned */
        iowrite16 (TxDisable, ioaddr + MACCtrl1);
-       iowrite16 (TxReset | DMAReset | FIFOReset | NetworkReset,
-                       ioaddr + ASICCtrl + 2);
-       for (i=50; i > 0; i--) {
-               if ((ioread16(ioaddr + ASICCtrl + 2) & ResetBusy) == 0)
-                       break;
-               mdelay(1);
-       }
+       sundance_reset(dev, (NetworkReset|FIFOReset|DMAReset|TxReset) << 16);
+
        /* free all tx skbuff */
        for (i = 0; i < TX_RING_SIZE; i++) {
                skb = np->tx_skbuff[i];
@@ -1736,7 +1733,7 @@ static int __init sundance_init(void)
 #ifdef MODULE
        printk(version);
 #endif
-       return pci_module_init(&sundance_driver);
+       return pci_register_driver(&sundance_driver);
 }
 
 static void __exit sundance_exit(void)
index b70bbd7489789f826fd969262dfa16912b565e65..1a441a8a2add819a9f3b39150f63a8055a52ccc9 100644 (file)
@@ -3194,7 +3194,7 @@ static struct pci_driver gem_driver = {
 
 static int __init gem_init(void)
 {
-       return pci_module_init(&gem_driver);
+       return pci_register_driver(&gem_driver);
 }
 
 static void __exit gem_cleanup(void)
index 8b53ded66d3714ba16541c3e475868edd5b1d60b..39460fa916fe9df45216b7315297b9fc9372e83c 100644 (file)
@@ -1725,7 +1725,7 @@ static struct pci_driver tc35815_driver = {
 
 static int __init tc35815_init_module(void)
 {
-       return pci_module_init(&tc35815_driver);
+       return pci_register_driver(&tc35815_driver);
 }
 
 static void __exit tc35815_cleanup_module(void)
index 6f97962dd06b33429b463a8c69096035c74e400f..d6e2a6869f28526cef7a5c5d460d7c10b211cf66 100644 (file)
@@ -68,8 +68,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.64"
-#define DRV_MODULE_RELDATE     "July 31, 2006"
+#define DRV_MODULE_VERSION     "3.65"
+#define DRV_MODULE_RELDATE     "August 07, 2006"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
                                   TG3_RX_RCB_RING_SIZE(tp))
 #define TG3_TX_RING_BYTES      (sizeof(struct tg3_tx_buffer_desc) * \
                                 TG3_TX_RING_SIZE)
-#define TX_BUFFS_AVAIL(TP)                                             \
-       ((TP)->tx_pending -                                             \
-        (((TP)->tx_prod - (TP)->tx_cons) & (TG3_TX_RING_SIZE - 1)))
 #define NEXT_TX(N)             (((N) + 1) & (TG3_TX_RING_SIZE - 1))
 
 #define RX_PKT_BUF_SZ          (1536 + tp->rx_offset + 64)
@@ -2987,6 +2984,13 @@ static void tg3_tx_recover(struct tg3 *tp)
        spin_unlock(&tp->lock);
 }
 
+static inline u32 tg3_tx_avail(struct tg3 *tp)
+{
+       smp_mb();
+       return (tp->tx_pending -
+               ((tp->tx_prod - tp->tx_cons) & (TG3_TX_RING_SIZE - 1)));
+}
+
 /* Tigon3 never reports partial packet sends.  So we do not
  * need special logic to handle SKBs that have not had all
  * of their frags sent yet, like SunGEM does.
@@ -3038,12 +3042,20 @@ static void tg3_tx(struct tg3 *tp)
 
        tp->tx_cons = sw_idx;
 
-       if (unlikely(netif_queue_stopped(tp->dev))) {
-               spin_lock(&tp->tx_lock);
+       /* Need to make the tx_cons update visible to tg3_start_xmit()
+        * before checking for netif_queue_stopped().  Without the
+        * memory barrier, there is a small possibility that tg3_start_xmit()
+        * will miss it and cause the queue to be stopped forever.
+        */
+       smp_mb();
+
+       if (unlikely(netif_queue_stopped(tp->dev) &&
+                    (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))) {
+               netif_tx_lock(tp->dev);
                if (netif_queue_stopped(tp->dev) &&
-                   (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH))
+                   (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))
                        netif_wake_queue(tp->dev);
-               spin_unlock(&tp->tx_lock);
+               netif_tx_unlock(tp->dev);
        }
 }
 
@@ -3101,7 +3113,6 @@ static int tg3_alloc_rx_skb(struct tg3 *tp, u32 opaque_key,
        if (skb == NULL)
                return -ENOMEM;
 
-       skb->dev = tp->dev;
        skb_reserve(skb, tp->rx_offset);
 
        mapping = pci_map_single(tp->pdev, skb->data,
@@ -3274,7 +3285,6 @@ static int tg3_rx(struct tg3 *tp, int budget)
                        if (copy_skb == NULL)
                                goto drop_it_no_recycle;
 
-                       copy_skb->dev = tp->dev;
                        skb_reserve(copy_skb, 2);
                        skb_put(copy_skb, len);
                        pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE);
@@ -3797,7 +3807,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
         * interrupt.  Furthermore, IRQ processing runs lockless so we have
         * no IRQ context deadlocks to worry about either.  Rejoice!
         */
-       if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
+       if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
                if (!netif_queue_stopped(dev)) {
                        netif_stop_queue(dev);
 
@@ -3893,12 +3903,10 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
 
        tp->tx_prod = entry;
-       if (unlikely(TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))) {
-               spin_lock(&tp->tx_lock);
+       if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
                netif_stop_queue(dev);
-               if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)
+               if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)
                        netif_wake_queue(tp->dev);
-               spin_unlock(&tp->tx_lock);
        }
 
 out_unlock:
@@ -3920,7 +3928,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb)
        struct sk_buff *segs, *nskb;
 
        /* Estimate the number of fragments in the worst case */
-       if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->gso_segs * 3))) {
+       if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->gso_segs * 3))) {
                netif_stop_queue(tp->dev);
                return NETDEV_TX_BUSY;
        }
@@ -3960,7 +3968,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
         * interrupt.  Furthermore, IRQ processing runs lockless so we have
         * no IRQ context deadlocks to worry about either.  Rejoice!
         */
-       if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
+       if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
                if (!netif_queue_stopped(dev)) {
                        netif_stop_queue(dev);
 
@@ -4110,12 +4118,10 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
        tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
 
        tp->tx_prod = entry;
-       if (unlikely(TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))) {
-               spin_lock(&tp->tx_lock);
+       if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
                netif_stop_queue(dev);
-               if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)
+               if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)
                        netif_wake_queue(tp->dev);
-               spin_unlock(&tp->tx_lock);
        }
 
 out_unlock:
@@ -11474,7 +11480,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        tp->grc_mode |= GRC_MODE_BSWAP_NONFRM_DATA;
 #endif
        spin_lock_init(&tp->lock);
-       spin_lock_init(&tp->tx_lock);
        spin_lock_init(&tp->indirect_lock);
        INIT_WORK(&tp->reset_task, tg3_reset_task, tp);
 
@@ -11814,7 +11819,7 @@ static struct pci_driver tg3_driver = {
 
 static int __init tg3_init(void)
 {
-       return pci_module_init(&tg3_driver);
+       return pci_register_driver(&tg3_driver);
 }
 
 static void __exit tg3_cleanup(void)
index ba2c98711c88dc9d524f35204652e823b9d4c177..3ecf356cfb082e17cc17875aec9eaf0c7e5b3cbb 100644 (file)
@@ -2079,9 +2079,9 @@ struct tg3 {
         * lock: Held during reset, PHY access, timer, and when
         *       updating tg3_flags and tg3_flags2.
         *
-        * tx_lock: Held during tg3_start_xmit and tg3_tx only
-        *          when calling netif_[start|stop]_queue.
-        *          tg3_start_xmit is protected by netif_tx_lock.
+        * netif_tx_lock: Held during tg3_start_xmit. tg3_tx holds
+        *                netif_tx_lock when it needs to call
+        *                netif_wake_queue.
         *
         * Both of these locks are to be held with BH safety.
         *
@@ -2118,8 +2118,6 @@ struct tg3 {
        u32                             tx_cons;
        u32                             tx_pending;
 
-       spinlock_t                      tx_lock;
-
        struct tg3_tx_buffer_desc       *tx_ring;
        struct tx_ring_info             *tx_buffers;
        dma_addr_t                      tx_desc_mapping;
index 465921e3874c933e7e114c71c7d1179b25ffabc5..412390ba142ecff7b14ba41f773403bda4ba6575 100644 (file)
@@ -1815,7 +1815,7 @@ static struct pci_driver xl_3c359_driver = {
 
 static int __init xl_pci_init (void)
 {
-       return pci_module_init (&xl_3c359_driver);
+       return pci_register_driver(&xl_3c359_driver);
 }
 
 
index 9f491563944e917efc754b3d9c59645cefbc24a6..4470025ff7f85bc86e580aee983b653a3181c2ce 100644 (file)
@@ -140,7 +140,7 @@ in the event that chatty debug messages are desired - jjs 12/30/98 */
 
 /* version and credits */
 #ifndef PCMCIA
-static char version[] __initdata =
+static char version[] __devinitdata =
     "\nibmtr.c: v1.3.57   8/ 7/94 Peter De Schrijver and Mark Swanson\n"
     "         v2.1.125 10/20/98 Paul Norton    <pnorton@ieee.org>\n"
     "         v2.2.0   12/30/98 Joel Sloan     <jjs@c-me.com>\n"
@@ -216,7 +216,7 @@ static int __devinitdata turbo_irq[IBMTR_MAX_ADAPTERS] = {0};
 static int __devinitdata turbo_searched = 0;
 
 #ifndef PCMCIA
-static __u32 ibmtr_mem_base __initdata = 0xd0000;
+static __u32 ibmtr_mem_base __devinitdata = 0xd0000;
 #endif
 
 static void __devinit PrtChanID(char *pcid, short stride)
index 28d968ffd5d0ff37f6ed82fe67e0c23f40ee2844..0d66700c6cedb3d9934a815f15c7ac2e2e327931 100644 (file)
@@ -1998,7 +1998,7 @@ static struct pci_driver streamer_pci_driver = {
 };
 
 static int __init streamer_init_module(void) {
-  return pci_module_init(&streamer_pci_driver);
+  return pci_register_driver(&streamer_pci_driver);
 }
 
 static void __exit streamer_cleanup_module(void) {
index cd2e0251e2bc387c910622d2e0ee25e73690bc6d..85a7f797d343de01d19d713e59516f9550c3bff6 100644 (file)
@@ -5666,7 +5666,7 @@ module_param_array(io, int, NULL, 0);
 module_param_array(irq, int, NULL, 0);
 module_param(ringspeed, int, 0);
 
-static struct net_device *setup_card(int n)
+static struct net_device * __init setup_card(int n)
 {
        struct net_device *dev = alloc_trdev(sizeof(struct net_local));
        int err;
@@ -5696,9 +5696,8 @@ out:
        free_netdev(dev);
        return ERR_PTR(err);
 }
-                       
 
-int init_module(void)
+int __init init_module(void)
 {
         int i, found = 0;
        struct net_device *dev;
index d05c5aa254eeb1163ffcc80c438a79072f20b22b..350a73e99a852eeb5674e24e753081c6b2eafed4 100644 (file)
@@ -2172,7 +2172,7 @@ static int __init de_init (void)
 #ifdef MODULE
        printk("%s", version);
 #endif
-       return pci_module_init (&de_driver);
+       return pci_register_driver(&de_driver);
 }
 
 static void __exit de_exit (void)
index 75ff14a552399937f052d4f970e8a5cb9cbd818f..e661d0a9cc64d5be35fc42ab81c402dd9970cea6 100644 (file)
@@ -5754,7 +5754,7 @@ static int __init de4x5_module_init (void)
        int err = 0;
 
 #ifdef CONFIG_PCI
-       err = pci_module_init (&de4x5_pci_driver);
+       err = pci_register_driver(&de4x5_pci_driver);
 #endif
 #ifdef CONFIG_EISA
        err |= eisa_driver_register (&de4x5_eisa_driver);
index 4e5b0f2acc395b2b407ca1a76d12564baac38151..66dade556821a26be204c7d0f5cc4ddf9a9ee806 100644 (file)
@@ -2039,7 +2039,7 @@ static int __init dmfe_init_module(void)
        if (HPNA_NoiseFloor > 15)
                HPNA_NoiseFloor = 0;
 
-       rc = pci_module_init(&dmfe_driver);
+       rc = pci_register_driver(&dmfe_driver);
        if (rc < 0)
                return rc;
 
index 7351831f57cec5f96c9687515c017a2e51d33b00..e1987ec493c216432f2c8b30d3a29ab609cb6b53 100644 (file)
@@ -1849,7 +1849,7 @@ static int __init tulip_init (void)
        tulip_max_interrupt_work = max_interrupt_work;
 
        /* probe for and init boards */
-       return pci_module_init (&tulip_driver);
+       return pci_register_driver(&tulip_driver);
 }
 
 
index fd64b2b3e99c7d3949723b22a08ac677b0ab07fb..c4c720e2d4c320a9af4bb0db350563ac0379f927 100644 (file)
@@ -1702,7 +1702,6 @@ MODULE_PARM_DESC(mode, "ULi M5261/M5263: Bit 0: 10/100Mbps, bit 2: duplex, bit 8
 
 static int __init uli526x_init_module(void)
 {
-       int rc;
 
        printk(version);
        printed_version = 1;
@@ -1714,22 +1713,19 @@ static int __init uli526x_init_module(void)
        if (cr6set)
                uli526x_cr6_user_set = cr6set;
 
-       switch(mode) {
+       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;
+       default:
+               uli526x_media_mode = ULI526X_AUTO;
                break;
        }
 
-       rc = pci_module_init(&uli526x_driver);
-       if (rc < 0)
-               return rc;
-
-       return 0;
+       return pci_register_driver(&uli526x_driver);
 }
 
 
index 7f414815cc624ac1f1ef1fec5f2ebfde6cd4fea7..6b82d1498223d300d1b83a3a1abf005e4e693f5e 100644 (file)
@@ -138,7 +138,7 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 #include <asm/irq.h>
 
 /* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
+static char version[] =
 KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) " DRV_RELDATE "  Donald Becker <becker@scyld.com>\n"
 KERN_INFO "  http://www.scyld.com/network/drivers.html\n";
 
@@ -1689,7 +1689,7 @@ static struct pci_driver w840_driver = {
 static int __init w840_init(void)
 {
        printk(version);
-       return pci_module_init(&w840_driver);
+       return pci_register_driver(&w840_driver);
 }
 
 static void __exit w840_exit(void)
index f874e4f6ccf6076d90899a3f73ba80c4fe4a58c2..cf43390d2c80d44943cc056eb373977874dab50d 100644 (file)
@@ -1264,8 +1264,7 @@ static void investigate_write_descriptor(struct net_device *dev, struct xircom_p
 
 static int __init xircom_init(void)
 {
-       pci_register_driver(&xircom_ops);
-       return 0;
+       return pci_register_driver(&xircom_ops);
 }
 
 static void __exit xircom_exit(void)
index 17ca7dc42e6fd6467a88a1a9f3876bb043102bda..d797b7b2e35f0577877cfd0e9ec641b4392e75f3 100644 (file)
@@ -1707,7 +1707,7 @@ static int __init xircom_init(void)
 #ifdef MODULE
        printk(version);
 #endif
-       return pci_module_init(&xircom_driver);
+       return pci_register_driver(&xircom_driver);
 }
 
 
index 4103c37172f9b154804f882ebf87be6ae3e26e29..1014461178cc4e1a0aae32591f0bd919cf200009 100644 (file)
@@ -2660,7 +2660,7 @@ static struct pci_driver typhoon_driver = {
 static int __init
 typhoon_init(void)
 {
-       return pci_module_init(&typhoon_driver);
+       return pci_register_driver(&typhoon_driver);
 }
 
 static void __exit
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
new file mode 100644 (file)
index 0000000..47f49ef
--- /dev/null
@@ -0,0 +1,4278 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ *
+ * Author: Shlomi Gridish <gridish@freescale.com>
+ *
+ * Description:
+ * QE UCC Gigabit Ethernet Driver
+ *
+ * Changelog:
+ * Jul 6, 2006 Li Yang <LeoLi@freescale.com>
+ * - Rearrange code and style fixes
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/ethtool.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/fsl_devices.h>
+#include <linux/ethtool.h>
+#include <linux/platform_device.h>
+#include <linux/mii.h>
+
+#include <asm/uaccess.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/immap_qe.h>
+#include <asm/qe.h>
+#include <asm/ucc.h>
+#include <asm/ucc_fast.h>
+
+#include "ucc_geth.h"
+#include "ucc_geth_phy.h"
+
+#undef DEBUG
+
+#define DRV_DESC "QE UCC Gigabit Ethernet Controller version:June 20, 2006"
+#define DRV_NAME "ucc_geth"
+
+#define ugeth_printk(level, format, arg...)  \
+        printk(level format "\n", ## arg)
+
+#define ugeth_dbg(format, arg...)            \
+        ugeth_printk(KERN_DEBUG , format , ## arg)
+#define ugeth_err(format, arg...)            \
+        ugeth_printk(KERN_ERR , format , ## arg)
+#define ugeth_info(format, arg...)           \
+        ugeth_printk(KERN_INFO , format , ## arg)
+#define ugeth_warn(format, arg...)           \
+        ugeth_printk(KERN_WARNING , format , ## arg)
+
+#ifdef UGETH_VERBOSE_DEBUG
+#define ugeth_vdbg ugeth_dbg
+#else
+#define ugeth_vdbg(fmt, args...) do { } while (0)
+#endif                         /* UGETH_VERBOSE_DEBUG */
+
+static DEFINE_SPINLOCK(ugeth_lock);
+
+static ucc_geth_info_t ugeth_primary_info = {
+       .uf_info = {
+                   .bd_mem_part = MEM_PART_SYSTEM,
+                   .rtsm = UCC_FAST_SEND_IDLES_BETWEEN_FRAMES,
+                   .max_rx_buf_length = 1536,
+/* FIXME: should be changed in run time for 1G and 100M */
+#ifdef CONFIG_UGETH_HAS_GIGA
+                   .urfs = UCC_GETH_URFS_GIGA_INIT,
+                   .urfet = UCC_GETH_URFET_GIGA_INIT,
+                   .urfset = UCC_GETH_URFSET_GIGA_INIT,
+                   .utfs = UCC_GETH_UTFS_GIGA_INIT,
+                   .utfet = UCC_GETH_UTFET_GIGA_INIT,
+                   .utftt = UCC_GETH_UTFTT_GIGA_INIT,
+#else
+                   .urfs = UCC_GETH_URFS_INIT,
+                   .urfet = UCC_GETH_URFET_INIT,
+                   .urfset = UCC_GETH_URFSET_INIT,
+                   .utfs = UCC_GETH_UTFS_INIT,
+                   .utfet = UCC_GETH_UTFET_INIT,
+                   .utftt = UCC_GETH_UTFTT_INIT,
+#endif
+                   .ufpt = 256,
+                   .mode = UCC_FAST_PROTOCOL_MODE_ETHERNET,
+                   .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL,
+                   .tenc = UCC_FAST_TX_ENCODING_NRZ,
+                   .renc = UCC_FAST_RX_ENCODING_NRZ,
+                   .tcrc = UCC_FAST_16_BIT_CRC,
+                   .synl = UCC_FAST_SYNC_LEN_NOT_USED,
+                   },
+       .numQueuesTx = 1,
+       .numQueuesRx = 1,
+       .extendedFilteringChainPointer = ((uint32_t) NULL),
+       .typeorlen = 3072 /*1536 */ ,
+       .nonBackToBackIfgPart1 = 0x40,
+       .nonBackToBackIfgPart2 = 0x60,
+       .miminumInterFrameGapEnforcement = 0x50,
+       .backToBackInterFrameGap = 0x60,
+       .mblinterval = 128,
+       .nortsrbytetime = 5,
+       .fracsiz = 1,
+       .strictpriorityq = 0xff,
+       .altBebTruncation = 0xa,
+       .excessDefer = 1,
+       .maxRetransmission = 0xf,
+       .collisionWindow = 0x37,
+       .receiveFlowControl = 1,
+       .maxGroupAddrInHash = 4,
+       .maxIndAddrInHash = 4,
+       .prel = 7,
+       .maxFrameLength = 1518,
+       .minFrameLength = 64,
+       .maxD1Length = 1520,
+       .maxD2Length = 1520,
+       .vlantype = 0x8100,
+       .ecamptr = ((uint32_t) NULL),
+       .eventRegMask = UCCE_OTHER,
+       .pausePeriod = 0xf000,
+       .interruptcoalescingmaxvalue = {1, 1, 1, 1, 1, 1, 1, 1},
+       .bdRingLenTx = {
+                       TX_BD_RING_LEN,
+                       TX_BD_RING_LEN,
+                       TX_BD_RING_LEN,
+                       TX_BD_RING_LEN,
+                       TX_BD_RING_LEN,
+                       TX_BD_RING_LEN,
+                       TX_BD_RING_LEN,
+                       TX_BD_RING_LEN},
+
+       .bdRingLenRx = {
+                       RX_BD_RING_LEN,
+                       RX_BD_RING_LEN,
+                       RX_BD_RING_LEN,
+                       RX_BD_RING_LEN,
+                       RX_BD_RING_LEN,
+                       RX_BD_RING_LEN,
+                       RX_BD_RING_LEN,
+                       RX_BD_RING_LEN},
+
+       .numStationAddresses = UCC_GETH_NUM_OF_STATION_ADDRESSES_1,
+       .largestexternallookupkeysize =
+           QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE,
+       .statisticsMode = UCC_GETH_STATISTICS_GATHERING_MODE_NONE,
+       .vlanOperationTagged = UCC_GETH_VLAN_OPERATION_TAGGED_NOP,
+       .vlanOperationNonTagged = UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP,
+       .rxQoSMode = UCC_GETH_QOS_MODE_DEFAULT,
+       .aufc = UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE,
+       .padAndCrc = MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC,
+       .numThreadsTx = UCC_GETH_NUM_OF_THREADS_4,
+       .numThreadsRx = UCC_GETH_NUM_OF_THREADS_4,
+       .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
+       .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
+};
+
+static ucc_geth_info_t ugeth_info[8];
+
+#ifdef DEBUG
+static void mem_disp(u8 *addr, int size)
+{
+       u8 *i;
+       int size16Aling = (size >> 4) << 4;
+       int size4Aling = (size >> 2) << 2;
+       int notAlign = 0;
+       if (size % 16)
+               notAlign = 1;
+
+       for (i = addr; (u32) i < (u32) addr + size16Aling; i += 16)
+               printk("0x%08x: %08x %08x %08x %08x\r\n",
+                      (u32) i,
+                      *((u32 *) (i)),
+                      *((u32 *) (i + 4)),
+                      *((u32 *) (i + 8)), *((u32 *) (i + 12)));
+       if (notAlign == 1)
+               printk("0x%08x: ", (u32) i);
+       for (; (u32) i < (u32) addr + size4Aling; i += 4)
+               printk("%08x ", *((u32 *) (i)));
+       for (; (u32) i < (u32) addr + size; i++)
+               printk("%02x", *((u8 *) (i)));
+       if (notAlign == 1)
+               printk("\r\n");
+}
+#endif /* DEBUG */
+
+#ifdef CONFIG_UGETH_FILTERING
+static void enqueue(struct list_head *node, struct list_head *lh)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(ugeth_lock, flags);
+       list_add_tail(node, lh);
+       spin_unlock_irqrestore(ugeth_lock, flags);
+}
+#endif /* CONFIG_UGETH_FILTERING */
+
+static struct list_head *dequeue(struct list_head *lh)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(ugeth_lock, flags);
+       if (!list_empty(lh)) {
+               struct list_head *node = lh->next;
+               list_del(node);
+               spin_unlock_irqrestore(ugeth_lock, flags);
+               return node;
+       } else {
+               spin_unlock_irqrestore(ugeth_lock, flags);
+               return NULL;
+       }
+}
+
+static int get_interface_details(enet_interface_e enet_interface,
+                                enet_speed_e *speed,
+                                int *r10m,
+                                int *rmm,
+                                int *rpm,
+                                int *tbi, int *limited_to_full_duplex)
+{
+       /* Analyze enet_interface according to Interface Mode
+       Configuration table */
+       switch (enet_interface) {
+       case ENET_10_MII:
+               *speed = ENET_SPEED_10BT;
+               break;
+       case ENET_10_RMII:
+               *speed = ENET_SPEED_10BT;
+               *r10m = 1;
+               *rmm = 1;
+               break;
+       case ENET_10_RGMII:
+               *speed = ENET_SPEED_10BT;
+               *rpm = 1;
+               *r10m = 1;
+               *limited_to_full_duplex = 1;
+               break;
+       case ENET_100_MII:
+               *speed = ENET_SPEED_100BT;
+               break;
+       case ENET_100_RMII:
+               *speed = ENET_SPEED_100BT;
+               *rmm = 1;
+               break;
+       case ENET_100_RGMII:
+               *speed = ENET_SPEED_100BT;
+               *rpm = 1;
+               *limited_to_full_duplex = 1;
+               break;
+       case ENET_1000_GMII:
+               *speed = ENET_SPEED_1000BT;
+               *limited_to_full_duplex = 1;
+               break;
+       case ENET_1000_RGMII:
+               *speed = ENET_SPEED_1000BT;
+               *rpm = 1;
+               *limited_to_full_duplex = 1;
+               break;
+       case ENET_1000_TBI:
+               *speed = ENET_SPEED_1000BT;
+               *tbi = 1;
+               *limited_to_full_duplex = 1;
+               break;
+       case ENET_1000_RTBI:
+               *speed = ENET_SPEED_1000BT;
+               *rpm = 1;
+               *tbi = 1;
+               *limited_to_full_duplex = 1;
+               break;
+       default:
+               return -EINVAL;
+               break;
+       }
+
+       return 0;
+}
+
+static struct sk_buff *get_new_skb(ucc_geth_private_t *ugeth, u8 *bd)
+{
+       struct sk_buff *skb = NULL;
+
+       skb = dev_alloc_skb(ugeth->ug_info->uf_info.max_rx_buf_length +
+                                 UCC_GETH_RX_DATA_BUF_ALIGNMENT);
+
+       if (skb == NULL)
+               return NULL;
+
+       /* We need the data buffer to be aligned properly.  We will reserve
+        * as many bytes as needed to align the data properly
+        */
+       skb_reserve(skb,
+                   UCC_GETH_RX_DATA_BUF_ALIGNMENT -
+                   (((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT -
+                                             1)));
+
+       skb->dev = ugeth->dev;
+
+       BD_BUFFER_SET(bd,
+                     dma_map_single(NULL,
+                                    skb->data,
+                                    ugeth->ug_info->uf_info.max_rx_buf_length +
+                                    UCC_GETH_RX_DATA_BUF_ALIGNMENT,
+                                    DMA_FROM_DEVICE));
+
+       BD_STATUS_AND_LENGTH_SET(bd,
+                                (R_E | R_I |
+                                 (BD_STATUS_AND_LENGTH(bd) & R_W)));
+
+       return skb;
+}
+
+static int rx_bd_buffer_set(ucc_geth_private_t *ugeth, u8 rxQ)
+{
+       u8 *bd;
+       u32 bd_status;
+       struct sk_buff *skb;
+       int i;
+
+       bd = ugeth->p_rx_bd_ring[rxQ];
+       i = 0;
+
+       do {
+               bd_status = BD_STATUS_AND_LENGTH(bd);
+               skb = get_new_skb(ugeth, bd);
+
+               if (!skb)       /* If can not allocate data buffer,
+                               abort. Cleanup will be elsewhere */
+                       return -ENOMEM;
+
+               ugeth->rx_skbuff[rxQ][i] = skb;
+
+               /* advance the BD pointer */
+               bd += UCC_GETH_SIZE_OF_BD;
+               i++;
+       } while (!(bd_status & R_W));
+
+       return 0;
+}
+
+static int fill_init_enet_entries(ucc_geth_private_t *ugeth,
+                                 volatile u32 *p_start,
+                                 u8 num_entries,
+                                 u32 thread_size,
+                                 u32 thread_alignment,
+                                 qe_risc_allocation_e risc,
+                                 int skip_page_for_first_entry)
+{
+       u32 init_enet_offset;
+       u8 i;
+       int snum;
+
+       for (i = 0; i < num_entries; i++) {
+               if ((snum = qe_get_snum()) < 0) {
+                       ugeth_err("fill_init_enet_entries: Can not get SNUM.");
+                       return snum;
+               }
+               if ((i == 0) && skip_page_for_first_entry)
+               /* First entry of Rx does not have page */
+                       init_enet_offset = 0;
+               else {
+                       init_enet_offset =
+                           qe_muram_alloc(thread_size, thread_alignment);
+                       if (IS_MURAM_ERR(init_enet_offset)) {
+                               ugeth_err
+               ("fill_init_enet_entries: Can not allocate DPRAM memory.");
+                               qe_put_snum((u8) snum);
+                               return -ENOMEM;
+                       }
+               }
+               *(p_start++) =
+                   ((u8) snum << ENET_INIT_PARAM_SNUM_SHIFT) | init_enet_offset
+                   | risc;
+       }
+
+       return 0;
+}
+
+static int return_init_enet_entries(ucc_geth_private_t *ugeth,
+                                   volatile u32 *p_start,
+                                   u8 num_entries,
+                                   qe_risc_allocation_e risc,
+                                   int skip_page_for_first_entry)
+{
+       u32 init_enet_offset;
+       u8 i;
+       int snum;
+
+       for (i = 0; i < num_entries; i++) {
+               /* Check that this entry was actually valid --
+               needed in case failed in allocations */
+               if ((*p_start & ENET_INIT_PARAM_RISC_MASK) == risc) {
+                       snum =
+                           (u32) (*p_start & ENET_INIT_PARAM_SNUM_MASK) >>
+                           ENET_INIT_PARAM_SNUM_SHIFT;
+                       qe_put_snum((u8) snum);
+                       if (!((i == 0) && skip_page_for_first_entry)) {
+                       /* First entry of Rx does not have page */
+                               init_enet_offset =
+                                   (in_be32(p_start) &
+                                    ENET_INIT_PARAM_PTR_MASK);
+                               qe_muram_free(init_enet_offset);
+                       }
+                       *(p_start++) = 0;       /* Just for cosmetics */
+               }
+       }
+
+       return 0;
+}
+
+#ifdef DEBUG
+static int dump_init_enet_entries(ucc_geth_private_t *ugeth,
+                                 volatile u32 *p_start,
+                                 u8 num_entries,
+                                 u32 thread_size,
+                                 qe_risc_allocation_e risc,
+                                 int skip_page_for_first_entry)
+{
+       u32 init_enet_offset;
+       u8 i;
+       int snum;
+
+       for (i = 0; i < num_entries; i++) {
+               /* Check that this entry was actually valid --
+               needed in case failed in allocations */
+               if ((*p_start & ENET_INIT_PARAM_RISC_MASK) == risc) {
+                       snum =
+                           (u32) (*p_start & ENET_INIT_PARAM_SNUM_MASK) >>
+                           ENET_INIT_PARAM_SNUM_SHIFT;
+                       qe_put_snum((u8) snum);
+                       if (!((i == 0) && skip_page_for_first_entry)) {
+                       /* First entry of Rx does not have page */
+                               init_enet_offset =
+                                   (in_be32(p_start) &
+                                    ENET_INIT_PARAM_PTR_MASK);
+                               ugeth_info("Init enet entry %d:", i);
+                               ugeth_info("Base address: 0x%08x",
+                                          (u32)
+                                          qe_muram_addr(init_enet_offset));
+                               mem_disp(qe_muram_addr(init_enet_offset),
+                                        thread_size);
+                       }
+                       p_start++;
+               }
+       }
+
+       return 0;
+}
+#endif
+
+#ifdef CONFIG_UGETH_FILTERING
+static enet_addr_container_t *get_enet_addr_container(void)
+{
+       enet_addr_container_t *enet_addr_cont;
+
+       /* allocate memory */
+       enet_addr_cont = kmalloc(sizeof(enet_addr_container_t), GFP_KERNEL);
+       if (!enet_addr_cont) {
+               ugeth_err("%s: No memory for enet_addr_container_t object.",
+                         __FUNCTION__);
+               return NULL;
+       }
+
+       return enet_addr_cont;
+}
+#endif /* CONFIG_UGETH_FILTERING */
+
+static void put_enet_addr_container(enet_addr_container_t *enet_addr_cont)
+{
+       kfree(enet_addr_cont);
+}
+
+#ifdef CONFIG_UGETH_FILTERING
+static int hw_add_addr_in_paddr(ucc_geth_private_t *ugeth,
+                               enet_addr_t *p_enet_addr, u8 paddr_num)
+{
+       ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+
+       if (!(paddr_num < NUM_OF_PADDRS)) {
+               ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       p_82xx_addr_filt =
+           (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+           addressfiltering;
+
+       /* Ethernet frames are defined in Little Endian mode,    */
+       /* therefore to insert the address we reverse the bytes. */
+       out_be16(&p_82xx_addr_filt->paddr[paddr_num].h,
+                (u16) (((u16) (((u16) ((*p_enet_addr)[5])) << 8)) |
+                       (u16) (*p_enet_addr)[4]));
+       out_be16(&p_82xx_addr_filt->paddr[paddr_num].m,
+                (u16) (((u16) (((u16) ((*p_enet_addr)[3])) << 8)) |
+                       (u16) (*p_enet_addr)[2]));
+       out_be16(&p_82xx_addr_filt->paddr[paddr_num].l,
+                (u16) (((u16) (((u16) ((*p_enet_addr)[1])) << 8)) |
+                       (u16) (*p_enet_addr)[0]));
+
+       return 0;
+}
+#endif /* CONFIG_UGETH_FILTERING */
+
+static int hw_clear_addr_in_paddr(ucc_geth_private_t *ugeth, u8 paddr_num)
+{
+       ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+
+       if (!(paddr_num < NUM_OF_PADDRS)) {
+               ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       p_82xx_addr_filt =
+           (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+           addressfiltering;
+
+       /* Writing address ff.ff.ff.ff.ff.ff disables address
+       recognition for this register */
+       out_be16(&p_82xx_addr_filt->paddr[paddr_num].h, 0xffff);
+       out_be16(&p_82xx_addr_filt->paddr[paddr_num].m, 0xffff);
+       out_be16(&p_82xx_addr_filt->paddr[paddr_num].l, 0xffff);
+
+       return 0;
+}
+
+static void hw_add_addr_in_hash(ucc_geth_private_t *ugeth,
+                               enet_addr_t *p_enet_addr)
+{
+       ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+       u32 cecr_subblock;
+
+       p_82xx_addr_filt =
+           (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+           addressfiltering;
+
+       cecr_subblock =
+           ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+
+       /* Ethernet frames are defined in Little Endian mode,
+       therefor to insert */
+       /* the address to the hash (Big Endian mode), we reverse the bytes.*/
+       out_be16(&p_82xx_addr_filt->taddr.h,
+                (u16) (((u16) (((u16) ((*p_enet_addr)[5])) << 8)) |
+                       (u16) (*p_enet_addr)[4]));
+       out_be16(&p_82xx_addr_filt->taddr.m,
+                (u16) (((u16) (((u16) ((*p_enet_addr)[3])) << 8)) |
+                       (u16) (*p_enet_addr)[2]));
+       out_be16(&p_82xx_addr_filt->taddr.l,
+                (u16) (((u16) (((u16) ((*p_enet_addr)[1])) << 8)) |
+                       (u16) (*p_enet_addr)[0]));
+
+       qe_issue_cmd(QE_SET_GROUP_ADDRESS, cecr_subblock,
+                    (u8) QE_CR_PROTOCOL_ETHERNET, 0);
+}
+
+#ifdef CONFIG_UGETH_MAGIC_PACKET
+static void magic_packet_detection_enable(ucc_geth_private_t *ugeth)
+{
+       ucc_fast_private_t *uccf;
+       ucc_geth_t *ug_regs;
+       u32 maccfg2, uccm;
+
+       uccf = ugeth->uccf;
+       ug_regs = ugeth->ug_regs;
+
+       /* Enable interrupts for magic packet detection */
+       uccm = in_be32(uccf->p_uccm);
+       uccm |= UCCE_MPD;
+       out_be32(uccf->p_uccm, uccm);
+
+       /* Enable magic packet detection */
+       maccfg2 = in_be32(&ug_regs->maccfg2);
+       maccfg2 |= MACCFG2_MPE;
+       out_be32(&ug_regs->maccfg2, maccfg2);
+}
+
+static void magic_packet_detection_disable(ucc_geth_private_t *ugeth)
+{
+       ucc_fast_private_t *uccf;
+       ucc_geth_t *ug_regs;
+       u32 maccfg2, uccm;
+
+       uccf = ugeth->uccf;
+       ug_regs = ugeth->ug_regs;
+
+       /* Disable interrupts for magic packet detection */
+       uccm = in_be32(uccf->p_uccm);
+       uccm &= ~UCCE_MPD;
+       out_be32(uccf->p_uccm, uccm);
+
+       /* Disable magic packet detection */
+       maccfg2 = in_be32(&ug_regs->maccfg2);
+       maccfg2 &= ~MACCFG2_MPE;
+       out_be32(&ug_regs->maccfg2, maccfg2);
+}
+#endif /* MAGIC_PACKET */
+
+static inline int compare_addr(enet_addr_t *addr1, enet_addr_t *addr2)
+{
+       return memcmp(addr1, addr2, ENET_NUM_OCTETS_PER_ADDRESS);
+}
+
+#ifdef DEBUG
+static void get_statistics(ucc_geth_private_t *ugeth,
+                          ucc_geth_tx_firmware_statistics_t *
+                          tx_firmware_statistics,
+                          ucc_geth_rx_firmware_statistics_t *
+                          rx_firmware_statistics,
+                          ucc_geth_hardware_statistics_t *hardware_statistics)
+{
+       ucc_fast_t *uf_regs;
+       ucc_geth_t *ug_regs;
+       ucc_geth_tx_firmware_statistics_pram_t *p_tx_fw_statistics_pram;
+       ucc_geth_rx_firmware_statistics_pram_t *p_rx_fw_statistics_pram;
+
+       ug_regs = ugeth->ug_regs;
+       uf_regs = (ucc_fast_t *) ug_regs;
+       p_tx_fw_statistics_pram = ugeth->p_tx_fw_statistics_pram;
+       p_rx_fw_statistics_pram = ugeth->p_rx_fw_statistics_pram;
+
+       /* Tx firmware only if user handed pointer and driver actually
+       gathers Tx firmware statistics */
+       if (tx_firmware_statistics && p_tx_fw_statistics_pram) {
+               tx_firmware_statistics->sicoltx =
+                   in_be32(&p_tx_fw_statistics_pram->sicoltx);
+               tx_firmware_statistics->mulcoltx =
+                   in_be32(&p_tx_fw_statistics_pram->mulcoltx);
+               tx_firmware_statistics->latecoltxfr =
+                   in_be32(&p_tx_fw_statistics_pram->latecoltxfr);
+               tx_firmware_statistics->frabortduecol =
+                   in_be32(&p_tx_fw_statistics_pram->frabortduecol);
+               tx_firmware_statistics->frlostinmactxer =
+                   in_be32(&p_tx_fw_statistics_pram->frlostinmactxer);
+               tx_firmware_statistics->carriersenseertx =
+                   in_be32(&p_tx_fw_statistics_pram->carriersenseertx);
+               tx_firmware_statistics->frtxok =
+                   in_be32(&p_tx_fw_statistics_pram->frtxok);
+               tx_firmware_statistics->txfrexcessivedefer =
+                   in_be32(&p_tx_fw_statistics_pram->txfrexcessivedefer);
+               tx_firmware_statistics->txpkts256 =
+                   in_be32(&p_tx_fw_statistics_pram->txpkts256);
+               tx_firmware_statistics->txpkts512 =
+                   in_be32(&p_tx_fw_statistics_pram->txpkts512);
+               tx_firmware_statistics->txpkts1024 =
+                   in_be32(&p_tx_fw_statistics_pram->txpkts1024);
+               tx_firmware_statistics->txpktsjumbo =
+                   in_be32(&p_tx_fw_statistics_pram->txpktsjumbo);
+       }
+
+       /* Rx firmware only if user handed pointer and driver actually
+        * gathers Rx firmware statistics */
+       if (rx_firmware_statistics && p_rx_fw_statistics_pram) {
+               int i;
+               rx_firmware_statistics->frrxfcser =
+                   in_be32(&p_rx_fw_statistics_pram->frrxfcser);
+               rx_firmware_statistics->fraligner =
+                   in_be32(&p_rx_fw_statistics_pram->fraligner);
+               rx_firmware_statistics->inrangelenrxer =
+                   in_be32(&p_rx_fw_statistics_pram->inrangelenrxer);
+               rx_firmware_statistics->outrangelenrxer =
+                   in_be32(&p_rx_fw_statistics_pram->outrangelenrxer);
+               rx_firmware_statistics->frtoolong =
+                   in_be32(&p_rx_fw_statistics_pram->frtoolong);
+               rx_firmware_statistics->runt =
+                   in_be32(&p_rx_fw_statistics_pram->runt);
+               rx_firmware_statistics->verylongevent =
+                   in_be32(&p_rx_fw_statistics_pram->verylongevent);
+               rx_firmware_statistics->symbolerror =
+                   in_be32(&p_rx_fw_statistics_pram->symbolerror);
+               rx_firmware_statistics->dropbsy =
+                   in_be32(&p_rx_fw_statistics_pram->dropbsy);
+               for (i = 0; i < 0x8; i++)
+                       rx_firmware_statistics->res0[i] =
+                           p_rx_fw_statistics_pram->res0[i];
+               rx_firmware_statistics->mismatchdrop =
+                   in_be32(&p_rx_fw_statistics_pram->mismatchdrop);
+               rx_firmware_statistics->underpkts =
+                   in_be32(&p_rx_fw_statistics_pram->underpkts);
+               rx_firmware_statistics->pkts256 =
+                   in_be32(&p_rx_fw_statistics_pram->pkts256);
+               rx_firmware_statistics->pkts512 =
+                   in_be32(&p_rx_fw_statistics_pram->pkts512);
+               rx_firmware_statistics->pkts1024 =
+                   in_be32(&p_rx_fw_statistics_pram->pkts1024);
+               rx_firmware_statistics->pktsjumbo =
+                   in_be32(&p_rx_fw_statistics_pram->pktsjumbo);
+               rx_firmware_statistics->frlossinmacer =
+                   in_be32(&p_rx_fw_statistics_pram->frlossinmacer);
+               rx_firmware_statistics->pausefr =
+                   in_be32(&p_rx_fw_statistics_pram->pausefr);
+               for (i = 0; i < 0x4; i++)
+                       rx_firmware_statistics->res1[i] =
+                           p_rx_fw_statistics_pram->res1[i];
+               rx_firmware_statistics->removevlan =
+                   in_be32(&p_rx_fw_statistics_pram->removevlan);
+               rx_firmware_statistics->replacevlan =
+                   in_be32(&p_rx_fw_statistics_pram->replacevlan);
+               rx_firmware_statistics->insertvlan =
+                   in_be32(&p_rx_fw_statistics_pram->insertvlan);
+       }
+
+       /* Hardware only if user handed pointer and driver actually
+       gathers hardware statistics */
+       if (hardware_statistics && (in_be32(&uf_regs->upsmr) & UPSMR_HSE)) {
+               hardware_statistics->tx64 = in_be32(&ug_regs->tx64);
+               hardware_statistics->tx127 = in_be32(&ug_regs->tx127);
+               hardware_statistics->tx255 = in_be32(&ug_regs->tx255);
+               hardware_statistics->rx64 = in_be32(&ug_regs->rx64);
+               hardware_statistics->rx127 = in_be32(&ug_regs->rx127);
+               hardware_statistics->rx255 = in_be32(&ug_regs->rx255);
+               hardware_statistics->txok = in_be32(&ug_regs->txok);
+               hardware_statistics->txcf = in_be16(&ug_regs->txcf);
+               hardware_statistics->tmca = in_be32(&ug_regs->tmca);
+               hardware_statistics->tbca = in_be32(&ug_regs->tbca);
+               hardware_statistics->rxfok = in_be32(&ug_regs->rxfok);
+               hardware_statistics->rxbok = in_be32(&ug_regs->rxbok);
+               hardware_statistics->rbyt = in_be32(&ug_regs->rbyt);
+               hardware_statistics->rmca = in_be32(&ug_regs->rmca);
+               hardware_statistics->rbca = in_be32(&ug_regs->rbca);
+       }
+}
+
+static void dump_bds(ucc_geth_private_t *ugeth)
+{
+       int i;
+       int length;
+
+       for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) {
+               if (ugeth->p_tx_bd_ring[i]) {
+                       length =
+                           (ugeth->ug_info->bdRingLenTx[i] *
+                            UCC_GETH_SIZE_OF_BD);
+                       ugeth_info("TX BDs[%d]", i);
+                       mem_disp(ugeth->p_tx_bd_ring[i], length);
+               }
+       }
+       for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
+               if (ugeth->p_rx_bd_ring[i]) {
+                       length =
+                           (ugeth->ug_info->bdRingLenRx[i] *
+                            UCC_GETH_SIZE_OF_BD);
+                       ugeth_info("RX BDs[%d]", i);
+                       mem_disp(ugeth->p_rx_bd_ring[i], length);
+               }
+       }
+}
+
+static void dump_regs(ucc_geth_private_t *ugeth)
+{
+       int i;
+
+       ugeth_info("UCC%d Geth registers:", ugeth->ug_info->uf_info.ucc_num);
+       ugeth_info("Base address: 0x%08x", (u32) ugeth->ug_regs);
+
+       ugeth_info("maccfg1    : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->maccfg1,
+                  in_be32(&ugeth->ug_regs->maccfg1));
+       ugeth_info("maccfg2    : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->maccfg2,
+                  in_be32(&ugeth->ug_regs->maccfg2));
+       ugeth_info("ipgifg     : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->ipgifg,
+                  in_be32(&ugeth->ug_regs->ipgifg));
+       ugeth_info("hafdup     : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->hafdup,
+                  in_be32(&ugeth->ug_regs->hafdup));
+       ugeth_info("miimcfg    : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->miimng.miimcfg,
+                  in_be32(&ugeth->ug_regs->miimng.miimcfg));
+       ugeth_info("miimcom    : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->miimng.miimcom,
+                  in_be32(&ugeth->ug_regs->miimng.miimcom));
+       ugeth_info("miimadd    : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->miimng.miimadd,
+                  in_be32(&ugeth->ug_regs->miimng.miimadd));
+       ugeth_info("miimcon    : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->miimng.miimcon,
+                  in_be32(&ugeth->ug_regs->miimng.miimcon));
+       ugeth_info("miimstat   : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->miimng.miimstat,
+                  in_be32(&ugeth->ug_regs->miimng.miimstat));
+       ugeth_info("miimmind   : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->miimng.miimind,
+                  in_be32(&ugeth->ug_regs->miimng.miimind));
+       ugeth_info("ifctl      : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->ifctl,
+                  in_be32(&ugeth->ug_regs->ifctl));
+       ugeth_info("ifstat     : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->ifstat,
+                  in_be32(&ugeth->ug_regs->ifstat));
+       ugeth_info("macstnaddr1: addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->macstnaddr1,
+                  in_be32(&ugeth->ug_regs->macstnaddr1));
+       ugeth_info("macstnaddr2: addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->macstnaddr2,
+                  in_be32(&ugeth->ug_regs->macstnaddr2));
+       ugeth_info("uempr      : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->uempr,
+                  in_be32(&ugeth->ug_regs->uempr));
+       ugeth_info("utbipar    : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->utbipar,
+                  in_be32(&ugeth->ug_regs->utbipar));
+       ugeth_info("uescr      : addr - 0x%08x, val - 0x%04x",
+                  (u32) & ugeth->ug_regs->uescr,
+                  in_be16(&ugeth->ug_regs->uescr));
+       ugeth_info("tx64       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->tx64,
+                  in_be32(&ugeth->ug_regs->tx64));
+       ugeth_info("tx127      : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->tx127,
+                  in_be32(&ugeth->ug_regs->tx127));
+       ugeth_info("tx255      : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->tx255,
+                  in_be32(&ugeth->ug_regs->tx255));
+       ugeth_info("rx64       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->rx64,
+                  in_be32(&ugeth->ug_regs->rx64));
+       ugeth_info("rx127      : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->rx127,
+                  in_be32(&ugeth->ug_regs->rx127));
+       ugeth_info("rx255      : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->rx255,
+                  in_be32(&ugeth->ug_regs->rx255));
+       ugeth_info("txok       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->txok,
+                  in_be32(&ugeth->ug_regs->txok));
+       ugeth_info("txcf       : addr - 0x%08x, val - 0x%04x",
+                  (u32) & ugeth->ug_regs->txcf,
+                  in_be16(&ugeth->ug_regs->txcf));
+       ugeth_info("tmca       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->tmca,
+                  in_be32(&ugeth->ug_regs->tmca));
+       ugeth_info("tbca       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->tbca,
+                  in_be32(&ugeth->ug_regs->tbca));
+       ugeth_info("rxfok      : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->rxfok,
+                  in_be32(&ugeth->ug_regs->rxfok));
+       ugeth_info("rxbok      : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->rxbok,
+                  in_be32(&ugeth->ug_regs->rxbok));
+       ugeth_info("rbyt       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->rbyt,
+                  in_be32(&ugeth->ug_regs->rbyt));
+       ugeth_info("rmca       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->rmca,
+                  in_be32(&ugeth->ug_regs->rmca));
+       ugeth_info("rbca       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->rbca,
+                  in_be32(&ugeth->ug_regs->rbca));
+       ugeth_info("scar       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->scar,
+                  in_be32(&ugeth->ug_regs->scar));
+       ugeth_info("scam       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->scam,
+                  in_be32(&ugeth->ug_regs->scam));
+
+       if (ugeth->p_thread_data_tx) {
+               int numThreadsTxNumerical;
+               switch (ugeth->ug_info->numThreadsTx) {
+               case UCC_GETH_NUM_OF_THREADS_1:
+                       numThreadsTxNumerical = 1;
+                       break;
+               case UCC_GETH_NUM_OF_THREADS_2:
+                       numThreadsTxNumerical = 2;
+                       break;
+               case UCC_GETH_NUM_OF_THREADS_4:
+                       numThreadsTxNumerical = 4;
+                       break;
+               case UCC_GETH_NUM_OF_THREADS_6:
+                       numThreadsTxNumerical = 6;
+                       break;
+               case UCC_GETH_NUM_OF_THREADS_8:
+                       numThreadsTxNumerical = 8;
+                       break;
+               default:
+                       numThreadsTxNumerical = 0;
+                       break;
+               }
+
+               ugeth_info("Thread data TXs:");
+               ugeth_info("Base address: 0x%08x",
+                          (u32) ugeth->p_thread_data_tx);
+               for (i = 0; i < numThreadsTxNumerical; i++) {
+                       ugeth_info("Thread data TX[%d]:", i);
+                       ugeth_info("Base address: 0x%08x",
+                                  (u32) & ugeth->p_thread_data_tx[i]);
+                       mem_disp((u8 *) & ugeth->p_thread_data_tx[i],
+                                sizeof(ucc_geth_thread_data_tx_t));
+               }
+       }
+       if (ugeth->p_thread_data_rx) {
+               int numThreadsRxNumerical;
+               switch (ugeth->ug_info->numThreadsRx) {
+               case UCC_GETH_NUM_OF_THREADS_1:
+                       numThreadsRxNumerical = 1;
+                       break;
+               case UCC_GETH_NUM_OF_THREADS_2:
+                       numThreadsRxNumerical = 2;
+                       break;
+               case UCC_GETH_NUM_OF_THREADS_4:
+                       numThreadsRxNumerical = 4;
+                       break;
+               case UCC_GETH_NUM_OF_THREADS_6:
+                       numThreadsRxNumerical = 6;
+                       break;
+               case UCC_GETH_NUM_OF_THREADS_8:
+                       numThreadsRxNumerical = 8;
+                       break;
+               default:
+                       numThreadsRxNumerical = 0;
+                       break;
+               }
+
+               ugeth_info("Thread data RX:");
+               ugeth_info("Base address: 0x%08x",
+                          (u32) ugeth->p_thread_data_rx);
+               for (i = 0; i < numThreadsRxNumerical; i++) {
+                       ugeth_info("Thread data RX[%d]:", i);
+                       ugeth_info("Base address: 0x%08x",
+                                  (u32) & ugeth->p_thread_data_rx[i]);
+                       mem_disp((u8 *) & ugeth->p_thread_data_rx[i],
+                                sizeof(ucc_geth_thread_data_rx_t));
+               }
+       }
+       if (ugeth->p_exf_glbl_param) {
+               ugeth_info("EXF global param:");
+               ugeth_info("Base address: 0x%08x",
+                          (u32) ugeth->p_exf_glbl_param);
+               mem_disp((u8 *) ugeth->p_exf_glbl_param,
+                        sizeof(*ugeth->p_exf_glbl_param));
+       }
+       if (ugeth->p_tx_glbl_pram) {
+               ugeth_info("TX global param:");
+               ugeth_info("Base address: 0x%08x", (u32) ugeth->p_tx_glbl_pram);
+               ugeth_info("temoder      : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_tx_glbl_pram->temoder,
+                          in_be16(&ugeth->p_tx_glbl_pram->temoder));
+               ugeth_info("sqptr        : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->sqptr,
+                          in_be32(&ugeth->p_tx_glbl_pram->sqptr));
+               ugeth_info("schedulerbasepointer: addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->schedulerbasepointer,
+                          in_be32(&ugeth->p_tx_glbl_pram->
+                                  schedulerbasepointer));
+               ugeth_info("txrmonbaseptr: addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->txrmonbaseptr,
+                          in_be32(&ugeth->p_tx_glbl_pram->txrmonbaseptr));
+               ugeth_info("tstate       : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->tstate,
+                          in_be32(&ugeth->p_tx_glbl_pram->tstate));
+               ugeth_info("iphoffset[0] : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_tx_glbl_pram->iphoffset[0],
+                          ugeth->p_tx_glbl_pram->iphoffset[0]);
+               ugeth_info("iphoffset[1] : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_tx_glbl_pram->iphoffset[1],
+                          ugeth->p_tx_glbl_pram->iphoffset[1]);
+               ugeth_info("iphoffset[2] : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_tx_glbl_pram->iphoffset[2],
+                          ugeth->p_tx_glbl_pram->iphoffset[2]);
+               ugeth_info("iphoffset[3] : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_tx_glbl_pram->iphoffset[3],
+                          ugeth->p_tx_glbl_pram->iphoffset[3]);
+               ugeth_info("iphoffset[4] : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_tx_glbl_pram->iphoffset[4],
+                          ugeth->p_tx_glbl_pram->iphoffset[4]);
+               ugeth_info("iphoffset[5] : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_tx_glbl_pram->iphoffset[5],
+                          ugeth->p_tx_glbl_pram->iphoffset[5]);
+               ugeth_info("iphoffset[6] : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_tx_glbl_pram->iphoffset[6],
+                          ugeth->p_tx_glbl_pram->iphoffset[6]);
+               ugeth_info("iphoffset[7] : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_tx_glbl_pram->iphoffset[7],
+                          ugeth->p_tx_glbl_pram->iphoffset[7]);
+               ugeth_info("vtagtable[0] : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->vtagtable[0],
+                          in_be32(&ugeth->p_tx_glbl_pram->vtagtable[0]));
+               ugeth_info("vtagtable[1] : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->vtagtable[1],
+                          in_be32(&ugeth->p_tx_glbl_pram->vtagtable[1]));
+               ugeth_info("vtagtable[2] : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->vtagtable[2],
+                          in_be32(&ugeth->p_tx_glbl_pram->vtagtable[2]));
+               ugeth_info("vtagtable[3] : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->vtagtable[3],
+                          in_be32(&ugeth->p_tx_glbl_pram->vtagtable[3]));
+               ugeth_info("vtagtable[4] : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->vtagtable[4],
+                          in_be32(&ugeth->p_tx_glbl_pram->vtagtable[4]));
+               ugeth_info("vtagtable[5] : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->vtagtable[5],
+                          in_be32(&ugeth->p_tx_glbl_pram->vtagtable[5]));
+               ugeth_info("vtagtable[6] : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->vtagtable[6],
+                          in_be32(&ugeth->p_tx_glbl_pram->vtagtable[6]));
+               ugeth_info("vtagtable[7] : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->vtagtable[7],
+                          in_be32(&ugeth->p_tx_glbl_pram->vtagtable[7]));
+               ugeth_info("tqptr        : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->tqptr,
+                          in_be32(&ugeth->p_tx_glbl_pram->tqptr));
+       }
+       if (ugeth->p_rx_glbl_pram) {
+               ugeth_info("RX global param:");
+               ugeth_info("Base address: 0x%08x", (u32) ugeth->p_rx_glbl_pram);
+               ugeth_info("remoder         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->remoder,
+                          in_be32(&ugeth->p_rx_glbl_pram->remoder));
+               ugeth_info("rqptr           : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->rqptr,
+                          in_be32(&ugeth->p_rx_glbl_pram->rqptr));
+               ugeth_info("typeorlen       : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_rx_glbl_pram->typeorlen,
+                          in_be16(&ugeth->p_rx_glbl_pram->typeorlen));
+               ugeth_info("rxgstpack       : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_rx_glbl_pram->rxgstpack,
+                          ugeth->p_rx_glbl_pram->rxgstpack);
+               ugeth_info("rxrmonbaseptr   : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->rxrmonbaseptr,
+                          in_be32(&ugeth->p_rx_glbl_pram->rxrmonbaseptr));
+               ugeth_info("intcoalescingptr: addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->intcoalescingptr,
+                          in_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr));
+               ugeth_info("rstate          : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_rx_glbl_pram->rstate,
+                          ugeth->p_rx_glbl_pram->rstate);
+               ugeth_info("mrblr           : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_rx_glbl_pram->mrblr,
+                          in_be16(&ugeth->p_rx_glbl_pram->mrblr));
+               ugeth_info("rbdqptr         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->rbdqptr,
+                          in_be32(&ugeth->p_rx_glbl_pram->rbdqptr));
+               ugeth_info("mflr            : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_rx_glbl_pram->mflr,
+                          in_be16(&ugeth->p_rx_glbl_pram->mflr));
+               ugeth_info("minflr          : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_rx_glbl_pram->minflr,
+                          in_be16(&ugeth->p_rx_glbl_pram->minflr));
+               ugeth_info("maxd1           : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_rx_glbl_pram->maxd1,
+                          in_be16(&ugeth->p_rx_glbl_pram->maxd1));
+               ugeth_info("maxd2           : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_rx_glbl_pram->maxd2,
+                          in_be16(&ugeth->p_rx_glbl_pram->maxd2));
+               ugeth_info("ecamptr         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->ecamptr,
+                          in_be32(&ugeth->p_rx_glbl_pram->ecamptr));
+               ugeth_info("l2qt            : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l2qt,
+                          in_be32(&ugeth->p_rx_glbl_pram->l2qt));
+               ugeth_info("l3qt[0]         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l3qt[0],
+                          in_be32(&ugeth->p_rx_glbl_pram->l3qt[0]));
+               ugeth_info("l3qt[1]         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l3qt[1],
+                          in_be32(&ugeth->p_rx_glbl_pram->l3qt[1]));
+               ugeth_info("l3qt[2]         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l3qt[2],
+                          in_be32(&ugeth->p_rx_glbl_pram->l3qt[2]));
+               ugeth_info("l3qt[3]         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l3qt[3],
+                          in_be32(&ugeth->p_rx_glbl_pram->l3qt[3]));
+               ugeth_info("l3qt[4]         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l3qt[4],
+                          in_be32(&ugeth->p_rx_glbl_pram->l3qt[4]));
+               ugeth_info("l3qt[5]         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l3qt[5],
+                          in_be32(&ugeth->p_rx_glbl_pram->l3qt[5]));
+               ugeth_info("l3qt[6]         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l3qt[6],
+                          in_be32(&ugeth->p_rx_glbl_pram->l3qt[6]));
+               ugeth_info("l3qt[7]         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l3qt[7],
+                          in_be32(&ugeth->p_rx_glbl_pram->l3qt[7]));
+               ugeth_info("vlantype        : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_rx_glbl_pram->vlantype,
+                          in_be16(&ugeth->p_rx_glbl_pram->vlantype));
+               ugeth_info("vlantci         : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_rx_glbl_pram->vlantci,
+                          in_be16(&ugeth->p_rx_glbl_pram->vlantci));
+               for (i = 0; i < 64; i++)
+                       ugeth_info
+                   ("addressfiltering[%d]: addr - 0x%08x, val - 0x%02x",
+                            i,
+                            (u32) & ugeth->p_rx_glbl_pram->addressfiltering[i],
+                            ugeth->p_rx_glbl_pram->addressfiltering[i]);
+               ugeth_info("exfGlobalParam  : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->exfGlobalParam,
+                          in_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam));
+       }
+       if (ugeth->p_send_q_mem_reg) {
+               ugeth_info("Send Q memory registers:");
+               ugeth_info("Base address: 0x%08x",
+                          (u32) ugeth->p_send_q_mem_reg);
+               for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) {
+                       ugeth_info("SQQD[%d]:", i);
+                       ugeth_info("Base address: 0x%08x",
+                                  (u32) & ugeth->p_send_q_mem_reg->sqqd[i]);
+                       mem_disp((u8 *) & ugeth->p_send_q_mem_reg->sqqd[i],
+                                sizeof(ucc_geth_send_queue_qd_t));
+               }
+       }
+       if (ugeth->p_scheduler) {
+               ugeth_info("Scheduler:");
+               ugeth_info("Base address: 0x%08x", (u32) ugeth->p_scheduler);
+               mem_disp((u8 *) ugeth->p_scheduler,
+                        sizeof(*ugeth->p_scheduler));
+       }
+       if (ugeth->p_tx_fw_statistics_pram) {
+               ugeth_info("TX FW statistics pram:");
+               ugeth_info("Base address: 0x%08x",
+                          (u32) ugeth->p_tx_fw_statistics_pram);
+               mem_disp((u8 *) ugeth->p_tx_fw_statistics_pram,
+                        sizeof(*ugeth->p_tx_fw_statistics_pram));
+       }
+       if (ugeth->p_rx_fw_statistics_pram) {
+               ugeth_info("RX FW statistics pram:");
+               ugeth_info("Base address: 0x%08x",
+                          (u32) ugeth->p_rx_fw_statistics_pram);
+               mem_disp((u8 *) ugeth->p_rx_fw_statistics_pram,
+                        sizeof(*ugeth->p_rx_fw_statistics_pram));
+       }
+       if (ugeth->p_rx_irq_coalescing_tbl) {
+               ugeth_info("RX IRQ coalescing tables:");
+               ugeth_info("Base address: 0x%08x",
+                          (u32) ugeth->p_rx_irq_coalescing_tbl);
+               for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
+                       ugeth_info("RX IRQ coalescing table entry[%d]:", i);
+                       ugeth_info("Base address: 0x%08x",
+                                  (u32) & ugeth->p_rx_irq_coalescing_tbl->
+                                  coalescingentry[i]);
+                       ugeth_info
+               ("interruptcoalescingmaxvalue: addr - 0x%08x, val - 0x%08x",
+                            (u32) & ugeth->p_rx_irq_coalescing_tbl->
+                            coalescingentry[i].interruptcoalescingmaxvalue,
+                            in_be32(&ugeth->p_rx_irq_coalescing_tbl->
+                                    coalescingentry[i].
+                                    interruptcoalescingmaxvalue));
+                       ugeth_info
+               ("interruptcoalescingcounter : addr - 0x%08x, val - 0x%08x",
+                            (u32) & ugeth->p_rx_irq_coalescing_tbl->
+                            coalescingentry[i].interruptcoalescingcounter,
+                            in_be32(&ugeth->p_rx_irq_coalescing_tbl->
+                                    coalescingentry[i].
+                                    interruptcoalescingcounter));
+               }
+       }
+       if (ugeth->p_rx_bd_qs_tbl) {
+               ugeth_info("RX BD QS tables:");
+               ugeth_info("Base address: 0x%08x", (u32) ugeth->p_rx_bd_qs_tbl);
+               for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
+                       ugeth_info("RX BD QS table[%d]:", i);
+                       ugeth_info("Base address: 0x%08x",
+                                  (u32) & ugeth->p_rx_bd_qs_tbl[i]);
+                       ugeth_info
+                           ("bdbaseptr        : addr - 0x%08x, val - 0x%08x",
+                            (u32) & ugeth->p_rx_bd_qs_tbl[i].bdbaseptr,
+                            in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdbaseptr));
+                       ugeth_info
+                           ("bdptr            : addr - 0x%08x, val - 0x%08x",
+                            (u32) & ugeth->p_rx_bd_qs_tbl[i].bdptr,
+                            in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdptr));
+                       ugeth_info
+                           ("externalbdbaseptr: addr - 0x%08x, val - 0x%08x",
+                            (u32) & ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr,
+                            in_be32(&ugeth->p_rx_bd_qs_tbl[i].
+                                    externalbdbaseptr));
+                       ugeth_info
+                           ("externalbdptr    : addr - 0x%08x, val - 0x%08x",
+                            (u32) & ugeth->p_rx_bd_qs_tbl[i].externalbdptr,
+                            in_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdptr));
+                       ugeth_info("ucode RX Prefetched BDs:");
+                       ugeth_info("Base address: 0x%08x",
+                                  (u32)
+                                  qe_muram_addr(in_be32
+                                                (&ugeth->p_rx_bd_qs_tbl[i].
+                                                 bdbaseptr)));
+                       mem_disp((u8 *)
+                                qe_muram_addr(in_be32
+                                              (&ugeth->p_rx_bd_qs_tbl[i].
+                                               bdbaseptr)),
+                                sizeof(ucc_geth_rx_prefetched_bds_t));
+               }
+       }
+       if (ugeth->p_init_enet_param_shadow) {
+               int size;
+               ugeth_info("Init enet param shadow:");
+               ugeth_info("Base address: 0x%08x",
+                          (u32) ugeth->p_init_enet_param_shadow);
+               mem_disp((u8 *) ugeth->p_init_enet_param_shadow,
+                        sizeof(*ugeth->p_init_enet_param_shadow));
+
+               size = sizeof(ucc_geth_thread_rx_pram_t);
+               if (ugeth->ug_info->rxExtendedFiltering) {
+                       size +=
+                           THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING;
+                       if (ugeth->ug_info->largestexternallookupkeysize ==
+                           QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES)
+                               size +=
+                       THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8;
+                       if (ugeth->ug_info->largestexternallookupkeysize ==
+                           QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES)
+                               size +=
+                       THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16;
+               }
+
+               dump_init_enet_entries(ugeth,
+                                      &(ugeth->p_init_enet_param_shadow->
+                                        txthread[0]),
+                                      ENET_INIT_PARAM_MAX_ENTRIES_TX,
+                                      sizeof(ucc_geth_thread_tx_pram_t),
+                                      ugeth->ug_info->riscTx, 0);
+               dump_init_enet_entries(ugeth,
+                                      &(ugeth->p_init_enet_param_shadow->
+                                        rxthread[0]),
+                                      ENET_INIT_PARAM_MAX_ENTRIES_RX, size,
+                                      ugeth->ug_info->riscRx, 1);
+       }
+}
+#endif /* DEBUG */
+
+static void init_default_reg_vals(volatile u32 *upsmr_register,
+                                 volatile u32 *maccfg1_register,
+                                 volatile u32 *maccfg2_register)
+{
+       out_be32(upsmr_register, UCC_GETH_UPSMR_INIT);
+       out_be32(maccfg1_register, UCC_GETH_MACCFG1_INIT);
+       out_be32(maccfg2_register, UCC_GETH_MACCFG2_INIT);
+}
+
+static int init_half_duplex_params(int alt_beb,
+                                  int back_pressure_no_backoff,
+                                  int no_backoff,
+                                  int excess_defer,
+                                  u8 alt_beb_truncation,
+                                  u8 max_retransmissions,
+                                  u8 collision_window,
+                                  volatile u32 *hafdup_register)
+{
+       u32 value = 0;
+
+       if ((alt_beb_truncation > HALFDUP_ALT_BEB_TRUNCATION_MAX) ||
+           (max_retransmissions > HALFDUP_MAX_RETRANSMISSION_MAX) ||
+           (collision_window > HALFDUP_COLLISION_WINDOW_MAX))
+               return -EINVAL;
+
+       value = (u32) (alt_beb_truncation << HALFDUP_ALT_BEB_TRUNCATION_SHIFT);
+
+       if (alt_beb)
+               value |= HALFDUP_ALT_BEB;
+       if (back_pressure_no_backoff)
+               value |= HALFDUP_BACK_PRESSURE_NO_BACKOFF;
+       if (no_backoff)
+               value |= HALFDUP_NO_BACKOFF;
+       if (excess_defer)
+               value |= HALFDUP_EXCESSIVE_DEFER;
+
+       value |= (max_retransmissions << HALFDUP_MAX_RETRANSMISSION_SHIFT);
+
+       value |= collision_window;
+
+       out_be32(hafdup_register, value);
+       return 0;
+}
+
+static int init_inter_frame_gap_params(u8 non_btb_cs_ipg,
+                                      u8 non_btb_ipg,
+                                      u8 min_ifg,
+                                      u8 btb_ipg,
+                                      volatile u32 *ipgifg_register)
+{
+       u32 value = 0;
+
+       /* Non-Back-to-back IPG part 1 should be <= Non-Back-to-back
+       IPG part 2 */
+       if (non_btb_cs_ipg > non_btb_ipg)
+               return -EINVAL;
+
+       if ((non_btb_cs_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART1_MAX) ||
+           (non_btb_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART2_MAX) ||
+           /*(min_ifg        > IPGIFG_MINIMUM_IFG_ENFORCEMENT_MAX) || */
+           (btb_ipg > IPGIFG_BACK_TO_BACK_IFG_MAX))
+               return -EINVAL;
+
+       value |=
+           ((non_btb_cs_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART1_SHIFT) &
+            IPGIFG_NBTB_CS_IPG_MASK);
+       value |=
+           ((non_btb_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART2_SHIFT) &
+            IPGIFG_NBTB_IPG_MASK);
+       value |=
+           ((min_ifg << IPGIFG_MINIMUM_IFG_ENFORCEMENT_SHIFT) &
+            IPGIFG_MIN_IFG_MASK);
+       value |= (btb_ipg & IPGIFG_BTB_IPG_MASK);
+
+       out_be32(ipgifg_register, value);
+       return 0;
+}
+
+static int init_flow_control_params(u32 automatic_flow_control_mode,
+                                   int rx_flow_control_enable,
+                                   int tx_flow_control_enable,
+                                   u16 pause_period,
+                                   u16 extension_field,
+                                   volatile u32 *upsmr_register,
+                                   volatile u32 *uempr_register,
+                                   volatile u32 *maccfg1_register)
+{
+       u32 value = 0;
+
+       /* Set UEMPR register */
+       value = (u32) pause_period << UEMPR_PAUSE_TIME_VALUE_SHIFT;
+       value |= (u32) extension_field << UEMPR_EXTENDED_PAUSE_TIME_VALUE_SHIFT;
+       out_be32(uempr_register, value);
+
+       /* Set UPSMR register */
+       value = in_be32(upsmr_register);
+       value |= automatic_flow_control_mode;
+       out_be32(upsmr_register, value);
+
+       value = in_be32(maccfg1_register);
+       if (rx_flow_control_enable)
+               value |= MACCFG1_FLOW_RX;
+       if (tx_flow_control_enable)
+               value |= MACCFG1_FLOW_TX;
+       out_be32(maccfg1_register, value);
+
+       return 0;
+}
+
+static int init_hw_statistics_gathering_mode(int enable_hardware_statistics,
+                                            int auto_zero_hardware_statistics,
+                                            volatile u32 *upsmr_register,
+                                            volatile u16 *uescr_register)
+{
+       u32 upsmr_value = 0;
+       u16 uescr_value = 0;
+       /* Enable hardware statistics gathering if requested */
+       if (enable_hardware_statistics) {
+               upsmr_value = in_be32(upsmr_register);
+               upsmr_value |= UPSMR_HSE;
+               out_be32(upsmr_register, upsmr_value);
+       }
+
+       /* Clear hardware statistics counters */
+       uescr_value = in_be16(uescr_register);
+       uescr_value |= UESCR_CLRCNT;
+       /* Automatically zero hardware statistics counters on read,
+       if requested */
+       if (auto_zero_hardware_statistics)
+               uescr_value |= UESCR_AUTOZ;
+       out_be16(uescr_register, uescr_value);
+
+       return 0;
+}
+
+static int init_firmware_statistics_gathering_mode(int
+               enable_tx_firmware_statistics,
+               int enable_rx_firmware_statistics,
+               volatile u32 *tx_rmon_base_ptr,
+               u32 tx_firmware_statistics_structure_address,
+               volatile u32 *rx_rmon_base_ptr,
+               u32 rx_firmware_statistics_structure_address,
+               volatile u16 *temoder_register,
+               volatile u32 *remoder_register)
+{
+       /* Note: this function does not check if */
+       /* the parameters it receives are NULL   */
+       u16 temoder_value;
+       u32 remoder_value;
+
+       if (enable_tx_firmware_statistics) {
+               out_be32(tx_rmon_base_ptr,
+                        tx_firmware_statistics_structure_address);
+               temoder_value = in_be16(temoder_register);
+               temoder_value |= TEMODER_TX_RMON_STATISTICS_ENABLE;
+               out_be16(temoder_register, temoder_value);
+       }
+
+       if (enable_rx_firmware_statistics) {
+               out_be32(rx_rmon_base_ptr,
+                        rx_firmware_statistics_structure_address);
+               remoder_value = in_be32(remoder_register);
+               remoder_value |= REMODER_RX_RMON_STATISTICS_ENABLE;
+               out_be32(remoder_register, remoder_value);
+       }
+
+       return 0;
+}
+
+static int init_mac_station_addr_regs(u8 address_byte_0,
+                                     u8 address_byte_1,
+                                     u8 address_byte_2,
+                                     u8 address_byte_3,
+                                     u8 address_byte_4,
+                                     u8 address_byte_5,
+                                     volatile u32 *macstnaddr1_register,
+                                     volatile u32 *macstnaddr2_register)
+{
+       u32 value = 0;
+
+       /* Example: for a station address of 0x12345678ABCD, */
+       /* 0x12 is byte 0, 0x34 is byte 1 and so on and 0xCD is byte 5 */
+
+       /* MACSTNADDR1 Register: */
+
+       /* 0                      7   8                      15  */
+       /* station address byte 5     station address byte 4     */
+       /* 16                     23  24                     31  */
+       /* station address byte 3     station address byte 2     */
+       value |= (u32) ((address_byte_2 << 0) & 0x000000FF);
+       value |= (u32) ((address_byte_3 << 8) & 0x0000FF00);
+       value |= (u32) ((address_byte_4 << 16) & 0x00FF0000);
+       value |= (u32) ((address_byte_5 << 24) & 0xFF000000);
+
+       out_be32(macstnaddr1_register, value);
+
+       /* MACSTNADDR2 Register: */
+
+       /* 0                      7   8                      15  */
+       /* station address byte 1     station address byte 0     */
+       /* 16                     23  24                     31  */
+       /*         reserved                   reserved           */
+       value = 0;
+       value |= (u32) ((address_byte_0 << 16) & 0x00FF0000);
+       value |= (u32) ((address_byte_1 << 24) & 0xFF000000);
+
+       out_be32(macstnaddr2_register, value);
+
+       return 0;
+}
+
+static int init_mac_duplex_mode(int full_duplex,
+                               int limited_to_full_duplex,
+                               volatile u32 *maccfg2_register)
+{
+       u32 value = 0;
+
+       /* some interfaces must work in full duplex mode */
+       if ((full_duplex == 0) && (limited_to_full_duplex == 1))
+               return -EINVAL;
+
+       value = in_be32(maccfg2_register);
+
+       if (full_duplex)
+               value |= MACCFG2_FDX;
+       else
+               value &= ~MACCFG2_FDX;
+
+       out_be32(maccfg2_register, value);
+       return 0;
+}
+
+static int init_check_frame_length_mode(int length_check,
+                                       volatile u32 *maccfg2_register)
+{
+       u32 value = 0;
+
+       value = in_be32(maccfg2_register);
+
+       if (length_check)
+               value |= MACCFG2_LC;
+       else
+               value &= ~MACCFG2_LC;
+
+       out_be32(maccfg2_register, value);
+       return 0;
+}
+
+static int init_preamble_length(u8 preamble_length,
+                               volatile u32 *maccfg2_register)
+{
+       u32 value = 0;
+
+       if ((preamble_length < 3) || (preamble_length > 7))
+               return -EINVAL;
+
+       value = in_be32(maccfg2_register);
+       value &= ~MACCFG2_PREL_MASK;
+       value |= (preamble_length << MACCFG2_PREL_SHIFT);
+       out_be32(maccfg2_register, value);
+       return 0;
+}
+
+static int init_mii_management_configuration(int reset_mgmt,
+                                            int preamble_supress,
+                                            volatile u32 *miimcfg_register,
+                                            volatile u32 *miimind_register)
+{
+       unsigned int timeout = PHY_INIT_TIMEOUT;
+       u32 value = 0;
+
+       value = in_be32(miimcfg_register);
+       if (reset_mgmt) {
+               value |= MIIMCFG_RESET_MANAGEMENT;
+               out_be32(miimcfg_register, value);
+       }
+
+       value = 0;
+
+       if (preamble_supress)
+               value |= MIIMCFG_NO_PREAMBLE;
+
+       value |= UCC_GETH_MIIMCFG_MNGMNT_CLC_DIV_INIT;
+       out_be32(miimcfg_register, value);
+
+       /* Wait until the bus is free */
+       while ((in_be32(miimind_register) & MIIMIND_BUSY) && timeout--)
+               cpu_relax();
+
+       if (timeout <= 0) {
+               ugeth_err("%s: The MII Bus is stuck!", __FUNCTION__);
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int init_rx_parameters(int reject_broadcast,
+                             int receive_short_frames,
+                             int promiscuous, volatile u32 *upsmr_register)
+{
+       u32 value = 0;
+
+       value = in_be32(upsmr_register);
+
+       if (reject_broadcast)
+               value |= UPSMR_BRO;
+       else
+               value &= ~UPSMR_BRO;
+
+       if (receive_short_frames)
+               value |= UPSMR_RSH;
+       else
+               value &= ~UPSMR_RSH;
+
+       if (promiscuous)
+               value |= UPSMR_PRO;
+       else
+               value &= ~UPSMR_PRO;
+
+       out_be32(upsmr_register, value);
+
+       return 0;
+}
+
+static int init_max_rx_buff_len(u16 max_rx_buf_len,
+                               volatile u16 *mrblr_register)
+{
+       /* max_rx_buf_len value must be a multiple of 128 */
+       if ((max_rx_buf_len == 0)
+           || (max_rx_buf_len % UCC_GETH_MRBLR_ALIGNMENT))
+               return -EINVAL;
+
+       out_be16(mrblr_register, max_rx_buf_len);
+       return 0;
+}
+
+static int init_min_frame_len(u16 min_frame_length,
+                             volatile u16 *minflr_register,
+                             volatile u16 *mrblr_register)
+{
+       u16 mrblr_value = 0;
+
+       mrblr_value = in_be16(mrblr_register);
+       if (min_frame_length >= (mrblr_value - 4))
+               return -EINVAL;
+
+       out_be16(minflr_register, min_frame_length);
+       return 0;
+}
+
+static int adjust_enet_interface(ucc_geth_private_t *ugeth)
+{
+       ucc_geth_info_t *ug_info;
+       ucc_geth_t *ug_regs;
+       ucc_fast_t *uf_regs;
+       enet_speed_e speed;
+       int ret_val, rpm = 0, tbi = 0, r10m = 0, rmm =
+           0, limited_to_full_duplex = 0;
+       u32 upsmr, maccfg2, utbipar, tbiBaseAddress;
+       u16 value;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       ug_info = ugeth->ug_info;
+       ug_regs = ugeth->ug_regs;
+       uf_regs = ugeth->uccf->uf_regs;
+
+       /* Analyze enet_interface according to Interface Mode Configuration
+       table */
+       ret_val =
+           get_interface_details(ug_info->enet_interface, &speed, &r10m, &rmm,
+                                 &rpm, &tbi, &limited_to_full_duplex);
+       if (ret_val != 0) {
+               ugeth_err
+                 ("%s: half duplex not supported in requested configuration.",
+                    __FUNCTION__);
+               return ret_val;
+       }
+
+       /*                    Set MACCFG2                    */
+       maccfg2 = in_be32(&ug_regs->maccfg2);
+       maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK;
+       if ((speed == ENET_SPEED_10BT) || (speed == ENET_SPEED_100BT))
+               maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
+       else if (speed == ENET_SPEED_1000BT)
+               maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE;
+       maccfg2 |= ug_info->padAndCrc;
+       out_be32(&ug_regs->maccfg2, maccfg2);
+
+       /*                    Set UPSMR                      */
+       upsmr = in_be32(&uf_regs->upsmr);
+       upsmr &= ~(UPSMR_RPM | UPSMR_R10M | UPSMR_TBIM | UPSMR_RMM);
+       if (rpm)
+               upsmr |= UPSMR_RPM;
+       if (r10m)
+               upsmr |= UPSMR_R10M;
+       if (tbi)
+               upsmr |= UPSMR_TBIM;
+       if (rmm)
+               upsmr |= UPSMR_RMM;
+       out_be32(&uf_regs->upsmr, upsmr);
+
+       /*                    Set UTBIPAR                    */
+       utbipar = in_be32(&ug_regs->utbipar);
+       utbipar &= ~UTBIPAR_PHY_ADDRESS_MASK;
+       if (tbi)
+               utbipar |=
+                   (ug_info->phy_address +
+                    ugeth->ug_info->uf_info.
+                    ucc_num) << UTBIPAR_PHY_ADDRESS_SHIFT;
+       else
+               utbipar |=
+                   (0x10 +
+                    ugeth->ug_info->uf_info.
+                    ucc_num) << UTBIPAR_PHY_ADDRESS_SHIFT;
+       out_be32(&ug_regs->utbipar, utbipar);
+
+       /* Disable autonegotiation in tbi mode, because by default it
+       comes up in autonegotiation mode. */
+       /* Note that this depends on proper setting in utbipar register. */
+       if (tbi) {
+               tbiBaseAddress = in_be32(&ug_regs->utbipar);
+               tbiBaseAddress &= UTBIPAR_PHY_ADDRESS_MASK;
+               tbiBaseAddress >>= UTBIPAR_PHY_ADDRESS_SHIFT;
+               value =
+                   ugeth->mii_info->mdio_read(ugeth->dev, (u8) tbiBaseAddress,
+                                              ENET_TBI_MII_CR);
+               value &= ~0x1000;       /* Turn off autonegotiation */
+               ugeth->mii_info->mdio_write(ugeth->dev, (u8) tbiBaseAddress,
+                                           ENET_TBI_MII_CR, value);
+       }
+
+       ret_val = init_mac_duplex_mode(1,
+                                      limited_to_full_duplex,
+                                      &ug_regs->maccfg2);
+       if (ret_val != 0) {
+               ugeth_err
+               ("%s: half duplex not supported in requested configuration.",
+                    __FUNCTION__);
+               return ret_val;
+       }
+
+       init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2);
+
+       ret_val = init_preamble_length(ug_info->prel, &ug_regs->maccfg2);
+       if (ret_val != 0) {
+               ugeth_err
+                   ("%s: Preamble length must be between 3 and 7 inclusive.",
+                    __FUNCTION__);
+               return ret_val;
+       }
+
+       return 0;
+}
+
+/* Called every time the controller might need to be made
+ * aware of new link state.  The PHY code conveys this
+ * information through variables in the ugeth structure, and this
+ * function converts those variables into the appropriate
+ * register values, and can bring down the device if needed.
+ */
+static void adjust_link(struct net_device *dev)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       ucc_geth_t *ug_regs;
+       u32 tempval;
+       struct ugeth_mii_info *mii_info = ugeth->mii_info;
+
+       ug_regs = ugeth->ug_regs;
+
+       if (mii_info->link) {
+               /* Now we make sure that we can be in full duplex mode.
+                * If not, we operate in half-duplex mode. */
+               if (mii_info->duplex != ugeth->oldduplex) {
+                       if (!(mii_info->duplex)) {
+                               tempval = in_be32(&ug_regs->maccfg2);
+                               tempval &= ~(MACCFG2_FDX);
+                               out_be32(&ug_regs->maccfg2, tempval);
+
+                               ugeth_info("%s: Half Duplex", dev->name);
+                       } else {
+                               tempval = in_be32(&ug_regs->maccfg2);
+                               tempval |= MACCFG2_FDX;
+                               out_be32(&ug_regs->maccfg2, tempval);
+
+                               ugeth_info("%s: Full Duplex", dev->name);
+                       }
+
+                       ugeth->oldduplex = mii_info->duplex;
+               }
+
+               if (mii_info->speed != ugeth->oldspeed) {
+                       switch (mii_info->speed) {
+                       case 1000:
+#ifdef CONFIG_MPC836x
+/* FIXME: This code is for 100Mbs BUG fixing,
+remove this when it is fixed!!! */
+                               if (ugeth->ug_info->enet_interface ==
+                                   ENET_1000_GMII)
+                               /* Run the commands which initialize the PHY */
+                               {
+                                       tempval =
+                                           (u32) mii_info->mdio_read(ugeth->
+                                               dev, mii_info->mii_id, 0x1b);
+                                       tempval |= 0x000f;
+                                       mii_info->mdio_write(ugeth->dev,
+                                               mii_info->mii_id, 0x1b,
+                                               (u16) tempval);
+                                       tempval =
+                                           (u32) mii_info->mdio_read(ugeth->
+                                               dev, mii_info->mii_id,
+                                               MII_BMCR);
+                                       mii_info->mdio_write(ugeth->dev,
+                                               mii_info->mii_id, MII_BMCR,
+                                               (u16) (tempval | BMCR_RESET));
+                               } else if (ugeth->ug_info->enet_interface ==
+                                          ENET_1000_RGMII)
+                               /* Run the commands which initialize the PHY */
+                               {
+                                       tempval =
+                                           (u32) mii_info->mdio_read(ugeth->
+                                               dev, mii_info->mii_id, 0x1b);
+                                       tempval = (tempval & ~0x000f) | 0x000b;
+                                       mii_info->mdio_write(ugeth->dev,
+                                               mii_info->mii_id, 0x1b,
+                                               (u16) tempval);
+                                       tempval =
+                                           (u32) mii_info->mdio_read(ugeth->
+                                               dev, mii_info->mii_id,
+                                               MII_BMCR);
+                                       mii_info->mdio_write(ugeth->dev,
+                                               mii_info->mii_id, MII_BMCR,
+                                               (u16) (tempval | BMCR_RESET));
+                               }
+                               msleep(4000);
+#endif                         /* CONFIG_MPC8360 */
+                               adjust_enet_interface(ugeth);
+                               break;
+                       case 100:
+                       case 10:
+#ifdef CONFIG_MPC836x
+/* FIXME: This code is for 100Mbs BUG fixing,
+remove this lines when it will be fixed!!! */
+                               ugeth->ug_info->enet_interface = ENET_100_RGMII;
+                               tempval =
+                                   (u32) mii_info->mdio_read(ugeth->dev,
+                                                             mii_info->mii_id,
+                                                             0x1b);
+                               tempval = (tempval & ~0x000f) | 0x000b;
+                               mii_info->mdio_write(ugeth->dev,
+                                                    mii_info->mii_id, 0x1b,
+                                                    (u16) tempval);
+                               tempval =
+                                   (u32) mii_info->mdio_read(ugeth->dev,
+                                                             mii_info->mii_id,
+                                                             MII_BMCR);
+                               mii_info->mdio_write(ugeth->dev,
+                                                    mii_info->mii_id, MII_BMCR,
+                                                    (u16) (tempval |
+                                                           BMCR_RESET));
+                               msleep(4000);
+#endif                         /* CONFIG_MPC8360 */
+                               adjust_enet_interface(ugeth);
+                               break;
+                       default:
+                               ugeth_warn
+                                   ("%s: Ack!  Speed (%d) is not 10/100/1000!",
+                                    dev->name, mii_info->speed);
+                               break;
+                       }
+
+                       ugeth_info("%s: Speed %dBT", dev->name,
+                                  mii_info->speed);
+
+                       ugeth->oldspeed = mii_info->speed;
+               }
+
+               if (!ugeth->oldlink) {
+                       ugeth_info("%s: Link is up", dev->name);
+                       ugeth->oldlink = 1;
+                       netif_carrier_on(dev);
+                       netif_schedule(dev);
+               }
+       } else {
+               if (ugeth->oldlink) {
+                       ugeth_info("%s: Link is down", dev->name);
+                       ugeth->oldlink = 0;
+                       ugeth->oldspeed = 0;
+                       ugeth->oldduplex = -1;
+                       netif_carrier_off(dev);
+               }
+       }
+}
+
+/* Configure the PHY for dev.
+ * returns 0 if success.  -1 if failure
+ */
+static int init_phy(struct net_device *dev)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       struct phy_info *curphy;
+       ucc_mii_mng_t *mii_regs;
+       struct ugeth_mii_info *mii_info;
+       int err;
+
+       mii_regs = &ugeth->ug_regs->miimng;
+
+       ugeth->oldlink = 0;
+       ugeth->oldspeed = 0;
+       ugeth->oldduplex = -1;
+
+       mii_info = kmalloc(sizeof(struct ugeth_mii_info), GFP_KERNEL);
+
+       if (NULL == mii_info) {
+               ugeth_err("%s: Could not allocate mii_info", dev->name);
+               return -ENOMEM;
+       }
+
+       mii_info->mii_regs = mii_regs;
+       mii_info->speed = SPEED_1000;
+       mii_info->duplex = DUPLEX_FULL;
+       mii_info->pause = 0;
+       mii_info->link = 0;
+
+       mii_info->advertising = (ADVERTISED_10baseT_Half |
+                                ADVERTISED_10baseT_Full |
+                                ADVERTISED_100baseT_Half |
+                                ADVERTISED_100baseT_Full |
+                                ADVERTISED_1000baseT_Full);
+       mii_info->autoneg = 1;
+
+       mii_info->mii_id = ugeth->ug_info->phy_address;
+
+       mii_info->dev = dev;
+
+       mii_info->mdio_read = &read_phy_reg;
+       mii_info->mdio_write = &write_phy_reg;
+
+       ugeth->mii_info = mii_info;
+
+       spin_lock_irq(&ugeth->lock);
+
+       /* Set this UCC to be the master of the MII managment */
+       ucc_set_qe_mux_mii_mng(ugeth->ug_info->uf_info.ucc_num);
+
+       if (init_mii_management_configuration(1,
+                                             ugeth->ug_info->
+                                             miiPreambleSupress,
+                                             &mii_regs->miimcfg,
+                                             &mii_regs->miimind)) {
+               ugeth_err("%s: The MII Bus is stuck!", dev->name);
+               err = -1;
+               goto bus_fail;
+       }
+
+       spin_unlock_irq(&ugeth->lock);
+
+       /* get info for this PHY */
+       curphy = get_phy_info(ugeth->mii_info);
+
+       if (curphy == NULL) {
+               ugeth_err("%s: No PHY found", dev->name);
+               err = -1;
+               goto no_phy;
+       }
+
+       mii_info->phyinfo = curphy;
+
+       /* Run the commands which initialize the PHY */
+       if (curphy->init) {
+               err = curphy->init(ugeth->mii_info);
+               if (err)
+                       goto phy_init_fail;
+       }
+
+       return 0;
+
+      phy_init_fail:
+      no_phy:
+      bus_fail:
+       kfree(mii_info);
+
+       return err;
+}
+
+#ifdef CONFIG_UGETH_TX_ON_DEMOND
+static int ugeth_transmit_on_demand(ucc_geth_private_t *ugeth)
+{
+       ucc_fast_transmit_on_demand(ugeth->uccf);
+
+       return 0;
+}
+#endif
+
+static int ugeth_graceful_stop_tx(ucc_geth_private_t *ugeth)
+{
+       ucc_fast_private_t *uccf;
+       u32 cecr_subblock;
+       u32 temp;
+
+       uccf = ugeth->uccf;
+
+       /* Mask GRACEFUL STOP TX interrupt bit and clear it */
+       temp = in_be32(uccf->p_uccm);
+       temp &= ~UCCE_GRA;
+       out_be32(uccf->p_uccm, temp);
+       out_be32(uccf->p_ucce, UCCE_GRA);       /* clear by writing 1 */
+
+       /* Issue host command */
+       cecr_subblock =
+           ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+       qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock,
+                    (u8) QE_CR_PROTOCOL_ETHERNET, 0);
+
+       /* Wait for command to complete */
+       do {
+               temp = in_be32(uccf->p_ucce);
+       } while (!(temp & UCCE_GRA));
+
+       uccf->stopped_tx = 1;
+
+       return 0;
+}
+
+static int ugeth_graceful_stop_rx(ucc_geth_private_t * ugeth)
+{
+       ucc_fast_private_t *uccf;
+       u32 cecr_subblock;
+       u8 temp;
+
+       uccf = ugeth->uccf;
+
+       /* Clear acknowledge bit */
+       temp = ugeth->p_rx_glbl_pram->rxgstpack;
+       temp &= ~GRACEFUL_STOP_ACKNOWLEDGE_RX;
+       ugeth->p_rx_glbl_pram->rxgstpack = temp;
+
+       /* Keep issuing command and checking acknowledge bit until
+       it is asserted, according to spec */
+       do {
+               /* Issue host command */
+               cecr_subblock =
+                   ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.
+                                               ucc_num);
+               qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock,
+                            (u8) QE_CR_PROTOCOL_ETHERNET, 0);
+
+               temp = ugeth->p_rx_glbl_pram->rxgstpack;
+       } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX));
+
+       uccf->stopped_rx = 1;
+
+       return 0;
+}
+
+static int ugeth_restart_tx(ucc_geth_private_t *ugeth)
+{
+       ucc_fast_private_t *uccf;
+       u32 cecr_subblock;
+
+       uccf = ugeth->uccf;
+
+       cecr_subblock =
+           ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+       qe_issue_cmd(QE_RESTART_TX, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET,
+                    0);
+       uccf->stopped_tx = 0;
+
+       return 0;
+}
+
+static int ugeth_restart_rx(ucc_geth_private_t *ugeth)
+{
+       ucc_fast_private_t *uccf;
+       u32 cecr_subblock;
+
+       uccf = ugeth->uccf;
+
+       cecr_subblock =
+           ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+       qe_issue_cmd(QE_RESTART_RX, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET,
+                    0);
+       uccf->stopped_rx = 0;
+
+       return 0;
+}
+
+static int ugeth_enable(ucc_geth_private_t *ugeth, comm_dir_e mode)
+{
+       ucc_fast_private_t *uccf;
+       int enabled_tx, enabled_rx;
+
+       uccf = ugeth->uccf;
+
+       /* check if the UCC number is in range. */
+       if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
+               ugeth_err("%s: ucc_num out of range.", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       enabled_tx = uccf->enabled_tx;
+       enabled_rx = uccf->enabled_rx;
+
+       /* Get Tx and Rx going again, in case this channel was actively
+       disabled. */
+       if ((mode & COMM_DIR_TX) && (!enabled_tx) && uccf->stopped_tx)
+               ugeth_restart_tx(ugeth);
+       if ((mode & COMM_DIR_RX) && (!enabled_rx) && uccf->stopped_rx)
+               ugeth_restart_rx(ugeth);
+
+       ucc_fast_enable(uccf, mode);    /* OK to do even if not disabled */
+
+       return 0;
+
+}
+
+static int ugeth_disable(ucc_geth_private_t * ugeth, comm_dir_e mode)
+{
+       ucc_fast_private_t *uccf;
+
+       uccf = ugeth->uccf;
+
+       /* check if the UCC number is in range. */
+       if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
+               ugeth_err("%s: ucc_num out of range.", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* Stop any transmissions */
+       if ((mode & COMM_DIR_TX) && uccf->enabled_tx && !uccf->stopped_tx)
+               ugeth_graceful_stop_tx(ugeth);
+
+       /* Stop any receptions */
+       if ((mode & COMM_DIR_RX) && uccf->enabled_rx && !uccf->stopped_rx)
+               ugeth_graceful_stop_rx(ugeth);
+
+       ucc_fast_disable(ugeth->uccf, mode); /* OK to do even if not enabled */
+
+       return 0;
+}
+
+static void ugeth_dump_regs(ucc_geth_private_t *ugeth)
+{
+#ifdef DEBUG
+       ucc_fast_dump_regs(ugeth->uccf);
+       dump_regs(ugeth);
+       dump_bds(ugeth);
+#endif
+}
+
+#ifdef CONFIG_UGETH_FILTERING
+static int ugeth_ext_filtering_serialize_tad(ucc_geth_tad_params_t *
+                                            p_UccGethTadParams,
+                                            qe_fltr_tad_t *qe_fltr_tad)
+{
+       u16 temp;
+
+       /* Zero serialized TAD */
+       memset(qe_fltr_tad, 0, QE_FLTR_TAD_SIZE);
+
+       qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_V;   /* Must have this */
+       if (p_UccGethTadParams->rx_non_dynamic_extended_features_mode ||
+           (p_UccGethTadParams->vtag_op != UCC_GETH_VLAN_OPERATION_TAGGED_NOP)
+           || (p_UccGethTadParams->vnontag_op !=
+               UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP)
+           )
+               qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_EF;
+       if (p_UccGethTadParams->reject_frame)
+               qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_REJ;
+       temp =
+           (u16) (((u16) p_UccGethTadParams->
+                   vtag_op) << UCC_GETH_TAD_VTAG_OP_SHIFT);
+       qe_fltr_tad->serialized[0] |= (u8) (temp >> 8); /* upper bits */
+
+       qe_fltr_tad->serialized[1] |= (u8) (temp & 0x00ff);     /* lower bits */
+       if (p_UccGethTadParams->vnontag_op ==
+           UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT)
+               qe_fltr_tad->serialized[1] |= UCC_GETH_TAD_V_NON_VTAG_OP;
+       qe_fltr_tad->serialized[1] |=
+           p_UccGethTadParams->rqos << UCC_GETH_TAD_RQOS_SHIFT;
+
+       qe_fltr_tad->serialized[2] |=
+           p_UccGethTadParams->vpri << UCC_GETH_TAD_V_PRIORITY_SHIFT;
+       /* upper bits */
+       qe_fltr_tad->serialized[2] |= (u8) (p_UccGethTadParams->vid >> 8);
+       /* lower bits */
+       qe_fltr_tad->serialized[3] |= (u8) (p_UccGethTadParams->vid & 0x00ff);
+
+       return 0;
+}
+
+static enet_addr_container_t
+    *ugeth_82xx_filtering_get_match_addr_in_hash(ucc_geth_private_t *ugeth,
+                                                enet_addr_t *p_enet_addr)
+{
+       enet_addr_container_t *enet_addr_cont;
+       struct list_head *p_lh;
+       u16 i, num;
+       int32_t j;
+       u8 *p_counter;
+
+       if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
+               p_lh = &ugeth->group_hash_q;
+               p_counter = &(ugeth->numGroupAddrInHash);
+       } else {
+               p_lh = &ugeth->ind_hash_q;
+               p_counter = &(ugeth->numIndAddrInHash);
+       }
+
+       if (!p_lh)
+               return NULL;
+
+       num = *p_counter;
+
+       for (i = 0; i < num; i++) {
+               enet_addr_cont =
+                   (enet_addr_container_t *)
+                   ENET_ADDR_CONT_ENTRY(dequeue(p_lh));
+               for (j = ENET_NUM_OCTETS_PER_ADDRESS - 1; j >= 0; j--) {
+                       if ((*p_enet_addr)[j] != (enet_addr_cont->address)[j])
+                               break;
+                       if (j == 0)
+                               return enet_addr_cont;  /* Found */
+               }
+               enqueue(p_lh, &enet_addr_cont->node);   /* Put it back */
+       }
+       return NULL;
+}
+
+static int ugeth_82xx_filtering_add_addr_in_hash(ucc_geth_private_t *ugeth,
+                                                enet_addr_t *p_enet_addr)
+{
+       ucc_geth_enet_address_recognition_location_e location;
+       enet_addr_container_t *enet_addr_cont;
+       struct list_head *p_lh;
+       u8 i;
+       u32 limit;
+       u8 *p_counter;
+
+       if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
+               p_lh = &ugeth->group_hash_q;
+               limit = ugeth->ug_info->maxGroupAddrInHash;
+               location =
+                   UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH;
+               p_counter = &(ugeth->numGroupAddrInHash);
+       } else {
+               p_lh = &ugeth->ind_hash_q;
+               limit = ugeth->ug_info->maxIndAddrInHash;
+               location =
+                   UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH;
+               p_counter = &(ugeth->numIndAddrInHash);
+       }
+
+       if ((enet_addr_cont =
+            ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr))) {
+               list_add(p_lh, &enet_addr_cont->node);  /* Put it back */
+               return 0;
+       }
+       if ((!p_lh) || (!(*p_counter < limit)))
+               return -EBUSY;
+       if (!(enet_addr_cont = get_enet_addr_container()))
+               return -ENOMEM;
+       for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++)
+               (enet_addr_cont->address)[i] = (*p_enet_addr)[i];
+       enet_addr_cont->location = location;
+       enqueue(p_lh, &enet_addr_cont->node);   /* Put it back */
+       ++(*p_counter);
+
+       hw_add_addr_in_hash(ugeth, &(enet_addr_cont->address));
+
+       return 0;
+}
+
+static int ugeth_82xx_filtering_clear_addr_in_hash(ucc_geth_private_t *ugeth,
+                                                  enet_addr_t *p_enet_addr)
+{
+       ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+       enet_addr_container_t *enet_addr_cont;
+       ucc_fast_private_t *uccf;
+       comm_dir_e comm_dir;
+       u16 i, num;
+       struct list_head *p_lh;
+       u32 *addr_h, *addr_l;
+       u8 *p_counter;
+
+       uccf = ugeth->uccf;
+
+       p_82xx_addr_filt =
+           (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+           addressfiltering;
+
+       if (!
+           (enet_addr_cont =
+            ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr)))
+               return -ENOENT;
+
+       /* It's been found and removed from the CQ. */
+       /* Now destroy its container */
+       put_enet_addr_container(enet_addr_cont);
+
+       if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
+               addr_h = &(p_82xx_addr_filt->gaddr_h);
+               addr_l = &(p_82xx_addr_filt->gaddr_l);
+               p_lh = &ugeth->group_hash_q;
+               p_counter = &(ugeth->numGroupAddrInHash);
+       } else {
+               addr_h = &(p_82xx_addr_filt->iaddr_h);
+               addr_l = &(p_82xx_addr_filt->iaddr_l);
+               p_lh = &ugeth->ind_hash_q;
+               p_counter = &(ugeth->numIndAddrInHash);
+       }
+
+       comm_dir = 0;
+       if (uccf->enabled_tx)
+               comm_dir |= COMM_DIR_TX;
+       if (uccf->enabled_rx)
+               comm_dir |= COMM_DIR_RX;
+       if (comm_dir)
+               ugeth_disable(ugeth, comm_dir);
+
+       /* Clear the hash table. */
+       out_be32(addr_h, 0x00000000);
+       out_be32(addr_l, 0x00000000);
+
+       /* Add all remaining CQ elements back into hash */
+       num = --(*p_counter);
+       for (i = 0; i < num; i++) {
+               enet_addr_cont =
+                   (enet_addr_container_t *)
+                   ENET_ADDR_CONT_ENTRY(dequeue(p_lh));
+               hw_add_addr_in_hash(ugeth, &(enet_addr_cont->address));
+               enqueue(p_lh, &enet_addr_cont->node);   /* Put it back */
+       }
+
+       if (comm_dir)
+               ugeth_enable(ugeth, comm_dir);
+
+       return 0;
+}
+#endif /* CONFIG_UGETH_FILTERING */
+
+static int ugeth_82xx_filtering_clear_all_addr_in_hash(ucc_geth_private_t *
+                                                      ugeth,
+                                                      enet_addr_type_e
+                                                      enet_addr_type)
+{
+       ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+       ucc_fast_private_t *uccf;
+       comm_dir_e comm_dir;
+       struct list_head *p_lh;
+       u16 i, num;
+       u32 *addr_h, *addr_l;
+       u8 *p_counter;
+
+       uccf = ugeth->uccf;
+
+       p_82xx_addr_filt =
+           (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+           addressfiltering;
+
+       if (enet_addr_type == ENET_ADDR_TYPE_GROUP) {
+               addr_h = &(p_82xx_addr_filt->gaddr_h);
+               addr_l = &(p_82xx_addr_filt->gaddr_l);
+               p_lh = &ugeth->group_hash_q;
+               p_counter = &(ugeth->numGroupAddrInHash);
+       } else if (enet_addr_type == ENET_ADDR_TYPE_INDIVIDUAL) {
+               addr_h = &(p_82xx_addr_filt->iaddr_h);
+               addr_l = &(p_82xx_addr_filt->iaddr_l);
+               p_lh = &ugeth->ind_hash_q;
+               p_counter = &(ugeth->numIndAddrInHash);
+       } else
+               return -EINVAL;
+
+       comm_dir = 0;
+       if (uccf->enabled_tx)
+               comm_dir |= COMM_DIR_TX;
+       if (uccf->enabled_rx)
+               comm_dir |= COMM_DIR_RX;
+       if (comm_dir)
+               ugeth_disable(ugeth, comm_dir);
+
+       /* Clear the hash table. */
+       out_be32(addr_h, 0x00000000);
+       out_be32(addr_l, 0x00000000);
+
+       if (!p_lh)
+               return 0;
+
+       num = *p_counter;
+
+       /* Delete all remaining CQ elements */
+       for (i = 0; i < num; i++)
+               put_enet_addr_container(ENET_ADDR_CONT_ENTRY(dequeue(p_lh)));
+
+       *p_counter = 0;
+
+       if (comm_dir)
+               ugeth_enable(ugeth, comm_dir);
+
+       return 0;
+}
+
+#ifdef CONFIG_UGETH_FILTERING
+static int ugeth_82xx_filtering_add_addr_in_paddr(ucc_geth_private_t *ugeth,
+                                                 enet_addr_t *p_enet_addr,
+                                                 u8 paddr_num)
+{
+       int i;
+
+       if ((*p_enet_addr)[0] & ENET_GROUP_ADDR)
+               ugeth_warn
+                   ("%s: multicast address added to paddr will have no "
+                    "effect - is this what you wanted?",
+                    __FUNCTION__);
+
+       ugeth->indAddrRegUsed[paddr_num] = 1;   /* mark this paddr as used */
+       /* store address in our database */
+       for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++)
+               ugeth->paddr[paddr_num][i] = (*p_enet_addr)[i];
+       /* put in hardware */
+       return hw_add_addr_in_paddr(ugeth, p_enet_addr, paddr_num);
+}
+#endif /* CONFIG_UGETH_FILTERING */
+
+static int ugeth_82xx_filtering_clear_addr_in_paddr(ucc_geth_private_t *ugeth,
+                                                   u8 paddr_num)
+{
+       ugeth->indAddrRegUsed[paddr_num] = 0; /* mark this paddr as not used */
+       return hw_clear_addr_in_paddr(ugeth, paddr_num);/* clear in hardware */
+}
+
+static void ucc_geth_memclean(ucc_geth_private_t *ugeth)
+{
+       u16 i, j;
+       u8 *bd;
+
+       if (!ugeth)
+               return;
+
+       if (ugeth->uccf)
+               ucc_fast_free(ugeth->uccf);
+
+       if (ugeth->p_thread_data_tx) {
+               qe_muram_free(ugeth->thread_dat_tx_offset);
+               ugeth->p_thread_data_tx = NULL;
+       }
+       if (ugeth->p_thread_data_rx) {
+               qe_muram_free(ugeth->thread_dat_rx_offset);
+               ugeth->p_thread_data_rx = NULL;
+       }
+       if (ugeth->p_exf_glbl_param) {
+               qe_muram_free(ugeth->exf_glbl_param_offset);
+               ugeth->p_exf_glbl_param = NULL;
+       }
+       if (ugeth->p_rx_glbl_pram) {
+               qe_muram_free(ugeth->rx_glbl_pram_offset);
+               ugeth->p_rx_glbl_pram = NULL;
+       }
+       if (ugeth->p_tx_glbl_pram) {
+               qe_muram_free(ugeth->tx_glbl_pram_offset);
+               ugeth->p_tx_glbl_pram = NULL;
+       }
+       if (ugeth->p_send_q_mem_reg) {
+               qe_muram_free(ugeth->send_q_mem_reg_offset);
+               ugeth->p_send_q_mem_reg = NULL;
+       }
+       if (ugeth->p_scheduler) {
+               qe_muram_free(ugeth->scheduler_offset);
+               ugeth->p_scheduler = NULL;
+       }
+       if (ugeth->p_tx_fw_statistics_pram) {
+               qe_muram_free(ugeth->tx_fw_statistics_pram_offset);
+               ugeth->p_tx_fw_statistics_pram = NULL;
+       }
+       if (ugeth->p_rx_fw_statistics_pram) {
+               qe_muram_free(ugeth->rx_fw_statistics_pram_offset);
+               ugeth->p_rx_fw_statistics_pram = NULL;
+       }
+       if (ugeth->p_rx_irq_coalescing_tbl) {
+               qe_muram_free(ugeth->rx_irq_coalescing_tbl_offset);
+               ugeth->p_rx_irq_coalescing_tbl = NULL;
+       }
+       if (ugeth->p_rx_bd_qs_tbl) {
+               qe_muram_free(ugeth->rx_bd_qs_tbl_offset);
+               ugeth->p_rx_bd_qs_tbl = NULL;
+       }
+       if (ugeth->p_init_enet_param_shadow) {
+               return_init_enet_entries(ugeth,
+                                        &(ugeth->p_init_enet_param_shadow->
+                                          rxthread[0]),
+                                        ENET_INIT_PARAM_MAX_ENTRIES_RX,
+                                        ugeth->ug_info->riscRx, 1);
+               return_init_enet_entries(ugeth,
+                                        &(ugeth->p_init_enet_param_shadow->
+                                          txthread[0]),
+                                        ENET_INIT_PARAM_MAX_ENTRIES_TX,
+                                        ugeth->ug_info->riscTx, 0);
+               kfree(ugeth->p_init_enet_param_shadow);
+               ugeth->p_init_enet_param_shadow = NULL;
+       }
+       for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) {
+               bd = ugeth->p_tx_bd_ring[i];
+               for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) {
+                       if (ugeth->tx_skbuff[i][j]) {
+                               dma_unmap_single(NULL,
+                                                BD_BUFFER_ARG(bd),
+                                                (BD_STATUS_AND_LENGTH(bd) &
+                                                 BD_LENGTH_MASK),
+                                                DMA_TO_DEVICE);
+                               dev_kfree_skb_any(ugeth->tx_skbuff[i][j]);
+                               ugeth->tx_skbuff[i][j] = NULL;
+                       }
+               }
+
+               kfree(ugeth->tx_skbuff[i]);
+
+               if (ugeth->p_tx_bd_ring[i]) {
+                       if (ugeth->ug_info->uf_info.bd_mem_part ==
+                           MEM_PART_SYSTEM)
+                               kfree((void *)ugeth->tx_bd_ring_offset[i]);
+                       else if (ugeth->ug_info->uf_info.bd_mem_part ==
+                                MEM_PART_MURAM)
+                               qe_muram_free(ugeth->tx_bd_ring_offset[i]);
+                       ugeth->p_tx_bd_ring[i] = NULL;
+               }
+       }
+       for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
+               if (ugeth->p_rx_bd_ring[i]) {
+                       /* Return existing data buffers in ring */
+                       bd = ugeth->p_rx_bd_ring[i];
+                       for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) {
+                               if (ugeth->rx_skbuff[i][j]) {
+                                       dma_unmap_single(NULL, BD_BUFFER(bd),
+                                                ugeth->ug_info->
+                                                uf_info.
+                                                max_rx_buf_length +
+                                                UCC_GETH_RX_DATA_BUF_ALIGNMENT,
+                                                DMA_FROM_DEVICE);
+
+                                       dev_kfree_skb_any(ugeth->
+                                                         rx_skbuff[i][j]);
+                                       ugeth->rx_skbuff[i][j] = NULL;
+                               }
+                               bd += UCC_GETH_SIZE_OF_BD;
+                       }
+
+                       kfree(ugeth->rx_skbuff[i]);
+
+                       if (ugeth->ug_info->uf_info.bd_mem_part ==
+                           MEM_PART_SYSTEM)
+                               kfree((void *)ugeth->rx_bd_ring_offset[i]);
+                       else if (ugeth->ug_info->uf_info.bd_mem_part ==
+                                MEM_PART_MURAM)
+                               qe_muram_free(ugeth->rx_bd_ring_offset[i]);
+                       ugeth->p_rx_bd_ring[i] = NULL;
+               }
+       }
+       while (!list_empty(&ugeth->group_hash_q))
+               put_enet_addr_container(ENET_ADDR_CONT_ENTRY
+                                       (dequeue(&ugeth->group_hash_q)));
+       while (!list_empty(&ugeth->ind_hash_q))
+               put_enet_addr_container(ENET_ADDR_CONT_ENTRY
+                                       (dequeue(&ugeth->ind_hash_q)));
+
+}
+
+static void ucc_geth_set_multi(struct net_device *dev)
+{
+       ucc_geth_private_t *ugeth;
+       struct dev_mc_list *dmi;
+       ucc_fast_t *uf_regs;
+       ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+       enet_addr_t tempaddr;
+       u8 *mcptr, *tdptr;
+       int i, j;
+
+       ugeth = netdev_priv(dev);
+
+       uf_regs = ugeth->uccf->uf_regs;
+
+       if (dev->flags & IFF_PROMISC) {
+
+               /* Log any net taps. */
+               printk("%s: Promiscuous mode enabled.\n", dev->name);
+               uf_regs->upsmr |= UPSMR_PRO;
+
+       } else {
+
+               uf_regs->upsmr &= ~UPSMR_PRO;
+
+               p_82xx_addr_filt =
+                   (ucc_geth_82xx_address_filtering_pram_t *) ugeth->
+                   p_rx_glbl_pram->addressfiltering;
+
+               if (dev->flags & IFF_ALLMULTI) {
+                       /* Catch all multicast addresses, so set the
+                        * filter to all 1's.
+                        */
+                       out_be32(&p_82xx_addr_filt->gaddr_h, 0xffffffff);
+                       out_be32(&p_82xx_addr_filt->gaddr_l, 0xffffffff);
+               } else {
+                       /* Clear filter and add the addresses in the list.
+                        */
+                       out_be32(&p_82xx_addr_filt->gaddr_h, 0x0);
+                       out_be32(&p_82xx_addr_filt->gaddr_l, 0x0);
+
+                       dmi = dev->mc_list;
+
+                       for (i = 0; i < dev->mc_count; i++, dmi = dmi->next) {
+
+                               /* Only support group multicast for now.
+                                */
+                               if (!(dmi->dmi_addr[0] & 1))
+                                       continue;
+
+                               /* The address in dmi_addr is LSB first,
+                                * and taddr is MSB first.  We have to
+                                * copy bytes MSB first from dmi_addr.
+                                */
+                               mcptr = (u8 *) dmi->dmi_addr + 5;
+                               tdptr = (u8 *) & tempaddr;
+                               for (j = 0; j < 6; j++)
+                                       *tdptr++ = *mcptr--;
+
+                               /* Ask CPM to run CRC and set bit in
+                                * filter mask.
+                                */
+                               hw_add_addr_in_hash(ugeth, &tempaddr);
+
+                       }
+               }
+       }
+}
+
+static void ucc_geth_stop(ucc_geth_private_t *ugeth)
+{
+       ucc_geth_t *ug_regs = ugeth->ug_regs;
+       u32 tempval;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       /* Disable the controller */
+       ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
+
+       /* Tell the kernel the link is down */
+       ugeth->mii_info->link = 0;
+       adjust_link(ugeth->dev);
+
+       /* Mask all interrupts */
+       out_be32(ugeth->uccf->p_ucce, 0x00000000);
+
+       /* Clear all interrupts */
+       out_be32(ugeth->uccf->p_ucce, 0xffffffff);
+
+       /* Disable Rx and Tx */
+       tempval = in_be32(&ug_regs->maccfg1);
+       tempval &= ~(MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);
+       out_be32(&ug_regs->maccfg1, tempval);
+
+       if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) {
+               /* Clear any pending interrupts */
+               mii_clear_phy_interrupt(ugeth->mii_info);
+
+               /* Disable PHY Interrupts */
+               mii_configure_phy_interrupt(ugeth->mii_info,
+                                           MII_INTERRUPT_DISABLED);
+       }
+
+       free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev);
+
+       if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) {
+               free_irq(ugeth->ug_info->phy_interrupt, ugeth->dev);
+       } else {
+               del_timer_sync(&ugeth->phy_info_timer);
+       }
+
+       ucc_geth_memclean(ugeth);
+}
+
+static int ucc_geth_startup(ucc_geth_private_t *ugeth)
+{
+       ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+       ucc_geth_init_pram_t *p_init_enet_pram;
+       ucc_fast_private_t *uccf;
+       ucc_geth_info_t *ug_info;
+       ucc_fast_info_t *uf_info;
+       ucc_fast_t *uf_regs;
+       ucc_geth_t *ug_regs;
+       int ret_val = -EINVAL;
+       u32 remoder = UCC_GETH_REMODER_INIT;
+       u32 init_enet_pram_offset, cecr_subblock, command, maccfg1;
+       u32 ifstat, i, j, size, l2qt, l3qt, length;
+       u16 temoder = UCC_GETH_TEMODER_INIT;
+       u16 test;
+       u8 function_code = 0;
+       u8 *bd, *endOfRing;
+       u8 numThreadsRxNumerical, numThreadsTxNumerical;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       ug_info = ugeth->ug_info;
+       uf_info = &ug_info->uf_info;
+
+       if (!((uf_info->bd_mem_part == MEM_PART_SYSTEM) ||
+             (uf_info->bd_mem_part == MEM_PART_MURAM))) {
+               ugeth_err("%s: Bad memory partition value.", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* Rx BD lengths */
+       for (i = 0; i < ug_info->numQueuesRx; i++) {
+               if ((ug_info->bdRingLenRx[i] < UCC_GETH_RX_BD_RING_SIZE_MIN) ||
+                   (ug_info->bdRingLenRx[i] %
+                    UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT)) {
+                       ugeth_err
+                           ("%s: Rx BD ring length must be multiple of 4,"
+                               " no smaller than 8.", __FUNCTION__);
+                       return -EINVAL;
+               }
+       }
+
+       /* Tx BD lengths */
+       for (i = 0; i < ug_info->numQueuesTx; i++) {
+               if (ug_info->bdRingLenTx[i] < UCC_GETH_TX_BD_RING_SIZE_MIN) {
+                       ugeth_err
+                           ("%s: Tx BD ring length must be no smaller than 2.",
+                            __FUNCTION__);
+                       return -EINVAL;
+               }
+       }
+
+       /* mrblr */
+       if ((uf_info->max_rx_buf_length == 0) ||
+           (uf_info->max_rx_buf_length % UCC_GETH_MRBLR_ALIGNMENT)) {
+               ugeth_err
+                   ("%s: max_rx_buf_length must be non-zero multiple of 128.",
+                    __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* num Tx queues */
+       if (ug_info->numQueuesTx > NUM_TX_QUEUES) {
+               ugeth_err("%s: number of tx queues too large.", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* num Rx queues */
+       if (ug_info->numQueuesRx > NUM_RX_QUEUES) {
+               ugeth_err("%s: number of rx queues too large.", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* l2qt */
+       for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++) {
+               if (ug_info->l2qt[i] >= ug_info->numQueuesRx) {
+                       ugeth_err
+                           ("%s: VLAN priority table entry must not be"
+                               " larger than number of Rx queues.",
+                            __FUNCTION__);
+                       return -EINVAL;
+               }
+       }
+
+       /* l3qt */
+       for (i = 0; i < UCC_GETH_IP_PRIORITY_MAX; i++) {
+               if (ug_info->l3qt[i] >= ug_info->numQueuesRx) {
+                       ugeth_err
+                           ("%s: IP priority table entry must not be"
+                               " larger than number of Rx queues.",
+                            __FUNCTION__);
+                       return -EINVAL;
+               }
+       }
+
+       if (ug_info->cam && !ug_info->ecamptr) {
+               ugeth_err("%s: If cam mode is chosen, must supply cam ptr.",
+                         __FUNCTION__);
+               return -EINVAL;
+       }
+
+       if ((ug_info->numStationAddresses !=
+            UCC_GETH_NUM_OF_STATION_ADDRESSES_1)
+           && ug_info->rxExtendedFiltering) {
+               ugeth_err("%s: Number of station addresses greater than 1 "
+                         "not allowed in extended parsing mode.",
+                         __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* Generate uccm_mask for receive */
+       uf_info->uccm_mask = ug_info->eventRegMask & UCCE_OTHER;/* Errors */
+       for (i = 0; i < ug_info->numQueuesRx; i++)
+               uf_info->uccm_mask |= (UCCE_RXBF_SINGLE_MASK << i);
+
+       for (i = 0; i < ug_info->numQueuesTx; i++)
+               uf_info->uccm_mask |= (UCCE_TXBF_SINGLE_MASK << i);
+       /* Initialize the general fast UCC block. */
+       if (ucc_fast_init(uf_info, &uccf)) {
+               ugeth_err("%s: Failed to init uccf.", __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+       ugeth->uccf = uccf;
+
+       switch (ug_info->numThreadsRx) {
+       case UCC_GETH_NUM_OF_THREADS_1:
+               numThreadsRxNumerical = 1;
+               break;
+       case UCC_GETH_NUM_OF_THREADS_2:
+               numThreadsRxNumerical = 2;
+               break;
+       case UCC_GETH_NUM_OF_THREADS_4:
+               numThreadsRxNumerical = 4;
+               break;
+       case UCC_GETH_NUM_OF_THREADS_6:
+               numThreadsRxNumerical = 6;
+               break;
+       case UCC_GETH_NUM_OF_THREADS_8:
+               numThreadsRxNumerical = 8;
+               break;
+       default:
+               ugeth_err("%s: Bad number of Rx threads value.", __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -EINVAL;
+               break;
+       }
+
+       switch (ug_info->numThreadsTx) {
+       case UCC_GETH_NUM_OF_THREADS_1:
+               numThreadsTxNumerical = 1;
+               break;
+       case UCC_GETH_NUM_OF_THREADS_2:
+               numThreadsTxNumerical = 2;
+               break;
+       case UCC_GETH_NUM_OF_THREADS_4:
+               numThreadsTxNumerical = 4;
+               break;
+       case UCC_GETH_NUM_OF_THREADS_6:
+               numThreadsTxNumerical = 6;
+               break;
+       case UCC_GETH_NUM_OF_THREADS_8:
+               numThreadsTxNumerical = 8;
+               break;
+       default:
+               ugeth_err("%s: Bad number of Tx threads value.", __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -EINVAL;
+               break;
+       }
+
+       /* Calculate rx_extended_features */
+       ugeth->rx_non_dynamic_extended_features = ug_info->ipCheckSumCheck ||
+           ug_info->ipAddressAlignment ||
+           (ug_info->numStationAddresses !=
+            UCC_GETH_NUM_OF_STATION_ADDRESSES_1);
+
+       ugeth->rx_extended_features = ugeth->rx_non_dynamic_extended_features ||
+           (ug_info->vlanOperationTagged != UCC_GETH_VLAN_OPERATION_TAGGED_NOP)
+           || (ug_info->vlanOperationNonTagged !=
+               UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP);
+
+       uf_regs = uccf->uf_regs;
+       ug_regs = (ucc_geth_t *) (uccf->uf_regs);
+       ugeth->ug_regs = ug_regs;
+
+       init_default_reg_vals(&uf_regs->upsmr,
+                             &ug_regs->maccfg1, &ug_regs->maccfg2);
+
+       /*                    Set UPSMR                      */
+       /* For more details see the hardware spec.           */
+       init_rx_parameters(ug_info->bro,
+                          ug_info->rsh, ug_info->pro, &uf_regs->upsmr);
+
+       /* We're going to ignore other registers for now, */
+       /* except as needed to get up and running         */
+
+       /*                    Set MACCFG1                    */
+       /* For more details see the hardware spec.           */
+       init_flow_control_params(ug_info->aufc,
+                                ug_info->receiveFlowControl,
+                                1,
+                                ug_info->pausePeriod,
+                                ug_info->extensionField,
+                                &uf_regs->upsmr,
+                                &ug_regs->uempr, &ug_regs->maccfg1);
+
+       maccfg1 = in_be32(&ug_regs->maccfg1);
+       maccfg1 |= MACCFG1_ENABLE_RX;
+       maccfg1 |= MACCFG1_ENABLE_TX;
+       out_be32(&ug_regs->maccfg1, maccfg1);
+
+       /*                    Set IPGIFG                     */
+       /* For more details see the hardware spec.           */
+       ret_val = init_inter_frame_gap_params(ug_info->nonBackToBackIfgPart1,
+                                             ug_info->nonBackToBackIfgPart2,
+                                             ug_info->
+                                             miminumInterFrameGapEnforcement,
+                                             ug_info->backToBackInterFrameGap,
+                                             &ug_regs->ipgifg);
+       if (ret_val != 0) {
+               ugeth_err("%s: IPGIFG initialization parameter too large.",
+                         __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return ret_val;
+       }
+
+       /*                    Set HAFDUP                     */
+       /* For more details see the hardware spec.           */
+       ret_val = init_half_duplex_params(ug_info->altBeb,
+                                         ug_info->backPressureNoBackoff,
+                                         ug_info->noBackoff,
+                                         ug_info->excessDefer,
+                                         ug_info->altBebTruncation,
+                                         ug_info->maxRetransmission,
+                                         ug_info->collisionWindow,
+                                         &ug_regs->hafdup);
+       if (ret_val != 0) {
+               ugeth_err("%s: Half Duplex initialization parameter too large.",
+                         __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return ret_val;
+       }
+
+       /*                    Set IFSTAT                     */
+       /* For more details see the hardware spec.           */
+       /* Read only - resets upon read                      */
+       ifstat = in_be32(&ug_regs->ifstat);
+
+       /*                    Clear UEMPR                    */
+       /* For more details see the hardware spec.           */
+       out_be32(&ug_regs->uempr, 0);
+
+       /*                    Set UESCR                      */
+       /* For more details see the hardware spec.           */
+       init_hw_statistics_gathering_mode((ug_info->statisticsMode &
+                               UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE),
+                               0, &uf_regs->upsmr, &ug_regs->uescr);
+
+       /* Allocate Tx bds */
+       for (j = 0; j < ug_info->numQueuesTx; j++) {
+               /* Allocate in multiple of
+                  UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT,
+                  according to spec */
+               length = ((ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD)
+                         / UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT)
+                   * UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT;
+               if ((ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD) %
+                   UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT)
+                       length += UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT;
+               if (uf_info->bd_mem_part == MEM_PART_SYSTEM) {
+                       u32 align = 4;
+                       if (UCC_GETH_TX_BD_RING_ALIGNMENT > 4)
+                               align = UCC_GETH_TX_BD_RING_ALIGNMENT;
+                       ugeth->tx_bd_ring_offset[j] =
+                               (u32) (kmalloc((u32) (length + align),
+                               GFP_KERNEL));
+                       if (ugeth->tx_bd_ring_offset[j] != 0)
+                               ugeth->p_tx_bd_ring[j] =
+                                       (void*)((ugeth->tx_bd_ring_offset[j] +
+                                       align) & ~(align - 1));
+               } else if (uf_info->bd_mem_part == MEM_PART_MURAM) {
+                       ugeth->tx_bd_ring_offset[j] =
+                           qe_muram_alloc(length,
+                                          UCC_GETH_TX_BD_RING_ALIGNMENT);
+                       if (!IS_MURAM_ERR(ugeth->tx_bd_ring_offset[j]))
+                               ugeth->p_tx_bd_ring[j] =
+                                   (u8 *) qe_muram_addr(ugeth->
+                                                        tx_bd_ring_offset[j]);
+               }
+               if (!ugeth->p_tx_bd_ring[j]) {
+                       ugeth_err
+                           ("%s: Can not allocate memory for Tx bd rings.",
+                            __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -ENOMEM;
+               }
+               /* Zero unused end of bd ring, according to spec */
+               memset(ugeth->p_tx_bd_ring[j] +
+                      ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD, 0,
+                      length - ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD);
+       }
+
+       /* Allocate Rx bds */
+       for (j = 0; j < ug_info->numQueuesRx; j++) {
+               length = ug_info->bdRingLenRx[j] * UCC_GETH_SIZE_OF_BD;
+               if (uf_info->bd_mem_part == MEM_PART_SYSTEM) {
+                       u32 align = 4;
+                       if (UCC_GETH_RX_BD_RING_ALIGNMENT > 4)
+                               align = UCC_GETH_RX_BD_RING_ALIGNMENT;
+                       ugeth->rx_bd_ring_offset[j] =
+                           (u32) (kmalloc((u32) (length + align), GFP_KERNEL));
+                       if (ugeth->rx_bd_ring_offset[j] != 0)
+                               ugeth->p_rx_bd_ring[j] =
+                                       (void*)((ugeth->rx_bd_ring_offset[j] +
+                                       align) & ~(align - 1));
+               } else if (uf_info->bd_mem_part == MEM_PART_MURAM) {
+                       ugeth->rx_bd_ring_offset[j] =
+                           qe_muram_alloc(length,
+                                          UCC_GETH_RX_BD_RING_ALIGNMENT);
+                       if (!IS_MURAM_ERR(ugeth->rx_bd_ring_offset[j]))
+                               ugeth->p_rx_bd_ring[j] =
+                                   (u8 *) qe_muram_addr(ugeth->
+                                                        rx_bd_ring_offset[j]);
+               }
+               if (!ugeth->p_rx_bd_ring[j]) {
+                       ugeth_err
+                           ("%s: Can not allocate memory for Rx bd rings.",
+                            __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -ENOMEM;
+               }
+       }
+
+       /* Init Tx bds */
+       for (j = 0; j < ug_info->numQueuesTx; j++) {
+               /* Setup the skbuff rings */
+               ugeth->tx_skbuff[j] =
+                   (struct sk_buff **)kmalloc(sizeof(struct sk_buff *) *
+                                              ugeth->ug_info->bdRingLenTx[j],
+                                              GFP_KERNEL);
+
+               if (ugeth->tx_skbuff[j] == NULL) {
+                       ugeth_err("%s: Could not allocate tx_skbuff",
+                                 __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -ENOMEM;
+               }
+
+               for (i = 0; i < ugeth->ug_info->bdRingLenTx[j]; i++)
+                       ugeth->tx_skbuff[j][i] = NULL;
+
+               ugeth->skb_curtx[j] = ugeth->skb_dirtytx[j] = 0;
+               bd = ugeth->confBd[j] = ugeth->txBd[j] = ugeth->p_tx_bd_ring[j];
+               for (i = 0; i < ug_info->bdRingLenTx[j]; i++) {
+                       BD_BUFFER_CLEAR(bd);
+                       BD_STATUS_AND_LENGTH_SET(bd, 0);
+                       bd += UCC_GETH_SIZE_OF_BD;
+               }
+               bd -= UCC_GETH_SIZE_OF_BD;
+               BD_STATUS_AND_LENGTH_SET(bd, T_W);/* for last BD set Wrap bit */
+       }
+
+       /* Init Rx bds */
+       for (j = 0; j < ug_info->numQueuesRx; j++) {
+               /* Setup the skbuff rings */
+               ugeth->rx_skbuff[j] =
+                   (struct sk_buff **)kmalloc(sizeof(struct sk_buff *) *
+                                              ugeth->ug_info->bdRingLenRx[j],
+                                              GFP_KERNEL);
+
+               if (ugeth->rx_skbuff[j] == NULL) {
+                       ugeth_err("%s: Could not allocate rx_skbuff",
+                                 __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -ENOMEM;
+               }
+
+               for (i = 0; i < ugeth->ug_info->bdRingLenRx[j]; i++)
+                       ugeth->rx_skbuff[j][i] = NULL;
+
+               ugeth->skb_currx[j] = 0;
+               bd = ugeth->rxBd[j] = ugeth->p_rx_bd_ring[j];
+               for (i = 0; i < ug_info->bdRingLenRx[j]; i++) {
+                       BD_STATUS_AND_LENGTH_SET(bd, R_I);
+                       BD_BUFFER_CLEAR(bd);
+                       bd += UCC_GETH_SIZE_OF_BD;
+               }
+               bd -= UCC_GETH_SIZE_OF_BD;
+               BD_STATUS_AND_LENGTH_SET(bd, R_W);/* for last BD set Wrap bit */
+       }
+
+       /*
+        * Global PRAM
+        */
+       /* Tx global PRAM */
+       /* Allocate global tx parameter RAM page */
+       ugeth->tx_glbl_pram_offset =
+           qe_muram_alloc(sizeof(ucc_geth_tx_global_pram_t),
+                          UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT);
+       if (IS_MURAM_ERR(ugeth->tx_glbl_pram_offset)) {
+               ugeth_err
+                   ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.",
+                    __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+       ugeth->p_tx_glbl_pram =
+           (ucc_geth_tx_global_pram_t *) qe_muram_addr(ugeth->
+                                                       tx_glbl_pram_offset);
+       /* Zero out p_tx_glbl_pram */
+       memset(ugeth->p_tx_glbl_pram, 0, sizeof(ucc_geth_tx_global_pram_t));
+
+       /* Fill global PRAM */
+
+       /* TQPTR */
+       /* Size varies with number of Tx threads */
+       ugeth->thread_dat_tx_offset =
+           qe_muram_alloc(numThreadsTxNumerical *
+                          sizeof(ucc_geth_thread_data_tx_t) +
+                          32 * (numThreadsTxNumerical == 1),
+                          UCC_GETH_THREAD_DATA_ALIGNMENT);
+       if (IS_MURAM_ERR(ugeth->thread_dat_tx_offset)) {
+               ugeth_err
+                   ("%s: Can not allocate DPRAM memory for p_thread_data_tx.",
+                    __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+
+       ugeth->p_thread_data_tx =
+           (ucc_geth_thread_data_tx_t *) qe_muram_addr(ugeth->
+                                                       thread_dat_tx_offset);
+       out_be32(&ugeth->p_tx_glbl_pram->tqptr, ugeth->thread_dat_tx_offset);
+
+       /* vtagtable */
+       for (i = 0; i < UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX; i++)
+               out_be32(&ugeth->p_tx_glbl_pram->vtagtable[i],
+                        ug_info->vtagtable[i]);
+
+       /* iphoffset */
+       for (i = 0; i < TX_IP_OFFSET_ENTRY_MAX; i++)
+               ugeth->p_tx_glbl_pram->iphoffset[i] = ug_info->iphoffset[i];
+
+       /* SQPTR */
+       /* Size varies with number of Tx queues */
+       ugeth->send_q_mem_reg_offset =
+           qe_muram_alloc(ug_info->numQueuesTx *
+                          sizeof(ucc_geth_send_queue_qd_t),
+                          UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT);
+       if (IS_MURAM_ERR(ugeth->send_q_mem_reg_offset)) {
+               ugeth_err
+                   ("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.",
+                    __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+
+       ugeth->p_send_q_mem_reg =
+           (ucc_geth_send_queue_mem_region_t *) qe_muram_addr(ugeth->
+                       send_q_mem_reg_offset);
+       out_be32(&ugeth->p_tx_glbl_pram->sqptr, ugeth->send_q_mem_reg_offset);
+
+       /* Setup the table */
+       /* Assume BD rings are already established */
+       for (i = 0; i < ug_info->numQueuesTx; i++) {
+               endOfRing =
+                   ugeth->p_tx_bd_ring[i] + (ug_info->bdRingLenTx[i] -
+                                             1) * UCC_GETH_SIZE_OF_BD;
+               if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) {
+                       out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base,
+                                (u32) virt_to_phys(ugeth->p_tx_bd_ring[i]));
+                       out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].
+                                last_bd_completed_address,
+                                (u32) virt_to_phys(endOfRing));
+               } else if (ugeth->ug_info->uf_info.bd_mem_part ==
+                          MEM_PART_MURAM) {
+                       out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base,
+                                (u32) immrbar_virt_to_phys(ugeth->
+                                                           p_tx_bd_ring[i]));
+                       out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].
+                                last_bd_completed_address,
+                                (u32) immrbar_virt_to_phys(endOfRing));
+               }
+       }
+
+       /* schedulerbasepointer */
+
+       if (ug_info->numQueuesTx > 1) {
+       /* scheduler exists only if more than 1 tx queue */
+               ugeth->scheduler_offset =
+                   qe_muram_alloc(sizeof(ucc_geth_scheduler_t),
+                                  UCC_GETH_SCHEDULER_ALIGNMENT);
+               if (IS_MURAM_ERR(ugeth->scheduler_offset)) {
+                       ugeth_err
+                        ("%s: Can not allocate DPRAM memory for p_scheduler.",
+                            __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -ENOMEM;
+               }
+
+               ugeth->p_scheduler =
+                   (ucc_geth_scheduler_t *) qe_muram_addr(ugeth->
+                                                          scheduler_offset);
+               out_be32(&ugeth->p_tx_glbl_pram->schedulerbasepointer,
+                        ugeth->scheduler_offset);
+               /* Zero out p_scheduler */
+               memset(ugeth->p_scheduler, 0, sizeof(ucc_geth_scheduler_t));
+
+               /* Set values in scheduler */
+               out_be32(&ugeth->p_scheduler->mblinterval,
+                        ug_info->mblinterval);
+               out_be16(&ugeth->p_scheduler->nortsrbytetime,
+                        ug_info->nortsrbytetime);
+               ugeth->p_scheduler->fracsiz = ug_info->fracsiz;
+               ugeth->p_scheduler->strictpriorityq = ug_info->strictpriorityq;
+               ugeth->p_scheduler->txasap = ug_info->txasap;
+               ugeth->p_scheduler->extrabw = ug_info->extrabw;
+               for (i = 0; i < NUM_TX_QUEUES; i++)
+                       ugeth->p_scheduler->weightfactor[i] =
+                           ug_info->weightfactor[i];
+
+               /* Set pointers to cpucount registers in scheduler */
+               ugeth->p_cpucount[0] = &(ugeth->p_scheduler->cpucount0);
+               ugeth->p_cpucount[1] = &(ugeth->p_scheduler->cpucount1);
+               ugeth->p_cpucount[2] = &(ugeth->p_scheduler->cpucount2);
+               ugeth->p_cpucount[3] = &(ugeth->p_scheduler->cpucount3);
+               ugeth->p_cpucount[4] = &(ugeth->p_scheduler->cpucount4);
+               ugeth->p_cpucount[5] = &(ugeth->p_scheduler->cpucount5);
+               ugeth->p_cpucount[6] = &(ugeth->p_scheduler->cpucount6);
+               ugeth->p_cpucount[7] = &(ugeth->p_scheduler->cpucount7);
+       }
+
+       /* schedulerbasepointer */
+       /* TxRMON_PTR (statistics) */
+       if (ug_info->
+           statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) {
+               ugeth->tx_fw_statistics_pram_offset =
+                   qe_muram_alloc(sizeof
+                                  (ucc_geth_tx_firmware_statistics_pram_t),
+                                  UCC_GETH_TX_STATISTICS_ALIGNMENT);
+               if (IS_MURAM_ERR(ugeth->tx_fw_statistics_pram_offset)) {
+                       ugeth_err
+                           ("%s: Can not allocate DPRAM memory for"
+                               " p_tx_fw_statistics_pram.", __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -ENOMEM;
+               }
+               ugeth->p_tx_fw_statistics_pram =
+                   (ucc_geth_tx_firmware_statistics_pram_t *)
+                   qe_muram_addr(ugeth->tx_fw_statistics_pram_offset);
+               /* Zero out p_tx_fw_statistics_pram */
+               memset(ugeth->p_tx_fw_statistics_pram,
+                      0, sizeof(ucc_geth_tx_firmware_statistics_pram_t));
+       }
+
+       /* temoder */
+       /* Already has speed set */
+
+       if (ug_info->numQueuesTx > 1)
+               temoder |= TEMODER_SCHEDULER_ENABLE;
+       if (ug_info->ipCheckSumGenerate)
+               temoder |= TEMODER_IP_CHECKSUM_GENERATE;
+       temoder |= ((ug_info->numQueuesTx - 1) << TEMODER_NUM_OF_QUEUES_SHIFT);
+       out_be16(&ugeth->p_tx_glbl_pram->temoder, temoder);
+
+       test = in_be16(&ugeth->p_tx_glbl_pram->temoder);
+
+       /* Function code register value to be used later */
+       function_code = QE_BMR_BYTE_ORDER_BO_MOT | UCC_FAST_FUNCTION_CODE_GBL;
+       /* Required for QE */
+
+       /* function code register */
+       out_be32(&ugeth->p_tx_glbl_pram->tstate, ((u32) function_code) << 24);
+
+       /* Rx global PRAM */
+       /* Allocate global rx parameter RAM page */
+       ugeth->rx_glbl_pram_offset =
+           qe_muram_alloc(sizeof(ucc_geth_rx_global_pram_t),
+                          UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT);
+       if (IS_MURAM_ERR(ugeth->rx_glbl_pram_offset)) {
+               ugeth_err
+                   ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.",
+                    __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+       ugeth->p_rx_glbl_pram =
+           (ucc_geth_rx_global_pram_t *) qe_muram_addr(ugeth->
+                                                       rx_glbl_pram_offset);
+       /* Zero out p_rx_glbl_pram */
+       memset(ugeth->p_rx_glbl_pram, 0, sizeof(ucc_geth_rx_global_pram_t));
+
+       /* Fill global PRAM */
+
+       /* RQPTR */
+       /* Size varies with number of Rx threads */
+       ugeth->thread_dat_rx_offset =
+           qe_muram_alloc(numThreadsRxNumerical *
+                          sizeof(ucc_geth_thread_data_rx_t),
+                          UCC_GETH_THREAD_DATA_ALIGNMENT);
+       if (IS_MURAM_ERR(ugeth->thread_dat_rx_offset)) {
+               ugeth_err
+                   ("%s: Can not allocate DPRAM memory for p_thread_data_rx.",
+                    __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+
+       ugeth->p_thread_data_rx =
+           (ucc_geth_thread_data_rx_t *) qe_muram_addr(ugeth->
+                                                       thread_dat_rx_offset);
+       out_be32(&ugeth->p_rx_glbl_pram->rqptr, ugeth->thread_dat_rx_offset);
+
+       /* typeorlen */
+       out_be16(&ugeth->p_rx_glbl_pram->typeorlen, ug_info->typeorlen);
+
+       /* rxrmonbaseptr (statistics) */
+       if (ug_info->
+           statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) {
+               ugeth->rx_fw_statistics_pram_offset =
+                   qe_muram_alloc(sizeof
+                                  (ucc_geth_rx_firmware_statistics_pram_t),
+                                  UCC_GETH_RX_STATISTICS_ALIGNMENT);
+               if (IS_MURAM_ERR(ugeth->rx_fw_statistics_pram_offset)) {
+                       ugeth_err
+                               ("%s: Can not allocate DPRAM memory for"
+                               " p_rx_fw_statistics_pram.", __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -ENOMEM;
+               }
+               ugeth->p_rx_fw_statistics_pram =
+                   (ucc_geth_rx_firmware_statistics_pram_t *)
+                   qe_muram_addr(ugeth->rx_fw_statistics_pram_offset);
+               /* Zero out p_rx_fw_statistics_pram */
+               memset(ugeth->p_rx_fw_statistics_pram, 0,
+                      sizeof(ucc_geth_rx_firmware_statistics_pram_t));
+       }
+
+       /* intCoalescingPtr */
+
+       /* Size varies with number of Rx queues */
+       ugeth->rx_irq_coalescing_tbl_offset =
+           qe_muram_alloc(ug_info->numQueuesRx *
+                          sizeof(ucc_geth_rx_interrupt_coalescing_entry_t),
+                          UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT);
+       if (IS_MURAM_ERR(ugeth->rx_irq_coalescing_tbl_offset)) {
+               ugeth_err
+                   ("%s: Can not allocate DPRAM memory for"
+                       " p_rx_irq_coalescing_tbl.", __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+
+       ugeth->p_rx_irq_coalescing_tbl =
+           (ucc_geth_rx_interrupt_coalescing_table_t *)
+           qe_muram_addr(ugeth->rx_irq_coalescing_tbl_offset);
+       out_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr,
+                ugeth->rx_irq_coalescing_tbl_offset);
+
+       /* Fill interrupt coalescing table */
+       for (i = 0; i < ug_info->numQueuesRx; i++) {
+               out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i].
+                        interruptcoalescingmaxvalue,
+                        ug_info->interruptcoalescingmaxvalue[i]);
+               out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i].
+                        interruptcoalescingcounter,
+                        ug_info->interruptcoalescingmaxvalue[i]);
+       }
+
+       /* MRBLR */
+       init_max_rx_buff_len(uf_info->max_rx_buf_length,
+                            &ugeth->p_rx_glbl_pram->mrblr);
+       /* MFLR */
+       out_be16(&ugeth->p_rx_glbl_pram->mflr, ug_info->maxFrameLength);
+       /* MINFLR */
+       init_min_frame_len(ug_info->minFrameLength,
+                          &ugeth->p_rx_glbl_pram->minflr,
+                          &ugeth->p_rx_glbl_pram->mrblr);
+       /* MAXD1 */
+       out_be16(&ugeth->p_rx_glbl_pram->maxd1, ug_info->maxD1Length);
+       /* MAXD2 */
+       out_be16(&ugeth->p_rx_glbl_pram->maxd2, ug_info->maxD2Length);
+
+       /* l2qt */
+       l2qt = 0;
+       for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++)
+               l2qt |= (ug_info->l2qt[i] << (28 - 4 * i));
+       out_be32(&ugeth->p_rx_glbl_pram->l2qt, l2qt);
+
+       /* l3qt */
+       for (j = 0; j < UCC_GETH_IP_PRIORITY_MAX; j += 8) {
+               l3qt = 0;
+               for (i = 0; i < 8; i++)
+                       l3qt |= (ug_info->l3qt[j + i] << (28 - 4 * i));
+               out_be32(&ugeth->p_rx_glbl_pram->l3qt[j], l3qt);
+       }
+
+       /* vlantype */
+       out_be16(&ugeth->p_rx_glbl_pram->vlantype, ug_info->vlantype);
+
+       /* vlantci */
+       out_be16(&ugeth->p_rx_glbl_pram->vlantci, ug_info->vlantci);
+
+       /* ecamptr */
+       out_be32(&ugeth->p_rx_glbl_pram->ecamptr, ug_info->ecamptr);
+
+       /* RBDQPTR */
+       /* Size varies with number of Rx queues */
+       ugeth->rx_bd_qs_tbl_offset =
+           qe_muram_alloc(ug_info->numQueuesRx *
+                          (sizeof(ucc_geth_rx_bd_queues_entry_t) +
+                           sizeof(ucc_geth_rx_prefetched_bds_t)),
+                          UCC_GETH_RX_BD_QUEUES_ALIGNMENT);
+       if (IS_MURAM_ERR(ugeth->rx_bd_qs_tbl_offset)) {
+               ugeth_err
+                   ("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.",
+                    __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+
+       ugeth->p_rx_bd_qs_tbl =
+           (ucc_geth_rx_bd_queues_entry_t *) qe_muram_addr(ugeth->
+                                   rx_bd_qs_tbl_offset);
+       out_be32(&ugeth->p_rx_glbl_pram->rbdqptr, ugeth->rx_bd_qs_tbl_offset);
+       /* Zero out p_rx_bd_qs_tbl */
+       memset(ugeth->p_rx_bd_qs_tbl,
+              0,
+              ug_info->numQueuesRx * (sizeof(ucc_geth_rx_bd_queues_entry_t) +
+                                      sizeof(ucc_geth_rx_prefetched_bds_t)));
+
+       /* Setup the table */
+       /* Assume BD rings are already established */
+       for (i = 0; i < ug_info->numQueuesRx; i++) {
+               if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) {
+                       out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr,
+                                (u32) virt_to_phys(ugeth->p_rx_bd_ring[i]));
+               } else if (ugeth->ug_info->uf_info.bd_mem_part ==
+                          MEM_PART_MURAM) {
+                       out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr,
+                                (u32) immrbar_virt_to_phys(ugeth->
+                                                           p_rx_bd_ring[i]));
+               }
+               /* rest of fields handled by QE */
+       }
+
+       /* remoder */
+       /* Already has speed set */
+
+       if (ugeth->rx_extended_features)
+               remoder |= REMODER_RX_EXTENDED_FEATURES;
+       if (ug_info->rxExtendedFiltering)
+               remoder |= REMODER_RX_EXTENDED_FILTERING;
+       if (ug_info->dynamicMaxFrameLength)
+               remoder |= REMODER_DYNAMIC_MAX_FRAME_LENGTH;
+       if (ug_info->dynamicMinFrameLength)
+               remoder |= REMODER_DYNAMIC_MIN_FRAME_LENGTH;
+       remoder |=
+           ug_info->vlanOperationTagged << REMODER_VLAN_OPERATION_TAGGED_SHIFT;
+       remoder |=
+           ug_info->
+           vlanOperationNonTagged << REMODER_VLAN_OPERATION_NON_TAGGED_SHIFT;
+       remoder |= ug_info->rxQoSMode << REMODER_RX_QOS_MODE_SHIFT;
+       remoder |= ((ug_info->numQueuesRx - 1) << REMODER_NUM_OF_QUEUES_SHIFT);
+       if (ug_info->ipCheckSumCheck)
+               remoder |= REMODER_IP_CHECKSUM_CHECK;
+       if (ug_info->ipAddressAlignment)
+               remoder |= REMODER_IP_ADDRESS_ALIGNMENT;
+       out_be32(&ugeth->p_rx_glbl_pram->remoder, remoder);
+
+       /* Note that this function must be called */
+       /* ONLY AFTER p_tx_fw_statistics_pram */
+       /* andp_UccGethRxFirmwareStatisticsPram are allocated ! */
+       init_firmware_statistics_gathering_mode((ug_info->
+               statisticsMode &
+               UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX),
+               (ug_info->statisticsMode &
+               UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX),
+               &ugeth->p_tx_glbl_pram->txrmonbaseptr,
+               ugeth->tx_fw_statistics_pram_offset,
+               &ugeth->p_rx_glbl_pram->rxrmonbaseptr,
+               ugeth->rx_fw_statistics_pram_offset,
+               &ugeth->p_tx_glbl_pram->temoder,
+               &ugeth->p_rx_glbl_pram->remoder);
+
+       /* function code register */
+       ugeth->p_rx_glbl_pram->rstate = function_code;
+
+       /* initialize extended filtering */
+       if (ug_info->rxExtendedFiltering) {
+               if (!ug_info->extendedFilteringChainPointer) {
+                       ugeth_err("%s: Null Extended Filtering Chain Pointer.",
+                                 __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -EINVAL;
+               }
+
+               /* Allocate memory for extended filtering Mode Global
+               Parameters */
+               ugeth->exf_glbl_param_offset =
+                   qe_muram_alloc(sizeof(ucc_geth_exf_global_pram_t),
+               UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT);
+               if (IS_MURAM_ERR(ugeth->exf_glbl_param_offset)) {
+                       ugeth_err
+                               ("%s: Can not allocate DPRAM memory for"
+                               " p_exf_glbl_param.", __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -ENOMEM;
+               }
+
+               ugeth->p_exf_glbl_param =
+                   (ucc_geth_exf_global_pram_t *) qe_muram_addr(ugeth->
+                                exf_glbl_param_offset);
+               out_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam,
+                        ugeth->exf_glbl_param_offset);
+               out_be32(&ugeth->p_exf_glbl_param->l2pcdptr,
+                        (u32) ug_info->extendedFilteringChainPointer);
+
+       } else {                /* initialize 82xx style address filtering */
+
+               /* Init individual address recognition registers to disabled */
+
+               for (j = 0; j < NUM_OF_PADDRS; j++)
+                       ugeth_82xx_filtering_clear_addr_in_paddr(ugeth, (u8) j);
+
+               /* Create CQs for hash tables */
+               if (ug_info->maxGroupAddrInHash > 0) {
+                       INIT_LIST_HEAD(&ugeth->group_hash_q);
+               }
+               if (ug_info->maxIndAddrInHash > 0) {
+                       INIT_LIST_HEAD(&ugeth->ind_hash_q);
+               }
+               p_82xx_addr_filt =
+                   (ucc_geth_82xx_address_filtering_pram_t *) ugeth->
+                   p_rx_glbl_pram->addressfiltering;
+
+               ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth,
+                       ENET_ADDR_TYPE_GROUP);
+               ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth,
+                       ENET_ADDR_TYPE_INDIVIDUAL);
+       }
+
+       /*
+        * Initialize UCC at QE level
+        */
+
+       command = QE_INIT_TX_RX;
+
+       /* Allocate shadow InitEnet command parameter structure.
+        * This is needed because after the InitEnet command is executed,
+        * the structure in DPRAM is released, because DPRAM is a premium
+        * resource.
+        * This shadow structure keeps a copy of what was done so that the
+        * allocated resources can be released when the channel is freed.
+        */
+       if (!(ugeth->p_init_enet_param_shadow =
+            (ucc_geth_init_pram_t *) kmalloc(sizeof(ucc_geth_init_pram_t),
+                                             GFP_KERNEL))) {
+               ugeth_err
+                   ("%s: Can not allocate memory for"
+                       " p_UccInitEnetParamShadows.", __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+       /* Zero out *p_init_enet_param_shadow */
+       memset((char *)ugeth->p_init_enet_param_shadow,
+              0, sizeof(ucc_geth_init_pram_t));
+
+       /* Fill shadow InitEnet command parameter structure */
+
+       ugeth->p_init_enet_param_shadow->resinit1 =
+           ENET_INIT_PARAM_MAGIC_RES_INIT1;
+       ugeth->p_init_enet_param_shadow->resinit2 =
+           ENET_INIT_PARAM_MAGIC_RES_INIT2;
+       ugeth->p_init_enet_param_shadow->resinit3 =
+           ENET_INIT_PARAM_MAGIC_RES_INIT3;
+       ugeth->p_init_enet_param_shadow->resinit4 =
+           ENET_INIT_PARAM_MAGIC_RES_INIT4;
+       ugeth->p_init_enet_param_shadow->resinit5 =
+           ENET_INIT_PARAM_MAGIC_RES_INIT5;
+       ugeth->p_init_enet_param_shadow->rgftgfrxglobal |=
+           ((u32) ug_info->numThreadsRx) << ENET_INIT_PARAM_RGF_SHIFT;
+       ugeth->p_init_enet_param_shadow->rgftgfrxglobal |=
+           ((u32) ug_info->numThreadsTx) << ENET_INIT_PARAM_TGF_SHIFT;
+
+       ugeth->p_init_enet_param_shadow->rgftgfrxglobal |=
+           ugeth->rx_glbl_pram_offset | ug_info->riscRx;
+       if ((ug_info->largestexternallookupkeysize !=
+            QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE)
+           && (ug_info->largestexternallookupkeysize !=
+               QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES)
+           && (ug_info->largestexternallookupkeysize !=
+               QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)) {
+               ugeth_err("%s: Invalid largest External Lookup Key Size.",
+                         __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -EINVAL;
+       }
+       ugeth->p_init_enet_param_shadow->largestexternallookupkeysize =
+           ug_info->largestexternallookupkeysize;
+       size = sizeof(ucc_geth_thread_rx_pram_t);
+       if (ug_info->rxExtendedFiltering) {
+               size += THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING;
+               if (ug_info->largestexternallookupkeysize ==
+                   QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES)
+                       size +=
+                           THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8;
+               if (ug_info->largestexternallookupkeysize ==
+                   QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES)
+                       size +=
+                           THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16;
+       }
+
+       if ((ret_val = fill_init_enet_entries(ugeth, &(ugeth->
+               p_init_enet_param_shadow->rxthread[0]),
+               (u8) (numThreadsRxNumerical + 1)
+               /* Rx needs one extra for terminator */
+               , size, UCC_GETH_THREAD_RX_PRAM_ALIGNMENT,
+               ug_info->riscRx, 1)) != 0) {
+                       ugeth_err("%s: Can not fill p_init_enet_param_shadow.",
+                               __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return ret_val;
+       }
+
+       ugeth->p_init_enet_param_shadow->txglobal =
+           ugeth->tx_glbl_pram_offset | ug_info->riscTx;
+       if ((ret_val =
+            fill_init_enet_entries(ugeth,
+                                   &(ugeth->p_init_enet_param_shadow->
+                                     txthread[0]), numThreadsTxNumerical,
+                                   sizeof(ucc_geth_thread_tx_pram_t),
+                                   UCC_GETH_THREAD_TX_PRAM_ALIGNMENT,
+                                   ug_info->riscTx, 0)) != 0) {
+               ugeth_err("%s: Can not fill p_init_enet_param_shadow.",
+                         __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return ret_val;
+       }
+
+       /* Load Rx bds with buffers */
+       for (i = 0; i < ug_info->numQueuesRx; i++) {
+               if ((ret_val = rx_bd_buffer_set(ugeth, (u8) i)) != 0) {
+                       ugeth_err("%s: Can not fill Rx bds with buffers.",
+                                 __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return ret_val;
+               }
+       }
+
+       /* Allocate InitEnet command parameter structure */
+       init_enet_pram_offset = qe_muram_alloc(sizeof(ucc_geth_init_pram_t), 4);
+       if (IS_MURAM_ERR(init_enet_pram_offset)) {
+               ugeth_err
+                   ("%s: Can not allocate DPRAM memory for p_init_enet_pram.",
+                    __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+       p_init_enet_pram =
+           (ucc_geth_init_pram_t *) qe_muram_addr(init_enet_pram_offset);
+
+       /* Copy shadow InitEnet command parameter structure into PRAM */
+       p_init_enet_pram->resinit1 = ugeth->p_init_enet_param_shadow->resinit1;
+       p_init_enet_pram->resinit2 = ugeth->p_init_enet_param_shadow->resinit2;
+       p_init_enet_pram->resinit3 = ugeth->p_init_enet_param_shadow->resinit3;
+       p_init_enet_pram->resinit4 = ugeth->p_init_enet_param_shadow->resinit4;
+       out_be16(&p_init_enet_pram->resinit5,
+                ugeth->p_init_enet_param_shadow->resinit5);
+       p_init_enet_pram->largestexternallookupkeysize =
+           ugeth->p_init_enet_param_shadow->largestexternallookupkeysize;
+       out_be32(&p_init_enet_pram->rgftgfrxglobal,
+                ugeth->p_init_enet_param_shadow->rgftgfrxglobal);
+       for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_RX; i++)
+               out_be32(&p_init_enet_pram->rxthread[i],
+                        ugeth->p_init_enet_param_shadow->rxthread[i]);
+       out_be32(&p_init_enet_pram->txglobal,
+                ugeth->p_init_enet_param_shadow->txglobal);
+       for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_TX; i++)
+               out_be32(&p_init_enet_pram->txthread[i],
+                        ugeth->p_init_enet_param_shadow->txthread[i]);
+
+       /* Issue QE command */
+       cecr_subblock =
+           ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+       qe_issue_cmd(command, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET,
+                    init_enet_pram_offset);
+
+       /* Free InitEnet command parameter */
+       qe_muram_free(init_enet_pram_offset);
+
+       return 0;
+}
+
+/* returns a net_device_stats structure pointer */
+static struct net_device_stats *ucc_geth_get_stats(struct net_device *dev)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+
+       return &(ugeth->stats);
+}
+
+/* ucc_geth_timeout gets called when a packet has not been
+ * transmitted after a set amount of time.
+ * For now, assume that clearing out all the structures, and
+ * starting over will fix the problem. */
+static void ucc_geth_timeout(struct net_device *dev)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       ugeth->stats.tx_errors++;
+
+       ugeth_dump_regs(ugeth);
+
+       if (dev->flags & IFF_UP) {
+               ucc_geth_stop(ugeth);
+               ucc_geth_startup(ugeth);
+       }
+
+       netif_schedule(dev);
+}
+
+/* This is called by the kernel when a frame is ready for transmission. */
+/* It is pointed to by the dev->hard_start_xmit function pointer */
+static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       u8 *bd;                 /* BD pointer */
+       u32 bd_status;
+       u8 txQ = 0;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       spin_lock_irq(&ugeth->lock);
+
+       ugeth->stats.tx_bytes += skb->len;
+
+       /* Start from the next BD that should be filled */
+       bd = ugeth->txBd[txQ];
+       bd_status = BD_STATUS_AND_LENGTH(bd);
+       /* Save the skb pointer so we can free it later */
+       ugeth->tx_skbuff[txQ][ugeth->skb_curtx[txQ]] = skb;
+
+       /* Update the current skb pointer (wrapping if this was the last) */
+       ugeth->skb_curtx[txQ] =
+           (ugeth->skb_curtx[txQ] +
+            1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]);
+
+       /* set up the buffer descriptor */
+       BD_BUFFER_SET(bd,
+                     dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE));
+
+       //printk(KERN_DEBUG"skb->data is 0x%x\n",skb->data);
+
+       bd_status = (bd_status & T_W) | T_R | T_I | T_L | skb->len;
+
+       BD_STATUS_AND_LENGTH_SET(bd, bd_status);
+
+       dev->trans_start = jiffies;
+
+       /* Move to next BD in the ring */
+       if (!(bd_status & T_W))
+               ugeth->txBd[txQ] = bd + UCC_GETH_SIZE_OF_BD;
+       else
+               ugeth->txBd[txQ] = ugeth->p_tx_bd_ring[txQ];
+
+       /* If the next BD still needs to be cleaned up, then the bds
+          are full.  We need to tell the kernel to stop sending us stuff. */
+       if (bd == ugeth->confBd[txQ]) {
+               if (!netif_queue_stopped(dev))
+                       netif_stop_queue(dev);
+       }
+
+       if (ugeth->p_scheduler) {
+               ugeth->cpucount[txQ]++;
+               /* Indicate to QE that there are more Tx bds ready for
+               transmission */
+               /* This is done by writing a running counter of the bd
+               count to the scheduler PRAM. */
+               out_be16(ugeth->p_cpucount[txQ], ugeth->cpucount[txQ]);
+       }
+
+       spin_unlock_irq(&ugeth->lock);
+
+       return 0;
+}
+
+static int ucc_geth_rx(ucc_geth_private_t *ugeth, u8 rxQ, int rx_work_limit)
+{
+       struct sk_buff *skb;
+       u8 *bd;
+       u16 length, howmany = 0;
+       u32 bd_status;
+       u8 *bdBuffer;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       spin_lock(&ugeth->lock);
+       /* collect received buffers */
+       bd = ugeth->rxBd[rxQ];
+
+       bd_status = BD_STATUS_AND_LENGTH(bd);
+
+       /* while there are received buffers and BD is full (~R_E) */
+       while (!((bd_status & (R_E)) || (--rx_work_limit < 0))) {
+               bdBuffer = (u8 *) BD_BUFFER(bd);
+               length = (u16) ((bd_status & BD_LENGTH_MASK) - 4);
+               skb = ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]];
+
+               /* determine whether buffer is first, last, first and last
+               (single buffer frame) or middle (not first and not last) */
+               if (!skb ||
+                   (!(bd_status & (R_F | R_L))) ||
+                   (bd_status & R_ERRORS_FATAL)) {
+                       ugeth_vdbg("%s, %d: ERROR!!! skb - 0x%08x",
+                                  __FUNCTION__, __LINE__, (u32) skb);
+                       if (skb)
+                               dev_kfree_skb_any(skb);
+
+                       ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = NULL;
+                       ugeth->stats.rx_dropped++;
+               } else {
+                       ugeth->stats.rx_packets++;
+                       howmany++;
+
+                       /* Prep the skb for the packet */
+                       skb_put(skb, length);
+
+                       /* Tell the skb what kind of packet this is */
+                       skb->protocol = eth_type_trans(skb, ugeth->dev);
+
+                       ugeth->stats.rx_bytes += length;
+                       /* Send the packet up the stack */
+#ifdef CONFIG_UGETH_NAPI
+                       netif_receive_skb(skb);
+#else
+                       netif_rx(skb);
+#endif                         /* CONFIG_UGETH_NAPI */
+               }
+
+               ugeth->dev->last_rx = jiffies;
+
+               skb = get_new_skb(ugeth, bd);
+               if (!skb) {
+                       ugeth_warn("%s: No Rx Data Buffer", __FUNCTION__);
+                       spin_unlock(&ugeth->lock);
+                       ugeth->stats.rx_dropped++;
+                       break;
+               }
+
+               ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = skb;
+
+               /* update to point at the next skb */
+               ugeth->skb_currx[rxQ] =
+                   (ugeth->skb_currx[rxQ] +
+                    1) & RX_RING_MOD_MASK(ugeth->ug_info->bdRingLenRx[rxQ]);
+
+               if (bd_status & R_W)
+                       bd = ugeth->p_rx_bd_ring[rxQ];
+               else
+                       bd += UCC_GETH_SIZE_OF_BD;
+
+               bd_status = BD_STATUS_AND_LENGTH(bd);
+       }
+
+       ugeth->rxBd[rxQ] = bd;
+       spin_unlock(&ugeth->lock);
+       return howmany;
+}
+
+static int ucc_geth_tx(struct net_device *dev, u8 txQ)
+{
+       /* Start from the next BD that should be filled */
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       u8 *bd;                 /* BD pointer */
+       u32 bd_status;
+
+       bd = ugeth->confBd[txQ];
+       bd_status = BD_STATUS_AND_LENGTH(bd);
+
+       /* Normal processing. */
+       while ((bd_status & T_R) == 0) {
+               /* BD contains already transmitted buffer.   */
+               /* Handle the transmitted buffer and release */
+               /* the BD to be used with the current frame  */
+
+               if ((bd = ugeth->txBd[txQ]) && (netif_queue_stopped(dev) == 0))
+                       break;
+
+               ugeth->stats.tx_packets++;
+
+               /* Free the sk buffer associated with this TxBD */
+               dev_kfree_skb_irq(ugeth->
+                                 tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]]);
+               ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL;
+               ugeth->skb_dirtytx[txQ] =
+                   (ugeth->skb_dirtytx[txQ] +
+                    1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]);
+
+               /* We freed a buffer, so now we can restart transmission */
+               if (netif_queue_stopped(dev))
+                       netif_wake_queue(dev);
+
+               /* Advance the confirmation BD pointer */
+               if (!(bd_status & T_W))
+                       ugeth->confBd[txQ] += UCC_GETH_SIZE_OF_BD;
+               else
+                       ugeth->confBd[txQ] = ugeth->p_tx_bd_ring[txQ];
+       }
+       return 0;
+}
+
+#ifdef CONFIG_UGETH_NAPI
+static int ucc_geth_poll(struct net_device *dev, int *budget)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       int howmany;
+       int rx_work_limit = *budget;
+       u8 rxQ = 0;
+
+       if (rx_work_limit > dev->quota)
+               rx_work_limit = dev->quota;
+
+       howmany = ucc_geth_rx(ugeth, rxQ, rx_work_limit);
+
+       dev->quota -= howmany;
+       rx_work_limit -= howmany;
+       *budget -= howmany;
+
+       if (rx_work_limit >= 0)
+               netif_rx_complete(dev);
+
+       return (rx_work_limit < 0) ? 1 : 0;
+}
+#endif                         /* CONFIG_UGETH_NAPI */
+
+static irqreturn_t ucc_geth_irq_handler(int irq, void *info,
+                                       struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *)info;
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       ucc_fast_private_t *uccf;
+       ucc_geth_info_t *ug_info;
+       register u32 ucce = 0;
+       register u32 bit_mask = UCCE_RXBF_SINGLE_MASK;
+       register u32 tx_mask = UCCE_TXBF_SINGLE_MASK;
+       register u8 i;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       if (!ugeth)
+               return IRQ_NONE;
+
+       uccf = ugeth->uccf;
+       ug_info = ugeth->ug_info;
+
+       do {
+               ucce |= (u32) (in_be32(uccf->p_ucce) & in_be32(uccf->p_uccm));
+
+               /* clear event bits for next time */
+               /* Side effect here is to mask ucce variable
+               for future processing below. */
+               out_be32(uccf->p_ucce, ucce);   /* Clear with ones,
+                                               but only bits in UCCM */
+
+               /* We ignore Tx interrupts because Tx confirmation is
+               done inside Tx routine */
+
+               for (i = 0; i < ug_info->numQueuesRx; i++) {
+                       if (ucce & bit_mask)
+                               ucc_geth_rx(ugeth, i,
+                                           (int)ugeth->ug_info->
+                                           bdRingLenRx[i]);
+                       ucce &= ~bit_mask;
+                       bit_mask <<= 1;
+               }
+
+               for (i = 0; i < ug_info->numQueuesTx; i++) {
+                       if (ucce & tx_mask)
+                               ucc_geth_tx(dev, i);
+                       ucce &= ~tx_mask;
+                       tx_mask <<= 1;
+               }
+
+               /* Exceptions */
+               if (ucce & UCCE_BSY) {
+                       ugeth_vdbg("Got BUSY irq!!!!");
+                       ugeth->stats.rx_errors++;
+                       ucce &= ~UCCE_BSY;
+               }
+               if (ucce & UCCE_OTHER) {
+                       ugeth_vdbg("Got frame with error (ucce - 0x%08x)!!!!",
+                                  ucce);
+                       ugeth->stats.rx_errors++;
+                       ucce &= ~ucce;
+               }
+       }
+       while (ucce);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *)dev_id;
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       /* Clear the interrupt */
+       mii_clear_phy_interrupt(ugeth->mii_info);
+
+       /* Disable PHY interrupts */
+       mii_configure_phy_interrupt(ugeth->mii_info, MII_INTERRUPT_DISABLED);
+
+       /* Schedule the phy change */
+       schedule_work(&ugeth->tq);
+
+       return IRQ_HANDLED;
+}
+
+/* Scheduled by the phy_interrupt/timer to handle PHY changes */
+static void ugeth_phy_change(void *data)
+{
+       struct net_device *dev = (struct net_device *)data;
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       ucc_geth_t *ug_regs;
+       int result = 0;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       ug_regs = ugeth->ug_regs;
+
+       /* Delay to give the PHY a chance to change the
+        * register state */
+       msleep(1);
+
+       /* Update the link, speed, duplex */
+       result = ugeth->mii_info->phyinfo->read_status(ugeth->mii_info);
+
+       /* Adjust the known status as long as the link
+        * isn't still coming up */
+       if ((0 == result) || (ugeth->mii_info->link == 0))
+               adjust_link(dev);
+
+       /* Reenable interrupts, if needed */
+       if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR)
+               mii_configure_phy_interrupt(ugeth->mii_info,
+                                           MII_INTERRUPT_ENABLED);
+}
+
+/* Called every so often on systems that don't interrupt
+ * the core for PHY changes */
+static void ugeth_phy_timer(unsigned long data)
+{
+       struct net_device *dev = (struct net_device *)data;
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+
+       schedule_work(&ugeth->tq);
+
+       mod_timer(&ugeth->phy_info_timer, jiffies + PHY_CHANGE_TIME * HZ);
+}
+
+/* Keep trying aneg for some time
+ * If, after GFAR_AN_TIMEOUT seconds, it has not
+ * finished, we switch to forced.
+ * Either way, once the process has completed, we either
+ * request the interrupt, or switch the timer over to
+ * using ugeth_phy_timer to check status */
+static void ugeth_phy_startup_timer(unsigned long data)
+{
+       struct ugeth_mii_info *mii_info = (struct ugeth_mii_info *)data;
+       ucc_geth_private_t *ugeth = netdev_priv(mii_info->dev);
+       static int secondary = UGETH_AN_TIMEOUT;
+       int result;
+
+       /* Configure the Auto-negotiation */
+       result = mii_info->phyinfo->config_aneg(mii_info);
+
+       /* If autonegotiation failed to start, and
+        * we haven't timed out, reset the timer, and return */
+       if (result && secondary--) {
+               mod_timer(&ugeth->phy_info_timer, jiffies + HZ);
+               return;
+       } else if (result) {
+               /* Couldn't start autonegotiation.
+                * Try switching to forced */
+               mii_info->autoneg = 0;
+               result = mii_info->phyinfo->config_aneg(mii_info);
+
+               /* Forcing failed!  Give up */
+               if (result) {
+                       ugeth_err("%s: Forcing failed!", mii_info->dev->name);
+                       return;
+               }
+       }
+
+       /* Kill the timer so it can be restarted */
+       del_timer_sync(&ugeth->phy_info_timer);
+
+       /* Grab the PHY interrupt, if necessary/possible */
+       if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) {
+               if (request_irq(ugeth->ug_info->phy_interrupt,
+                               phy_interrupt,
+                               SA_SHIRQ, "phy_interrupt", mii_info->dev) < 0) {
+                       ugeth_err("%s: Can't get IRQ %d (PHY)",
+                                 mii_info->dev->name,
+                                 ugeth->ug_info->phy_interrupt);
+               } else {
+                       mii_configure_phy_interrupt(ugeth->mii_info,
+                                                   MII_INTERRUPT_ENABLED);
+                       return;
+               }
+       }
+
+       /* Start the timer again, this time in order to
+        * handle a change in status */
+       init_timer(&ugeth->phy_info_timer);
+       ugeth->phy_info_timer.function = &ugeth_phy_timer;
+       ugeth->phy_info_timer.data = (unsigned long)mii_info->dev;
+       mod_timer(&ugeth->phy_info_timer, jiffies + PHY_CHANGE_TIME * HZ);
+}
+
+/* Called when something needs to use the ethernet device */
+/* Returns 0 for success. */
+static int ucc_geth_open(struct net_device *dev)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       int err;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       /* Test station address */
+       if (dev->dev_addr[0] & ENET_GROUP_ADDR) {
+               ugeth_err("%s: Multicast address used for station address"
+                         " - is this what you wanted?", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       err = ucc_geth_startup(ugeth);
+       if (err) {
+               ugeth_err("%s: Cannot configure net device, aborting.",
+                         dev->name);
+               return err;
+       }
+
+       err = adjust_enet_interface(ugeth);
+       if (err) {
+               ugeth_err("%s: Cannot configure net device, aborting.",
+                         dev->name);
+               return err;
+       }
+
+       /*       Set MACSTNADDR1, MACSTNADDR2                */
+       /* For more details see the hardware spec.           */
+       init_mac_station_addr_regs(dev->dev_addr[0],
+                                  dev->dev_addr[1],
+                                  dev->dev_addr[2],
+                                  dev->dev_addr[3],
+                                  dev->dev_addr[4],
+                                  dev->dev_addr[5],
+                                  &ugeth->ug_regs->macstnaddr1,
+                                  &ugeth->ug_regs->macstnaddr2);
+
+       err = init_phy(dev);
+       if (err) {
+               ugeth_err("%s: Cannot initialzie PHY, aborting.", dev->name);
+               return err;
+       }
+#ifndef CONFIG_UGETH_NAPI
+       err =
+           request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, 0,
+                       "UCC Geth", dev);
+       if (err) {
+               ugeth_err("%s: Cannot get IRQ for net device, aborting.",
+                         dev->name);
+               ucc_geth_stop(ugeth);
+               return err;
+       }
+#endif                         /* CONFIG_UGETH_NAPI */
+
+       /* Set up the PHY change work queue */
+       INIT_WORK(&ugeth->tq, ugeth_phy_change, dev);
+
+       init_timer(&ugeth->phy_info_timer);
+       ugeth->phy_info_timer.function = &ugeth_phy_startup_timer;
+       ugeth->phy_info_timer.data = (unsigned long)ugeth->mii_info;
+       mod_timer(&ugeth->phy_info_timer, jiffies + HZ);
+
+       err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
+       if (err) {
+               ugeth_err("%s: Cannot enable net device, aborting.", dev->name);
+               ucc_geth_stop(ugeth);
+               return err;
+       }
+
+       netif_start_queue(dev);
+
+       return err;
+}
+
+/* Stops the kernel queue, and halts the controller */
+static int ucc_geth_close(struct net_device *dev)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       ucc_geth_stop(ugeth);
+
+       /* Shutdown the PHY */
+       if (ugeth->mii_info->phyinfo->close)
+               ugeth->mii_info->phyinfo->close(ugeth->mii_info);
+
+       kfree(ugeth->mii_info);
+
+       netif_stop_queue(dev);
+
+       return 0;
+}
+
+struct ethtool_ops ucc_geth_ethtool_ops = {
+       .get_settings = NULL,
+       .get_drvinfo = NULL,
+       .get_regs_len = NULL,
+       .get_regs = NULL,
+       .get_link = NULL,
+       .get_coalesce = NULL,
+       .set_coalesce = NULL,
+       .get_ringparam = NULL,
+       .set_ringparam = NULL,
+       .get_strings = NULL,
+       .get_stats_count = NULL,
+       .get_ethtool_stats = NULL,
+};
+
+static int ucc_geth_probe(struct device *device)
+{
+       struct platform_device *pdev = to_platform_device(device);
+       struct ucc_geth_platform_data *ugeth_pdata;
+       struct net_device *dev = NULL;
+       struct ucc_geth_private *ugeth = NULL;
+       struct ucc_geth_info *ug_info;
+       int err;
+       static int mii_mng_configured = 0;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       ugeth_pdata = (struct ucc_geth_platform_data *)pdev->dev.platform_data;
+
+       ug_info = &ugeth_info[pdev->id];
+       ug_info->uf_info.ucc_num = pdev->id;
+       ug_info->uf_info.rx_clock = ugeth_pdata->rx_clock;
+       ug_info->uf_info.tx_clock = ugeth_pdata->tx_clock;
+       ug_info->uf_info.regs = ugeth_pdata->phy_reg_addr;
+       ug_info->uf_info.irq = platform_get_irq(pdev, 0);
+       ug_info->phy_address = ugeth_pdata->phy_id;
+       ug_info->enet_interface = ugeth_pdata->phy_interface;
+       ug_info->board_flags = ugeth_pdata->board_flags;
+       ug_info->phy_interrupt = ugeth_pdata->phy_interrupt;
+
+       printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n",
+               ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs,
+               ug_info->uf_info.irq);
+
+       if (ug_info == NULL) {
+               ugeth_err("%s: [%d] Missing additional data!", __FUNCTION__,
+                         pdev->id);
+               return -ENODEV;
+       }
+
+       if (!mii_mng_configured) {
+               ucc_set_qe_mux_mii_mng(ug_info->uf_info.ucc_num);
+               mii_mng_configured = 1;
+       }
+
+       /* Create an ethernet device instance */
+       dev = alloc_etherdev(sizeof(*ugeth));
+
+       if (dev == NULL)
+               return -ENOMEM;
+
+       ugeth = netdev_priv(dev);
+       spin_lock_init(&ugeth->lock);
+
+       dev_set_drvdata(device, dev);
+
+       /* Set the dev->base_addr to the gfar reg region */
+       dev->base_addr = (unsigned long)(ug_info->uf_info.regs);
+
+       SET_MODULE_OWNER(dev);
+       SET_NETDEV_DEV(dev, device);
+
+       /* Fill in the dev structure */
+       dev->open = ucc_geth_open;
+       dev->hard_start_xmit = ucc_geth_start_xmit;
+       dev->tx_timeout = ucc_geth_timeout;
+       dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_UGETH_NAPI
+       dev->poll = ucc_geth_poll;
+       dev->weight = UCC_GETH_DEV_WEIGHT;
+#endif                         /* CONFIG_UGETH_NAPI */
+       dev->stop = ucc_geth_close;
+       dev->get_stats = ucc_geth_get_stats;
+//    dev->change_mtu = ucc_geth_change_mtu;
+       dev->mtu = 1500;
+       dev->set_multicast_list = ucc_geth_set_multi;
+       dev->ethtool_ops = &ucc_geth_ethtool_ops;
+
+       err = register_netdev(dev);
+       if (err) {
+               ugeth_err("%s: Cannot register net device, aborting.",
+                         dev->name);
+               free_netdev(dev);
+               return err;
+       }
+
+       ugeth->ug_info = ug_info;
+       ugeth->dev = dev;
+       memcpy(dev->dev_addr, ugeth_pdata->mac_addr, 6);
+
+       return 0;
+}
+
+static int ucc_geth_remove(struct device *device)
+{
+       struct net_device *dev = dev_get_drvdata(device);
+       struct ucc_geth_private *ugeth = netdev_priv(dev);
+
+       dev_set_drvdata(device, NULL);
+       ucc_geth_memclean(ugeth);
+       free_netdev(dev);
+
+       return 0;
+}
+
+/* Structure for a device driver */
+static struct device_driver ucc_geth_driver = {
+       .name = DRV_NAME,
+       .bus = &platform_bus_type,
+       .probe = ucc_geth_probe,
+       .remove = ucc_geth_remove,
+};
+
+static int __init ucc_geth_init(void)
+{
+       int i;
+       printk(KERN_INFO "ucc_geth: " DRV_DESC "\n");
+       for (i = 0; i < 8; i++)
+               memcpy(&(ugeth_info[i]), &ugeth_primary_info,
+                      sizeof(ugeth_primary_info));
+
+       return driver_register(&ucc_geth_driver);
+}
+
+static void __exit ucc_geth_exit(void)
+{
+       driver_unregister(&ucc_geth_driver);
+}
+
+module_init(ucc_geth_init);
+module_exit(ucc_geth_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc");
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
new file mode 100644 (file)
index 0000000..005965f
--- /dev/null
@@ -0,0 +1,1339 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ *
+ * Author: Shlomi Gridish <gridish@freescale.com>
+ *
+ * Description:
+ * Internal header file for UCC Gigabit Ethernet unit routines.
+ *
+ * Changelog:
+ * Jun 28, 2006 Li Yang <LeoLi@freescale.com>
+ * - Rearrange code and style fixes
+ *
+ * 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 __UCC_GETH_H__
+#define __UCC_GETH_H__
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/immap_qe.h>
+#include <asm/qe.h>
+
+#include <asm/ucc.h>
+#include <asm/ucc_fast.h>
+
+#define NUM_TX_QUEUES                   8
+#define NUM_RX_QUEUES                   8
+#define NUM_BDS_IN_PREFETCHED_BDS       4
+#define TX_IP_OFFSET_ENTRY_MAX          8
+#define NUM_OF_PADDRS                   4
+#define ENET_INIT_PARAM_MAX_ENTRIES_RX  9
+#define ENET_INIT_PARAM_MAX_ENTRIES_TX  8
+
+typedef struct ucc_mii_mng {
+       u32 miimcfg;            /* MII management configuration reg */
+       u32 miimcom;            /* MII management command reg */
+       u32 miimadd;            /* MII management address reg */
+       u32 miimcon;            /* MII management control reg */
+       u32 miimstat;           /* MII management status reg */
+       u32 miimind;            /* MII management indication reg */
+} __attribute__ ((packed)) ucc_mii_mng_t;
+
+typedef struct ucc_geth {
+       ucc_fast_t uccf;
+
+       u32 maccfg1;            /* mac configuration reg. 1 */
+       u32 maccfg2;            /* mac configuration reg. 2 */
+       u32 ipgifg;             /* interframe gap reg.  */
+       u32 hafdup;             /* half-duplex reg.  */
+       u8 res1[0x10];
+       ucc_mii_mng_t miimng;   /* MII management structure */
+       u32 ifctl;              /* interface control reg */
+       u32 ifstat;             /* interface statux reg */
+       u32 macstnaddr1;        /* mac station address part 1 reg */
+       u32 macstnaddr2;        /* mac station address part 2 reg */
+       u8 res2[0x8];
+       u32 uempr;              /* UCC Ethernet Mac parameter reg */
+       u32 utbipar;            /* UCC tbi address reg */
+       u16 uescr;              /* UCC Ethernet statistics control reg */
+       u8 res3[0x180 - 0x15A];
+       u32 tx64;               /* Total number of frames (including bad
+                                  frames) transmitted that were exactly of the
+                                  minimal length (64 for un tagged, 68 for
+                                  tagged, or with length exactly equal to the
+                                  parameter MINLength */
+       u32 tx127;              /* Total number of frames (including bad
+                                  frames) transmitted that were between
+                                  MINLength (Including FCS length==4) and 127
+                                  octets */
+       u32 tx255;              /* Total number of frames (including bad
+                                  frames) transmitted that were between 128
+                                  (Including FCS length==4) and 255 octets */
+       u32 rx64;               /* Total number of frames received including
+                                  bad frames that were exactly of the mninimal
+                                  length (64 bytes) */
+       u32 rx127;              /* Total number of frames (including bad
+                                  frames) received that were between MINLength
+                                  (Including FCS length==4) and 127 octets */
+       u32 rx255;              /* Total number of frames (including bad
+                                  frames) received that were between 128
+                                  (Including FCS length==4) and 255 octets */
+       u32 txok;               /* Total number of octets residing in frames
+                                  that where involved in succesfull
+                                  transmission */
+       u16 txcf;               /* Total number of PAUSE control frames
+                                  transmitted by this MAC */
+       u8 res4[0x2];
+       u32 tmca;               /* Total number of frames that were transmitted
+                                  succesfully with the group address bit set
+                                  that are not broadcast frames */
+       u32 tbca;               /* Total number of frames transmitted
+                                  succesfully that had destination address
+                                  field equal to the broadcast address */
+       u32 rxfok;              /* Total number of frames received OK */
+       u32 rxbok;              /* Total number of octets received OK */
+       u32 rbyt;               /* Total number of octets received including
+                                  octets in bad frames. Must be implemented in
+                                  HW because it includes octets in frames that
+                                  never even reach the UCC */
+       u32 rmca;               /* Total number of frames that were received
+                                  succesfully with the group address bit set
+                                  that are not broadcast frames */
+       u32 rbca;               /* Total number of frames received succesfully
+                                  that had destination address equal to the
+                                  broadcast address */
+       u32 scar;               /* Statistics carry register */
+       u32 scam;               /* Statistics caryy mask register */
+       u8 res5[0x200 - 0x1c4];
+} __attribute__ ((packed)) ucc_geth_t;
+
+/* UCC GETH TEMODR Register */
+#define TEMODER_TX_RMON_STATISTICS_ENABLE       0x0100 /* enable Tx statistics
+                                                        */
+#define TEMODER_SCHEDULER_ENABLE                0x2000 /* enable scheduler */
+#define TEMODER_IP_CHECKSUM_GENERATE            0x0400 /* generate IPv4
+                                                          checksums */
+#define TEMODER_PERFORMANCE_OPTIMIZATION_MODE1  0x0200 /* enable performance
+                                                          optimization
+                                                          enhancement (mode1) */
+#define TEMODER_RMON_STATISTICS                 0x0100 /* enable tx statistics
+                                                        */
+#define TEMODER_NUM_OF_QUEUES_SHIFT             (15-15)        /* Number of queues <<
+                                                          shift */
+
+/* UCC GETH TEMODR Register */
+#define REMODER_RX_RMON_STATISTICS_ENABLE       0x00001000     /* enable Rx
+                                                                  statistics */
+#define REMODER_RX_EXTENDED_FEATURES            0x80000000     /* enable
+                                                                  extended
+                                                                  features */
+#define REMODER_VLAN_OPERATION_TAGGED_SHIFT     (31-9 )        /* vlan operation
+                                                          tagged << shift */
+#define REMODER_VLAN_OPERATION_NON_TAGGED_SHIFT (31-10)        /* vlan operation non
+                                                          tagged << shift */
+#define REMODER_RX_QOS_MODE_SHIFT               (31-15)        /* rx QoS mode << shift
+                                                        */
+#define REMODER_RMON_STATISTICS                 0x00001000     /* enable rx
+                                                                  statistics */
+#define REMODER_RX_EXTENDED_FILTERING           0x00000800     /* extended
+                                                                  filtering
+                                                                  vs.
+                                                                  mpc82xx-like
+                                                                  filtering */
+#define REMODER_NUM_OF_QUEUES_SHIFT             (31-23)        /* Number of queues <<
+                                                          shift */
+#define REMODER_DYNAMIC_MAX_FRAME_LENGTH        0x00000008     /* enable
+                                                                  dynamic max
+                                                                  frame length
+                                                                */
+#define REMODER_DYNAMIC_MIN_FRAME_LENGTH        0x00000004     /* enable
+                                                                  dynamic min
+                                                                  frame length
+                                                                */
+#define REMODER_IP_CHECKSUM_CHECK               0x00000002     /* check IPv4
+                                                                  checksums */
+#define REMODER_IP_ADDRESS_ALIGNMENT            0x00000001     /* align ip
+                                                                  address to
+                                                                  4-byte
+                                                                  boundary */
+
+/* UCC GETH Event Register */
+#define UCCE_MPD                                0x80000000     /* Magic packet
+                                                                  detection */
+#define UCCE_SCAR                               0x40000000
+#define UCCE_GRA                                0x20000000     /* Tx graceful
+                                                                  stop
+                                                                  complete */
+#define UCCE_CBPR                               0x10000000
+#define UCCE_BSY                                0x08000000
+#define UCCE_RXC                                0x04000000
+#define UCCE_TXC                                0x02000000
+#define UCCE_TXE                                0x01000000
+#define UCCE_TXB7                               0x00800000
+#define UCCE_TXB6                               0x00400000
+#define UCCE_TXB5                               0x00200000
+#define UCCE_TXB4                               0x00100000
+#define UCCE_TXB3                               0x00080000
+#define UCCE_TXB2                               0x00040000
+#define UCCE_TXB1                               0x00020000
+#define UCCE_TXB0                               0x00010000
+#define UCCE_RXB7                               0x00008000
+#define UCCE_RXB6                               0x00004000
+#define UCCE_RXB5                               0x00002000
+#define UCCE_RXB4                               0x00001000
+#define UCCE_RXB3                               0x00000800
+#define UCCE_RXB2                               0x00000400
+#define UCCE_RXB1                               0x00000200
+#define UCCE_RXB0                               0x00000100
+#define UCCE_RXF7                               0x00000080
+#define UCCE_RXF6                               0x00000040
+#define UCCE_RXF5                               0x00000020
+#define UCCE_RXF4                               0x00000010
+#define UCCE_RXF3                               0x00000008
+#define UCCE_RXF2                               0x00000004
+#define UCCE_RXF1                               0x00000002
+#define UCCE_RXF0                               0x00000001
+
+#define UCCE_RXBF_SINGLE_MASK                   (UCCE_RXF0)
+#define UCCE_TXBF_SINGLE_MASK                   (UCCE_TXB0)
+
+#define UCCE_TXB         (UCCE_TXB7 | UCCE_TXB6 | UCCE_TXB5 | UCCE_TXB4 |\
+                       UCCE_TXB3 | UCCE_TXB2 | UCCE_TXB1 | UCCE_TXB0)
+#define UCCE_RXB         (UCCE_RXB7 | UCCE_RXB6 | UCCE_RXB5 | UCCE_RXB4 |\
+                       UCCE_RXB3 | UCCE_RXB2 | UCCE_RXB1 | UCCE_RXB0)
+#define UCCE_RXF         (UCCE_RXF7 | UCCE_RXF6 | UCCE_RXF5 | UCCE_RXF4 |\
+                       UCCE_RXF3 | UCCE_RXF2 | UCCE_RXF1 | UCCE_RXF0)
+#define UCCE_OTHER       (UCCE_SCAR | UCCE_GRA  | UCCE_CBPR | UCCE_BSY  |\
+                       UCCE_RXC  | UCCE_TXC  | UCCE_TXE)
+
+/* UCC GETH UPSMR (Protocol Specific Mode Register) */
+#define UPSMR_ECM                               0x04000000     /* Enable CAM
+                                                                  Miss or
+                                                                  Enable
+                                                                  Filtering
+                                                                  Miss */
+#define UPSMR_HSE                               0x02000000     /* Hardware
+                                                                  Statistics
+                                                                  Enable */
+#define UPSMR_PRO                               0x00400000     /* Promiscuous*/
+#define UPSMR_CAP                               0x00200000     /* CAM polarity
+                                                                */
+#define UPSMR_RSH                               0x00100000     /* Receive
+                                                                  Short Frames
+                                                                */
+#define UPSMR_RPM                               0x00080000     /* Reduced Pin
+                                                                  Mode
+                                                                  interfaces */
+#define UPSMR_R10M                              0x00040000     /* RGMII/RMII
+                                                                  10 Mode */
+#define UPSMR_RLPB                              0x00020000     /* RMII
+                                                                  Loopback
+                                                                  Mode */
+#define UPSMR_TBIM                              0x00010000     /* Ten-bit
+                                                                  Interface
+                                                                  Mode */
+#define UPSMR_RMM                               0x00001000     /* RMII/RGMII
+                                                                  Mode */
+#define UPSMR_CAM                               0x00000400     /* CAM Address
+                                                                  Matching */
+#define UPSMR_BRO                               0x00000200     /* Broadcast
+                                                                  Address */
+#define UPSMR_RES1                              0x00002000     /* Reserved
+                                                                  feild - must
+                                                                  be 1 */
+
+/* UCC GETH MACCFG1 (MAC Configuration 1 Register) */
+#define MACCFG1_FLOW_RX                         0x00000020     /* Flow Control
+                                                                  Rx */
+#define MACCFG1_FLOW_TX                         0x00000010     /* Flow Control
+                                                                  Tx */
+#define MACCFG1_ENABLE_SYNCHED_RX               0x00000008     /* Rx Enable
+                                                                  synchronized
+                                                                  to Rx stream
+                                                                */
+#define MACCFG1_ENABLE_RX                       0x00000004     /* Enable Rx */
+#define MACCFG1_ENABLE_SYNCHED_TX               0x00000002     /* Tx Enable
+                                                                  synchronized
+                                                                  to Tx stream
+                                                                */
+#define MACCFG1_ENABLE_TX                       0x00000001     /* Enable Tx */
+
+/* UCC GETH MACCFG2 (MAC Configuration 2 Register) */
+#define MACCFG2_PREL_SHIFT                      (31 - 19)      /* Preamble
+                                                                  Length <<
+                                                                  shift */
+#define MACCFG2_PREL_MASK                       0x0000f000     /* Preamble
+                                                                  Length mask */
+#define MACCFG2_SRP                             0x00000080     /* Soft Receive
+                                                                  Preamble */
+#define MACCFG2_STP                             0x00000040     /* Soft
+                                                                  Transmit
+                                                                  Preamble */
+#define MACCFG2_RESERVED_1                      0x00000020     /* Reserved -
+                                                                  must be set
+                                                                  to 1 */
+#define MACCFG2_LC                              0x00000010     /* Length Check
+                                                                */
+#define MACCFG2_MPE                             0x00000008     /* Magic packet
+                                                                  detect */
+#define MACCFG2_FDX                             0x00000001     /* Full Duplex */
+#define MACCFG2_FDX_MASK                        0x00000001     /* Full Duplex
+                                                                  mask */
+#define MACCFG2_PAD_CRC                         0x00000004
+#define MACCFG2_CRC_EN                          0x00000002
+#define MACCFG2_PAD_AND_CRC_MODE_NONE           0x00000000     /* Neither
+                                                                  Padding
+                                                                  short frames
+                                                                  nor CRC */
+#define MACCFG2_PAD_AND_CRC_MODE_CRC_ONLY       0x00000002     /* Append CRC
+                                                                  only */
+#define MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC    0x00000004
+#define MACCFG2_INTERFACE_MODE_NIBBLE           0x00000100     /* nibble mode
+                                                                  (MII/RMII/RGMII
+                                                                  10/100bps) */
+#define MACCFG2_INTERFACE_MODE_BYTE             0x00000200     /* byte mode
+                                                                  (GMII/TBI/RTB/RGMII
+                                                                  1000bps ) */
+#define MACCFG2_INTERFACE_MODE_MASK             0x00000300     /* mask
+                                                                  covering all
+                                                                  relevant
+                                                                  bits */
+
+/* UCC GETH IPGIFG (Inter-frame Gap / Inter-Frame Gap Register) */
+#define IPGIFG_NON_BACK_TO_BACK_IFG_PART1_SHIFT (31 -  7)      /* Non
+                                                                  back-to-back
+                                                                  inter frame
+                                                                  gap part 1.
+                                                                  << shift */
+#define IPGIFG_NON_BACK_TO_BACK_IFG_PART2_SHIFT (31 - 15)      /* Non
+                                                                  back-to-back
+                                                                  inter frame
+                                                                  gap part 2.
+                                                                  << shift */
+#define IPGIFG_MINIMUM_IFG_ENFORCEMENT_SHIFT    (31 - 23)      /* Mimimum IFG
+                                                                  Enforcement
+                                                                  << shift */
+#define IPGIFG_BACK_TO_BACK_IFG_SHIFT           (31 - 31)      /* back-to-back
+                                                                  inter frame
+                                                                  gap << shift
+                                                                */
+#define IPGIFG_NON_BACK_TO_BACK_IFG_PART1_MAX   127    /* Non back-to-back
+                                                          inter frame gap part
+                                                          1. max val */
+#define IPGIFG_NON_BACK_TO_BACK_IFG_PART2_MAX   127    /* Non back-to-back
+                                                          inter frame gap part
+                                                          2. max val */
+#define IPGIFG_MINIMUM_IFG_ENFORCEMENT_MAX      255    /* Mimimum IFG
+                                                          Enforcement max val */
+#define IPGIFG_BACK_TO_BACK_IFG_MAX             127    /* back-to-back inter
+                                                          frame gap max val */
+#define IPGIFG_NBTB_CS_IPG_MASK                 0x7F000000
+#define IPGIFG_NBTB_IPG_MASK                    0x007F0000
+#define IPGIFG_MIN_IFG_MASK                     0x0000FF00
+#define IPGIFG_BTB_IPG_MASK                     0x0000007F
+
+/* UCC GETH HAFDUP (Half Duplex Register) */
+#define HALFDUP_ALT_BEB_TRUNCATION_SHIFT        (31 - 11)      /* Alternate
+                                                                  Binary
+                                                                  Exponential
+                                                                  Backoff
+                                                                  Truncation
+                                                                  << shift */
+#define HALFDUP_ALT_BEB_TRUNCATION_MAX          0xf    /* Alternate Binary
+                                                          Exponential Backoff
+                                                          Truncation max val */
+#define HALFDUP_ALT_BEB                         0x00080000     /* Alternate
+                                                                  Binary
+                                                                  Exponential
+                                                                  Backoff */
+#define HALFDUP_BACK_PRESSURE_NO_BACKOFF        0x00040000     /* Back
+                                                                  pressure no
+                                                                  backoff */
+#define HALFDUP_NO_BACKOFF                      0x00020000     /* No Backoff */
+#define HALFDUP_EXCESSIVE_DEFER                 0x00010000     /* Excessive
+                                                                  Defer */
+#define HALFDUP_MAX_RETRANSMISSION_SHIFT        (31 - 19)      /* Maximum
+                                                                  Retransmission
+                                                                  << shift */
+#define HALFDUP_MAX_RETRANSMISSION_MAX          0xf    /* Maximum
+                                                          Retransmission max
+                                                          val */
+#define HALFDUP_COLLISION_WINDOW_SHIFT          (31 - 31)      /* Collision
+                                                                  Window <<
+                                                                  shift */
+#define HALFDUP_COLLISION_WINDOW_MAX            0x3f   /* Collision Window max
+                                                          val */
+#define HALFDUP_ALT_BEB_TR_MASK                 0x00F00000
+#define HALFDUP_RETRANS_MASK                    0x0000F000
+#define HALFDUP_COL_WINDOW_MASK                 0x0000003F
+
+/* UCC GETH UCCS (Ethernet Status Register) */
+#define UCCS_BPR                                0x02   /* Back pressure (in
+                                                          half duplex mode) */
+#define UCCS_PAU                                0x02   /* Pause state (in full
+                                                          duplex mode) */
+#define UCCS_MPD                                0x01   /* Magic Packet
+                                                          Detected */
+
+/* UCC GETH MIIMCFG (MII Management Configuration Register) */
+#define MIIMCFG_RESET_MANAGEMENT                0x80000000     /* Reset
+                                                                  management */
+#define MIIMCFG_NO_PREAMBLE                     0x00000010     /* Preamble
+                                                                  suppress */
+#define MIIMCFG_CLOCK_DIVIDE_SHIFT              (31 - 31)      /* clock divide
+                                                                  << shift */
+#define MIIMCFG_CLOCK_DIVIDE_MAX                0xf    /* clock divide max val
+                                                        */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_2    0x00000000     /* divide by 2 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_4    0x00000001     /* divide by 4 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_6    0x00000002     /* divide by 6 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_8    0x00000003     /* divide by 8 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_10   0x00000004     /* divide by 10
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_14   0x00000005     /* divide by 14
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_16   0x00000008     /* divide by 16
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_20   0x00000006     /* divide by 20
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_28   0x00000007     /* divide by 28
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_32   0x00000009     /* divide by 32
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_48   0x0000000a     /* divide by 48
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_64   0x0000000b     /* divide by 64
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_80   0x0000000c     /* divide by 80
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112  0x0000000d     /* divide by
+                                                                  112 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_160  0x0000000e     /* divide by
+                                                                  160 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_224  0x0000000f     /* divide by
+                                                                  224 */
+
+/* UCC GETH MIIMCOM (MII Management Command Register) */
+#define MIIMCOM_SCAN_CYCLE                      0x00000002     /* Scan cycle */
+#define MIIMCOM_READ_CYCLE                      0x00000001     /* Read cycle */
+
+/* UCC GETH MIIMADD (MII Management Address Register) */
+#define MIIMADD_PHY_ADDRESS_SHIFT               (31 - 23)      /* PHY Address
+                                                                  << shift */
+#define MIIMADD_PHY_REGISTER_SHIFT              (31 - 31)      /* PHY Register
+                                                                  << shift */
+
+/* UCC GETH MIIMCON (MII Management Control Register) */
+#define MIIMCON_PHY_CONTROL_SHIFT               (31 - 31)      /* PHY Control
+                                                                  << shift */
+#define MIIMCON_PHY_STATUS_SHIFT                (31 - 31)      /* PHY Status
+                                                                  << shift */
+
+/* UCC GETH MIIMIND (MII Management Indicator Register) */
+#define MIIMIND_NOT_VALID                       0x00000004     /* Not valid */
+#define MIIMIND_SCAN                            0x00000002     /* Scan in
+                                                                  progress */
+#define MIIMIND_BUSY                            0x00000001
+
+/* UCC GETH IFSTAT (Interface Status Register) */
+#define IFSTAT_EXCESS_DEFER                     0x00000200     /* Excessive
+                                                                  transmission
+                                                                  defer */
+
+/* UCC GETH MACSTNADDR1 (Station Address Part 1 Register) */
+#define MACSTNADDR1_OCTET_6_SHIFT               (31 -  7)      /* Station
+                                                                  address 6th
+                                                                  octet <<
+                                                                  shift */
+#define MACSTNADDR1_OCTET_5_SHIFT               (31 - 15)      /* Station
+                                                                  address 5th
+                                                                  octet <<
+                                                                  shift */
+#define MACSTNADDR1_OCTET_4_SHIFT               (31 - 23)      /* Station
+                                                                  address 4th
+                                                                  octet <<
+                                                                  shift */
+#define MACSTNADDR1_OCTET_3_SHIFT               (31 - 31)      /* Station
+                                                                  address 3rd
+                                                                  octet <<
+                                                                  shift */
+
+/* UCC GETH MACSTNADDR2 (Station Address Part 2 Register) */
+#define MACSTNADDR2_OCTET_2_SHIFT               (31 -  7)      /* Station
+                                                                  address 2nd
+                                                                  octet <<
+                                                                  shift */
+#define MACSTNADDR2_OCTET_1_SHIFT               (31 - 15)      /* Station
+                                                                  address 1st
+                                                                  octet <<
+                                                                  shift */
+
+/* UCC GETH UEMPR (Ethernet Mac Parameter Register) */
+#define UEMPR_PAUSE_TIME_VALUE_SHIFT            (31 - 15)      /* Pause time
+                                                                  value <<
+                                                                  shift */
+#define UEMPR_EXTENDED_PAUSE_TIME_VALUE_SHIFT   (31 - 31)      /* Extended
+                                                                  pause time
+                                                                  value <<
+                                                                  shift */
+
+/* UCC GETH UTBIPAR (Ten Bit Interface Physical Address Register) */
+#define UTBIPAR_PHY_ADDRESS_SHIFT               (31 - 31)      /* Phy address
+                                                                  << shift */
+#define UTBIPAR_PHY_ADDRESS_MASK                0x0000001f     /* Phy address
+                                                                  mask */
+
+/* UCC GETH UESCR (Ethernet Statistics Control Register) */
+#define UESCR_AUTOZ                             0x8000 /* Automatically zero
+                                                          addressed
+                                                          statistical counter
+                                                          values */
+#define UESCR_CLRCNT                            0x4000 /* Clear all statistics
+                                                          counters */
+#define UESCR_MAXCOV_SHIFT                      (15 -  7)      /* Max
+                                                                  Coalescing
+                                                                  Value <<
+                                                                  shift */
+#define UESCR_SCOV_SHIFT                        (15 - 15)      /* Status
+                                                                  Coalescing
+                                                                  Value <<
+                                                                  shift */
+
+/* UCC GETH UDSR (Data Synchronization Register) */
+#define UDSR_MAGIC                              0x067E
+
+typedef struct ucc_geth_thread_data_tx {
+       u8 res0[104];
+} __attribute__ ((packed)) ucc_geth_thread_data_tx_t;
+
+typedef struct ucc_geth_thread_data_rx {
+       u8 res0[40];
+} __attribute__ ((packed)) ucc_geth_thread_data_rx_t;
+
+/* Send Queue Queue-Descriptor */
+typedef struct ucc_geth_send_queue_qd {
+       u32 bd_ring_base;       /* pointer to BD ring base address */
+       u8 res0[0x8];
+       u32 last_bd_completed_address;/* initialize to last entry in BD ring */
+       u8 res1[0x30];
+} __attribute__ ((packed)) ucc_geth_send_queue_qd_t;
+
+typedef struct ucc_geth_send_queue_mem_region {
+       ucc_geth_send_queue_qd_t sqqd[NUM_TX_QUEUES];
+} __attribute__ ((packed)) ucc_geth_send_queue_mem_region_t;
+
+typedef struct ucc_geth_thread_tx_pram {
+       u8 res0[64];
+} __attribute__ ((packed)) ucc_geth_thread_tx_pram_t;
+
+typedef struct ucc_geth_thread_rx_pram {
+       u8 res0[128];
+} __attribute__ ((packed)) ucc_geth_thread_rx_pram_t;
+
+#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING        64
+#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8      64
+#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16     96
+
+typedef struct ucc_geth_scheduler {
+       u16 cpucount0;          /* CPU packet counter */
+       u16 cpucount1;          /* CPU packet counter */
+       u16 cecount0;           /* QE packet counter */
+       u16 cecount1;           /* QE packet counter */
+       u16 cpucount2;          /* CPU packet counter */
+       u16 cpucount3;          /* CPU packet counter */
+       u16 cecount2;           /* QE packet counter */
+       u16 cecount3;           /* QE packet counter */
+       u16 cpucount4;          /* CPU packet counter */
+       u16 cpucount5;          /* CPU packet counter */
+       u16 cecount4;           /* QE packet counter */
+       u16 cecount5;           /* QE packet counter */
+       u16 cpucount6;          /* CPU packet counter */
+       u16 cpucount7;          /* CPU packet counter */
+       u16 cecount6;           /* QE packet counter */
+       u16 cecount7;           /* QE packet counter */
+       u32 weightstatus[NUM_TX_QUEUES];        /* accumulated weight factor */
+       u32 rtsrshadow;         /* temporary variable handled by QE */
+       u32 time;               /* temporary variable handled by QE */
+       u32 ttl;                /* temporary variable handled by QE */
+       u32 mblinterval;        /* max burst length interval */
+       u16 nortsrbytetime;     /* normalized value of byte time in tsr units */
+       u8 fracsiz;             /* radix 2 log value of denom. of
+                                  NorTSRByteTime */
+       u8 res0[1];
+       u8 strictpriorityq;     /* Strict Priority Mask register */
+       u8 txasap;              /* Transmit ASAP register */
+       u8 extrabw;             /* Extra BandWidth register */
+       u8 oldwfqmask;          /* temporary variable handled by QE */
+       u8 weightfactor[NUM_TX_QUEUES];
+                                     /**< weight factor for queues   */
+       u32 minw;               /* temporary variable handled by QE */
+       u8 res1[0x70 - 0x64];
+} __attribute__ ((packed)) ucc_geth_scheduler_t;
+
+typedef struct ucc_geth_tx_firmware_statistics_pram {
+       u32 sicoltx;            /* single collision */
+       u32 mulcoltx;           /* multiple collision */
+       u32 latecoltxfr;        /* late collision */
+       u32 frabortduecol;      /* frames aborted due to transmit collision */
+       u32 frlostinmactxer;    /* frames lost due to internal MAC error
+                                  transmission that are not counted on any
+                                  other counter */
+       u32 carriersenseertx;   /* carrier sense error */
+       u32 frtxok;             /* frames transmitted OK */
+       u32 txfrexcessivedefer; /* frames with defferal time greater than
+                                  specified threshold */
+       u32 txpkts256;          /* total packets (including bad) between 256
+                                  and 511 octets */
+       u32 txpkts512;          /* total packets (including bad) between 512
+                                  and 1023 octets */
+       u32 txpkts1024;         /* total packets (including bad) between 1024
+                                  and 1518 octets */
+       u32 txpktsjumbo;        /* total packets (including bad) between 1024
+                                  and MAXLength octets */
+} __attribute__ ((packed)) ucc_geth_tx_firmware_statistics_pram_t;
+
+typedef struct ucc_geth_rx_firmware_statistics_pram {
+       u32 frrxfcser;          /* frames with crc error */
+       u32 fraligner;          /* frames with alignment error */
+       u32 inrangelenrxer;     /* in range length error */
+       u32 outrangelenrxer;    /* out of range length error */
+       u32 frtoolong;          /* frame too long */
+       u32 runt;               /* runt */
+       u32 verylongevent;      /* very long event */
+       u32 symbolerror;        /* symbol error */
+       u32 dropbsy;            /* drop because of BD not ready */
+       u8 res0[0x8];
+       u32 mismatchdrop;       /* drop because of MAC filtering (e.g. address
+                                  or type mismatch) */
+       u32 underpkts;          /* total frames less than 64 octets */
+       u32 pkts256;            /* total frames (including bad) between 256 and
+                                  511 octets */
+       u32 pkts512;            /* total frames (including bad) between 512 and
+                                  1023 octets */
+       u32 pkts1024;           /* total frames (including bad) between 1024
+                                  and 1518 octets */
+       u32 pktsjumbo;          /* total frames (including bad) between 1024
+                                  and MAXLength octets */
+       u32 frlossinmacer;      /* frames lost because of internal MAC error
+                                  that is not counted in any other counter */
+       u32 pausefr;            /* pause frames */
+       u8 res1[0x4];
+       u32 removevlan;         /* total frames that had their VLAN tag removed
+                                */
+       u32 replacevlan;        /* total frames that had their VLAN tag
+                                  replaced */
+       u32 insertvlan;         /* total frames that had their VLAN tag
+                                  inserted */
+} __attribute__ ((packed)) ucc_geth_rx_firmware_statistics_pram_t;
+
+typedef struct ucc_geth_rx_interrupt_coalescing_entry {
+       u32 interruptcoalescingmaxvalue;        /* interrupt coalescing max
+                                                  value */
+       u32 interruptcoalescingcounter; /* interrupt coalescing counter,
+                                          initialize to
+                                          interruptcoalescingmaxvalue */
+} __attribute__ ((packed)) ucc_geth_rx_interrupt_coalescing_entry_t;
+
+typedef struct ucc_geth_rx_interrupt_coalescing_table {
+       ucc_geth_rx_interrupt_coalescing_entry_t coalescingentry[NUM_RX_QUEUES];
+                                      /**< interrupt coalescing entry */
+} __attribute__ ((packed)) ucc_geth_rx_interrupt_coalescing_table_t;
+
+typedef struct ucc_geth_rx_prefetched_bds {
+       qe_bd_t bd[NUM_BDS_IN_PREFETCHED_BDS];  /* prefetched bd */
+} __attribute__ ((packed)) ucc_geth_rx_prefetched_bds_t;
+
+typedef struct ucc_geth_rx_bd_queues_entry {
+       u32 bdbaseptr;          /* BD base pointer */
+       u32 bdptr;              /* BD pointer */
+       u32 externalbdbaseptr;  /* external BD base pointer */
+       u32 externalbdptr;      /* external BD pointer */
+} __attribute__ ((packed)) ucc_geth_rx_bd_queues_entry_t;
+
+typedef struct ucc_geth_tx_global_pram {
+       u16 temoder;
+       u8 res0[0x38 - 0x02];
+       u32 sqptr;              /* a base pointer to send queue memory region */
+       u32 schedulerbasepointer;       /* a base pointer to scheduler memory
+                                          region */
+       u32 txrmonbaseptr;      /* base pointer to Tx RMON statistics counter */
+       u32 tstate;             /* tx internal state. High byte contains
+                                  function code */
+       u8 iphoffset[TX_IP_OFFSET_ENTRY_MAX];
+       u32 vtagtable[0x8];     /* 8 4-byte VLAN tags */
+       u32 tqptr;              /* a base pointer to the Tx Queues Memory
+                                  Region */
+       u8 res2[0x80 - 0x74];
+} __attribute__ ((packed)) ucc_geth_tx_global_pram_t;
+
+/* structure representing Extended Filtering Global Parameters in PRAM */
+typedef struct ucc_geth_exf_global_pram {
+       u32 l2pcdptr;           /* individual address filter, high */
+       u8 res0[0x10 - 0x04];
+} __attribute__ ((packed)) ucc_geth_exf_global_pram_t;
+
+typedef struct ucc_geth_rx_global_pram {
+       u32 remoder;            /* ethernet mode reg. */
+       u32 rqptr;              /* base pointer to the Rx Queues Memory Region*/
+       u32 res0[0x1];
+       u8 res1[0x20 - 0xC];
+       u16 typeorlen;          /* cutoff point less than which, type/len field
+                                  is considered length */
+       u8 res2[0x1];
+       u8 rxgstpack;           /* acknowledgement on GRACEFUL STOP RX command*/
+       u32 rxrmonbaseptr;      /* base pointer to Rx RMON statistics counter */
+       u8 res3[0x30 - 0x28];
+       u32 intcoalescingptr;   /* Interrupt coalescing table pointer */
+       u8 res4[0x36 - 0x34];
+       u8 rstate;              /* rx internal state. High byte contains
+                                  function code */
+       u8 res5[0x46 - 0x37];
+       u16 mrblr;              /* max receive buffer length reg. */
+       u32 rbdqptr;            /* base pointer to RxBD parameter table
+                                  description */
+       u16 mflr;               /* max frame length reg. */
+       u16 minflr;             /* min frame length reg. */
+       u16 maxd1;              /* max dma1 length reg. */
+       u16 maxd2;              /* max dma2 length reg. */
+       u32 ecamptr;            /* external CAM address */
+       u32 l2qt;               /* VLAN priority mapping table. */
+       u32 l3qt[0x8];          /* IP priority mapping table. */
+       u16 vlantype;           /* vlan type */
+       u16 vlantci;            /* default vlan tci */
+       u8 addressfiltering[64];        /* address filtering data structure */
+       u32 exfGlobalParam;     /* base address for extended filtering global
+                                  parameters */
+       u8 res6[0x100 - 0xC4];  /* Initialize to zero */
+} __attribute__ ((packed)) ucc_geth_rx_global_pram_t;
+
+#define GRACEFUL_STOP_ACKNOWLEDGE_RX            0x01
+
+/* structure representing InitEnet command */
+typedef struct ucc_geth_init_pram {
+       u8 resinit1;
+       u8 resinit2;
+       u8 resinit3;
+       u8 resinit4;
+       u16 resinit5;
+       u8 res1[0x1];
+       u8 largestexternallookupkeysize;
+       u32 rgftgfrxglobal;
+       u32 rxthread[ENET_INIT_PARAM_MAX_ENTRIES_RX];   /* rx threads */
+       u8 res2[0x38 - 0x30];
+       u32 txglobal;           /* tx global */
+       u32 txthread[ENET_INIT_PARAM_MAX_ENTRIES_TX];   /* tx threads */
+       u8 res3[0x1];
+} __attribute__ ((packed)) ucc_geth_init_pram_t;
+
+#define ENET_INIT_PARAM_RGF_SHIFT               (32 - 4)
+#define ENET_INIT_PARAM_TGF_SHIFT               (32 - 8)
+
+#define ENET_INIT_PARAM_RISC_MASK               0x0000003f
+#define ENET_INIT_PARAM_PTR_MASK                0x00ffffc0
+#define ENET_INIT_PARAM_SNUM_MASK               0xff000000
+#define ENET_INIT_PARAM_SNUM_SHIFT              24
+
+#define ENET_INIT_PARAM_MAGIC_RES_INIT1         0x06
+#define ENET_INIT_PARAM_MAGIC_RES_INIT2         0x30
+#define ENET_INIT_PARAM_MAGIC_RES_INIT3         0xff
+#define ENET_INIT_PARAM_MAGIC_RES_INIT4         0x00
+#define ENET_INIT_PARAM_MAGIC_RES_INIT5         0x0400
+
+/* structure representing 82xx Address Filtering Enet Address in PRAM */
+typedef struct ucc_geth_82xx_enet_address {
+       u8 res1[0x2];
+       u16 h;                  /* address (MSB) */
+       u16 m;                  /* address */
+       u16 l;                  /* address (LSB) */
+} __attribute__ ((packed)) ucc_geth_82xx_enet_address_t;
+
+/* structure representing 82xx Address Filtering PRAM */
+typedef struct ucc_geth_82xx_address_filtering_pram {
+       u32 iaddr_h;            /* individual address filter, high */
+       u32 iaddr_l;            /* individual address filter, low */
+       u32 gaddr_h;            /* group address filter, high */
+       u32 gaddr_l;            /* group address filter, low */
+       ucc_geth_82xx_enet_address_t taddr;
+       ucc_geth_82xx_enet_address_t paddr[NUM_OF_PADDRS];
+       u8 res0[0x40 - 0x38];
+} __attribute__ ((packed)) ucc_geth_82xx_address_filtering_pram_t;
+
+/* GETH Tx firmware statistics structure, used when calling
+   UCC_GETH_GetStatistics. */
+typedef struct ucc_geth_tx_firmware_statistics {
+       u32 sicoltx;            /* single collision */
+       u32 mulcoltx;           /* multiple collision */
+       u32 latecoltxfr;        /* late collision */
+       u32 frabortduecol;      /* frames aborted due to transmit collision */
+       u32 frlostinmactxer;    /* frames lost due to internal MAC error
+                                  transmission that are not counted on any
+                                  other counter */
+       u32 carriersenseertx;   /* carrier sense error */
+       u32 frtxok;             /* frames transmitted OK */
+       u32 txfrexcessivedefer; /* frames with defferal time greater than
+                                  specified threshold */
+       u32 txpkts256;          /* total packets (including bad) between 256
+                                  and 511 octets */
+       u32 txpkts512;          /* total packets (including bad) between 512
+                                  and 1023 octets */
+       u32 txpkts1024;         /* total packets (including bad) between 1024
+                                  and 1518 octets */
+       u32 txpktsjumbo;        /* total packets (including bad) between 1024
+                                  and MAXLength octets */
+} __attribute__ ((packed)) ucc_geth_tx_firmware_statistics_t;
+
+/* GETH Rx firmware statistics structure, used when calling
+   UCC_GETH_GetStatistics. */
+typedef struct ucc_geth_rx_firmware_statistics {
+       u32 frrxfcser;          /* frames with crc error */
+       u32 fraligner;          /* frames with alignment error */
+       u32 inrangelenrxer;     /* in range length error */
+       u32 outrangelenrxer;    /* out of range length error */
+       u32 frtoolong;          /* frame too long */
+       u32 runt;               /* runt */
+       u32 verylongevent;      /* very long event */
+       u32 symbolerror;        /* symbol error */
+       u32 dropbsy;            /* drop because of BD not ready */
+       u8 res0[0x8];
+       u32 mismatchdrop;       /* drop because of MAC filtering (e.g. address
+                                  or type mismatch) */
+       u32 underpkts;          /* total frames less than 64 octets */
+       u32 pkts256;            /* total frames (including bad) between 256 and
+                                  511 octets */
+       u32 pkts512;            /* total frames (including bad) between 512 and
+                                  1023 octets */
+       u32 pkts1024;           /* total frames (including bad) between 1024
+                                  and 1518 octets */
+       u32 pktsjumbo;          /* total frames (including bad) between 1024
+                                  and MAXLength octets */
+       u32 frlossinmacer;      /* frames lost because of internal MAC error
+                                  that is not counted in any other counter */
+       u32 pausefr;            /* pause frames */
+       u8 res1[0x4];
+       u32 removevlan;         /* total frames that had their VLAN tag removed
+                                */
+       u32 replacevlan;        /* total frames that had their VLAN tag
+                                  replaced */
+       u32 insertvlan;         /* total frames that had their VLAN tag
+                                  inserted */
+} __attribute__ ((packed)) ucc_geth_rx_firmware_statistics_t;
+
+/* GETH hardware statistics structure, used when calling
+   UCC_GETH_GetStatistics. */
+typedef struct ucc_geth_hardware_statistics {
+       u32 tx64;               /* Total number of frames (including bad
+                                  frames) transmitted that were exactly of the
+                                  minimal length (64 for un tagged, 68 for
+                                  tagged, or with length exactly equal to the
+                                  parameter MINLength */
+       u32 tx127;              /* Total number of frames (including bad
+                                  frames) transmitted that were between
+                                  MINLength (Including FCS length==4) and 127
+                                  octets */
+       u32 tx255;              /* Total number of frames (including bad
+                                  frames) transmitted that were between 128
+                                  (Including FCS length==4) and 255 octets */
+       u32 rx64;               /* Total number of frames received including
+                                  bad frames that were exactly of the mninimal
+                                  length (64 bytes) */
+       u32 rx127;              /* Total number of frames (including bad
+                                  frames) received that were between MINLength
+                                  (Including FCS length==4) and 127 octets */
+       u32 rx255;              /* Total number of frames (including bad
+                                  frames) received that were between 128
+                                  (Including FCS length==4) and 255 octets */
+       u32 txok;               /* Total number of octets residing in frames
+                                  that where involved in succesfull
+                                  transmission */
+       u16 txcf;               /* Total number of PAUSE control frames
+                                  transmitted by this MAC */
+       u32 tmca;               /* Total number of frames that were transmitted
+                                  succesfully with the group address bit set
+                                  that are not broadcast frames */
+       u32 tbca;               /* Total number of frames transmitted
+                                  succesfully that had destination address
+                                  field equal to the broadcast address */
+       u32 rxfok;              /* Total number of frames received OK */
+       u32 rxbok;              /* Total number of octets received OK */
+       u32 rbyt;               /* Total number of octets received including
+                                  octets in bad frames. Must be implemented in
+                                  HW because it includes octets in frames that
+                                  never even reach the UCC */
+       u32 rmca;               /* Total number of frames that were received
+                                  succesfully with the group address bit set
+                                  that are not broadcast frames */
+       u32 rbca;               /* Total number of frames received succesfully
+                                  that had destination address equal to the
+                                  broadcast address */
+} __attribute__ ((packed)) ucc_geth_hardware_statistics_t;
+
+/* UCC GETH Tx errors returned via TxConf callback */
+#define TX_ERRORS_DEF      0x0200
+#define TX_ERRORS_EXDEF    0x0100
+#define TX_ERRORS_LC       0x0080
+#define TX_ERRORS_RL       0x0040
+#define TX_ERRORS_RC_MASK  0x003C
+#define TX_ERRORS_RC_SHIFT 2
+#define TX_ERRORS_UN       0x0002
+#define TX_ERRORS_CSL      0x0001
+
+/* UCC GETH Rx errors returned via RxStore callback */
+#define RX_ERRORS_CMR      0x0200
+#define RX_ERRORS_M        0x0100
+#define RX_ERRORS_BC       0x0080
+#define RX_ERRORS_MC       0x0040
+
+/* Transmit BD. These are in addition to values defined in uccf. */
+#define T_VID      0x003c0000  /* insert VLAN id index mask. */
+#define T_DEF      (((u32) TX_ERRORS_DEF     ) << 16)
+#define T_EXDEF    (((u32) TX_ERRORS_EXDEF   ) << 16)
+#define T_LC       (((u32) TX_ERRORS_LC      ) << 16)
+#define T_RL       (((u32) TX_ERRORS_RL      ) << 16)
+#define T_RC_MASK  (((u32) TX_ERRORS_RC_MASK ) << 16)
+#define T_UN       (((u32) TX_ERRORS_UN      ) << 16)
+#define T_CSL      (((u32) TX_ERRORS_CSL     ) << 16)
+#define T_ERRORS_REPORT  (T_DEF | T_EXDEF | T_LC | T_RL | T_RC_MASK \
+               | T_UN | T_CSL) /* transmit errors to report */
+
+/* Receive BD. These are in addition to values defined in uccf. */
+#define R_LG    0x00200000     /* Frame length violation.  */
+#define R_NO    0x00100000     /* Non-octet aligned frame.  */
+#define R_SH    0x00080000     /* Short frame.  */
+#define R_CR    0x00040000     /* CRC error.  */
+#define R_OV    0x00020000     /* Overrun.  */
+#define R_IPCH  0x00010000     /* IP checksum check failed. */
+#define R_CMR   (((u32) RX_ERRORS_CMR  ) << 16)
+#define R_M     (((u32) RX_ERRORS_M    ) << 16)
+#define R_BC    (((u32) RX_ERRORS_BC   ) << 16)
+#define R_MC    (((u32) RX_ERRORS_MC   ) << 16)
+#define R_ERRORS_REPORT (R_CMR | R_M | R_BC | R_MC)    /* receive errors to
+                                                          report */
+#define R_ERRORS_FATAL  (R_LG  | R_NO | R_SH | R_CR | \
+               R_OV | R_IPCH)  /* receive errors to discard */
+
+/* Alignments */
+#define UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT      256
+#define UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT       128
+#define UCC_GETH_THREAD_RX_PRAM_ALIGNMENT       128
+#define UCC_GETH_THREAD_TX_PRAM_ALIGNMENT       64
+#define UCC_GETH_THREAD_DATA_ALIGNMENT          256    /* spec gives values
+                                                          based on num of
+                                                          threads, but always
+                                                          using the maximum is
+                                                          easier */
+#define UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT 32
+#define UCC_GETH_SCHEDULER_ALIGNMENT           4       /* This is a guess */
+#define UCC_GETH_TX_STATISTICS_ALIGNMENT       4       /* This is a guess */
+#define UCC_GETH_RX_STATISTICS_ALIGNMENT       4       /* This is a guess */
+#define UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT     4       /* This is a
+                                                                  guess */
+#define UCC_GETH_RX_BD_QUEUES_ALIGNMENT                8       /* This is a guess */
+#define UCC_GETH_RX_PREFETCHED_BDS_ALIGNMENT   128     /* This is a guess */
+#define UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT 4   /* This
+                                                                          is a
+                                                                          guess
+                                                                        */
+#define UCC_GETH_RX_BD_RING_ALIGNMENT          32
+#define UCC_GETH_TX_BD_RING_ALIGNMENT          32
+#define UCC_GETH_MRBLR_ALIGNMENT               128
+#define UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT     4
+#define UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT      32
+#define UCC_GETH_RX_DATA_BUF_ALIGNMENT         64
+
+#define UCC_GETH_TAD_EF                         0x80
+#define UCC_GETH_TAD_V                          0x40
+#define UCC_GETH_TAD_REJ                        0x20
+#define UCC_GETH_TAD_VTAG_OP_RIGHT_SHIFT        2
+#define UCC_GETH_TAD_VTAG_OP_SHIFT              6
+#define UCC_GETH_TAD_V_NON_VTAG_OP              0x20
+#define UCC_GETH_TAD_RQOS_SHIFT                 0
+#define UCC_GETH_TAD_V_PRIORITY_SHIFT           5
+#define UCC_GETH_TAD_CFI                        0x10
+
+#define UCC_GETH_VLAN_PRIORITY_MAX              8
+#define UCC_GETH_IP_PRIORITY_MAX                64
+#define UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX        8
+#define UCC_GETH_RX_BD_RING_SIZE_MIN            8
+#define UCC_GETH_TX_BD_RING_SIZE_MIN            2
+
+#define UCC_GETH_SIZE_OF_BD                     QE_SIZEOF_BD
+
+/* Driver definitions */
+#define TX_BD_RING_LEN                          0x10
+#define RX_BD_RING_LEN                          0x10
+#define UCC_GETH_DEV_WEIGHT                     TX_BD_RING_LEN
+
+#define TX_RING_MOD_MASK(size)                  (size-1)
+#define RX_RING_MOD_MASK(size)                  (size-1)
+
+#define ENET_NUM_OCTETS_PER_ADDRESS             6
+#define ENET_GROUP_ADDR                         0x01   /* Group address mask
+                                                          for ethernet
+                                                          addresses */
+
+#define TX_TIMEOUT                              (1*HZ)
+#define SKB_ALLOC_TIMEOUT                       100000
+#define PHY_INIT_TIMEOUT                        100000
+#define PHY_CHANGE_TIME                         2
+
+/* Fast Ethernet (10/100 Mbps) */
+#define UCC_GETH_URFS_INIT                      512    /* Rx virtual FIFO size
+                                                        */
+#define UCC_GETH_URFET_INIT                     256    /* 1/2 urfs */
+#define UCC_GETH_URFSET_INIT                    384    /* 3/4 urfs */
+#define UCC_GETH_UTFS_INIT                      512    /* Tx virtual FIFO size
+                                                        */
+#define UCC_GETH_UTFET_INIT                     256    /* 1/2 utfs */
+#define UCC_GETH_UTFTT_INIT                     128
+/* Gigabit Ethernet (1000 Mbps) */
+#define UCC_GETH_URFS_GIGA_INIT                 4096/*2048*/   /* Rx virtual
+                                                                  FIFO size */
+#define UCC_GETH_URFET_GIGA_INIT                2048/*1024*/   /* 1/2 urfs */
+#define UCC_GETH_URFSET_GIGA_INIT               3072/*1536*/   /* 3/4 urfs */
+#define UCC_GETH_UTFS_GIGA_INIT                 8192/*2048*/   /* Tx virtual
+                                                                  FIFO size */
+#define UCC_GETH_UTFET_GIGA_INIT                4096/*1024*/   /* 1/2 utfs */
+#define UCC_GETH_UTFTT_GIGA_INIT                0x400/*0x40*/  /* */
+
+#define UCC_GETH_REMODER_INIT                   0      /* bits that must be
+                                                          set */
+#define UCC_GETH_TEMODER_INIT                   0xC000 /* bits that must */
+#define UCC_GETH_UPSMR_INIT                     (UPSMR_RES1)   /* Start value
+                                                                  for this
+                                                                  register */
+#define UCC_GETH_MACCFG1_INIT                   0
+#define UCC_GETH_MACCFG2_INIT                   (MACCFG2_RESERVED_1)
+#define UCC_GETH_MIIMCFG_MNGMNT_CLC_DIV_INIT    \
+                               (MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112)
+
+/* Ethernet speed */
+typedef enum enet_speed {
+       ENET_SPEED_10BT,        /* 10 Base T */
+       ENET_SPEED_100BT,       /* 100 Base T */
+       ENET_SPEED_1000BT       /* 1000 Base T */
+} enet_speed_e;
+
+/* Ethernet Address Type. */
+typedef enum enet_addr_type {
+       ENET_ADDR_TYPE_INDIVIDUAL,
+       ENET_ADDR_TYPE_GROUP,
+       ENET_ADDR_TYPE_BROADCAST
+} enet_addr_type_e;
+
+/* TBI / MII Set Register */
+typedef enum enet_tbi_mii_reg {
+       ENET_TBI_MII_CR = 0x00, /* Control (CR ) */
+       ENET_TBI_MII_SR = 0x01, /* Status (SR ) */
+       ENET_TBI_MII_ANA = 0x04,        /* AN advertisement (ANA ) */
+       ENET_TBI_MII_ANLPBPA = 0x05,    /* AN link partner base page ability
+                                          (ANLPBPA) */
+       ENET_TBI_MII_ANEX = 0x06,       /* AN expansion (ANEX ) */
+       ENET_TBI_MII_ANNPT = 0x07,      /* AN next page transmit (ANNPT ) */
+       ENET_TBI_MII_ANLPANP = 0x08,    /* AN link partner ability next page
+                                          (ANLPANP) */
+       ENET_TBI_MII_EXST = 0x0F,       /* Extended status (EXST ) */
+       ENET_TBI_MII_JD = 0x10, /* Jitter diagnostics (JD ) */
+       ENET_TBI_MII_TBICON = 0x11      /* TBI control (TBICON ) */
+} enet_tbi_mii_reg_e;
+
+/* UCC GETH 82xx Ethernet Address Recognition Location */
+typedef enum ucc_geth_enet_address_recognition_location {
+       UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_STATION_ADDRESS,/* station
+                                                                     address */
+       UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR_FIRST, /* additional
+                                                                  station
+                                                                  address
+                                                                  paddr1 */
+       UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR2,      /* additional
+                                                                  station
+                                                                  address
+                                                                  paddr2 */
+       UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR3,      /* additional
+                                                                  station
+                                                                  address
+                                                                  paddr3 */
+       UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR_LAST,  /* additional
+                                                                  station
+                                                                  address
+                                                                  paddr4 */
+       UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH,  /* group hash */
+       UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH /* individual
+                                                                     hash */
+} ucc_geth_enet_address_recognition_location_e;
+
+/* UCC GETH vlan operation tagged */
+typedef enum ucc_geth_vlan_operation_tagged {
+       UCC_GETH_VLAN_OPERATION_TAGGED_NOP = 0x0,       /* Tagged - nop */
+       UCC_GETH_VLAN_OPERATION_TAGGED_REPLACE_VID_PORTION_OF_Q_TAG
+               = 0x1,  /* Tagged - replace vid portion of q tag */
+       UCC_GETH_VLAN_OPERATION_TAGGED_IF_VID0_REPLACE_VID_WITH_DEFAULT_VALUE
+               = 0x2,  /* Tagged - if vid0 replace vid with default value  */
+       UCC_GETH_VLAN_OPERATION_TAGGED_EXTRACT_Q_TAG_FROM_FRAME
+               = 0x3   /* Tagged - extract q tag from frame */
+} ucc_geth_vlan_operation_tagged_e;
+
+/* UCC GETH vlan operation non-tagged */
+typedef enum ucc_geth_vlan_operation_non_tagged {
+       UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP = 0x0,   /* Non tagged - nop */
+       UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT = 0x1   /* Non tagged -
+                                                                  q tag insert
+                                                                */
+} ucc_geth_vlan_operation_non_tagged_e;
+
+/* UCC GETH Rx Quality of Service Mode */
+typedef enum ucc_geth_qos_mode {
+       UCC_GETH_QOS_MODE_DEFAULT = 0x0,        /* default queue */
+       UCC_GETH_QOS_MODE_QUEUE_NUM_FROM_L2_CRITERIA = 0x1,     /* queue
+                                                                  determined
+                                                                  by L2
+                                                                  criteria */
+       UCC_GETH_QOS_MODE_QUEUE_NUM_FROM_L3_CRITERIA = 0x2      /* queue
+                                                                  determined
+                                                                  by L3
+                                                                  criteria */
+} ucc_geth_qos_mode_e;
+
+/* UCC GETH Statistics Gathering Mode - These are bit flags, 'or' them together
+   for combined functionality */
+typedef enum ucc_geth_statistics_gathering_mode {
+       UCC_GETH_STATISTICS_GATHERING_MODE_NONE = 0x00000000,   /* No
+                                                                  statistics
+                                                                  gathering */
+       UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE = 0x00000001,/* Enable
+                                                                   hardware
+                                                                   statistics
+                                                                   gathering
+                                                                 */
+       UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX = 0x00000004,/*Enable
+                                                                     firmware
+                                                                     tx
+                                                                     statistics
+                                                                     gathering
+                                                                    */
+       UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX = 0x00000008/* Enable
+                                                                     firmware
+                                                                     rx
+                                                                     statistics
+                                                                     gathering
+                                                                   */
+} ucc_geth_statistics_gathering_mode_e;
+
+/* UCC GETH Pad and CRC Mode - Note, Padding without CRC is not possible */
+typedef enum ucc_geth_maccfg2_pad_and_crc_mode {
+       UCC_GETH_PAD_AND_CRC_MODE_NONE
+               = MACCFG2_PAD_AND_CRC_MODE_NONE,        /* Neither Padding
+                                                          short frames
+                                                          nor CRC */
+       UCC_GETH_PAD_AND_CRC_MODE_CRC_ONLY
+               = MACCFG2_PAD_AND_CRC_MODE_CRC_ONLY,    /* Append
+                                                          CRC only */
+       UCC_GETH_PAD_AND_CRC_MODE_PAD_AND_CRC =
+           MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC
+} ucc_geth_maccfg2_pad_and_crc_mode_e;
+
+/* UCC GETH upsmr Flow Control Mode */
+typedef enum ucc_geth_flow_control_mode {
+       UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE = 0x00000000,    /* No automatic
+                                                                  flow control
+                                                                */
+       UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_PAUSE_WHEN_EMERGENCY
+               = 0x00004000    /* Send pause frame when RxFIFO reaches its
+                                  emergency threshold */
+} ucc_geth_flow_control_mode_e;
+
+/* UCC GETH number of threads */
+typedef enum ucc_geth_num_of_threads {
+       UCC_GETH_NUM_OF_THREADS_1 = 0x1,        /* 1 */
+       UCC_GETH_NUM_OF_THREADS_2 = 0x2,        /* 2 */
+       UCC_GETH_NUM_OF_THREADS_4 = 0x0,        /* 4 */
+       UCC_GETH_NUM_OF_THREADS_6 = 0x3,        /* 6 */
+       UCC_GETH_NUM_OF_THREADS_8 = 0x4 /* 8 */
+} ucc_geth_num_of_threads_e;
+
+/* UCC GETH number of station addresses */
+typedef enum ucc_geth_num_of_station_addresses {
+       UCC_GETH_NUM_OF_STATION_ADDRESSES_1,    /* 1 */
+       UCC_GETH_NUM_OF_STATION_ADDRESSES_5     /* 5 */
+} ucc_geth_num_of_station_addresses_e;
+
+typedef u8 enet_addr_t[ENET_NUM_OCTETS_PER_ADDRESS];
+
+/* UCC GETH 82xx Ethernet Address Container */
+typedef struct enet_addr_container {
+       enet_addr_t address;    /* ethernet address */
+       ucc_geth_enet_address_recognition_location_e location;  /* location in
+                                                                  82xx address
+                                                                  recognition
+                                                                  hardware */
+       struct list_head node;
+} enet_addr_container_t;
+
+#define ENET_ADDR_CONT_ENTRY(ptr) list_entry(ptr, enet_addr_container_t, node)
+
+/* UCC GETH Termination Action Descriptor (TAD) structure. */
+typedef struct ucc_geth_tad_params {
+       int rx_non_dynamic_extended_features_mode;
+       int reject_frame;
+       ucc_geth_vlan_operation_tagged_e vtag_op;
+       ucc_geth_vlan_operation_non_tagged_e vnontag_op;
+       ucc_geth_qos_mode_e rqos;
+       u8 vpri;
+       u16 vid;
+} ucc_geth_tad_params_t;
+
+/* GETH protocol initialization structure */
+typedef struct ucc_geth_info {
+       ucc_fast_info_t uf_info;
+       u8 numQueuesTx;
+       u8 numQueuesRx;
+       int ipCheckSumCheck;
+       int ipCheckSumGenerate;
+       int rxExtendedFiltering;
+       u32 extendedFilteringChainPointer;
+       u16 typeorlen;
+       int dynamicMaxFrameLength;
+       int dynamicMinFrameLength;
+       u8 nonBackToBackIfgPart1;
+       u8 nonBackToBackIfgPart2;
+       u8 miminumInterFrameGapEnforcement;
+       u8 backToBackInterFrameGap;
+       int ipAddressAlignment;
+       int lengthCheckRx;
+       u32 mblinterval;
+       u16 nortsrbytetime;
+       u8 fracsiz;
+       u8 strictpriorityq;
+       u8 txasap;
+       u8 extrabw;
+       int miiPreambleSupress;
+       u8 altBebTruncation;
+       int altBeb;
+       int backPressureNoBackoff;
+       int noBackoff;
+       int excessDefer;
+       u8 maxRetransmission;
+       u8 collisionWindow;
+       int pro;
+       int cap;
+       int rsh;
+       int rlpb;
+       int cam;
+       int bro;
+       int ecm;
+       int receiveFlowControl;
+       u8 maxGroupAddrInHash;
+       u8 maxIndAddrInHash;
+       u8 prel;
+       u16 maxFrameLength;
+       u16 minFrameLength;
+       u16 maxD1Length;
+       u16 maxD2Length;
+       u16 vlantype;
+       u16 vlantci;
+       u32 ecamptr;
+       u32 eventRegMask;
+       u16 pausePeriod;
+       u16 extensionField;
+       u8 phy_address;
+       u32 board_flags;
+       u32 phy_interrupt;
+       u8 weightfactor[NUM_TX_QUEUES];
+       u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES];
+       u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX];
+       u8 l3qt[UCC_GETH_IP_PRIORITY_MAX];
+       u32 vtagtable[UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX];
+       u8 iphoffset[TX_IP_OFFSET_ENTRY_MAX];
+       u16 bdRingLenTx[NUM_TX_QUEUES];
+       u16 bdRingLenRx[NUM_RX_QUEUES];
+       enet_interface_e enet_interface;
+       ucc_geth_num_of_station_addresses_e numStationAddresses;
+        qe_fltr_largest_external_tbl_lookup_key_size_e
+           largestexternallookupkeysize;
+       ucc_geth_statistics_gathering_mode_e statisticsMode;
+       ucc_geth_vlan_operation_tagged_e vlanOperationTagged;
+       ucc_geth_vlan_operation_non_tagged_e vlanOperationNonTagged;
+       ucc_geth_qos_mode_e rxQoSMode;
+       ucc_geth_flow_control_mode_e aufc;
+       ucc_geth_maccfg2_pad_and_crc_mode_e padAndCrc;
+       ucc_geth_num_of_threads_e numThreadsTx;
+       ucc_geth_num_of_threads_e numThreadsRx;
+       qe_risc_allocation_e riscTx;
+       qe_risc_allocation_e riscRx;
+} ucc_geth_info_t;
+
+/* structure representing UCC GETH */
+typedef struct ucc_geth_private {
+       ucc_geth_info_t *ug_info;
+       ucc_fast_private_t *uccf;
+       struct net_device *dev;
+       struct net_device_stats stats;  /* linux network statistics */
+       ucc_geth_t *ug_regs;
+       ucc_geth_init_pram_t *p_init_enet_param_shadow;
+       ucc_geth_exf_global_pram_t *p_exf_glbl_param;
+       u32 exf_glbl_param_offset;
+       ucc_geth_rx_global_pram_t *p_rx_glbl_pram;
+       u32 rx_glbl_pram_offset;
+       ucc_geth_tx_global_pram_t *p_tx_glbl_pram;
+       u32 tx_glbl_pram_offset;
+       ucc_geth_send_queue_mem_region_t *p_send_q_mem_reg;
+       u32 send_q_mem_reg_offset;
+       ucc_geth_thread_data_tx_t *p_thread_data_tx;
+       u32 thread_dat_tx_offset;
+       ucc_geth_thread_data_rx_t *p_thread_data_rx;
+       u32 thread_dat_rx_offset;
+       ucc_geth_scheduler_t *p_scheduler;
+       u32 scheduler_offset;
+       ucc_geth_tx_firmware_statistics_pram_t *p_tx_fw_statistics_pram;
+       u32 tx_fw_statistics_pram_offset;
+       ucc_geth_rx_firmware_statistics_pram_t *p_rx_fw_statistics_pram;
+       u32 rx_fw_statistics_pram_offset;
+       ucc_geth_rx_interrupt_coalescing_table_t *p_rx_irq_coalescing_tbl;
+       u32 rx_irq_coalescing_tbl_offset;
+       ucc_geth_rx_bd_queues_entry_t *p_rx_bd_qs_tbl;
+       u32 rx_bd_qs_tbl_offset;
+       u8 *p_tx_bd_ring[NUM_TX_QUEUES];
+       u32 tx_bd_ring_offset[NUM_TX_QUEUES];
+       u8 *p_rx_bd_ring[NUM_RX_QUEUES];
+       u32 rx_bd_ring_offset[NUM_RX_QUEUES];
+       u8 *confBd[NUM_TX_QUEUES];
+       u8 *txBd[NUM_TX_QUEUES];
+       u8 *rxBd[NUM_RX_QUEUES];
+       int badFrame[NUM_RX_QUEUES];
+       u16 cpucount[NUM_TX_QUEUES];
+       volatile u16 *p_cpucount[NUM_TX_QUEUES];
+       int indAddrRegUsed[NUM_OF_PADDRS];
+       enet_addr_t paddr[NUM_OF_PADDRS];
+       u8 numGroupAddrInHash;
+       u8 numIndAddrInHash;
+       u8 numIndAddrInReg;
+       int rx_extended_features;
+       int rx_non_dynamic_extended_features;
+       struct list_head conf_skbs;
+       struct list_head group_hash_q;
+       struct list_head ind_hash_q;
+       u32 saved_uccm;
+       spinlock_t lock;
+       /* pointers to arrays of skbuffs for tx and rx */
+       struct sk_buff **tx_skbuff[NUM_TX_QUEUES];
+       struct sk_buff **rx_skbuff[NUM_RX_QUEUES];
+       /* indices pointing to the next free sbk in skb arrays */
+       u16 skb_curtx[NUM_TX_QUEUES];
+       u16 skb_currx[NUM_RX_QUEUES];
+       /* index of the first skb which hasn't been transmitted yet. */
+       u16 skb_dirtytx[NUM_TX_QUEUES];
+
+       struct work_struct tq;
+       struct timer_list phy_info_timer;
+       struct ugeth_mii_info *mii_info;
+       int oldspeed;
+       int oldduplex;
+       int oldlink;
+} ucc_geth_private_t;
+
+#endif                         /* __UCC_GETH_H__ */
diff --git a/drivers/net/ucc_geth_phy.c b/drivers/net/ucc_geth_phy.c
new file mode 100644 (file)
index 0000000..f91028c
--- /dev/null
@@ -0,0 +1,801 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ *
+ * Author: Shlomi Gridish <gridish@freescale.com>
+ *
+ * Description:
+ * UCC GETH Driver -- PHY handling
+ *
+ * Changelog:
+ * Jun 28, 2006 Li Yang <LeoLi@freescale.com>
+ * - Rearrange code and style fixes
+ *
+ * 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/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/crc32.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "ucc_geth.h"
+#include "ucc_geth_phy.h"
+#include <platforms/83xx/mpc8360e_pb.h>
+
+#define ugphy_printk(level, format, arg...)  \
+        printk(level format "\n", ## arg)
+
+#define ugphy_dbg(format, arg...)            \
+        ugphy_printk(KERN_DEBUG, format , ## arg)
+#define ugphy_err(format, arg...)            \
+        ugphy_printk(KERN_ERR, format , ## arg)
+#define ugphy_info(format, arg...)           \
+        ugphy_printk(KERN_INFO, format , ## arg)
+#define ugphy_warn(format, arg...)           \
+        ugphy_printk(KERN_WARNING, format , ## arg)
+
+#ifdef UGETH_VERBOSE_DEBUG
+#define ugphy_vdbg ugphy_dbg
+#else
+#define ugphy_vdbg(fmt, args...) do { } while (0)
+#endif                         /* UGETH_VERBOSE_DEBUG */
+
+static void config_genmii_advert(struct ugeth_mii_info *mii_info);
+static void genmii_setup_forced(struct ugeth_mii_info *mii_info);
+static void genmii_restart_aneg(struct ugeth_mii_info *mii_info);
+static int gbit_config_aneg(struct ugeth_mii_info *mii_info);
+static int genmii_config_aneg(struct ugeth_mii_info *mii_info);
+static int genmii_update_link(struct ugeth_mii_info *mii_info);
+static int genmii_read_status(struct ugeth_mii_info *mii_info);
+u16 phy_read(struct ugeth_mii_info *mii_info, u16 regnum);
+void phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val);
+
+static u8 *bcsr_regs = NULL;
+
+/* Write value to the PHY for this device to the register at regnum, */
+/* waiting until the write is done before it returns.  All PHY */
+/* configuration has to be done through the TSEC1 MIIM regs */
+void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       ucc_mii_mng_t *mii_regs;
+       enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
+       u32 tmp_reg;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       spin_lock_irq(&ugeth->lock);
+
+       mii_regs = ugeth->mii_info->mii_regs;
+
+       /* Set this UCC to be the master of the MII managment */
+       ucc_set_qe_mux_mii_mng(ugeth->ug_info->uf_info.ucc_num);
+
+       /* Stop the MII management read cycle */
+       out_be32(&mii_regs->miimcom, 0);
+       /* Setting up the MII Mangement Address Register */
+       tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
+       out_be32(&mii_regs->miimadd, tmp_reg);
+
+       /* Setting up the MII Mangement Control Register with the value */
+       out_be32(&mii_regs->miimcon, (u32) value);
+
+       /* Wait till MII management write is complete */
+       while ((in_be32(&mii_regs->miimind)) & MIIMIND_BUSY)
+               cpu_relax();
+
+       spin_unlock_irq(&ugeth->lock);
+
+       udelay(10000);
+}
+
+/* Reads from register regnum in the PHY for device dev, */
+/* returning the value.  Clears miimcom first.  All PHY */
+/* configuration has to be done through the TSEC1 MIIM regs */
+int read_phy_reg(struct net_device *dev, int mii_id, int regnum)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       ucc_mii_mng_t *mii_regs;
+       enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
+       u32 tmp_reg;
+       u16 value;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       spin_lock_irq(&ugeth->lock);
+
+       mii_regs = ugeth->mii_info->mii_regs;
+
+       /* Setting up the MII Mangement Address Register */
+       tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
+       out_be32(&mii_regs->miimadd, tmp_reg);
+
+       /* Perform an MII management read cycle */
+       out_be32(&mii_regs->miimcom, MIIMCOM_READ_CYCLE);
+
+       /* Wait till MII management write is complete */
+       while ((in_be32(&mii_regs->miimind)) & MIIMIND_BUSY)
+               cpu_relax();
+
+       udelay(10000);
+
+       /* Read MII management status  */
+       value = (u16) in_be32(&mii_regs->miimstat);
+       out_be32(&mii_regs->miimcom, 0);
+       if (value == 0xffff)
+               ugphy_warn("read wrong value : mii_id %d,mii_reg %d, base %08x",
+                          mii_id, mii_reg, (u32) & (mii_regs->miimcfg));
+
+       spin_unlock_irq(&ugeth->lock);
+
+       return (value);
+}
+
+void mii_clear_phy_interrupt(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       if (mii_info->phyinfo->ack_interrupt)
+               mii_info->phyinfo->ack_interrupt(mii_info);
+}
+
+void mii_configure_phy_interrupt(struct ugeth_mii_info *mii_info,
+                                u32 interrupts)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       mii_info->interrupts = interrupts;
+       if (mii_info->phyinfo->config_intr)
+               mii_info->phyinfo->config_intr(mii_info);
+}
+
+/* Writes MII_ADVERTISE with the appropriate values, after
+ * sanitizing advertise to make sure only supported features
+ * are advertised
+ */
+static void config_genmii_advert(struct ugeth_mii_info *mii_info)
+{
+       u32 advertise;
+       u16 adv;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Only allow advertising what this PHY supports */
+       mii_info->advertising &= mii_info->phyinfo->features;
+       advertise = mii_info->advertising;
+
+       /* Setup standard advertisement */
+       adv = phy_read(mii_info, MII_ADVERTISE);
+       adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+       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;
+       phy_write(mii_info, MII_ADVERTISE, adv);
+}
+
+static void genmii_setup_forced(struct ugeth_mii_info *mii_info)
+{
+       u16 ctrl;
+       u32 features = mii_info->phyinfo->features;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       ctrl = phy_read(mii_info, MII_BMCR);
+
+       ctrl &=
+           ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
+       ctrl |= BMCR_RESET;
+
+       switch (mii_info->speed) {
+       case SPEED_1000:
+               if (features & (SUPPORTED_1000baseT_Half
+                               | SUPPORTED_1000baseT_Full)) {
+                       ctrl |= BMCR_SPEED1000;
+                       break;
+               }
+               mii_info->speed = SPEED_100;
+       case SPEED_100:
+               if (features & (SUPPORTED_100baseT_Half
+                               | SUPPORTED_100baseT_Full)) {
+                       ctrl |= BMCR_SPEED100;
+                       break;
+               }
+               mii_info->speed = SPEED_10;
+       case SPEED_10:
+               if (features & (SUPPORTED_10baseT_Half
+                               | SUPPORTED_10baseT_Full))
+                       break;
+       default:                /* Unsupported speed! */
+               ugphy_err("%s: Bad speed!", mii_info->dev->name);
+               break;
+       }
+
+       phy_write(mii_info, MII_BMCR, ctrl);
+}
+
+/* Enable and Restart Autonegotiation */
+static void genmii_restart_aneg(struct ugeth_mii_info *mii_info)
+{
+       u16 ctl;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       ctl = phy_read(mii_info, MII_BMCR);
+       ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+       phy_write(mii_info, MII_BMCR, ctl);
+}
+
+static int gbit_config_aneg(struct ugeth_mii_info *mii_info)
+{
+       u16 adv;
+       u32 advertise;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       if (mii_info->autoneg) {
+               /* Configure the ADVERTISE register */
+               config_genmii_advert(mii_info);
+               advertise = mii_info->advertising;
+
+               adv = phy_read(mii_info, MII_1000BASETCONTROL);
+               adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
+                        MII_1000BASETCONTROL_HALFDUPLEXCAP);
+               if (advertise & SUPPORTED_1000baseT_Half)
+                       adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
+               if (advertise & SUPPORTED_1000baseT_Full)
+                       adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
+               phy_write(mii_info, MII_1000BASETCONTROL, adv);
+
+               /* Start/Restart aneg */
+               genmii_restart_aneg(mii_info);
+       } else
+               genmii_setup_forced(mii_info);
+
+       return 0;
+}
+
+static int genmii_config_aneg(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       if (mii_info->autoneg) {
+               config_genmii_advert(mii_info);
+               genmii_restart_aneg(mii_info);
+       } else
+               genmii_setup_forced(mii_info);
+
+       return 0;
+}
+
+static int genmii_update_link(struct ugeth_mii_info *mii_info)
+{
+       u16 status;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Do a fake read */
+       phy_read(mii_info, MII_BMSR);
+
+       /* Read link and autonegotiation status */
+       status = phy_read(mii_info, MII_BMSR);
+       if ((status & BMSR_LSTATUS) == 0)
+               mii_info->link = 0;
+       else
+               mii_info->link = 1;
+
+       /* If we are autonegotiating, and not done,
+        * return an error */
+       if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE))
+               return -EAGAIN;
+
+       return 0;
+}
+
+static int genmii_read_status(struct ugeth_mii_info *mii_info)
+{
+       u16 status;
+       int err;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Update the link, but return if there
+        * was an error */
+       err = genmii_update_link(mii_info);
+       if (err)
+               return err;
+
+       if (mii_info->autoneg) {
+               status = phy_read(mii_info, MII_LPA);
+
+               if (status & (LPA_10FULL | LPA_100FULL))
+                       mii_info->duplex = DUPLEX_FULL;
+               else
+                       mii_info->duplex = DUPLEX_HALF;
+               if (status & (LPA_100FULL | LPA_100HALF))
+                       mii_info->speed = SPEED_100;
+               else
+                       mii_info->speed = SPEED_10;
+               mii_info->pause = 0;
+       }
+       /* On non-aneg, we assume what we put in BMCR is the speed,
+        * though magic-aneg shouldn't prevent this case from occurring
+        */
+
+       return 0;
+}
+
+static int marvell_init(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       phy_write(mii_info, 0x14, 0x0cd2);
+       phy_write(mii_info, MII_BMCR,
+                 phy_read(mii_info, MII_BMCR) | BMCR_RESET);
+       msleep(4000);
+
+       return 0;
+}
+
+static int marvell_config_aneg(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* The Marvell PHY has an errata which requires
+        * that certain registers get written in order
+        * to restart autonegotiation */
+       phy_write(mii_info, MII_BMCR, BMCR_RESET);
+
+       phy_write(mii_info, 0x1d, 0x1f);
+       phy_write(mii_info, 0x1e, 0x200c);
+       phy_write(mii_info, 0x1d, 0x5);
+       phy_write(mii_info, 0x1e, 0);
+       phy_write(mii_info, 0x1e, 0x100);
+
+       gbit_config_aneg(mii_info);
+
+       return 0;
+}
+
+static int marvell_read_status(struct ugeth_mii_info *mii_info)
+{
+       u16 status;
+       int err;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Update the link, but return if there
+        * was an error */
+       err = genmii_update_link(mii_info);
+       if (err)
+               return err;
+
+       /* If the link is up, read the speed and duplex */
+       /* If we aren't autonegotiating, assume speeds
+        * are as set */
+       if (mii_info->autoneg && mii_info->link) {
+               int speed;
+               status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
+
+               /* Get the duplexity */
+               if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
+                       mii_info->duplex = DUPLEX_FULL;
+               else
+                       mii_info->duplex = DUPLEX_HALF;
+
+               /* Get the speed */
+               speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
+               switch (speed) {
+               case MII_M1011_PHY_SPEC_STATUS_1000:
+                       mii_info->speed = SPEED_1000;
+                       break;
+               case MII_M1011_PHY_SPEC_STATUS_100:
+                       mii_info->speed = SPEED_100;
+                       break;
+               default:
+                       mii_info->speed = SPEED_10;
+                       break;
+               }
+               mii_info->pause = 0;
+       }
+
+       return 0;
+}
+
+static int marvell_ack_interrupt(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Clear the interrupts by reading the reg */
+       phy_read(mii_info, MII_M1011_IEVENT);
+
+       return 0;
+}
+
+static int marvell_config_intr(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
+               phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
+       else
+               phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
+
+       return 0;
+}
+
+static int cis820x_init(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       phy_write(mii_info, MII_CIS8201_AUX_CONSTAT,
+                 MII_CIS8201_AUXCONSTAT_INIT);
+       phy_write(mii_info, MII_CIS8201_EXT_CON1, MII_CIS8201_EXTCON1_INIT);
+
+       return 0;
+}
+
+static int cis820x_read_status(struct ugeth_mii_info *mii_info)
+{
+       u16 status;
+       int err;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Update the link, but return if there
+        * was an error */
+       err = genmii_update_link(mii_info);
+       if (err)
+               return err;
+
+       /* If the link is up, read the speed and duplex */
+       /* If we aren't autonegotiating, assume speeds
+        * are as set */
+       if (mii_info->autoneg && mii_info->link) {
+               int speed;
+
+               status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
+               if (status & MII_CIS8201_AUXCONSTAT_DUPLEX)
+                       mii_info->duplex = DUPLEX_FULL;
+               else
+                       mii_info->duplex = DUPLEX_HALF;
+
+               speed = status & MII_CIS8201_AUXCONSTAT_SPEED;
+
+               switch (speed) {
+               case MII_CIS8201_AUXCONSTAT_GBIT:
+                       mii_info->speed = SPEED_1000;
+                       break;
+               case MII_CIS8201_AUXCONSTAT_100:
+                       mii_info->speed = SPEED_100;
+                       break;
+               default:
+                       mii_info->speed = SPEED_10;
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static int cis820x_ack_interrupt(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       phy_read(mii_info, MII_CIS8201_ISTAT);
+
+       return 0;
+}
+
+static int cis820x_config_intr(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
+               phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
+       else
+               phy_write(mii_info, MII_CIS8201_IMASK, 0);
+
+       return 0;
+}
+
+#define DM9161_DELAY 10
+
+static int dm9161_read_status(struct ugeth_mii_info *mii_info)
+{
+       u16 status;
+       int err;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Update the link, but return if there
+        * was an error */
+       err = genmii_update_link(mii_info);
+       if (err)
+               return err;
+
+       /* If the link is up, read the speed and duplex */
+       /* If we aren't autonegotiating, assume speeds
+        * are as set */
+       if (mii_info->autoneg && mii_info->link) {
+               status = phy_read(mii_info, MII_DM9161_SCSR);
+               if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
+                       mii_info->speed = SPEED_100;
+               else
+                       mii_info->speed = SPEED_10;
+
+               if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
+                       mii_info->duplex = DUPLEX_FULL;
+               else
+                       mii_info->duplex = DUPLEX_HALF;
+       }
+
+       return 0;
+}
+
+static int dm9161_config_aneg(struct ugeth_mii_info *mii_info)
+{
+       struct dm9161_private *priv = mii_info->priv;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       if (0 == priv->resetdone)
+               return -EAGAIN;
+
+       return 0;
+}
+
+static void dm9161_timer(unsigned long data)
+{
+       struct ugeth_mii_info *mii_info = (struct ugeth_mii_info *)data;
+       struct dm9161_private *priv = mii_info->priv;
+       u16 status = phy_read(mii_info, MII_BMSR);
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       if (status & BMSR_ANEGCOMPLETE) {
+               priv->resetdone = 1;
+       } else
+               mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
+}
+
+static int dm9161_init(struct ugeth_mii_info *mii_info)
+{
+       struct dm9161_private *priv;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Allocate the private data structure */
+       priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL);
+
+       if (NULL == priv)
+               return -ENOMEM;
+
+       mii_info->priv = priv;
+
+       /* Reset is not done yet */
+       priv->resetdone = 0;
+
+       phy_write(mii_info, MII_BMCR,
+                 phy_read(mii_info, MII_BMCR) | BMCR_RESET);
+
+       phy_write(mii_info, MII_BMCR,
+                 phy_read(mii_info, MII_BMCR) & ~BMCR_ISOLATE);
+
+       config_genmii_advert(mii_info);
+       /* Start/Restart aneg */
+       genmii_config_aneg(mii_info);
+
+       /* Start a timer for DM9161_DELAY seconds to wait
+        * for the PHY to be ready */
+       init_timer(&priv->timer);
+       priv->timer.function = &dm9161_timer;
+       priv->timer.data = (unsigned long)mii_info;
+       mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
+
+       return 0;
+}
+
+static void dm9161_close(struct ugeth_mii_info *mii_info)
+{
+       struct dm9161_private *priv = mii_info->priv;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       del_timer_sync(&priv->timer);
+       kfree(priv);
+}
+
+static int dm9161_ack_interrupt(struct ugeth_mii_info *mii_info)
+{
+/* FIXME: This lines are for BUG fixing in the mpc8325.
+Remove this from here when it's fixed */
+       if (bcsr_regs == NULL)
+               bcsr_regs = (u8 *) ioremap(BCSR_PHYS_ADDR, BCSR_SIZE);
+       bcsr_regs[14] |= 0x40;
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Clear the interrupts by reading the reg */
+       phy_read(mii_info, MII_DM9161_INTR);
+
+
+       return 0;
+}
+
+static int dm9161_config_intr(struct ugeth_mii_info *mii_info)
+{
+/* FIXME: This lines are for BUG fixing in the mpc8325.
+Remove this from here when it's fixed */
+       if (bcsr_regs == NULL) {
+               bcsr_regs = (u8 *) ioremap(BCSR_PHYS_ADDR, BCSR_SIZE);
+               bcsr_regs[14] &= ~0x40;
+       }
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
+               phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
+       else
+               phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
+
+       return 0;
+}
+
+/* Cicada 820x */
+static struct phy_info phy_info_cis820x = {
+       .phy_id = 0x000fc440,
+       .name = "Cicada Cis8204",
+       .phy_id_mask = 0x000fffc0,
+       .features = MII_GBIT_FEATURES,
+       .init = &cis820x_init,
+       .config_aneg = &gbit_config_aneg,
+       .read_status = &cis820x_read_status,
+       .ack_interrupt = &cis820x_ack_interrupt,
+       .config_intr = &cis820x_config_intr,
+};
+
+static struct phy_info phy_info_dm9161 = {
+       .phy_id = 0x0181b880,
+       .phy_id_mask = 0x0ffffff0,
+       .name = "Davicom DM9161E",
+       .init = dm9161_init,
+       .config_aneg = dm9161_config_aneg,
+       .read_status = dm9161_read_status,
+       .close = dm9161_close,
+};
+
+static struct phy_info phy_info_dm9161a = {
+       .phy_id = 0x0181b8a0,
+       .phy_id_mask = 0x0ffffff0,
+       .name = "Davicom DM9161A",
+       .features = MII_BASIC_FEATURES,
+       .init = dm9161_init,
+       .config_aneg = dm9161_config_aneg,
+       .read_status = dm9161_read_status,
+       .ack_interrupt = dm9161_ack_interrupt,
+       .config_intr = dm9161_config_intr,
+       .close = dm9161_close,
+};
+
+static struct phy_info phy_info_marvell = {
+       .phy_id = 0x01410c00,
+       .phy_id_mask = 0xffffff00,
+       .name = "Marvell 88E11x1",
+       .features = MII_GBIT_FEATURES,
+       .init = &marvell_init,
+       .config_aneg = &marvell_config_aneg,
+       .read_status = &marvell_read_status,
+       .ack_interrupt = &marvell_ack_interrupt,
+       .config_intr = &marvell_config_intr,
+};
+
+static struct phy_info phy_info_genmii = {
+       .phy_id = 0x00000000,
+       .phy_id_mask = 0x00000000,
+       .name = "Generic MII",
+       .features = MII_BASIC_FEATURES,
+       .config_aneg = genmii_config_aneg,
+       .read_status = genmii_read_status,
+};
+
+static struct phy_info *phy_info[] = {
+       &phy_info_cis820x,
+       &phy_info_marvell,
+       &phy_info_dm9161,
+       &phy_info_dm9161a,
+       &phy_info_genmii,
+       NULL
+};
+
+u16 phy_read(struct ugeth_mii_info *mii_info, u16 regnum)
+{
+       u16 retval;
+       unsigned long flags;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       spin_lock_irqsave(&mii_info->mdio_lock, flags);
+       retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
+       spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
+
+       return retval;
+}
+
+void phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val)
+{
+       unsigned long flags;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       spin_lock_irqsave(&mii_info->mdio_lock, flags);
+       mii_info->mdio_write(mii_info->dev, mii_info->mii_id, regnum, val);
+       spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
+}
+
+/* Use the PHY ID registers to determine what type of PHY is attached
+ * to device dev.  return a struct phy_info structure describing that PHY
+ */
+struct phy_info *get_phy_info(struct ugeth_mii_info *mii_info)
+{
+       u16 phy_reg;
+       u32 phy_ID;
+       int i;
+       struct phy_info *theInfo = NULL;
+       struct net_device *dev = mii_info->dev;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Grab the bits from PHYIR1, and put them in the upper half */
+       phy_reg = phy_read(mii_info, MII_PHYSID1);
+       phy_ID = (phy_reg & 0xffff) << 16;
+
+       /* Grab the bits from PHYIR2, and put them in the lower half */
+       phy_reg = phy_read(mii_info, MII_PHYSID2);
+       phy_ID |= (phy_reg & 0xffff);
+
+       /* loop through all the known PHY types, and find one that */
+       /* matches the ID we read from the PHY. */
+       for (i = 0; phy_info[i]; i++)
+               if (phy_info[i]->phy_id == (phy_ID & phy_info[i]->phy_id_mask)){
+                       theInfo = phy_info[i];
+                       break;
+               }
+
+       /* This shouldn't happen, as we have generic PHY support */
+       if (theInfo == NULL) {
+               ugphy_info("%s: PHY id %x is not supported!", dev->name,
+                          phy_ID);
+               return NULL;
+       } else {
+               ugphy_info("%s: PHY is %s (%x)", dev->name, theInfo->name,
+                          phy_ID);
+       }
+
+       return theInfo;
+}
diff --git a/drivers/net/ucc_geth_phy.h b/drivers/net/ucc_geth_phy.h
new file mode 100644 (file)
index 0000000..2f98b8f
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ *
+ * Author: Shlomi Gridish <gridish@freescale.com>
+ *
+ * Description:
+ * UCC GETH Driver -- PHY handling
+ *
+ * Changelog:
+ * Jun 28, 2006 Li Yang <LeoLi@freescale.com>
+ * - Rearrange code and style fixes
+ *
+ * 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 __UCC_GETH_PHY_H__
+#define __UCC_GETH_PHY_H__
+
+#define MII_end ((u32)-2)
+#define MII_read ((u32)-1)
+
+#define MIIMIND_BUSY            0x00000001
+#define MIIMIND_NOTVALID        0x00000004
+
+#define UGETH_AN_TIMEOUT        2000
+
+/* 1000BT control (Marvell & BCM54xx at least) */
+#define MII_1000BASETCONTROL                  0x09
+#define MII_1000BASETCONTROL_FULLDUPLEXCAP    0x0200
+#define MII_1000BASETCONTROL_HALFDUPLEXCAP    0x0100
+
+/* 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
+
+/* 88E1011 PHY Status Register */
+#define MII_M1011_PHY_SPEC_STATUS               0x11
+#define MII_M1011_PHY_SPEC_STATUS_1000          0x8000
+#define MII_M1011_PHY_SPEC_STATUS_100           0x4000
+#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK      0xc000
+#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX    0x2000
+#define MII_M1011_PHY_SPEC_STATUS_RESOLVED      0x0800
+#define MII_M1011_PHY_SPEC_STATUS_LINK          0x0400
+
+#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
+
+#define MII_DM9161_SCR                  0x10
+#define MII_DM9161_SCR_INIT             0x0610
+
+/* DM9161 Specified Configuration and Status Register */
+#define MII_DM9161_SCSR                 0x11
+#define MII_DM9161_SCSR_100F            0x8000
+#define MII_DM9161_SCSR_100H            0x4000
+#define MII_DM9161_SCSR_10F             0x2000
+#define MII_DM9161_SCSR_10H             0x1000
+
+/* 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
+
+#define MII_BASIC_FEATURES    (SUPPORTED_10baseT_Half | \
+                 SUPPORTED_10baseT_Full | \
+                 SUPPORTED_100baseT_Half | \
+                 SUPPORTED_100baseT_Full | \
+                 SUPPORTED_Autoneg | \
+                 SUPPORTED_TP | \
+                 SUPPORTED_MII)
+
+#define MII_GBIT_FEATURES    (MII_BASIC_FEATURES | \
+                 SUPPORTED_1000baseT_Half | \
+                 SUPPORTED_1000baseT_Full)
+
+#define MII_READ_COMMAND                0x00000001
+
+#define MII_INTERRUPT_DISABLED          0x0
+#define MII_INTERRUPT_ENABLED           0x1
+/* Taken from mii_if_info and sungem_phy.h */
+struct ugeth_mii_info {
+       /* Information about the PHY type */
+       /* And management functions */
+       struct phy_info *phyinfo;
+
+       ucc_mii_mng_t *mii_regs;
+
+       /* forced speed & duplex (no autoneg)
+        * partner speed & duplex & pause (autoneg)
+        */
+       int speed;
+       int duplex;
+       int pause;
+
+       /* The most recently read link state */
+       int link;
+
+       /* Enabled Interrupts */
+       u32 interrupts;
+
+       u32 advertising;
+       int autoneg;
+       int mii_id;
+
+       /* private data pointer */
+       /* For use by PHYs to maintain extra state */
+       void *priv;
+
+       /* Provided by host chip */
+       struct net_device *dev;
+
+       /* A lock to ensure that only one thing can read/write
+        * the MDIO bus at a time */
+       spinlock_t mdio_lock;
+
+       /* Provided by ethernet driver */
+       int (*mdio_read) (struct net_device * dev, int mii_id, int reg);
+       void (*mdio_write) (struct net_device * dev, int mii_id, int reg,
+                           int val);
+};
+
+/* struct phy_info: a structure which defines attributes for a PHY
+ *
+ * id will contain a number which represents the PHY.  During
+ * startup, the driver will poll the PHY to find out what its
+ * UID--as defined by registers 2 and 3--is.  The 32-bit result
+ * gotten from the PHY will be ANDed with phy_id_mask to
+ * discard any bits which may change based on revision numbers
+ * unimportant to functionality
+ *
+ * There are 6 commands which take a ugeth_mii_info structure.
+ * Each PHY must declare config_aneg, and read_status.
+ */
+struct phy_info {
+       u32 phy_id;
+       char *name;
+       unsigned int phy_id_mask;
+       u32 features;
+
+       /* Called to initialize the PHY */
+       int (*init) (struct ugeth_mii_info * mii_info);
+
+       /* Called to suspend the PHY for power */
+       int (*suspend) (struct ugeth_mii_info * mii_info);
+
+       /* Reconfigures autonegotiation (or disables it) */
+       int (*config_aneg) (struct ugeth_mii_info * mii_info);
+
+       /* Determines the negotiated speed and duplex */
+       int (*read_status) (struct ugeth_mii_info * mii_info);
+
+       /* Clears any pending interrupts */
+       int (*ack_interrupt) (struct ugeth_mii_info * mii_info);
+
+       /* Enables or disables interrupts */
+       int (*config_intr) (struct ugeth_mii_info * mii_info);
+
+       /* Clears up any memory if needed */
+       void (*close) (struct ugeth_mii_info * mii_info);
+};
+
+struct phy_info *get_phy_info(struct ugeth_mii_info *mii_info);
+void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value);
+int read_phy_reg(struct net_device *dev, int mii_id, int regnum);
+void mii_clear_phy_interrupt(struct ugeth_mii_info *mii_info);
+void mii_configure_phy_interrupt(struct ugeth_mii_info *mii_info,
+                                u32 interrupts);
+
+struct dm9161_private {
+       struct timer_list timer;
+       int resetdone;
+};
+
+#endif                         /* __UCC_GETH_PHY_H__ */
index d3d0ec9703182ecd45f8633345b7ff41658f9ab9..efeb10b9c61b6e13f21f560809ac69b1b297bb04 100644 (file)
@@ -30,8 +30,8 @@
 */
 
 #define DRV_NAME       "via-rhine"
-#define DRV_VERSION    "1.4.0"
-#define DRV_RELDATE    "June-27-2006"
+#define DRV_VERSION    "1.4.1"
+#define DRV_RELDATE    "July-24-2006"
 
 
 /* A few user-configurable values.
@@ -44,6 +44,10 @@ static int max_interrupt_work = 20;
    Setting to > 1518 effectively disables this feature. */
 static int rx_copybreak;
 
+/* Work-around for broken BIOSes: they are unable to get the chip back out of
+   power state D3 so PXE booting fails. bootparam(7): via-rhine.avoid_D3=1 */
+static int avoid_D3;
+
 /*
  * In case you are looking for 'options[]' or 'full_duplex[]', they
  * are gone. Use ethtool(8) instead.
@@ -63,7 +67,11 @@ static const int multicast_filter_limit = 32;
    There are no ill effects from too-large receive rings. */
 #define TX_RING_SIZE   16
 #define TX_QUEUE_LEN   10      /* Limit ring entries actually used. */
+#ifdef CONFIG_VIA_RHINE_NAPI
+#define RX_RING_SIZE   64
+#else
 #define RX_RING_SIZE   16
+#endif
 
 
 /* Operational parameters that usually are not changed. */
@@ -116,9 +124,11 @@ MODULE_LICENSE("GPL");
 module_param(max_interrupt_work, int, 0);
 module_param(debug, int, 0);
 module_param(rx_copybreak, int, 0);
+module_param(avoid_D3, bool, 0);
 MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt");
 MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)");
 MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames");
+MODULE_PARM_DESC(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)");
 
 /*
                Theory of Operation
@@ -396,7 +406,7 @@ static void rhine_tx_timeout(struct net_device *dev);
 static int  rhine_start_tx(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 static void rhine_tx(struct net_device *dev);
-static void rhine_rx(struct net_device *dev);
+static int rhine_rx(struct net_device *dev, int limit);
 static void rhine_error(struct net_device *dev, int intr_status);
 static void rhine_set_rx_mode(struct net_device *dev);
 static struct net_device_stats *rhine_get_stats(struct net_device *dev);
@@ -564,6 +574,32 @@ static void rhine_poll(struct net_device *dev)
 }
 #endif
 
+#ifdef CONFIG_VIA_RHINE_NAPI
+static int rhine_napipoll(struct net_device *dev, int *budget)
+{
+       struct rhine_private *rp = netdev_priv(dev);
+       void __iomem *ioaddr = rp->base;
+       int done, limit = min(dev->quota, *budget);
+
+       done = rhine_rx(dev, limit);
+       *budget -= done;
+       dev->quota -= done;
+
+       if (done < limit) {
+               netif_rx_complete(dev);
+
+               iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
+                         IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
+                         IntrTxDone | IntrTxError | IntrTxUnderrun |
+                         IntrPCIErr | IntrStatsMax | IntrLinkChange,
+                         ioaddr + IntrEnable);
+               return 0;
+       }
+       else
+               return 1;
+}
+#endif
+
 static void rhine_hw_init(struct net_device *dev, long pioaddr)
 {
        struct rhine_private *rp = netdev_priv(dev);
@@ -743,6 +779,10 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
        dev->watchdog_timeo = TX_TIMEOUT;
 #ifdef CONFIG_NET_POLL_CONTROLLER
        dev->poll_controller = rhine_poll;
+#endif
+#ifdef CONFIG_VIA_RHINE_NAPI
+       dev->poll = rhine_napipoll;
+       dev->weight = 64;
 #endif
        if (rp->quirks & rqRhineI)
                dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
@@ -789,6 +829,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
                }
        }
        rp->mii_if.phy_id = phy_id;
+       if (debug > 1 && avoid_D3)
+               printk(KERN_INFO "%s: No D3 power state at shutdown.\n",
+                      dev->name);
 
        return 0;
 
@@ -1014,6 +1057,8 @@ static void init_registers(struct net_device *dev)
 
        rhine_set_rx_mode(dev);
 
+       netif_poll_enable(dev);
+
        /* Enable interrupts by setting the interrupt mask. */
        iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
               IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
@@ -1268,8 +1313,18 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *
                               dev->name, intr_status);
 
                if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped |
-                   IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf))
-                       rhine_rx(dev);
+                                  IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) {
+#ifdef CONFIG_VIA_RHINE_NAPI
+                       iowrite16(IntrTxAborted |
+                                 IntrTxDone | IntrTxError | IntrTxUnderrun |
+                                 IntrPCIErr | IntrStatsMax | IntrLinkChange,
+                                 ioaddr + IntrEnable);
+
+                       netif_rx_schedule(dev);
+#else
+                       rhine_rx(dev, RX_RING_SIZE);
+#endif
+               }
 
                if (intr_status & (IntrTxErrSummary | IntrTxDone)) {
                        if (intr_status & IntrTxErrSummary) {
@@ -1367,13 +1422,12 @@ static void rhine_tx(struct net_device *dev)
        spin_unlock(&rp->lock);
 }
 
-/* This routine is logically part of the interrupt handler, but isolated
-   for clarity and better register allocation. */
-static void rhine_rx(struct net_device *dev)
+/* Process up to limit frames from receive ring */
+static int rhine_rx(struct net_device *dev, int limit)
 {
        struct rhine_private *rp = netdev_priv(dev);
+       int count;
        int entry = rp->cur_rx % RX_RING_SIZE;
-       int boguscnt = rp->dirty_rx + RX_RING_SIZE - rp->cur_rx;
 
        if (debug > 4) {
                printk(KERN_DEBUG "%s: rhine_rx(), entry %d status %8.8x.\n",
@@ -1382,16 +1436,18 @@ static void rhine_rx(struct net_device *dev)
        }
 
        /* If EOP is set on the next entry, it's a new packet. Send it up. */
-       while (!(rp->rx_head_desc->rx_status & cpu_to_le32(DescOwn))) {
+       for (count = 0; count < limit; ++count) {
                struct rx_desc *desc = rp->rx_head_desc;
                u32 desc_status = le32_to_cpu(desc->rx_status);
                int data_size = desc_status >> 16;
 
+               if (desc_status & DescOwn)
+                       break;
+
                if (debug > 4)
                        printk(KERN_DEBUG "rhine_rx() status is %8.8x.\n",
                               desc_status);
-               if (--boguscnt < 0)
-                       break;
+
                if ((desc_status & (RxWholePkt | RxErr)) != RxWholePkt) {
                        if ((desc_status & RxWholePkt) != RxWholePkt) {
                                printk(KERN_WARNING "%s: Oversized Ethernet "
@@ -1460,7 +1516,11 @@ static void rhine_rx(struct net_device *dev)
                                                 PCI_DMA_FROMDEVICE);
                        }
                        skb->protocol = eth_type_trans(skb, dev);
+#ifdef CONFIG_VIA_RHINE_NAPI
+                       netif_receive_skb(skb);
+#else
                        netif_rx(skb);
+#endif
                        dev->last_rx = jiffies;
                        rp->stats.rx_bytes += pkt_len;
                        rp->stats.rx_packets++;
@@ -1487,6 +1547,8 @@ static void rhine_rx(struct net_device *dev)
                }
                rp->rx_ring[entry].rx_status = cpu_to_le32(DescOwn);
        }
+
+       return count;
 }
 
 /*
@@ -1776,6 +1838,7 @@ static int rhine_close(struct net_device *dev)
        spin_lock_irq(&rp->lock);
 
        netif_stop_queue(dev);
+       netif_poll_disable(dev);
 
        if (debug > 1)
                printk(KERN_DEBUG "%s: Shutting down ethercard, "
@@ -1857,7 +1920,8 @@ static void rhine_shutdown (struct pci_dev *pdev)
        }
 
        /* Hit power state D3 (sleep) */
-       iowrite8(ioread8(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW);
+       if (!avoid_D3)
+               iowrite8(ioread8(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW);
 
        /* TODO: Check use of pci_enable_wake() */
 
@@ -1941,7 +2005,7 @@ static int __init rhine_init(void)
 #ifdef MODULE
        printk(version);
 #endif
-       return pci_module_init(&rhine_driver);
+       return pci_register_driver(&rhine_driver);
 }
 
 
index aa9cd92f46b2dbbb51716416acd4f26d503aca1c..e266db1518e7e38943d79ccc916e9a6acc47b199 100644 (file)
@@ -2250,7 +2250,7 @@ static int __init velocity_init_module(void)
        int ret;
 
        velocity_register_notifier();
-       ret = pci_module_init(&velocity_driver);
+       ret = pci_register_driver(&velocity_driver);
        if (ret < 0)
                velocity_unregister_notifier();
        return ret;
index 496c3d5974444734f5aa6fa7ee3196e911943336..4665ef2c63dfca0a438cd313f4841b76f70f831e 100644 (file)
@@ -262,25 +262,6 @@ struct velocity_rd_info {
        dma_addr_t skb_dma;
 };
 
-/**
- *     alloc_rd_info           -       allocate an rd info block
- *
- *     Alocate and initialize a receive info structure used for keeping
- *     track of kernel side information related to each receive
- *     descriptor we are using
- */
-
-static inline struct velocity_rd_info *alloc_rd_info(void)
-{
-       struct velocity_rd_info *ptr;
-       if ((ptr = kmalloc(sizeof(struct velocity_rd_info), GFP_ATOMIC)) == NULL)
-               return NULL;
-       else {
-               memset(ptr, 0, sizeof(struct velocity_rd_info));
-               return ptr;
-       }
-}
-
 /*
  *     Used to track transmit side buffers.
  */
index 435e91ec4620735d4015b870fa96e1e23a5fabdd..6b63b350cd5216498d179f591b7cf7376493d9ba 100644 (file)
@@ -118,7 +118,7 @@ static inline void openwin(card_t *card, u8 page)
 
 static inline void set_carrier(port_t *port)
 {
-       if (!sca_in(MSCI1_OFFSET + ST3, port) & ST3_DCD)
+       if (!(sca_in(MSCI1_OFFSET + ST3, port) & ST3_DCD))
                netif_carrier_on(port_to_dev(port));
        else
                netif_carrier_off(port_to_dev(port));
@@ -127,10 +127,10 @@ static inline void set_carrier(port_t *port)
 
 static void sca_msci_intr(port_t *port)
 {
-       u8 stat = sca_in(MSCI1_OFFSET + ST1, port); /* read MSCI ST1 status */
+       u8 stat = sca_in(MSCI0_OFFSET + ST1, port); /* read MSCI ST1 status */
 
-       /* Reset MSCI TX underrun status bit */
-       sca_out(stat & ST1_UDRN, MSCI0_OFFSET + ST1, port);
+       /* Reset MSCI TX underrun and CDCD (ignored) status bit */
+       sca_out(stat & (ST1_UDRN | ST1_CDCD), MSCI0_OFFSET + ST1, port);
 
        if (stat & ST1_UDRN) {
                struct net_device_stats *stats = hdlc_stats(port_to_dev(port));
@@ -138,6 +138,7 @@ static void sca_msci_intr(port_t *port)
                stats->tx_fifo_errors++;
        }
 
+       stat = sca_in(MSCI1_OFFSET + ST1, port); /* read MSCI1 ST1 status */
        /* Reset MSCI CDCD status bit - uses ch#2 DCD input */
        sca_out(stat & ST1_CDCD, MSCI1_OFFSET + ST1, port);
 
index 430b1f630fb4a71147992411b3ad0eb71e997ad6..a5e7ce1bd16af46b3b9425a07ad8136f05c6aae7 100644 (file)
@@ -40,7 +40,6 @@
 * 1998/08/08   acme            Initial version.
 */
 
-#include <linux/config.h>      /* OS configuration options */
 #include <linux/stddef.h>      /* offsetof(), etc. */
 #include <linux/errno.h>       /* return codes */
 #include <linux/string.h>      /* inline memset(), etc. */
index 6e1ec5bf22fc702cd1b32895149ca109d666373f..7369875594321aaabe38457a55f29ff03e5964e6 100644 (file)
@@ -28,7 +28,6 @@
  *             2 of the License, or (at your option) any later version.
  */
 
-#include <linux/config.h> /* for CONFIG_DLCI_COUNT */
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
index 684af4316ffdafee26c70342cc765b8bdb8dcaf1..af4d4155905bfc70e2aa9c72d84befcb9d624069 100644 (file)
@@ -2062,7 +2062,7 @@ static struct pci_driver dscc4_driver = {
 
 static int __init dscc4_init_module(void)
 {
-       return pci_module_init(&dscc4_driver);
+       return pci_register_driver(&dscc4_driver);
 }
 
 static void __exit dscc4_cleanup_module(void)
index 3705db04a343b54ab345edcc313b9dfa0856f093..564351aafa4166de7a1b087a09339df7ad001eb4 100644 (file)
@@ -2697,7 +2697,7 @@ fst_init(void)
        for (i = 0; i < FST_MAX_CARDS; i++)
                fst_card_array[i] = NULL;
        spin_lock_init(&fst_work_q_lock);
-       return pci_module_init(&fst_driver);
+       return pci_register_driver(&fst_driver);
 }
 
 static void __exit
index 39f44241a72854781691f33e619785994486bf11..7b5d81deb0281be717b08377e39d4f19fd39e199 100644 (file)
@@ -1790,7 +1790,7 @@ static struct pci_driver lmc_driver = {
 
 static int __init init_lmc(void)
 {
-    return pci_module_init(&lmc_driver);
+    return pci_register_driver(&lmc_driver);
 }
 
 static void __exit exit_lmc(void)
index 567effff4a3e2b86849daae5c155bab5a42c10d0..56e69403d178f27ec908b4aa4c4162d8d8ad66d0 100644 (file)
@@ -3677,7 +3677,7 @@ static struct pci_driver cpc_driver = {
 
 static int __init cpc_init(void)
 {
-       return pci_module_init(&cpc_driver);
+       return pci_register_driver(&cpc_driver);
 }
 
 static void __exit cpc_cleanup_module(void)
index 4df61fa3214b52415a3972604a1df73a5d3bd463..a6b9c33b68e45b91bb502ad043fbe220467adf84 100644 (file)
@@ -476,7 +476,7 @@ static int __init pci200_init_module(void)
                printk(KERN_ERR "pci200syn: Invalid PCI clock frequency\n");
                return -EINVAL;
        }
-       return pci_module_init(&pci200_pci_driver);
+       return pci_register_driver(&pci200_pci_driver);
 }
 
 
index 7628c2d81f459beffed5296155feb46638933ae2..0ba018f8382b53b2806b71c0bf4d19b97f10f45a 100644 (file)
@@ -32,7 +32,6 @@
  *             2 of the License, or (at your option) any later version.
  */
 
-#include <linux/config.h> /* for CONFIG_DLCI_MAX */
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
index b2031dfc4bb1076426d9c0d45ebc1472eda449b3..ec68f7dfd93f7ca26f5a15d3d8f2117b4920b80c 100644 (file)
@@ -837,7 +837,7 @@ static int __init wanxl_init_module(void)
 #ifdef MODULE
        printk(KERN_INFO "%s\n", version);
 #endif
-       return pci_module_init(&wanxl_pci_driver);
+       return pci_register_driver(&wanxl_pci_driver);
 }
 
 static void __exit wanxl_cleanup_module(void)
index 7caa8dc88a5869716c098a5c819ce5b89c8cf750..b1ba1872f315b029a62dc7b15f73d0029df95f4f 100644 (file)
@@ -500,8 +500,8 @@ MODULE_LICENSE("GPL");
 
 /* This is set up so that only a single autoprobe takes place per call.
 ISA device autoprobes on a running machine are not recommended. */
-int
-init_module(void)
+
+int __init init_module(void)
 {
        struct net_device *dev;
        int this_dev, found = 0;
index a4dd1394271446192ccf51a26a82d70c4d0bf042..16befbcea58cb71ed901c4826456c32e36e17034 100644 (file)
@@ -3950,13 +3950,11 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
        pRsp->rsp0 = IN4500(ai, RESP0);
        pRsp->rsp1 = IN4500(ai, RESP1);
        pRsp->rsp2 = IN4500(ai, RESP2);
-       if ((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_SOFTRESET) {
-               airo_print_err(ai->dev->name, "cmd= %x\n", pCmd->cmd);
-               airo_print_err(ai->dev->name, "status= %x\n", pRsp->status);
-               airo_print_err(ai->dev->name, "Rsp0= %x\n", pRsp->rsp0);
-               airo_print_err(ai->dev->name, "Rsp1= %x\n", pRsp->rsp1);
-               airo_print_err(ai->dev->name, "Rsp2= %x\n", pRsp->rsp2);
-       }
+       if ((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_SOFTRESET)
+               airo_print_err(ai->dev->name,
+                       "cmd:%x status:%x rsp0:%x rsp1:%x rsp2:%x",
+                       pCmd->cmd, pRsp->status, pRsp->rsp0, pRsp->rsp1,
+                       pRsp->rsp2);
 
        // clear stuck command busy if necessary
        if (IN4500(ai, COMMAND) & COMMAND_BUSY) {
index d425c3cefdedbac00c91b1d320d01d9828587846..3bfa791c323d1234db3453ed3c5086a7270f7c48 100644 (file)
@@ -76,7 +76,7 @@ static void __devexit atmel_pci_remove(struct pci_dev *pdev)
 
 static int __init atmel_init_module(void)
 {
-       return pci_module_init(&atmel_driver);
+       return pci_register_driver(&atmel_driver);
 }
 
 static void __exit atmel_cleanup_module(void)
index 17a56828e232953a9c2ac0f80328606377918f1c..c6ee1e974c841c6c42c3dab869d678630103cf60 100644 (file)
@@ -504,6 +504,12 @@ struct bcm43xx_phyinfo {
         * This lock is only used by bcm43xx_phy_{un}lock()
         */
        spinlock_t lock;
+
+       /* Firmware. */
+       const struct firmware *ucode;
+       const struct firmware *pcm;
+       const struct firmware *initvals0;
+       const struct firmware *initvals1;
 };
 
 
@@ -593,12 +599,14 @@ struct bcm43xx_coreinfo {
        u8 available:1,
           enabled:1,
           initialized:1;
-       /** core_id ID number */
-       u16 id;
        /** core_rev revision number */
        u8 rev;
        /** Index number for _switch_core() */
        u8 index;
+       /** core_id ID number */
+       u16 id;
+       /** Core-specific data. */
+       void *priv;
 };
 
 /* Additional information for each 80211 core. */
@@ -647,7 +655,23 @@ enum {
        BCM43xx_STAT_RESTARTING,        /* controller_restart() called. */
 };
 #define bcm43xx_status(bcm)            atomic_read(&(bcm)->init_status)
-#define bcm43xx_set_status(bcm, stat)  atomic_set(&(bcm)->init_status, (stat))
+#define bcm43xx_set_status(bcm, stat)  do {                    \
+               atomic_set(&(bcm)->init_status, (stat));        \
+               smp_wmb();                                      \
+                                       } while (0)
+
+/*    *** THEORY OF LOCKING ***
+ *
+ * We have two different locks in the bcm43xx driver.
+ * => bcm->mutex:    General sleeping mutex. Protects struct bcm43xx_private
+ *                   and the device registers. This mutex does _not_ protect
+ *                   against concurrency from the IRQ handler.
+ * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency.
+ *
+ * Please note that, if you only take the irq_lock, you are not protected
+ * against concurrency from the periodic work handlers.
+ * Most times you want to take _both_ locks.
+ */
 
 struct bcm43xx_private {
        struct ieee80211_device *ieee;
@@ -659,7 +683,6 @@ struct bcm43xx_private {
 
        void __iomem *mmio_addr;
 
-       /* Locking, see "theory of locking" text below. */
        spinlock_t irq_lock;
        struct mutex mutex;
 
@@ -691,6 +714,7 @@ struct bcm43xx_private {
        struct bcm43xx_sprominfo sprom;
 #define BCM43xx_NR_LEDS                4
        struct bcm43xx_led leds[BCM43xx_NR_LEDS];
+       spinlock_t leds_lock;
 
        /* The currently active core. */
        struct bcm43xx_coreinfo *current_core;
@@ -708,10 +732,6 @@ struct bcm43xx_private {
        struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ];
        /* Additional information, specific to the 80211 cores. */
        struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ];
-       /* Index of the current 80211 core. If current_core is not
-        * an 80211 core, this is -1.
-        */
-       int current_80211_core_idx;
        /* Number of available 80211 cores. */
        int nr_80211_available;
 
@@ -724,6 +744,8 @@ struct bcm43xx_private {
        u32 irq_savedstate;
        /* Link Quality calculation context. */
        struct bcm43xx_noise_calculation noisecalc;
+       /* if > 0 MAC is suspended. if == 0 MAC is enabled. */
+       int mac_suspended;
 
        /* Threshold values. */
        //TODO: The RTS thr has to be _used_. Currently, it is only set via WX.
@@ -746,12 +768,6 @@ struct bcm43xx_private {
        struct bcm43xx_key key[54];
        u8 default_key_idx;
 
-       /* Firmware. */
-       const struct firmware *ucode;
-       const struct firmware *pcm;
-       const struct firmware *initvals0;
-       const struct firmware *initvals1;
-
        /* Random Number Generator. */
        struct hwrng rng;
        char rng_name[20 + 1];
@@ -763,55 +779,6 @@ struct bcm43xx_private {
 };
 
 
-/*    *** THEORY OF LOCKING ***
- *
- * We have two different locks in the bcm43xx driver.
- * => bcm->mutex:    General sleeping mutex. Protects struct bcm43xx_private
- *                   and the device registers.
- * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency.
- *
- * We have three types of helper function pairs to utilize these locks.
- *     (Always use the helper functions.)
- * 1) bcm43xx_{un}lock_noirq():
- *     Takes bcm->mutex. Does _not_ protect against IRQ concurrency,
- *     so it is almost always unsafe, if device IRQs are enabled.
- *     So only use this, if device IRQs are masked.
- *     Locking may sleep.
- *     You can sleep within the critical section.
- * 2) bcm43xx_{un}lock_irqonly():
- *     Takes bcm->irq_lock. Does _not_ protect against
- *     bcm43xx_lock_noirq() critical sections.
- *     Does only protect against the IRQ handler path and other
- *     irqonly() critical sections.
- *     Locking does not sleep.
- *     You must not sleep within the critical section.
- * 3) bcm43xx_{un}lock_irqsafe():
- *     This is the cummulative lock and takes both, mutex and irq_lock.
- *     Protects against noirq() and irqonly() critical sections (and
- *     the IRQ handler path).
- *     Locking may sleep.
- *     You must not sleep within the critical section.
- */
-
-/* Lock type 1 */
-#define bcm43xx_lock_noirq(bcm)                mutex_lock(&(bcm)->mutex)
-#define bcm43xx_unlock_noirq(bcm)      mutex_unlock(&(bcm)->mutex)
-/* Lock type 2 */
-#define bcm43xx_lock_irqonly(bcm, flags)       \
-       spin_lock_irqsave(&(bcm)->irq_lock, flags)
-#define bcm43xx_unlock_irqonly(bcm, flags)     \
-       spin_unlock_irqrestore(&(bcm)->irq_lock, flags)
-/* Lock type 3 */
-#define bcm43xx_lock_irqsafe(bcm, flags) do {  \
-       bcm43xx_lock_noirq(bcm);                \
-       bcm43xx_lock_irqonly(bcm, flags);       \
-               } while (0)
-#define bcm43xx_unlock_irqsafe(bcm, flags) do {        \
-       bcm43xx_unlock_irqonly(bcm, flags);     \
-       bcm43xx_unlock_noirq(bcm);              \
-               } while (0)
-
-
 static inline
 struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
 {
@@ -863,34 +830,33 @@ int bcm43xx_using_pio(struct bcm43xx_private *bcm)
  * any of these functions.
  */
 static inline
+struct bcm43xx_coreinfo_80211 *
+bcm43xx_current_80211_priv(struct bcm43xx_private *bcm)
+{
+       assert(bcm->current_core->id == BCM43xx_COREID_80211);
+       return bcm->current_core->priv;
+}
+static inline
 struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm)
 {
        assert(bcm43xx_using_pio(bcm));
-       assert(bcm->current_80211_core_idx >= 0);
-       assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
-       return &(bcm->core_80211_ext[bcm->current_80211_core_idx].pio);
+       return &(bcm43xx_current_80211_priv(bcm)->pio);
 }
 static inline
 struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm)
 {
        assert(!bcm43xx_using_pio(bcm));
-       assert(bcm->current_80211_core_idx >= 0);
-       assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
-       return &(bcm->core_80211_ext[bcm->current_80211_core_idx].dma);
+       return &(bcm43xx_current_80211_priv(bcm)->dma);
 }
 static inline
 struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm)
 {
-       assert(bcm->current_80211_core_idx >= 0);
-       assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
-       return &(bcm->core_80211_ext[bcm->current_80211_core_idx].phy);
+       return &(bcm43xx_current_80211_priv(bcm)->phy);
 }
 static inline
 struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm)
 {
-       assert(bcm->current_80211_core_idx >= 0);
-       assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
-       return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio);
+       return &(bcm43xx_current_80211_priv(bcm)->radio);
 }
 
 
index ce2e40b29b4f0533c1e8150161c29ccfeb18efd6..923275ea0789aa6e26b031a74b521b64f2ce7eb2 100644 (file)
@@ -77,7 +77,8 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf,
 
        down(&big_buffer_sem);
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
                fappend("Board not initialized.\n");
                goto out;
@@ -121,7 +122,8 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf,
        fappend("\n");
 
 out:
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
        res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
        up(&big_buffer_sem);
        return res;
@@ -159,7 +161,8 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf,
        unsigned long flags;
 
        down(&big_buffer_sem);
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
                fappend("Board not initialized.\n");
                goto out;
@@ -169,7 +172,8 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf,
        fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags);
 
 out:
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
        res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
        up(&big_buffer_sem);
        return res;
@@ -188,7 +192,8 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf,
        u64 tsf;
 
        down(&big_buffer_sem);
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
                fappend("Board not initialized.\n");
                goto out;
@@ -199,7 +204,8 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf,
                (unsigned int)(tsf & 0xFFFFFFFFULL));
 
 out:
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
        res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
        up(&big_buffer_sem);
        return res;
@@ -221,7 +227,8 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf,
                res = -EFAULT;
                goto out_up;
        }
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
                printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
                res = -EFAULT;
@@ -237,7 +244,8 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf,
        res = buf_size;
        
 out_unlock:
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
 out_up:
        up(&big_buffer_sem);
        return res;
@@ -258,7 +266,8 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf,
        int i, cnt, j = 0;
 
        down(&big_buffer_sem);
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
 
        fappend("Last %d logged xmitstatus blobs (Latest first):\n\n",
                BCM43xx_NR_LOGGED_XMITSTATUS);
@@ -294,14 +303,51 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf,
                        i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
        }
 
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
        res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
-       bcm43xx_lock_irqsafe(bcm, flags);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        if (*ppos == pos) {
                /* Done. Drop the copied data. */
                e->xmitstatus_printing = 0;
        }
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
+       up(&big_buffer_sem);
+       return res;
+}
+
+static ssize_t restart_write_file(struct file *file, const char __user *user_buf,
+                                 size_t count, loff_t *ppos)
+{
+       struct bcm43xx_private *bcm = file->private_data;
+       char *buf = really_big_buffer;
+       ssize_t buf_size;
+       ssize_t res;
+       unsigned long flags;
+
+       buf_size = min(count, sizeof (really_big_buffer) - 1);
+       down(&big_buffer_sem);
+       if (copy_from_user(buf, user_buf, buf_size)) {
+               res = -EFAULT;
+               goto out_up;
+       }
+       mutex_lock(&(bcm)->mutex);
+       spin_lock_irqsave(&(bcm)->irq_lock, flags);
+       if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
+               printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
+               res = -EFAULT;
+               goto out_unlock;
+       }
+       if (count > 0 && buf[0] == '1') {
+               bcm43xx_controller_restart(bcm, "manually restarted");
+               res = count;
+       } else
+               res = -EINVAL;
+
+out_unlock:
+       spin_unlock_irqrestore(&(bcm)->irq_lock, flags);
+       mutex_unlock(&(bcm)->mutex);
+out_up:
        up(&big_buffer_sem);
        return res;
 }
@@ -339,6 +385,11 @@ static struct file_operations txstat_fops = {
        .open = open_file_generic,
 };
 
+static struct file_operations restart_fops = {
+       .write = restart_write_file,
+       .open = open_file_generic,
+};
+
 
 void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm)
 {
@@ -390,6 +441,10 @@ void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm)
                                                bcm, &txstat_fops);
        if (!e->dentry_txstat)
                printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir);
+       e->dentry_restart = debugfs_create_file("restart", 0222, e->subdir,
+                                               bcm, &restart_fops);
+       if (!e->dentry_restart)
+               printk(KERN_ERR PFX "debugfs: creating \"restart\" for \"%s\" failed!\n", devdir);
 }
 
 void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm)
@@ -405,6 +460,7 @@ void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm)
        debugfs_remove(e->dentry_devinfo);
        debugfs_remove(e->dentry_tsf);
        debugfs_remove(e->dentry_txstat);
+       debugfs_remove(e->dentry_restart);
        debugfs_remove(e->subdir);
        kfree(e->xmitstatus_buffer);
        kfree(e->xmitstatus_print_buffer);
index 50ce267f794d0fe51a37dbee1e52e61919a2ca87..a40d1af355452eca3ec1d16fb967a58a2ca847c7 100644 (file)
@@ -20,6 +20,7 @@ struct bcm43xx_dfsentry {
        struct dentry *dentry_spromdump;
        struct dentry *dentry_tsf;
        struct dentry *dentry_txstat;
+       struct dentry *dentry_restart;
 
        struct bcm43xx_private *bcm;
 
index ec80692d638a45d7440cf83710eecad403847529..c3f90c8563d915ee4175afe6ca8cd6a4a41627fb 100644 (file)
@@ -51,12 +51,12 @@ static void bcm43xx_led_blink(unsigned long d)
        struct bcm43xx_private *bcm = led->bcm;
        unsigned long flags;
 
-       bcm43xx_lock_irqonly(bcm, flags);
+       spin_lock_irqsave(&bcm->leds_lock, flags);
        if (led->blink_interval) {
                bcm43xx_led_changestate(led);
                mod_timer(&led->blink_timer, jiffies + led->blink_interval);
        }
-       bcm43xx_unlock_irqonly(bcm, flags);
+       spin_unlock_irqrestore(&bcm->leds_lock, flags);
 }
 
 static void bcm43xx_led_blink_start(struct bcm43xx_led *led,
@@ -177,7 +177,9 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
        int i, turn_on;
        unsigned long interval = 0;
        u16 ledctl;
+       unsigned long flags;
 
+       spin_lock_irqsave(&bcm->leds_lock, flags);
        ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
        for (i = 0; i < BCM43xx_NR_LEDS; i++) {
                led = &(bcm->leds[i]);
@@ -266,6 +268,7 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
                        ledctl &= ~(1 << i);
        }
        bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+       spin_unlock_irqrestore(&bcm->leds_lock, flags);
 }
 
 void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
@@ -274,7 +277,9 @@ void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
        u16 ledctl;
        int i;
        int bit_on;
+       unsigned long flags;
 
+       spin_lock_irqsave(&bcm->leds_lock, flags);
        ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
        for (i = 0; i < BCM43xx_NR_LEDS; i++) {
                led = &(bcm->leds[i]);
@@ -290,4 +295,5 @@ void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
                        ledctl &= ~(1 << i);
        }
        bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+       spin_unlock_irqrestore(&bcm->leds_lock, flags);
 }
index df317c1e12a89df16d84ce861ffac7d302cea8ad..b095f3cc67303560090e75b7c4f12803d51dd2ae 100644 (file)
@@ -509,23 +509,19 @@ static void bcm43xx_synchronize_irq(struct bcm43xx_private *bcm)
 }
 
 /* Make sure we don't receive more data from the device. */
-static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate)
+static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm)
 {
        unsigned long flags;
-       u32 old;
 
-       bcm43xx_lock_irqonly(bcm, flags);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) {
-               bcm43xx_unlock_irqonly(bcm, flags);
+               spin_unlock_irqrestore(&bcm->irq_lock, flags);
                return -EBUSY;
        }
-       old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
-       bcm43xx_unlock_irqonly(bcm, flags);
+       bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
        bcm43xx_synchronize_irq(bcm);
 
-       if (oldstate)
-               *oldstate = old;
-
        return 0;
 }
 
@@ -537,7 +533,6 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm)
        u16 manufact;
        u16 version;
        u8 revision;
-       s8 i;
 
        if (bcm->chip_id == 0x4317) {
                if (bcm->chip_rev == 0x00)
@@ -580,20 +575,11 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm)
        radio->version = version;
        radio->revision = revision;
 
-       /* Set default attenuation values. */
-       radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm);
-       radio->radio_atten = bcm43xx_default_radio_attenuation(bcm);
-       radio->txctl1 = bcm43xx_default_txctl1(bcm);
-       radio->txctl2 = 0xFFFF;
        if (phy->type == BCM43xx_PHYTYPE_A)
                radio->txpower_desired = bcm->sprom.maxpower_aphy;
        else
                radio->txpower_desired = bcm->sprom.maxpower_bgphy;
 
-       /* Initialize the in-memory nrssi Lookup Table. */
-       for (i = 0; i < 64; i++)
-               radio->nrssi_lt[i] = i;
-
        return 0;
 
 err_unsupported_radio:
@@ -1250,10 +1236,6 @@ int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *ne
                goto out;
 
        bcm->current_core = new_core;
-       bcm->current_80211_core_idx = -1;
-       if (new_core->id == BCM43xx_COREID_80211)
-               bcm->current_80211_core_idx = (int)(new_core - &(bcm->core_80211[0]));
-
 out:
        return err;
 }
@@ -1423,43 +1405,23 @@ static void bcm43xx_wireless_core_disable(struct bcm43xx_private *bcm)
        bcm43xx_core_disable(bcm, 0);
 }
 
-/* Mark the current 80211 core inactive.
- * "active_80211_core" is the other 80211 core, which is used.
- */
-static int bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm,
-                                              struct bcm43xx_coreinfo *active_80211_core)
+/* Mark the current 80211 core inactive. */
+static void bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm)
 {
        u32 sbtmstatelow;
-       struct bcm43xx_coreinfo *old_core;
-       int err = 0;
 
        bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
        bcm43xx_radio_turn_off(bcm);
        sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-       sbtmstatelow &= ~0x200a0000;
-       sbtmstatelow |= 0xa0000;
+       sbtmstatelow &= 0xDFF5FFFF;
+       sbtmstatelow |= 0x000A0000;
        bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
        udelay(1);
        sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-       sbtmstatelow &= ~0xa0000;
-       sbtmstatelow |= 0x80000;
+       sbtmstatelow &= 0xFFF5FFFF;
+       sbtmstatelow |= 0x00080000;
        bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
        udelay(1);
-
-       if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G) {
-               old_core = bcm->current_core;
-               err = bcm43xx_switch_core(bcm, active_80211_core);
-               if (err)
-                       goto out;
-               sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-               sbtmstatelow &= ~0x20000000;
-               sbtmstatelow |= 0x20000000;
-               bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
-               err = bcm43xx_switch_core(bcm, old_core);
-       }
-
-out:
-       return err;
 }
 
 static void handle_irq_transmit_status(struct bcm43xx_private *bcm)
@@ -1720,7 +1682,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
 # define bcmirq_handled(irq)   do { /* nothing */ } while (0)
 #endif /* CONFIG_BCM43XX_DEBUG*/
 
-       bcm43xx_lock_irqonly(bcm, flags);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        reason = bcm->irq_reason;
        dma_reason[0] = bcm->dma_reason[0];
        dma_reason[1] = bcm->dma_reason[1];
@@ -1746,7 +1708,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
                        dma_reason[2], dma_reason[3]);
                bcm43xx_controller_restart(bcm, "DMA error");
                mmiowb();
-               bcm43xx_unlock_irqonly(bcm, flags);
+               spin_unlock_irqrestore(&bcm->irq_lock, flags);
                return;
        }
        if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) |
@@ -1834,7 +1796,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
                bcm43xx_leds_update(bcm, activity);
        bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
        mmiowb();
-       bcm43xx_unlock_irqonly(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
 }
 
 static void pio_irq_workaround(struct bcm43xx_private *bcm,
@@ -1885,14 +1847,8 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re
 
        spin_lock(&bcm->irq_lock);
 
-       /* Only accept IRQs, if we are initialized properly.
-        * This avoids an RX race while initializing.
-        * We should probably not enable IRQs before we are initialized
-        * completely, but some careful work is needed to fix this. I think it
-        * is best to stay with this cheap workaround for now... .
-        */
-       if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED))
-               goto out;
+       assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
+       assert(bcm->current_core->id == BCM43xx_COREID_80211);
 
        reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
        if (reason == 0xffffffff) {
@@ -1930,16 +1886,18 @@ out:
 
 static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force)
 {
+       struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+
        if (bcm->firmware_norelease && !force)
                return; /* Suspending or controller reset. */
-       release_firmware(bcm->ucode);
-       bcm->ucode = NULL;
-       release_firmware(bcm->pcm);
-       bcm->pcm = NULL;
-       release_firmware(bcm->initvals0);
-       bcm->initvals0 = NULL;
-       release_firmware(bcm->initvals1);
-       bcm->initvals1 = NULL;
+       release_firmware(phy->ucode);
+       phy->ucode = NULL;
+       release_firmware(phy->pcm);
+       phy->pcm = NULL;
+       release_firmware(phy->initvals0);
+       phy->initvals0 = NULL;
+       release_firmware(phy->initvals1);
+       phy->initvals1 = NULL;
 }
 
 static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
@@ -1950,11 +1908,11 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
        int nr;
        char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 };
 
-       if (!bcm->ucode) {
+       if (!phy->ucode) {
                snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw",
                         (rev >= 5 ? 5 : rev),
                         modparam_fwpostfix);
-               err = request_firmware(&bcm->ucode, buf, &bcm->pci_dev->dev);
+               err = request_firmware(&phy->ucode, buf, &bcm->pci_dev->dev);
                if (err) {
                        printk(KERN_ERR PFX 
                               "Error: Microcode \"%s\" not available or load failed.\n",
@@ -1963,12 +1921,12 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
                }
        }
 
-       if (!bcm->pcm) {
+       if (!phy->pcm) {
                snprintf(buf, ARRAY_SIZE(buf),
                         "bcm43xx_pcm%d%s.fw",
                         (rev < 5 ? 4 : 5),
                         modparam_fwpostfix);
-               err = request_firmware(&bcm->pcm, buf, &bcm->pci_dev->dev);
+               err = request_firmware(&phy->pcm, buf, &bcm->pci_dev->dev);
                if (err) {
                        printk(KERN_ERR PFX
                               "Error: PCM \"%s\" not available or load failed.\n",
@@ -1977,7 +1935,7 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
                }
        }
 
-       if (!bcm->initvals0) {
+       if (!phy->initvals0) {
                if (rev == 2 || rev == 4) {
                        switch (phy->type) {
                        case BCM43xx_PHYTYPE_A:
@@ -2008,20 +1966,20 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
                snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
                         nr, modparam_fwpostfix);
 
-               err = request_firmware(&bcm->initvals0, buf, &bcm->pci_dev->dev);
+               err = request_firmware(&phy->initvals0, buf, &bcm->pci_dev->dev);
                if (err) {
                        printk(KERN_ERR PFX 
                               "Error: InitVals \"%s\" not available or load failed.\n",
                                buf);
                        goto error;
                }
-               if (bcm->initvals0->size % sizeof(struct bcm43xx_initval)) {
+               if (phy->initvals0->size % sizeof(struct bcm43xx_initval)) {
                        printk(KERN_ERR PFX "InitVals fileformat error.\n");
                        goto error;
                }
        }
 
-       if (!bcm->initvals1) {
+       if (!phy->initvals1) {
                if (rev >= 5) {
                        u32 sbtmstatehigh;
 
@@ -2043,14 +2001,14 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
                        snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
                                 nr, modparam_fwpostfix);
 
-                       err = request_firmware(&bcm->initvals1, buf, &bcm->pci_dev->dev);
+                       err = request_firmware(&phy->initvals1, buf, &bcm->pci_dev->dev);
                        if (err) {
                                printk(KERN_ERR PFX 
                                       "Error: InitVals \"%s\" not available or load failed.\n",
                                        buf);
                                goto error;
                        }
-                       if (bcm->initvals1->size % sizeof(struct bcm43xx_initval)) {
+                       if (phy->initvals1->size % sizeof(struct bcm43xx_initval)) {
                                printk(KERN_ERR PFX "InitVals fileformat error.\n");
                                goto error;
                        }
@@ -2070,12 +2028,13 @@ err_noinitval:
 
 static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm)
 {
+       struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
        const u32 *data;
        unsigned int i, len;
 
        /* Upload Microcode. */
-       data = (u32 *)(bcm->ucode->data);
-       len = bcm->ucode->size / sizeof(u32);
+       data = (u32 *)(phy->ucode->data);
+       len = phy->ucode->size / sizeof(u32);
        bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000);
        for (i = 0; i < len; i++) {
                bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
@@ -2084,8 +2043,8 @@ static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm)
        }
 
        /* Upload PCM data. */
-       data = (u32 *)(bcm->pcm->data);
-       len = bcm->pcm->size / sizeof(u32);
+       data = (u32 *)(phy->pcm->data);
+       len = phy->pcm->size / sizeof(u32);
        bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea);
        bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000);
        bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb);
@@ -2131,15 +2090,16 @@ err_format:
 
 static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm)
 {
+       struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
        int err;
 
-       err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data,
-                                    bcm->initvals0->size / sizeof(struct bcm43xx_initval));
+       err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals0->data,
+                                    phy->initvals0->size / sizeof(struct bcm43xx_initval));
        if (err)
                goto out;
-       if (bcm->initvals1) {
-               err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data,
-                                            bcm->initvals1->size / sizeof(struct bcm43xx_initval));
+       if (phy->initvals1) {
+               err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals1->data,
+                                            phy->initvals1->size / sizeof(struct bcm43xx_initval));
                if (err)
                        goto out;
        }
@@ -2156,9 +2116,7 @@ static struct pci_device_id bcm43xx_47xx_ids[] = {
 
 static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
 {
-       int res;
-       unsigned int i;
-       u32 data;
+       int err;
 
        bcm->irq = bcm->pci_dev->irq;
 #ifdef CONFIG_BCM947XX
@@ -2175,32 +2133,12 @@ static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
                }
        }
 #endif
-       res = request_irq(bcm->irq, bcm43xx_interrupt_handler,
+       err = request_irq(bcm->irq, bcm43xx_interrupt_handler,
                          IRQF_SHARED, KBUILD_MODNAME, bcm);
-       if (res) {
+       if (err)
                printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq);
-               return -ENODEV;
-       }
-       bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xffffffff);
-       bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402);
-       i = 0;
-       while (1) {
-               data = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
-               if (data == BCM43xx_IRQ_READY)
-                       break;
-               i++;
-               if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) {
-                       printk(KERN_ERR PFX "Card IRQ register not responding. "
-                                           "Giving up.\n");
-                       free_irq(bcm->irq, bcm);
-                       return -ENODEV;
-               }
-               udelay(10);
-       }
-       // dummy read
-       bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
 
-       return 0;
+       return err;
 }
 
 /* Switch to the core used to write the GPIO register.
@@ -2298,13 +2236,17 @@ static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm)
 /* http://bcm-specs.sipsolutions.net/EnableMac */
 void bcm43xx_mac_enable(struct bcm43xx_private *bcm)
 {
-       bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
-                       bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
-                       | BCM43xx_SBF_MAC_ENABLED);
-       bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY);
-       bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
-       bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
-       bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+       bcm->mac_suspended--;
+       assert(bcm->mac_suspended >= 0);
+       if (bcm->mac_suspended == 0) {
+               bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+                               bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+                               | BCM43xx_SBF_MAC_ENABLED);
+               bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY);
+               bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
+               bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+               bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+       }
 }
 
 /* http://bcm-specs.sipsolutions.net/SuspendMAC */
@@ -2313,18 +2255,23 @@ void bcm43xx_mac_suspend(struct bcm43xx_private *bcm)
        int i;
        u32 tmp;
 
-       bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
-       bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
-                       bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
-                       & ~BCM43xx_SBF_MAC_ENABLED);
-       bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
-       for (i = 100000; i; i--) {
-               tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
-               if (tmp & BCM43xx_IRQ_READY)
-                       return;
-               udelay(10);
+       assert(bcm->mac_suspended >= 0);
+       if (bcm->mac_suspended == 0) {
+               bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
+               bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+                               bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+                               & ~BCM43xx_SBF_MAC_ENABLED);
+               bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+               for (i = 10000; i; i--) {
+                       tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+                       if (tmp & BCM43xx_IRQ_READY)
+                               goto out;
+                       udelay(1);
+               }
+               printkl(KERN_ERR PFX "MAC suspend failed\n");
        }
-       printkl(KERN_ERR PFX "MAC suspend failed\n");
+out:
+       bcm->mac_suspended++;
 }
 
 void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
@@ -2394,7 +2341,6 @@ static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm)
        if (!modparam_noleds)
                bcm43xx_leds_exit(bcm);
        bcm43xx_gpio_cleanup(bcm);
-       free_irq(bcm->irq, bcm);
        bcm43xx_release_firmware(bcm, 0);
 }
 
@@ -2406,7 +2352,7 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
        struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
        int err;
-       int tmp;
+       int i, tmp;
        u32 value32;
        u16 value16;
 
@@ -2419,13 +2365,26 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
                goto out;
        bcm43xx_upload_microcode(bcm);
 
-       err = bcm43xx_initialize_irq(bcm);
-       if (err)
-               goto err_release_fw;
+       bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xFFFFFFFF);
+       bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402);
+       i = 0;
+       while (1) {
+               value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+               if (value32 == BCM43xx_IRQ_READY)
+                       break;
+               i++;
+               if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) {
+                       printk(KERN_ERR PFX "IRQ_READY timeout\n");
+                       err = -ENODEV;
+                       goto err_release_fw;
+               }
+               udelay(10);
+       }
+       bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
 
        err = bcm43xx_gpio_init(bcm);
        if (err)
-               goto err_free_irq;
+               goto err_release_fw;
 
        err = bcm43xx_upload_initvals(bcm);
        if (err)
@@ -2509,8 +2468,6 @@ err_radio_off:
        bcm43xx_radio_turn_off(bcm);
 err_gpio_cleanup:
        bcm43xx_gpio_cleanup(bcm);
-err_free_irq:
-       free_irq(bcm->irq, bcm);
 err_release_fw:
        bcm43xx_release_firmware(bcm, 1);
        goto out;
@@ -2550,11 +2507,9 @@ static void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy)
 {
        /* Initialize a "phyinfo" structure. The structure is already
         * zeroed out.
+        * This is called on insmod time to initialize members.
         */
-       phy->antenna_diversity = 0xFFFF;
        phy->savedpctlreg = 0xFFFF;
-       phy->minlowsig[0] = 0xFFFF;
-       phy->minlowsig[1] = 0xFFFF;
        spin_lock_init(&phy->lock);
 }
 
@@ -2562,14 +2517,11 @@ static void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio)
 {
        /* Initialize a "radioinfo" structure. The structure is already
         * zeroed out.
+        * This is called on insmod time to initialize members.
         */
        radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
        radio->channel = 0xFF;
        radio->initial_channel = 0xFF;
-       radio->lofcal = 0xFFFF;
-       radio->initval = 0xFFFF;
-       radio->nrssi[0] = -1000;
-       radio->nrssi[1] = -1000;
 }
 
 static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
@@ -2587,7 +2539,6 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
                                    * BCM43xx_MAX_80211_CORES);
        memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211)
                                        * BCM43xx_MAX_80211_CORES);
-       bcm->current_80211_core_idx = -1;
        bcm->nr_80211_available = 0;
        bcm->current_core = NULL;
        bcm->active_80211_core = NULL;
@@ -2757,6 +2708,7 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
                                goto out;
                        }
                        bcm->nr_80211_available++;
+                       core->priv = ext_80211;
                        bcm43xx_init_struct_phyinfo(&ext_80211->phy);
                        bcm43xx_init_struct_radioinfo(&ext_80211->radio);
                        break;
@@ -2857,7 +2809,8 @@ static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm)
 }
 
 /* http://bcm-specs.sipsolutions.net/80211Init */
-static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm)
+static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm,
+                                     int active_wlcore)
 {
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
        struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
@@ -2939,19 +2892,26 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm)
        if (bcm->current_core->rev >= 5)
                bcm43xx_write16(bcm, 0x043C, 0x000C);
 
-       if (bcm43xx_using_pio(bcm))
-               err = bcm43xx_pio_init(bcm);
-       else
-               err = bcm43xx_dma_init(bcm);
-       if (err)
-               goto err_chip_cleanup;
+       if (active_wlcore) {
+               if (bcm43xx_using_pio(bcm))
+                       err = bcm43xx_pio_init(bcm);
+               else
+                       err = bcm43xx_dma_init(bcm);
+               if (err)
+                       goto err_chip_cleanup;
+       }
        bcm43xx_write16(bcm, 0x0612, 0x0050);
        bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050);
        bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4);
 
-       bcm43xx_mac_enable(bcm);
-       bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
+       if (active_wlcore) {
+               if (radio->initial_channel != 0xFF)
+                       bcm43xx_radio_selectchannel(bcm, radio->initial_channel, 0);
+       }
 
+       /* Don't enable MAC/IRQ here, as it will race with the IRQ handler.
+        * We enable it later.
+        */
        bcm->current_core->initialized = 1;
 out:
        return err;
@@ -3066,11 +3026,6 @@ out:
        return err;
 }
 
-static void bcm43xx_softmac_init(struct bcm43xx_private *bcm)
-{
-       ieee80211softmac_start(bcm->net_dev);
-}
-
 static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm)
 {
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
@@ -3182,39 +3137,40 @@ static void bcm43xx_periodic_work_handler(void *d)
                /* Periodic work will take a long time, so we want it to
                 * be preemtible.
                 */
-               bcm43xx_lock_irqonly(bcm, flags);
                netif_stop_queue(bcm->net_dev);
+               synchronize_net();
+               spin_lock_irqsave(&bcm->irq_lock, flags);
+               bcm43xx_mac_suspend(bcm);
                if (bcm43xx_using_pio(bcm))
                        bcm43xx_pio_freeze_txqueues(bcm);
                savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
-               bcm43xx_unlock_irqonly(bcm, flags);
-               bcm43xx_lock_noirq(bcm);
+               spin_unlock_irqrestore(&bcm->irq_lock, flags);
+               mutex_lock(&bcm->mutex);
                bcm43xx_synchronize_irq(bcm);
        } else {
                /* Periodic work should take short time, so we want low
                 * locking overhead.
                 */
-               bcm43xx_lock_irqsafe(bcm, flags);
+               mutex_lock(&bcm->mutex);
+               spin_lock_irqsave(&bcm->irq_lock, flags);
        }
 
        do_periodic_work(bcm);
 
        if (badness > BADNESS_LIMIT) {
-               bcm43xx_lock_irqonly(bcm, flags);
+               spin_lock_irqsave(&bcm->irq_lock, flags);
                if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
                        tasklet_enable(&bcm->isr_tasklet);
                        bcm43xx_interrupt_enable(bcm, savedirqs);
                        if (bcm43xx_using_pio(bcm))
                                bcm43xx_pio_thaw_txqueues(bcm);
+                       bcm43xx_mac_enable(bcm);
                }
                netif_wake_queue(bcm->net_dev);
-               mmiowb();
-               bcm43xx_unlock_irqonly(bcm, flags);
-               bcm43xx_unlock_noirq(bcm);
-       } else {
-               mmiowb();
-               bcm43xx_unlock_irqsafe(bcm, flags);
        }
+       mmiowb();
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
 }
 
 static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
@@ -3243,9 +3199,9 @@ static int bcm43xx_rng_read(struct hwrng *rng, u32 *data)
        struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv;
        unsigned long flags;
 
-       bcm43xx_lock_irqonly(bcm, flags);
+       spin_lock_irqsave(&(bcm)->irq_lock, flags);
        *data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG);
-       bcm43xx_unlock_irqonly(bcm, flags);
+       spin_unlock_irqrestore(&(bcm)->irq_lock, flags);
 
        return (sizeof(u16));
 }
@@ -3271,139 +3227,322 @@ static int bcm43xx_rng_init(struct bcm43xx_private *bcm)
        return err;
 }
 
-/* This is the opposite of bcm43xx_init_board() */
-static void bcm43xx_free_board(struct bcm43xx_private *bcm)
+static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm)
 {
+       int ret = 0;
        int i, err;
+       struct bcm43xx_coreinfo *core;
 
-       bcm43xx_lock_noirq(bcm);
+       bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);
+       for (i = 0; i < bcm->nr_80211_available; i++) {
+               core = &(bcm->core_80211[i]);
+               assert(core->available);
+               if (!core->initialized)
+                       continue;
+               err = bcm43xx_switch_core(bcm, core);
+               if (err) {
+                       dprintk(KERN_ERR PFX "shutdown_all_wireless_cores "
+                                            "switch_core failed (%d)\n", err);
+                       ret = err;
+                       continue;
+               }
+               bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+               bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+               bcm43xx_wireless_core_cleanup(bcm);
+               if (core == bcm->active_80211_core)
+                       bcm->active_80211_core = NULL;
+       }
+       free_irq(bcm->irq, bcm);
+       bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
+
+       return ret;
+}
+
+/* This is the opposite of bcm43xx_init_board() */
+static void bcm43xx_free_board(struct bcm43xx_private *bcm)
+{
        bcm43xx_sysfs_unregister(bcm);
        bcm43xx_periodic_tasks_delete(bcm);
 
-       bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);
+       mutex_lock(&(bcm)->mutex);
+       bcm43xx_shutdown_all_wireless_cores(bcm);
+       bcm43xx_pctl_set_crystal(bcm, 0);
+       mutex_unlock(&(bcm)->mutex);
+}
+
+static void prepare_phydata_for_init(struct bcm43xx_phyinfo *phy)
+{
+       phy->antenna_diversity = 0xFFFF;
+       memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
+       memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
+
+       /* Flags */
+       phy->calibrated = 0;
+       phy->is_locked = 0;
+
+       if (phy->_lo_pairs) {
+               memset(phy->_lo_pairs, 0,
+                      sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT);
+       }
+       memset(phy->loopback_gain, 0, sizeof(phy->loopback_gain));
+}
+
+static void prepare_radiodata_for_init(struct bcm43xx_private *bcm,
+                                      struct bcm43xx_radioinfo *radio)
+{
+       int i;
+
+       /* Set default attenuation values. */
+       radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm);
+       radio->radio_atten = bcm43xx_default_radio_attenuation(bcm);
+       radio->txctl1 = bcm43xx_default_txctl1(bcm);
+       radio->txctl2 = 0xFFFF;
+       radio->txpwr_offset = 0;
+
+       /* NRSSI */
+       radio->nrssislope = 0;
+       for (i = 0; i < ARRAY_SIZE(radio->nrssi); i++)
+               radio->nrssi[i] = -1000;
+       for (i = 0; i < ARRAY_SIZE(radio->nrssi_lt); i++)
+               radio->nrssi_lt[i] = i;
+
+       radio->lofcal = 0xFFFF;
+       radio->initval = 0xFFFF;
+
+       radio->aci_enable = 0;
+       radio->aci_wlan_automatic = 0;
+       radio->aci_hw_rssi = 0;
+}
+
+static void prepare_priv_for_init(struct bcm43xx_private *bcm)
+{
+       int i;
+       struct bcm43xx_coreinfo *core;
+       struct bcm43xx_coreinfo_80211 *wlext;
 
-       bcm43xx_rng_exit(bcm);
+       assert(!bcm->active_80211_core);
+
+       bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
+
+       /* Flags */
+       bcm->was_initialized = 0;
+       bcm->reg124_set_0x4 = 0;
+
+       /* Stats */
+       memset(&bcm->stats, 0, sizeof(bcm->stats));
+
+       /* Wireless core data */
        for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
-               if (!bcm->core_80211[i].available)
-                       continue;
-               if (!bcm->core_80211[i].initialized)
+               core = &(bcm->core_80211[i]);
+               wlext = core->priv;
+
+               if (!core->available)
                        continue;
+               assert(wlext == &(bcm->core_80211_ext[i]));
 
-               err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
-               assert(err == 0);
-               bcm43xx_wireless_core_cleanup(bcm);
+               prepare_phydata_for_init(&wlext->phy);
+               prepare_radiodata_for_init(bcm, &wlext->radio);
        }
 
-       bcm43xx_pctl_set_crystal(bcm, 0);
+       /* IRQ related flags */
+       bcm->irq_reason = 0;
+       memset(bcm->dma_reason, 0, sizeof(bcm->dma_reason));
+       bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
 
-       bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
-       bcm43xx_unlock_noirq(bcm);
+       /* Noise calculation context */
+       memset(&bcm->noisecalc, 0, sizeof(bcm->noisecalc));
+
+       /* Periodic work context */
+       bcm->periodic_state = 0;
 }
 
-static int bcm43xx_init_board(struct bcm43xx_private *bcm)
+static int wireless_core_up(struct bcm43xx_private *bcm,
+                           int active_wlcore)
+{
+       int err;
+
+       if (!bcm43xx_core_enabled(bcm))
+               bcm43xx_wireless_core_reset(bcm, 1);
+       if (!active_wlcore)
+               bcm43xx_wireless_core_mark_inactive(bcm);
+       err = bcm43xx_wireless_core_init(bcm, active_wlcore);
+       if (err)
+               goto out;
+       if (!active_wlcore)
+               bcm43xx_radio_turn_off(bcm);
+out:
+       return err;
+}
+
+/* Select and enable the "to be used" wireless core.
+ * Locking: bcm->mutex must be aquired before calling this.
+ *          bcm->irq_lock must not be aquired.
+ */
+int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
+                                int phytype)
 {
        int i, err;
-       int connect_phy;
+       struct bcm43xx_coreinfo *active_core = NULL;
+       struct bcm43xx_coreinfo_80211 *active_wlext = NULL;
+       struct bcm43xx_coreinfo *core;
+       struct bcm43xx_coreinfo_80211 *wlext;
+       int adjust_active_sbtmstatelow = 0;
 
        might_sleep();
 
-       bcm43xx_lock_noirq(bcm);
-       bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
+       if (phytype < 0) {
+               /* If no phytype is requested, select the first core. */
+               assert(bcm->core_80211[0].available);
+               wlext = bcm->core_80211[0].priv;
+               phytype = wlext->phy.type;
+       }
+       /* Find the requested core. */
+       for (i = 0; i < bcm->nr_80211_available; i++) {
+               core = &(bcm->core_80211[i]);
+               wlext = core->priv;
+               if (wlext->phy.type == phytype) {
+                       active_core = core;
+                       active_wlext = wlext;
+                       break;
+               }
+       }
+       if (!active_core)
+               return -ESRCH; /* No such PHYTYPE on this board. */
+
+       if (bcm->active_80211_core) {
+               /* We already selected a wl core in the past.
+                * So first clean up everything.
+                */
+               dprintk(KERN_INFO PFX "select_wireless_core: cleanup\n");
+               ieee80211softmac_stop(bcm->net_dev);
+               bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
+               err = bcm43xx_disable_interrupts_sync(bcm);
+               assert(!err);
+               tasklet_enable(&bcm->isr_tasklet);
+               err = bcm43xx_shutdown_all_wireless_cores(bcm);
+               if (err)
+                       goto error;
+               /* Ok, everything down, continue to re-initialize. */
+               bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
+       }
+
+       /* Reset all data structures. */
+       prepare_priv_for_init(bcm);
 
-       err = bcm43xx_pctl_set_crystal(bcm, 1);
-       if (err)
-               goto out;
-       err = bcm43xx_pctl_init(bcm);
-       if (err)
-               goto err_crystal_off;
        err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST);
        if (err)
-               goto err_crystal_off;
+               goto error;
 
-       tasklet_enable(&bcm->isr_tasklet);
+       /* Mark all unused cores "inactive". */
        for (i = 0; i < bcm->nr_80211_available; i++) {
-               err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
-               assert(err != -ENODEV);
-               if (err)
-                       goto err_80211_unwind;
+               core = &(bcm->core_80211[i]);
+               wlext = core->priv;
 
-               /* Enable the selected wireless core.
-                * Connect PHY only on the first core.
-                */
-               if (!bcm43xx_core_enabled(bcm)) {
-                       if (bcm->nr_80211_available == 1) {
-                               connect_phy = bcm43xx_current_phy(bcm)->connected;
-                       } else {
-                               if (i == 0)
-                                       connect_phy = 1;
-                               else
-                                       connect_phy = 0;
-                       }
-                       bcm43xx_wireless_core_reset(bcm, connect_phy);
+               if (core == active_core)
+                       continue;
+               err = bcm43xx_switch_core(bcm, core);
+               if (err) {
+                       dprintk(KERN_ERR PFX "Could not switch to inactive "
+                                            "802.11 core (%d)\n", err);
+                       goto error;
                }
+               err = wireless_core_up(bcm, 0);
+               if (err) {
+                       dprintk(KERN_ERR PFX "core_up for inactive 802.11 core "
+                                            "failed (%d)\n", err);
+                       goto error;
+               }
+               adjust_active_sbtmstatelow = 1;
+       }
 
-               if (i != 0)
-                       bcm43xx_wireless_core_mark_inactive(bcm, &bcm->core_80211[0]);
-
-               err = bcm43xx_wireless_core_init(bcm);
-               if (err)
-                       goto err_80211_unwind;
+       /* Now initialize the active 802.11 core. */
+       err = bcm43xx_switch_core(bcm, active_core);
+       if (err) {
+               dprintk(KERN_ERR PFX "Could not switch to active "
+                                    "802.11 core (%d)\n", err);
+               goto error;
+       }
+       if (adjust_active_sbtmstatelow &&
+           active_wlext->phy.type == BCM43xx_PHYTYPE_G) {
+               u32 sbtmstatelow;
 
-               if (i != 0) {
-                       bcm43xx_mac_suspend(bcm);
-                       bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
-                       bcm43xx_radio_turn_off(bcm);
-               }
+               sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+               sbtmstatelow |= 0x20000000;
+               bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
        }
-       bcm->active_80211_core = &bcm->core_80211[0];
-       if (bcm->nr_80211_available >= 2) {
-               bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
-               bcm43xx_mac_enable(bcm);
+       err = wireless_core_up(bcm, 1);
+       if (err) {
+               dprintk(KERN_ERR PFX "core_up for active 802.11 core "
+                                    "failed (%d)\n", err);
+               goto error;
        }
-       err = bcm43xx_rng_init(bcm);
+       err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC);
        if (err)
-               goto err_80211_unwind;
+               goto error;
+       bcm->active_80211_core = active_core;
+
        bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
        bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
-       dprintk(KERN_INFO PFX "80211 cores initialized\n");
        bcm43xx_security_init(bcm);
-       bcm43xx_softmac_init(bcm);
+       ieee80211softmac_start(bcm->net_dev);
 
-       bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC);
+       /* Let's go! Be careful after enabling the IRQs.
+        * Don't switch cores, for example.
+        */
+       bcm43xx_mac_enable(bcm);
+       bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
+       err = bcm43xx_initialize_irq(bcm);
+       if (err)
+               goto error;
+       bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
 
-       if (bcm43xx_current_radio(bcm)->initial_channel != 0xFF) {
-               bcm43xx_mac_suspend(bcm);
-               bcm43xx_radio_selectchannel(bcm, bcm43xx_current_radio(bcm)->initial_channel, 0);
-               bcm43xx_mac_enable(bcm);
-       }
+       dprintk(KERN_INFO PFX "Selected 802.11 core (phytype %d)\n",
+               active_wlext->phy.type);
 
-       /* Initialization of the board is done. Flag it as such. */
-       bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
+       return 0;
+
+error:
+       bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
+       bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
+       return err;
+}
+
+static int bcm43xx_init_board(struct bcm43xx_private *bcm)
+{
+       int err;
+
+       mutex_lock(&(bcm)->mutex);
+
+       tasklet_enable(&bcm->isr_tasklet);
+       err = bcm43xx_pctl_set_crystal(bcm, 1);
+       if (err)
+               goto err_tasklet;
+       err = bcm43xx_pctl_init(bcm);
+       if (err)
+               goto err_crystal_off;
+       err = bcm43xx_select_wireless_core(bcm, -1);
+       if (err)
+               goto err_crystal_off;
 
        bcm43xx_periodic_tasks_setup(bcm);
-       bcm43xx_sysfs_register(bcm);
-       //FIXME: check for bcm43xx_sysfs_register failure. This function is a bit messy regarding unwinding, though...
+       err = bcm43xx_sysfs_register(bcm);
+       if (err)
+               goto err_wlshutdown;
 
        /*FIXME: This should be handled by softmac instead. */
        schedule_work(&bcm->softmac->associnfo.work);
 
-       assert(err == 0);
 out:
-       bcm43xx_unlock_noirq(bcm);
+       mutex_unlock(&(bcm)->mutex);
 
        return err;
 
-err_80211_unwind:
-       tasklet_disable(&bcm->isr_tasklet);
-       /* unwind all 80211 initialization */
-       for (i = 0; i < bcm->nr_80211_available; i++) {
-               if (!bcm->core_80211[i].initialized)
-                       continue;
-               bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
-               bcm43xx_wireless_core_cleanup(bcm);
-       }
+err_wlshutdown:
+       bcm43xx_shutdown_all_wireless_cores(bcm);
 err_crystal_off:
        bcm43xx_pctl_set_crystal(bcm, 0);
+err_tasklet:
+       tasklet_disable(&bcm->isr_tasklet);
        goto out;
 }
 
@@ -3647,7 +3786,8 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev,
        struct bcm43xx_radioinfo *radio;
        unsigned long flags;
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
                bcm43xx_mac_suspend(bcm);
                bcm43xx_radio_selectchannel(bcm, channel, 0);
@@ -3656,7 +3796,8 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev,
                radio = bcm43xx_current_radio(bcm);
                radio->initial_channel = channel;
        }
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
 }
 
 /* set_security() callback in struct ieee80211_device */
@@ -3670,7 +3811,8 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
        
        dprintk(KERN_INFO PFX "set security called");
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
 
        for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
                if (sec->flags & (1<<keyidx)) {
@@ -3739,7 +3881,8 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
                } else
                                bcm43xx_clear_keys(bcm);
        }
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
 }
 
 /* hard_start_xmit() callback in struct ieee80211_device */
@@ -3751,10 +3894,10 @@ static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb,
        int err = -ENODEV;
        unsigned long flags;
 
-       bcm43xx_lock_irqonly(bcm, flags);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED))
                err = bcm43xx_tx(bcm, txb);
-       bcm43xx_unlock_irqonly(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
 
        return err;
 }
@@ -3769,9 +3912,9 @@ static void bcm43xx_net_tx_timeout(struct net_device *net_dev)
        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
        unsigned long flags;
 
-       bcm43xx_lock_irqonly(bcm, flags);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        bcm43xx_controller_restart(bcm, "TX timeout");
-       bcm43xx_unlock_irqonly(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3781,7 +3924,8 @@ static void bcm43xx_net_poll_controller(struct net_device *net_dev)
        unsigned long flags;
 
        local_irq_save(flags);
-       bcm43xx_interrupt_handler(bcm->irq, bcm, NULL);
+       if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
+               bcm43xx_interrupt_handler(bcm->irq, bcm, NULL);
        local_irq_restore(flags);
 }
 #endif /* CONFIG_NET_POLL_CONTROLLER */
@@ -3799,7 +3943,7 @@ static int bcm43xx_net_stop(struct net_device *net_dev)
        int err;
 
        ieee80211softmac_stop(net_dev);
-       err = bcm43xx_disable_interrupts_sync(bcm, NULL);
+       err = bcm43xx_disable_interrupts_sync(bcm);
        assert(!err);
        bcm43xx_free_board(bcm);
 
@@ -3818,10 +3962,12 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm,
        bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
 
        bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
+       bcm->mac_suspended = 1;
        bcm->pci_dev = pci_dev;
        bcm->net_dev = net_dev;
        bcm->bad_frames_preempt = modparam_bad_frames_preempt;
        spin_lock_init(&bcm->irq_lock);
+       spin_lock_init(&bcm->leds_lock);
        mutex_init(&bcm->mutex);
        tasklet_init(&bcm->isr_tasklet,
                     (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
@@ -3940,7 +4086,6 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
        bcm43xx_debugfs_remove_device(bcm);
        unregister_netdev(net_dev);
        bcm43xx_detach_board(bcm);
-       assert(bcm->ucode == NULL);
        free_ieee80211softmac(net_dev);
 }
 
@@ -3950,47 +4095,25 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
 static void bcm43xx_chip_reset(void *_bcm)
 {
        struct bcm43xx_private *bcm = _bcm;
-       struct net_device *net_dev = bcm->net_dev;
-       struct pci_dev *pci_dev = bcm->pci_dev;
+       struct bcm43xx_phyinfo *phy;
        int err;
-       int was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
 
-       netif_stop_queue(bcm->net_dev);
-       tasklet_disable(&bcm->isr_tasklet);
+       mutex_lock(&(bcm)->mutex);
+       phy = bcm43xx_current_phy(bcm);
+       err = bcm43xx_select_wireless_core(bcm, phy->type);
+       mutex_unlock(&(bcm)->mutex);
 
-       bcm->firmware_norelease = 1;
-       if (was_initialized)
-               bcm43xx_free_board(bcm);
-       bcm->firmware_norelease = 0;
-       bcm43xx_detach_board(bcm);
-       err = bcm43xx_init_private(bcm, net_dev, pci_dev);
-       if (err)
-               goto failure;
-       err = bcm43xx_attach_board(bcm);
-       if (err)
-               goto failure;
-       if (was_initialized) {
-               err = bcm43xx_init_board(bcm);
-               if (err)
-                       goto failure;
-       }
-       netif_wake_queue(bcm->net_dev);
-       printk(KERN_INFO PFX "Controller restarted\n");
-
-       return;
-failure:
-       printk(KERN_ERR PFX "Controller restart failed\n");
+       printk(KERN_ERR PFX "Controller restart%s\n",
+              (err == 0) ? "ed" : " failed");
 }
 
 /* Hard-reset the chip.
  * This can be called from interrupt or process context.
- * Make sure to _not_ re-enable device interrupts after this has been called.
-*/
+ */
 void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
 {
+       assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
        bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING);
-       bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
-       bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
        printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
        INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm);
        schedule_work(&bcm->restart_work);
@@ -4002,21 +4125,16 @@ static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct net_device *net_dev = pci_get_drvdata(pdev);
        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-       unsigned long flags;
-       int try_to_shutdown = 0, err;
+       int err;
 
        dprintk(KERN_INFO PFX "Suspending...\n");
 
-       bcm43xx_lock_irqsafe(bcm, flags);
-       bcm->was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
-       if (bcm->was_initialized)
-               try_to_shutdown = 1;
-       bcm43xx_unlock_irqsafe(bcm, flags);
-
        netif_device_detach(net_dev);
-       if (try_to_shutdown) {
+       bcm->was_initialized = 0;
+       if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
+               bcm->was_initialized = 1;
                ieee80211softmac_stop(net_dev);
-               err = bcm43xx_disable_interrupts_sync(bcm, &bcm->irq_savedstate);
+               err = bcm43xx_disable_interrupts_sync(bcm);
                if (unlikely(err)) {
                        dprintk(KERN_ERR PFX "Suspend failed.\n");
                        return -EAGAIN;
@@ -4049,17 +4167,14 @@ static int bcm43xx_resume(struct pci_dev *pdev)
        pci_restore_state(pdev);
 
        bcm43xx_chipset_attach(bcm);
-       if (bcm->was_initialized) {
-               bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
+       if (bcm->was_initialized)
                err = bcm43xx_init_board(bcm);
-       }
        if (err) {
                printk(KERN_ERR PFX "Resume failed!\n");
                return err;
        }
-
        netif_device_attach(net_dev);
-       
+
        dprintk(KERN_INFO PFX "Device resumed.\n");
 
        return 0;
index 116493671f88f00e41701348f59f3e8c0dc621b1..505c86e2007a3312c9674099666ef54ae8438bd8 100644 (file)
@@ -133,6 +133,9 @@ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm);
 
 int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core);
 
+int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
+                                int phytype);
+
 void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy);
 
 void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
index f8200deecc8a68020dfee39f87b5952c86f00988..eafd0f6626862ab5916f8ddd9906fd2e0b3c2450 100644 (file)
@@ -81,6 +81,16 @@ static const s8 bcm43xx_tssi2dbm_g_table[] = {
 static void bcm43xx_phy_initg(struct bcm43xx_private *bcm);
 
 
+static inline
+void bcm43xx_voluntary_preempt(void)
+{
+       assert(!in_atomic() && !in_irq() &&
+              !in_interrupt() && !irqs_disabled());
+#ifndef CONFIG_PREEMPT
+       cond_resched();
+#endif /* CONFIG_PREEMPT */
+}
+
 void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm)
 {
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
@@ -133,22 +143,14 @@ void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
 void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm)
 {
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-       unsigned long flags;
 
        bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */
        if (phy->calibrated)
                return;
        if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) {
-               /* We do not want to be preempted while calibrating
-                * the hardware.
-                */
-               local_irq_save(flags);
-
                bcm43xx_wireless_core_reset(bcm, 0);
                bcm43xx_phy_initg(bcm);
                bcm43xx_wireless_core_reset(bcm, 1);
-
-               local_irq_restore(flags);
        }
        phy->calibrated = 1;
 }
@@ -1299,7 +1301,9 @@ static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm)
 {
        int i;
        u16 ret = 0;
+       unsigned long flags;
 
+       local_irq_save(flags);
        for (i = 0; i < 10; i++){
                bcm43xx_phy_write(bcm, 0x0015, 0xAFA0);
                udelay(1);
@@ -1309,6 +1313,8 @@ static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm)
                udelay(40);
                ret += bcm43xx_phy_read(bcm, 0x002C);
        }
+       local_irq_restore(flags);
+       bcm43xx_voluntary_preempt();
 
        return ret;
 }
@@ -1435,6 +1441,7 @@ u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control)
        }
        ret = bcm43xx_phy_read(bcm, 0x002D);
        local_irq_restore(flags);
+       bcm43xx_voluntary_preempt();
 
        return ret;
 }
@@ -1760,6 +1767,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
                        bcm43xx_radio_write16(bcm, 0x43, i);
                        bcm43xx_radio_write16(bcm, 0x52, radio->txctl2);
                        udelay(10);
+                       bcm43xx_voluntary_preempt();
 
                        bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
 
@@ -1803,6 +1811,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
                                              radio->txctl2
                                              | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above?
                        udelay(10);
+                       bcm43xx_voluntary_preempt();
 
                        bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
 
@@ -1824,6 +1833,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
                bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2);
                udelay(2);
                bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3);
+               bcm43xx_voluntary_preempt();
        } else
                bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0);
        bcm43xx_phy_lo_adjust(bcm, is_initializing);
@@ -2188,12 +2198,6 @@ int bcm43xx_phy_init(struct bcm43xx_private *bcm)
 {
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
        int err = -ENODEV;
-       unsigned long flags;
-
-       /* We do not want to be preempted while calibrating
-        * the hardware.
-        */
-       local_irq_save(flags);
 
        switch (phy->type) {
        case BCM43xx_PHYTYPE_A:
@@ -2227,7 +2231,6 @@ int bcm43xx_phy_init(struct bcm43xx_private *bcm)
                err = 0;
                break;
        }
-       local_irq_restore(flags);
        if (err)
                printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n");
 
index 574085c461526927d97a1b896f2dbbb2f4df8b8e..c60c1743ea067d4b7535bc62ec331b1b63ba33fc 100644 (file)
@@ -262,7 +262,7 @@ static void tx_tasklet(unsigned long d)
        int err;
        u16 txctl;
 
-       bcm43xx_lock_irqonly(bcm, flags);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
 
        if (queue->tx_frozen)
                goto out_unlock;
@@ -300,7 +300,7 @@ static void tx_tasklet(unsigned long d)
                continue;
        }
 out_unlock:
-       bcm43xx_unlock_irqonly(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
 }
 
 static void setup_txqueues(struct bcm43xx_pioqueue *queue)
index 6a23bdc75412cf397a86cbffbe539be4efa924f8..ece335178f6a7483e81f142d2a24ef5128d0094d 100644 (file)
@@ -120,12 +120,14 @@ static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
                        GFP_KERNEL);
        if (!sprom)
                return -ENOMEM;
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        err = bcm43xx_sprom_read(bcm, sprom);
        if (!err)
                err = sprom2hex(sprom, buf, PAGE_SIZE);
        mmiowb();
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
        kfree(sprom);
 
        return err;
@@ -150,10 +152,14 @@ static ssize_t bcm43xx_attr_sprom_store(struct device *dev,
        err = hex2sprom(sprom, buf, count);
        if (err)
                goto out_kfree;
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
+       spin_lock(&bcm->leds_lock);
        err = bcm43xx_sprom_write(bcm, sprom);
        mmiowb();
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock(&bcm->leds_lock);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
 out_kfree:
        kfree(sprom);
 
@@ -176,7 +182,7 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
 
-       bcm43xx_lock_noirq(bcm);
+       mutex_lock(&bcm->mutex);
 
        switch (bcm43xx_current_radio(bcm)->interfmode) {
        case BCM43xx_RADIO_INTERFMODE_NONE:
@@ -193,7 +199,7 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
        }
        err = 0;
 
-       bcm43xx_unlock_noirq(bcm);
+       mutex_unlock(&bcm->mutex);
 
        return err ? err : count;
 
@@ -229,7 +235,8 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
                return -EINVAL;
        }
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
 
        err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
        if (err) {
@@ -237,7 +244,8 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
                                    "supported by device\n");
        }
        mmiowb();
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
 
        return err ? err : count;
 }
@@ -257,7 +265,7 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
 
-       bcm43xx_lock_noirq(bcm);
+       mutex_lock(&bcm->mutex);
 
        if (bcm->short_preamble)
                count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
@@ -265,7 +273,7 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
                count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
 
        err = 0;
-       bcm43xx_unlock_noirq(bcm);
+       mutex_unlock(&bcm->mutex);
 
        return err ? err : count;
 }
@@ -285,12 +293,14 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
        value = get_boolean(buf, count);
        if (value < 0)
                return value;
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
 
        bcm->short_preamble = !!value;
 
        err = 0;
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
 
        return err ? err : count;
 }
@@ -299,6 +309,70 @@ static DEVICE_ATTR(shortpreamble, 0644,
                   bcm43xx_attr_preamble_show,
                   bcm43xx_attr_preamble_store);
 
+static ssize_t bcm43xx_attr_phymode_store(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf, size_t count)
+{
+       struct bcm43xx_private *bcm = dev_to_bcm(dev);
+       int phytype;
+       int err = -EINVAL;
+
+       if (count < 1)
+               goto out;
+       switch (buf[0]) {
+       case 'a':  case 'A':
+               phytype = BCM43xx_PHYTYPE_A;
+               break;
+       case 'b':  case 'B':
+               phytype = BCM43xx_PHYTYPE_B;
+               break;
+       case 'g':  case 'G':
+               phytype = BCM43xx_PHYTYPE_G;
+               break;
+       default:
+               goto out;
+       }
+
+       mutex_lock(&(bcm)->mutex);
+       err = bcm43xx_select_wireless_core(bcm, phytype);
+       mutex_unlock(&(bcm)->mutex);
+       if (err == -ESRCH)
+               err = -ENODEV;
+
+out:
+       return err ? err : count;
+}
+
+static ssize_t bcm43xx_attr_phymode_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct bcm43xx_private *bcm = dev_to_bcm(dev);
+       ssize_t count = 0;
+
+       mutex_lock(&(bcm)->mutex);
+       switch (bcm43xx_current_phy(bcm)->type) {
+       case BCM43xx_PHYTYPE_A:
+               snprintf(buf, PAGE_SIZE, "A");
+               break;
+       case BCM43xx_PHYTYPE_B:
+               snprintf(buf, PAGE_SIZE, "B");
+               break;
+       case BCM43xx_PHYTYPE_G:
+               snprintf(buf, PAGE_SIZE, "G");
+               break;
+       default:
+               assert(0);
+       }
+       mutex_unlock(&(bcm)->mutex);
+
+       return count;
+}
+
+static DEVICE_ATTR(phymode, 0644,
+                  bcm43xx_attr_phymode_show,
+                  bcm43xx_attr_phymode_store);
+
 int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
 {
        struct device *dev = &bcm->pci_dev->dev;
@@ -315,9 +389,14 @@ int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
        err = device_create_file(dev, &dev_attr_shortpreamble);
        if (err)
                goto err_remove_interfmode;
+       err = device_create_file(dev, &dev_attr_phymode);
+       if (err)
+               goto err_remove_shortpreamble;
 
 out:
        return err;
+err_remove_shortpreamble:
+       device_remove_file(dev, &dev_attr_shortpreamble);
 err_remove_interfmode:
        device_remove_file(dev, &dev_attr_interference);
 err_remove_sprom:
@@ -329,6 +408,7 @@ void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm)
 {
        struct device *dev = &bcm->pci_dev->dev;
 
+       device_remove_file(dev, &dev_attr_phymode);
        device_remove_file(dev, &dev_attr_shortpreamble);
        device_remove_file(dev, &dev_attr_interference);
        device_remove_file(dev, &dev_attr_sprom);
index 5c36e29efff7e1082af46c193bd9b2255479da7e..1d3a3aaf96ec4bf9cc7a3aa3a29156fd7bde96d1 100644 (file)
@@ -47,6 +47,8 @@
 #define BCM43xx_WX_VERSION     18
 
 #define MAX_WX_STRING          80
+/* FIXME: the next line is a guess as to what the maximum RSSI value might be */
+#define RX_RSSI_MAX            60
 
 
 static int bcm43xx_wx_get_name(struct net_device *net_dev,
@@ -56,12 +58,11 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev,
 {
        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
        int i;
-       unsigned long flags;
        struct bcm43xx_phyinfo *phy;
        char suffix[7] = { 0 };
        int have_a = 0, have_b = 0, have_g = 0;
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
        for (i = 0; i < bcm->nr_80211_available; i++) {
                phy = &(bcm->core_80211_ext[i].phy);
                switch (phy->type) {
@@ -77,7 +78,7 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev,
                        assert(0);
                }
        }
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       mutex_unlock(&bcm->mutex);
 
        i = 0;
        if (have_a) {
@@ -111,7 +112,9 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
        int freq;
        int err = -EINVAL;
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
+
        if ((data->freq.m >= 0) && (data->freq.m <= 1000)) {
                channel = data->freq.m;
                freq = bcm43xx_channel_to_freq(bcm, channel);
@@ -131,7 +134,8 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
                err = 0;
        }
 out_unlock:
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
 
        return err;
 }
@@ -143,11 +147,10 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev,
 {
        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
        struct bcm43xx_radioinfo *radio;
-       unsigned long flags;
        int err = -ENODEV;
        u16 channel;
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
        radio = bcm43xx_current_radio(bcm);
        channel = radio->channel;
        if (channel == 0xFF) {
@@ -162,7 +165,7 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev,
 
        err = 0;
 out_unlock:
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       mutex_unlock(&bcm->mutex);
 
        return err;
 }
@@ -180,13 +183,15 @@ static int bcm43xx_wx_set_mode(struct net_device *net_dev,
        if (mode == IW_MODE_AUTO)
                mode = BCM43xx_INITIAL_IWMODE;
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
                if (bcm->ieee->iw_mode != mode)
                        bcm43xx_set_iwmode(bcm, mode);
        } else
                bcm->ieee->iw_mode = mode;
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
 
        return 0;
 }
@@ -197,11 +202,10 @@ static int bcm43xx_wx_get_mode(struct net_device *net_dev,
                               char *extra)
 {
        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-       unsigned long flags;
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
        data->mode = bcm->ieee->iw_mode;
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       mutex_unlock(&bcm->mutex);
 
        return 0;
 }
@@ -214,7 +218,6 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
        struct iw_range *range = (struct iw_range *)extra;
        const struct ieee80211_geo *geo;
-       unsigned long flags;
        int i, j;
        struct bcm43xx_phyinfo *phy;
 
@@ -226,15 +229,14 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
        range->throughput = 27 * 1000 * 1000;
 
        range->max_qual.qual = 100;
-       /* TODO: Real max RSSI */
-       range->max_qual.level = 3;
-       range->max_qual.noise = 100;
-       range->max_qual.updated = 7;
+       range->max_qual.level = 152; /* set floor at -104 dBm (152 - 256) */
+       range->max_qual.noise = 152;
+       range->max_qual.updated = IW_QUAL_ALL_UPDATED;
 
-       range->avg_qual.qual = 70;
-       range->avg_qual.level = 2;
-       range->avg_qual.noise = 40;
-       range->avg_qual.updated = 7;
+       range->avg_qual.qual = 50;
+       range->avg_qual.level = 0;
+       range->avg_qual.noise = 0;
+       range->avg_qual.updated = IW_QUAL_ALL_UPDATED;
 
        range->min_rts = BCM43xx_MIN_RTS_THRESHOLD;
        range->max_rts = BCM43xx_MAX_RTS_THRESHOLD;
@@ -254,7 +256,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
                          IW_ENC_CAPA_CIPHER_TKIP |
                          IW_ENC_CAPA_CIPHER_CCMP;
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
        phy = bcm43xx_current_phy(bcm);
 
        range->num_bitrates = 0;
@@ -301,7 +303,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
        }
        range->num_frequency = j;
 
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       mutex_unlock(&bcm->mutex);
 
        return 0;
 }
@@ -314,11 +316,11 @@ static int bcm43xx_wx_set_nick(struct net_device *net_dev,
        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
        size_t len;
 
-       bcm43xx_lock_noirq(bcm);
+       mutex_lock(&bcm->mutex);
        len =  min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
        memcpy(bcm->nick, extra, len);
        bcm->nick[len] = '\0';
-       bcm43xx_unlock_noirq(bcm);
+       mutex_unlock(&bcm->mutex);
 
        return 0;
 }
@@ -331,12 +333,12 @@ static int bcm43xx_wx_get_nick(struct net_device *net_dev,
        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
        size_t len;
 
-       bcm43xx_lock_noirq(bcm);
+       mutex_lock(&bcm->mutex);
        len = strlen(bcm->nick) + 1;
        memcpy(extra, bcm->nick, len);
        data->data.length = (__u16)len;
        data->data.flags = 1;
-       bcm43xx_unlock_noirq(bcm);
+       mutex_unlock(&bcm->mutex);
 
        return 0;
 }
@@ -350,7 +352,8 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev,
        unsigned long flags;
        int err = -EINVAL;
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        if (data->rts.disabled) {
                bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
                err = 0;
@@ -361,7 +364,8 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev,
                        err = 0;
                }
        }
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
 
        return err;
 }
@@ -372,13 +376,12 @@ static int bcm43xx_wx_get_rts(struct net_device *net_dev,
                              char *extra)
 {
        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-       unsigned long flags;
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
        data->rts.value = bcm->rts_threshold;
        data->rts.fixed = 0;
        data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       mutex_unlock(&bcm->mutex);
 
        return 0;
 }
@@ -392,7 +395,8 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev,
        unsigned long flags;
        int err = -EINVAL;
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        if (data->frag.disabled) {
                bcm->ieee->fts = MAX_FRAG_THRESHOLD;
                err = 0;
@@ -403,7 +407,8 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev,
                        err = 0;
                }
        }
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
 
        return err;
 }
@@ -414,13 +419,12 @@ static int bcm43xx_wx_get_frag(struct net_device *net_dev,
                               char *extra)
 {
        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-       unsigned long flags;
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
        data->frag.value = bcm->ieee->fts;
        data->frag.fixed = 0;
        data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       mutex_unlock(&bcm->mutex);
 
        return 0;
 }
@@ -442,7 +446,8 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
                return -EOPNOTSUPP;
        }
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
                goto out_unlock;
        radio = bcm43xx_current_radio(bcm);
@@ -466,7 +471,8 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
        err = 0;
 
 out_unlock:
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
 
        return err;
 }
@@ -478,10 +484,9 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev,
 {
        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
        struct bcm43xx_radioinfo *radio;
-       unsigned long flags;
        int err = -ENODEV;
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
        if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
                goto out_unlock;
        radio = bcm43xx_current_radio(bcm);
@@ -493,7 +498,7 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev,
 
        err = 0;
 out_unlock:
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       mutex_unlock(&bcm->mutex);
 
        return err;
 }
@@ -580,7 +585,8 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev,
                return -EINVAL;
        }
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
                err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
                if (err) {
@@ -595,7 +601,8 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev,
                } else
                        bcm43xx_current_radio(bcm)->interfmode = mode;
        }
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
 
        return err;
 }
@@ -606,12 +613,11 @@ static int bcm43xx_wx_get_interfmode(struct net_device *net_dev,
                                     char *extra)
 {
        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-       unsigned long flags;
        int mode;
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
        mode = bcm43xx_current_radio(bcm)->interfmode;
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       mutex_unlock(&bcm->mutex);
 
        switch (mode) {
        case BCM43xx_RADIO_INTERFMODE_NONE:
@@ -641,9 +647,11 @@ static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev,
        int on;
 
        on = *((int *)extra);
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        bcm->short_preamble = !!on;
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
 
        return 0;
 }
@@ -654,12 +662,11 @@ static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev,
                                        char *extra)
 {
        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-       unsigned long flags;
        int on;
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
        on = bcm->short_preamble;
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       mutex_unlock(&bcm->mutex);
 
        if (on)
                strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
@@ -681,11 +688,13 @@ static int bcm43xx_wx_set_swencryption(struct net_device *net_dev,
        
        on = *((int *)extra);
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        bcm->ieee->host_encrypt = !!on;
        bcm->ieee->host_decrypt = !!on;
        bcm->ieee->host_build_iv = !on;
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
 
        return 0;
 }
@@ -696,12 +705,11 @@ static int bcm43xx_wx_get_swencryption(struct net_device *net_dev,
                                       char *extra)
 {
        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-       unsigned long flags;
        int on;
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
        on = bcm->ieee->host_encrypt;
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       mutex_unlock(&bcm->mutex);
 
        if (on)
                strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
@@ -764,11 +772,13 @@ static int bcm43xx_wx_sprom_read(struct net_device *net_dev,
        if (!sprom)
                goto out;
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
        err = -ENODEV;
        if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
                err = bcm43xx_sprom_read(bcm, sprom);
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
        if (!err)
                data->data.length = sprom2hex(sprom, extra);
        kfree(sprom);
@@ -809,11 +819,15 @@ static int bcm43xx_wx_sprom_write(struct net_device *net_dev,
        if (err)
                goto out_kfree;
 
-       bcm43xx_lock_irqsafe(bcm, flags);
+       mutex_lock(&bcm->mutex);
+       spin_lock_irqsave(&bcm->irq_lock, flags);
+       spin_lock(&bcm->leds_lock);
        err = -ENODEV;
        if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
                err = bcm43xx_sprom_write(bcm, sprom);
-       bcm43xx_unlock_irqsafe(bcm, flags);
+       spin_unlock(&bcm->leds_lock);
+       spin_unlock_irqrestore(&bcm->irq_lock, flags);
+       mutex_unlock(&bcm->mutex);
 out_kfree:
        kfree(sprom);
 out:
@@ -827,6 +841,10 @@ static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_d
        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
        struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
        struct iw_statistics *wstats;
+       struct ieee80211_network *network = NULL;
+       static int tmp_level = 0;
+       static int tmp_qual = 0;
+       unsigned long flags;
 
        wstats = &bcm->stats.wstats;
        if (!mac->associated) {
@@ -844,16 +862,28 @@ static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_d
                wstats->qual.level = 0;
                wstats->qual.noise = 0;
                wstats->qual.updated = 7;
-               wstats->qual.updated |= IW_QUAL_NOISE_INVALID |
-                       IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
+               wstats->qual.updated |= IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
                return wstats;
        }
        /* fill in the real statistics when iface associated */
-       wstats->qual.qual = 100;     // TODO: get the real signal quality
-       wstats->qual.level = 3 - bcm->stats.link_quality;
+       spin_lock_irqsave(&mac->ieee->lock, flags);
+       list_for_each_entry(network, &mac->ieee->network_list, list) {
+               if (!memcmp(mac->associnfo.bssid, network->bssid, ETH_ALEN)) {
+                       if (!tmp_level) {       /* get initial values */
+                               tmp_level = network->stats.signal;
+                               tmp_qual = network->stats.rssi;
+                       } else {                /* smooth results */
+                               tmp_level = (15 * tmp_level + network->stats.signal)/16;
+                               tmp_qual = (15 * tmp_qual + network->stats.rssi)/16;
+                       }
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&mac->ieee->lock, flags);
+       wstats->qual.level = tmp_level;
+       wstats->qual.qual = 100 * tmp_qual / RX_RSSI_MAX;
        wstats->qual.noise = bcm->stats.noise;
-       wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
-                       IW_QUAL_NOISE_UPDATED;
+       wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
        wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable;
        wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded;
        wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa;
index 6dbd855b3647b0f80163c5c48893d051b6ae19e5..c0efbfe605a5a20d3996a5f173a9e4657aac3dde 100644 (file)
@@ -492,16 +492,15 @@ int bcm43xx_rx(struct bcm43xx_private *bcm,
 
        memset(&stats, 0, sizeof(stats));
        stats.mac_time = le16_to_cpu(rxhdr->mactime);
-       stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
+       stats.rssi = rxhdr->rssi;
+       stats.signal = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
                                              !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
                                              !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
-       stats.signal = rxhdr->signal_quality;   //FIXME
 //TODO stats.noise = 
        if (is_ofdm)
                stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
        else
                stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
-//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate);
        stats.received_channel = radio->channel;
 //TODO stats.control = 
        stats.mask = IEEE80211_STATMASK_SIGNAL |
index dafaa5ff5aa693d065f85cc4777e1c53c3c7054a..d500012fdc7a5446aef8315c5dc7172ee4b2eb8e 100644 (file)
@@ -1042,6 +1042,9 @@ static int prism2_reset_port(struct net_device *dev)
                       dev->name, local->fragm_threshold);
        }
 
+       /* Some firmwares lose antenna selection settings on reset */
+       (void) hostap_set_antsel(local);
+
        return res;
 }
 
index e955db435b30b4ef9e2c87106790ada253582fa6..5f8ccf48061abe6e58336389a6a53470c23e910b 100644 (file)
@@ -6531,7 +6531,7 @@ static int __init ipw2100_init(void)
        printk(KERN_INFO DRV_NAME ": %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
        printk(KERN_INFO DRV_NAME ": %s\n", DRV_COPYRIGHT);
 
-       ret = pci_module_init(&ipw2100_pci_driver);
+       ret = pci_register_driver(&ipw2100_pci_driver);
 
 #ifdef CONFIG_IPW2100_DEBUG
        ipw2100_debug_level = debug;
index b3300ffe4eecb8dc888091255d4fbda501ce7efc..a72f3e1e991bcd54410e4fa0bd992b5b1d7d3e7f 100644 (file)
@@ -2667,7 +2667,7 @@ static void ipw_fw_dma_abort(struct ipw_priv *priv)
 
        IPW_DEBUG_FW(">> :\n");
 
-       //set the Stop and Abort bit
+       /* set the Stop and Abort bit */
        control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_STOP_AND_ABORT;
        ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control);
        priv->sram_desc.last_cb_index = 0;
@@ -3002,8 +3002,6 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len)
        if (rc < 0)
                return rc;
 
-//      spin_lock_irqsave(&priv->lock, flags);
-
        for (addr = IPW_SHARED_LOWER_BOUND;
             addr < IPW_REGISTER_DOMAIN1_END; addr += 4) {
                ipw_write32(priv, addr, 0);
@@ -3097,8 +3095,6 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len)
           firmware have problem getting alive resp. */
        ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0);
 
-//      spin_unlock_irqrestore(&priv->lock, flags);
-
        return rc;
 }
 
@@ -6387,13 +6383,6 @@ static int ipw_wx_set_genie(struct net_device *dev,
            (wrqu->data.length && extra == NULL))
                return -EINVAL;
 
-       //mutex_lock(&priv->mutex);
-
-       //if (!ieee->wpa_enabled) {
-       //      err = -EOPNOTSUPP;
-       //      goto out;
-       //}
-
        if (wrqu->data.length) {
                buf = kmalloc(wrqu->data.length, GFP_KERNEL);
                if (buf == NULL) {
@@ -6413,7 +6402,6 @@ static int ipw_wx_set_genie(struct net_device *dev,
 
        ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len);
       out:
-       //mutex_unlock(&priv->mutex);
        return err;
 }
 
@@ -6426,13 +6414,6 @@ static int ipw_wx_get_genie(struct net_device *dev,
        struct ieee80211_device *ieee = priv->ieee;
        int err = 0;
 
-       //mutex_lock(&priv->mutex);
-
-       //if (!ieee->wpa_enabled) {
-       //      err = -EOPNOTSUPP;
-       //      goto out;
-       //}
-
        if (ieee->wpa_ie_len == 0 || ieee->wpa_ie == NULL) {
                wrqu->data.length = 0;
                goto out;
@@ -6447,7 +6428,6 @@ static int ipw_wx_get_genie(struct net_device *dev,
        memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len);
 
       out:
-       //mutex_unlock(&priv->mutex);
        return err;
 }
 
@@ -6558,7 +6538,6 @@ static int ipw_wx_set_auth(struct net_device *dev,
                ieee->ieee802_1x = param->value;
                break;
 
-               //case IW_AUTH_ROAMING_CONTROL:
        case IW_AUTH_PRIVACY_INVOKED:
                ieee->privacy_invoked = param->value;
                break;
@@ -6680,7 +6659,7 @@ static int ipw_wx_set_mlme(struct net_device *dev,
 
        switch (mlme->cmd) {
        case IW_MLME_DEAUTH:
-               // silently ignore
+               /* silently ignore */
                break;
 
        case IW_MLME_DISASSOC:
@@ -9766,7 +9745,7 @@ static int ipw_wx_set_monitor(struct net_device *dev,
        return 0;
 }
 
-#endif                         // CONFIG_IPW2200_MONITOR
+#endif                         /* CONFIG_IPW2200_MONITOR */
 
 static int ipw_wx_reset(struct net_device *dev,
                        struct iw_request_info *info,
@@ -10009,7 +9988,7 @@ static  void init_sys_config(struct ipw_sys_config *sys_config)
        sys_config->dot11g_auto_detection = 0;
        sys_config->enable_cts_to_self = 0;
        sys_config->bt_coexist_collision_thr = 0;
-       sys_config->pass_noise_stats_to_host = 1;       //1 -- fix for 256
+       sys_config->pass_noise_stats_to_host = 1;       /* 1 -- fix for 256 */
        sys_config->silence_threshold = 0x1e;
 }
 
@@ -11774,7 +11753,7 @@ static int __init ipw_init(void)
        printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
        printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
 
-       ret = pci_module_init(&ipw_driver);
+       ret = pci_register_driver(&ipw_driver);
        if (ret) {
                IPW_ERROR("Unable to initialize PCI module\n");
                return ret;
index bf05b907747eaae6e1f7ce03ec12584b465371e9..eaf3d13b851cc2288a75736bc4b349c2dae74b76 100644 (file)
@@ -304,7 +304,7 @@ MODULE_LICENSE("Dual MPL/GPL");
 static int __init orinoco_nortel_init(void)
 {
        printk(KERN_DEBUG "%s\n", version);
-       return pci_module_init(&orinoco_nortel_driver);
+       return pci_register_driver(&orinoco_nortel_driver);
 }
 
 static void __exit orinoco_nortel_exit(void)
index 1759c543fbee9bc6da6ed8bc2572cd765edc12e5..97a8b4ff32bd88d59b87a3deeb87d060385cb168 100644 (file)
@@ -244,7 +244,7 @@ MODULE_LICENSE("Dual MPL/GPL");
 static int __init orinoco_pci_init(void)
 {
        printk(KERN_DEBUG "%s\n", version);
-       return pci_module_init(&orinoco_pci_driver);
+       return pci_register_driver(&orinoco_pci_driver);
 }
 
 static void __exit orinoco_pci_exit(void)
index 7f006f6241711d0d6ad52e013d976e7284219b70..31162ac25a92fe32d7d4ddfbe26d8a2e961f04f3 100644 (file)
@@ -351,7 +351,7 @@ MODULE_LICENSE("Dual MPL/GPL");
 static int __init orinoco_plx_init(void)
 {
        printk(KERN_DEBUG "%s\n", version);
-       return pci_module_init(&orinoco_plx_driver);
+       return pci_register_driver(&orinoco_plx_driver);
 }
 
 static void __exit orinoco_plx_exit(void)
index 0831721e4d6ccf38e5e5052190cd09d41e4df8d7..7c7b960c91dfe057a2459d97f78ccf8a12204065 100644 (file)
@@ -228,7 +228,7 @@ MODULE_LICENSE("Dual MPL/GPL");
 static int __init orinoco_tmd_init(void)
 {
        printk(KERN_DEBUG "%s\n", version);
-       return pci_module_init(&orinoco_tmd_driver);
+       return pci_register_driver(&orinoco_tmd_driver);
 }
 
 static void __exit orinoco_tmd_exit(void)
index 989599ad33ef076e875ad944e41df82345ae19df..0c30fe7e8f7fed8289036584a015f7293315da72 100644 (file)
 
 #include <net/iw_handler.h>    /* New driver API */
 
+#define KEY_SIZE_WEP104 13     /* 104/128-bit WEP keys */
+#define KEY_SIZE_WEP40  5      /* 40/64-bit WEP keys */
+/* KEY_SIZE_TKIP should match isl_oid.h, struct obj_key.key[] size */
+#define KEY_SIZE_TKIP   32     /* TKIP keys */
 
-static void prism54_wpa_ie_add(islpci_private *priv, u8 *bssid,
+static void prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
                                u8 *wpa_ie, size_t wpa_ie_len);
-static size_t prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie);
+static size_t prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie);
 static int prism54_set_wpa(struct net_device *, struct iw_request_info *,
                                __u32 *, char *);
 
@@ -468,6 +472,9 @@ prism54_get_range(struct net_device *ndev, struct iw_request_info *info,
        range->event_capa[1] = IW_EVENT_CAPA_K_1;
        range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVCUSTOM);
 
+       range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+               IW_ENC_CAPA_CIPHER_TKIP;
+
        if (islpci_get_state(priv) < PRV_STATE_INIT)
                return 0;
 
@@ -567,6 +574,8 @@ prism54_translate_bss(struct net_device *ndev, char *current_ev,
        struct iw_event iwe;    /* Temporary buffer */
        short cap;
        islpci_private *priv = netdev_priv(ndev);
+       u8 wpa_ie[MAX_WPA_IE_LEN];
+       size_t wpa_ie_len;
 
        /* The first entry must be the MAC address */
        memcpy(iwe.u.ap_addr.sa_data, bss->address, 6);
@@ -627,27 +636,13 @@ prism54_translate_bss(struct net_device *ndev, char *current_ev,
        current_ev =
            iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
 
-       if (priv->wpa) {
-               u8 wpa_ie[MAX_WPA_IE_LEN];
-               char *buf, *p;
-               size_t wpa_ie_len;
-               int i;
-
-               wpa_ie_len = prism54_wpa_ie_get(priv, bss->address, wpa_ie);
-               if (wpa_ie_len > 0 &&
-                   (buf = kmalloc(wpa_ie_len * 2 + 10, GFP_ATOMIC))) {
-                       p = buf;
-                       p += sprintf(p, "wpa_ie=");
-                       for (i = 0; i < wpa_ie_len; i++) {
-                               p += sprintf(p, "%02x", wpa_ie[i]);
-                       }
-                       memset(&iwe, 0, sizeof (iwe));
-                       iwe.cmd = IWEVCUSTOM;
-                       iwe.u.data.length = strlen(buf);
-                       current_ev = iwe_stream_add_point(current_ev, end_buf,
-                                                         &iwe, buf);
-                       kfree(buf);
-               }
+       /* Add WPA/RSN Information Element, if any */
+       wpa_ie_len = prism54_wpa_bss_ie_get(priv, bss->address, wpa_ie);
+       if (wpa_ie_len > 0) {
+               iwe.cmd = IWEVGENIE;
+               iwe.u.data.length = min(wpa_ie_len, (size_t)MAX_WPA_IE_LEN);
+               current_ev = iwe_stream_add_point(current_ev, end_buf,
+                               &iwe, wpa_ie);
        }
        return current_ev;
 }
@@ -1051,12 +1046,24 @@ prism54_set_encode(struct net_device *ndev, struct iw_request_info *info,
                current_index = r.u;
                /* Verify that the key is not marked as invalid */
                if (!(dwrq->flags & IW_ENCODE_NOKEY)) {
-                       key.length = dwrq->length > sizeof (key.key) ?
-                           sizeof (key.key) : dwrq->length;
-                       memcpy(key.key, extra, key.length);
-                       if (key.length == 32)
-                               /* we want WPA-PSK */
+                       if (dwrq->length > KEY_SIZE_TKIP) {
+                               /* User-provided key data too big */
+                               return -EINVAL;
+                       }
+                       if (dwrq->length > KEY_SIZE_WEP104) {
+                               /* WPA-PSK TKIP */
                                key.type = DOT11_PRIV_TKIP;
+                               key.length = KEY_SIZE_TKIP;
+                       } else if (dwrq->length > KEY_SIZE_WEP40) {
+                               /* WEP 104/128 */
+                               key.length = KEY_SIZE_WEP104;
+                       } else {
+                               /* WEP 40/64 */
+                               key.length = KEY_SIZE_WEP40;
+                       }
+                       memset(key.key, 0, sizeof (key.key));
+                       memcpy(key.key, extra, dwrq->length);
+
                        if ((index < 0) || (index > 3))
                                /* no index provided use the current one */
                                index = current_index;
@@ -1210,6 +1217,489 @@ prism54_set_txpower(struct net_device *ndev, struct iw_request_info *info,
        }
 }
 
+static int prism54_set_genie(struct net_device *ndev,
+                            struct iw_request_info *info,
+                            struct iw_point *data, char *extra)
+{
+       islpci_private *priv = netdev_priv(ndev);
+       int alen, ret = 0;
+       struct obj_attachment *attach;
+
+       if (data->length > MAX_WPA_IE_LEN ||
+           (data->length && extra == NULL))
+               return -EINVAL;
+
+       memcpy(priv->wpa_ie, extra, data->length);
+       priv->wpa_ie_len = data->length;
+
+       alen = sizeof(*attach) + priv->wpa_ie_len;
+       attach = kzalloc(alen, GFP_KERNEL);
+       if (attach == NULL)
+               return -ENOMEM;
+
+#define WLAN_FC_TYPE_MGMT 0
+#define WLAN_FC_STYPE_ASSOC_REQ 0
+#define WLAN_FC_STYPE_REASSOC_REQ 2
+
+       /* Note: endianness is covered by mgt_set_varlen */
+       attach->type = (WLAN_FC_TYPE_MGMT << 2) |
+               (WLAN_FC_STYPE_ASSOC_REQ << 4);
+       attach->id = -1;
+       attach->size = priv->wpa_ie_len;
+       memcpy(attach->data, extra, priv->wpa_ie_len);
+
+       ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach,
+               priv->wpa_ie_len);
+       if (ret == 0) {
+               attach->type = (WLAN_FC_TYPE_MGMT << 2) |
+                       (WLAN_FC_STYPE_REASSOC_REQ << 4);
+
+               ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach,
+                       priv->wpa_ie_len);
+               if (ret == 0)
+                       printk(KERN_DEBUG "%s: WPA IE Attachment was set\n",
+                               ndev->name);
+       }
+
+       kfree(attach);
+       return ret;
+}
+
+
+static int prism54_get_genie(struct net_device *ndev,
+                            struct iw_request_info *info,
+                            struct iw_point *data, char *extra)
+{
+       islpci_private *priv = netdev_priv(ndev);
+       int len = priv->wpa_ie_len;
+
+       if (len <= 0) {
+               data->length = 0;
+               return 0;
+       }
+
+       if (data->length < len)
+               return -E2BIG;
+
+       data->length = len;
+       memcpy(extra, priv->wpa_ie, len);
+
+       return 0;
+}
+
+static int prism54_set_auth(struct net_device *ndev,
+                              struct iw_request_info *info,
+                              union iwreq_data *wrqu, char *extra)
+{
+       islpci_private *priv = netdev_priv(ndev);
+       struct iw_param *param = &wrqu->param;
+       u32 mlmelevel = 0, authen = 0, dot1x = 0;
+       u32 exunencrypt = 0, privinvoked = 0, wpa = 0;
+       u32 old_wpa;
+       int ret = 0;
+       union oid_res_t r;
+
+       if (islpci_get_state(priv) < PRV_STATE_INIT)
+               return 0;
+
+       /* first get the flags */
+       down_write(&priv->mib_sem);
+       wpa = old_wpa = priv->wpa;
+       up_write(&priv->mib_sem);
+       ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r);
+       authen = r.u;
+       ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r);
+       privinvoked = r.u;
+       ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r);
+       exunencrypt = r.u;
+       ret = mgt_get_request(priv, DOT11_OID_DOT1XENABLE, 0, NULL, &r);
+       dot1x = r.u;
+       ret = mgt_get_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, NULL, &r);
+       mlmelevel = r.u;
+
+       if (ret < 0)
+               goto out;
+
+       switch (param->flags & IW_AUTH_INDEX) {
+       case IW_AUTH_CIPHER_PAIRWISE:
+       case IW_AUTH_CIPHER_GROUP:
+       case IW_AUTH_KEY_MGMT:
+               break;
+
+       case IW_AUTH_WPA_ENABLED:
+               /* Do the same thing as IW_AUTH_WPA_VERSION */
+               if (param->value) {
+                       wpa = 1;
+                       privinvoked = 1; /* For privacy invoked */
+                       exunencrypt = 1; /* Filter out all unencrypted frames */
+                       dot1x = 0x01; /* To enable eap filter */
+                       mlmelevel = DOT11_MLME_EXTENDED;
+                       authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */
+               } else {
+                       wpa = 0;
+                       privinvoked = 0;
+                       exunencrypt = 0; /* Do not filter un-encrypted data */
+                       dot1x = 0;
+                       mlmelevel = DOT11_MLME_AUTO;
+               }
+               break;
+
+       case IW_AUTH_WPA_VERSION:
+               if (param->value & IW_AUTH_WPA_VERSION_DISABLED) {
+                       wpa = 0;
+                       privinvoked = 0;
+                       exunencrypt = 0; /* Do not filter un-encrypted data */
+                       dot1x = 0;
+                       mlmelevel = DOT11_MLME_AUTO;
+               } else {
+                       if (param->value & IW_AUTH_WPA_VERSION_WPA)
+                               wpa = 1;
+                       else if (param->value & IW_AUTH_WPA_VERSION_WPA2)
+                               wpa = 2;
+                       privinvoked = 1; /* For privacy invoked */
+                       exunencrypt = 1; /* Filter out all unencrypted frames */
+                       dot1x = 0x01; /* To enable eap filter */
+                       mlmelevel = DOT11_MLME_EXTENDED;
+                       authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */
+               }
+               break;
+
+       case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+               dot1x = param->value ? 1 : 0;
+               break;
+
+       case IW_AUTH_PRIVACY_INVOKED:
+               privinvoked = param->value ? 1 : 0;
+
+       case IW_AUTH_DROP_UNENCRYPTED:
+               exunencrypt = param->value ? 1 : 0;
+               break;
+
+       case IW_AUTH_80211_AUTH_ALG:
+               if (param->value & IW_AUTH_ALG_SHARED_KEY) {
+                       /* Only WEP uses _SK and _BOTH */
+                       if (wpa > 0) {
+                               ret = -EINVAL;
+                               goto out;
+                       }
+                       authen = DOT11_AUTH_SK;
+               } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
+                       authen = DOT11_AUTH_OS;
+               } else {
+                       ret = -EINVAL;
+                       goto out;
+               }
+               break;
+
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       /* Set all the values */
+       down_write(&priv->mib_sem);
+       priv->wpa = wpa;
+       up_write(&priv->mib_sem);
+       mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen);
+       mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &privinvoked);
+       mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, &exunencrypt);
+       mgt_set_request(priv, DOT11_OID_DOT1XENABLE, 0, &dot1x);
+       mgt_set_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, &mlmelevel);
+
+out:
+       return ret;
+}
+
+static int prism54_get_auth(struct net_device *ndev,
+                           struct iw_request_info *info,
+                           union iwreq_data *wrqu, char *extra)
+{
+       islpci_private *priv = netdev_priv(ndev);
+       struct iw_param *param = &wrqu->param;
+       u32 wpa = 0;
+       int ret = 0;
+       union oid_res_t r;
+
+       if (islpci_get_state(priv) < PRV_STATE_INIT)
+               return 0;
+
+       /* first get the flags */
+       down_write(&priv->mib_sem);
+       wpa = priv->wpa;
+       up_write(&priv->mib_sem);
+
+       switch (param->flags & IW_AUTH_INDEX) {
+       case IW_AUTH_CIPHER_PAIRWISE:
+       case IW_AUTH_CIPHER_GROUP:
+       case IW_AUTH_KEY_MGMT:
+               /*
+                * wpa_supplicant will control these internally
+                */
+               ret = -EOPNOTSUPP;
+               break;
+
+       case IW_AUTH_WPA_VERSION:
+               switch (wpa) {
+               case 1:
+                       param->value = IW_AUTH_WPA_VERSION_WPA;
+                       break;
+               case 2:
+                       param->value = IW_AUTH_WPA_VERSION_WPA2;
+                       break;
+               case 0:
+               default:
+                       param->value = IW_AUTH_WPA_VERSION_DISABLED;
+                       break;
+               }
+               break;
+
+       case IW_AUTH_DROP_UNENCRYPTED:
+               ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r);
+               if (ret >= 0)
+                       param->value = r.u > 0 ? 1 : 0;
+               break;
+
+       case IW_AUTH_80211_AUTH_ALG:
+               ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r);
+               if (ret >= 0) {
+                       switch (r.u) {
+                       case DOT11_AUTH_OS:
+                               param->value = IW_AUTH_ALG_OPEN_SYSTEM;
+                               break;
+                       case DOT11_AUTH_BOTH:
+                       case DOT11_AUTH_SK:
+                               param->value = IW_AUTH_ALG_SHARED_KEY;
+                       case DOT11_AUTH_NONE:
+                       default:
+                               param->value = 0;
+                               break;
+                       }
+               }
+               break;
+
+       case IW_AUTH_WPA_ENABLED:
+               param->value = wpa > 0 ? 1 : 0;
+               break;
+
+       case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+               ret = mgt_get_request(priv, DOT11_OID_DOT1XENABLE, 0, NULL, &r);
+               if (ret >= 0)
+                       param->value = r.u > 0 ? 1 : 0;
+               break;
+
+       case IW_AUTH_PRIVACY_INVOKED:
+               ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r);
+               if (ret >= 0)
+                       param->value = r.u > 0 ? 1 : 0;
+               break;
+
+       default:
+               return -EOPNOTSUPP;
+       }
+       return ret;
+}
+
+static int prism54_set_encodeext(struct net_device *ndev,
+                                struct iw_request_info *info,
+                                union iwreq_data *wrqu,
+                                char *extra)
+{
+       islpci_private *priv = netdev_priv(ndev);
+       struct iw_point *encoding = &wrqu->encoding;
+       struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+       int idx, alg = ext->alg, set_key = 1;
+       union oid_res_t r;
+       int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0;
+       int ret = 0;
+
+       if (islpci_get_state(priv) < PRV_STATE_INIT)
+               return 0;
+
+       /* Determine and validate the key index */
+       idx = (encoding->flags & IW_ENCODE_INDEX) - 1;
+       if (idx) {
+               if (idx < 0 || idx > 3)
+                       return -EINVAL;
+       } else {
+               ret = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r);
+               if (ret < 0)
+                       goto out;
+               idx = r.u;
+       }
+
+       if (encoding->flags & IW_ENCODE_DISABLED)
+               alg = IW_ENCODE_ALG_NONE;
+
+       if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+               /* Only set transmit key index here, actual
+                * key is set below if needed.
+                */
+               ret = mgt_set_request(priv, DOT11_OID_DEFKEYID, 0, &idx);
+               set_key = ext->key_len > 0 ? 1 : 0;
+       }
+
+       if (set_key) {
+               struct obj_key key = { DOT11_PRIV_WEP, 0, "" };
+               switch (alg) {
+               case IW_ENCODE_ALG_NONE:
+                       break;
+               case IW_ENCODE_ALG_WEP:
+                       if (ext->key_len > KEY_SIZE_WEP104) {
+                               ret = -EINVAL;
+                               goto out;
+                       }
+                       if (ext->key_len > KEY_SIZE_WEP40)
+                               key.length = KEY_SIZE_WEP104;
+                       else
+                               key.length = KEY_SIZE_WEP40;
+                       break;
+               case IW_ENCODE_ALG_TKIP:
+                       if (ext->key_len > KEY_SIZE_TKIP) {
+                               ret = -EINVAL;
+                               goto out;
+                       }
+                       key.type = DOT11_PRIV_TKIP;
+                       key.length = KEY_SIZE_TKIP;
+               default:
+                       return -EINVAL;
+               }
+
+               if (key.length) {
+                       memset(key.key, 0, sizeof(key.key));
+                       memcpy(key.key, ext->key, ext->key_len);
+                       ret = mgt_set_request(priv, DOT11_OID_DEFKEYX, idx,
+                                           &key);
+                       if (ret < 0)
+                               goto out;
+               }
+       }
+
+       /* Read the flags */
+       if (encoding->flags & IW_ENCODE_DISABLED) {
+               /* Encoding disabled,
+                * authen = DOT11_AUTH_OS;
+                * invoke = 0;
+                * exunencrypt = 0; */
+       }
+       if (encoding->flags & IW_ENCODE_OPEN) {
+               /* Encode but accept non-encoded packets. No auth */
+               invoke = 1;
+       }
+       if (encoding->flags & IW_ENCODE_RESTRICTED) {
+               /* Refuse non-encoded packets. Auth */
+               authen = DOT11_AUTH_BOTH;
+               invoke = 1;
+               exunencrypt = 1;
+       }
+
+       /* do the change if requested  */
+       if (encoding->flags & IW_ENCODE_MODE) {
+               ret = mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0,
+                                     &authen);
+               ret = mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0,
+                                     &invoke);
+               ret = mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0,
+                                     &exunencrypt);
+       }
+
+out:
+       return ret;
+}
+
+
+static int prism54_get_encodeext(struct net_device *ndev,
+                                struct iw_request_info *info,
+                                union iwreq_data *wrqu,
+                                char *extra)
+{
+       islpci_private *priv = netdev_priv(ndev);
+       struct iw_point *encoding = &wrqu->encoding;
+       struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+       int idx, max_key_len;
+       union oid_res_t r;
+       int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0, wpa = 0;
+       int ret = 0;
+
+       if (islpci_get_state(priv) < PRV_STATE_INIT)
+               return 0;
+
+       /* first get the flags */
+       ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r);
+       authen = r.u;
+       ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r);
+       invoke = r.u;
+       ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r);
+       exunencrypt = r.u;
+       if (ret < 0)
+               goto out;
+
+       max_key_len = encoding->length - sizeof(*ext);
+       if (max_key_len < 0)
+               return -EINVAL;
+
+       idx = (encoding->flags & IW_ENCODE_INDEX) - 1;
+       if (idx) {
+               if (idx < 0 || idx > 3)
+                       return -EINVAL;
+       } else {
+               ret = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r);
+               if (ret < 0)
+                       goto out;
+               idx = r.u;
+       }
+
+       encoding->flags = idx + 1;
+       memset(ext, 0, sizeof(*ext));
+
+       switch (authen) {
+       case DOT11_AUTH_BOTH:
+       case DOT11_AUTH_SK:
+               wrqu->encoding.flags |= IW_ENCODE_RESTRICTED;
+       case DOT11_AUTH_OS:
+       default:
+               wrqu->encoding.flags |= IW_ENCODE_OPEN;
+               break;
+       }
+
+       down_write(&priv->mib_sem);
+       wpa = priv->wpa;
+       up_write(&priv->mib_sem);
+
+       if (authen == DOT11_AUTH_OS && !exunencrypt && !invoke && !wpa) {
+               /* No encryption */
+               ext->alg = IW_ENCODE_ALG_NONE;
+               ext->key_len = 0;
+               wrqu->encoding.flags |= IW_ENCODE_DISABLED;
+       } else {
+               struct obj_key *key;
+
+               ret = mgt_get_request(priv, DOT11_OID_DEFKEYX, idx, NULL, &r);
+               if (ret < 0)
+                       goto out;
+               key = r.ptr;
+               if (max_key_len < key->length) {
+                       ret = -E2BIG;
+                       goto out;
+               }
+               memcpy(ext->key, key->key, key->length);
+               ext->key_len = key->length;
+
+               switch (key->type) {
+               case DOT11_PRIV_TKIP:
+                       ext->alg = IW_ENCODE_ALG_TKIP;
+                       break;
+               default:
+               case DOT11_PRIV_WEP:
+                       ext->alg = IW_ENCODE_ALG_WEP;
+                       break;
+               }
+               wrqu->encoding.flags |= IW_ENCODE_ENABLED;
+       }
+
+out:
+       return ret;
+}
+
+
 static int
 prism54_reset(struct net_device *ndev, struct iw_request_info *info,
              __u32 * uwrq, char *extra)
@@ -1591,8 +2081,8 @@ static u8 wpa_oid[4] = { 0x00, 0x50, 0xf2, 1 };
 #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
 
 static void
-prism54_wpa_ie_add(islpci_private *priv, u8 *bssid,
-                  u8 *wpa_ie, size_t wpa_ie_len)
+prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
+                      u8 *wpa_ie, size_t wpa_ie_len)
 {
        struct list_head *ptr;
        struct islpci_bss_wpa_ie *bss = NULL;
@@ -1658,7 +2148,7 @@ prism54_wpa_ie_add(islpci_private *priv, u8 *bssid,
 }
 
 static size_t
-prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
+prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
 {
        struct list_head *ptr;
        struct islpci_bss_wpa_ie *bss = NULL;
@@ -1683,14 +2173,14 @@ prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
 }
 
 void
-prism54_wpa_ie_init(islpci_private *priv)
+prism54_wpa_bss_ie_init(islpci_private *priv)
 {
        INIT_LIST_HEAD(&priv->bss_wpa_list);
        sema_init(&priv->wpa_sem, 1);
 }
 
 void
-prism54_wpa_ie_clean(islpci_private *priv)
+prism54_wpa_bss_ie_clean(islpci_private *priv)
 {
        struct list_head *ptr, *n;
 
@@ -1722,7 +2212,7 @@ prism54_process_bss_data(islpci_private *priv, u32 oid, u8 *addr,
                }
                if (pos[0] == WLAN_EID_GENERIC && pos[1] >= 4 &&
                    memcmp(pos + 2, wpa_oid, 4) == 0) {
-                       prism54_wpa_ie_add(priv, addr, pos, pos[1] + 2);
+                       prism54_wpa_bss_ie_add(priv, addr, pos, pos[1] + 2);
                        return;
                }
                pos += 2 + pos[1];
@@ -1879,7 +2369,7 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
                send_formatted_event(priv, "Associate request (ex)", mlme, 1);
 
                if (priv->iw_mode != IW_MODE_MASTER 
-                               && mlmeex->state != DOT11_STATE_AUTHING)
+                               && mlmeex->state != DOT11_STATE_ASSOCING)
                        break;
                
                confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC);
@@ -1893,7 +2383,7 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
                confirm->state = 0; /* not used */
                confirm->code = 0;
 
-               wpa_ie_len = prism54_wpa_ie_get(priv, mlmeex->address, wpa_ie);
+               wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie);
 
                if (!wpa_ie_len) {
                        printk(KERN_DEBUG "No WPA IE found from "
@@ -1937,7 +2427,7 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
                confirm->state = 0; /* not used */
                confirm->code = 0;
 
-               wpa_ie_len = prism54_wpa_ie_get(priv, mlmeex->address, wpa_ie);
+               wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie);
 
                if (!wpa_ie_len) {
                        printk(KERN_DEBUG "No WPA IE found from "
@@ -2553,6 +3043,15 @@ static const iw_handler prism54_handler[] = {
        (iw_handler) prism54_get_encode,        /* SIOCGIWENCODE */
        (iw_handler) NULL,      /* SIOCSIWPOWER */
        (iw_handler) NULL,      /* SIOCGIWPOWER */
+       NULL,                   /* -- hole -- */
+       NULL,                   /* -- hole -- */
+       (iw_handler) prism54_set_genie, /* SIOCSIWGENIE */
+       (iw_handler) prism54_get_genie, /* SIOCGIWGENIE */
+       (iw_handler) prism54_set_auth,  /* SIOCSIWAUTH */
+       (iw_handler) prism54_get_auth,  /* SIOCGIWAUTH */
+       (iw_handler) prism54_set_encodeext, /* SIOCSIWENCODEEXT */
+       (iw_handler) prism54_get_encodeext, /* SIOCGIWENCODEEXT */
+       NULL,                   /* SIOCSIWPMKSA */
 };
 
 /* The low order bit identify a SET (0) or a GET (1) ioctl.  */
index 46d5cde80c85e7f738c3e73ccaedf7b9c52224ca..65f33acd0a4275ffd6402f492dc3722ba36b42d8 100644 (file)
@@ -27,7 +27,7 @@
 
 #include <net/iw_handler.h>    /* New driver API */
 
-#define SUPPORTED_WIRELESS_EXT                  16
+#define SUPPORTED_WIRELESS_EXT                  19
 
 void prism54_mib_init(islpci_private *);
 
@@ -39,8 +39,8 @@ void prism54_acl_clean(struct islpci_acl *);
 
 void prism54_process_trap(void *);
 
-void prism54_wpa_ie_init(islpci_private *priv);
-void prism54_wpa_ie_clean(islpci_private *priv);
+void prism54_wpa_bss_ie_init(islpci_private *priv);
+void prism54_wpa_bss_ie_clean(islpci_private *priv);
 
 int prism54_set_mac_address(struct net_device *, void *);
 
index 5ddf295990321b4bb466241e73481947ccab9897..ab3c5a27efd902515854f2f3dbf1f6e7945cc596 100644 (file)
@@ -715,7 +715,7 @@ islpci_alloc_memory(islpci_private *priv)
        }
 
        prism54_acl_init(&priv->acl);
-       prism54_wpa_ie_init(priv);
+       prism54_wpa_bss_ie_init(priv);
        if (mgt_init(priv)) 
                goto out_free;
 
@@ -774,7 +774,7 @@ islpci_free_memory(islpci_private *priv)
 
        /* Free the acces control list and the WPA list */
        prism54_acl_clean(&priv->acl);
-       prism54_wpa_ie_clean(priv);
+       prism54_wpa_bss_ie_clean(priv);
        mgt_clean(priv);
 
        return 0;
index 07053165e4c587b121bcdcfa5cfe9bed1a877c22..5049f37455b1606fd1240f55f08134900359d09a 100644 (file)
@@ -179,6 +179,8 @@ typedef struct {
        struct list_head bss_wpa_list;
        int num_bss_wpa;
        struct semaphore wpa_sem;
+       u8 wpa_ie[MAX_WPA_IE_LEN];
+       size_t wpa_ie_len;
 
        struct work_struct reset_task;
        int reset_task_pending;
index 09fc17a0f02972494f96b28bfb34928f6e6ca49c..f692dccf0d0721d9e8614301db6142e1c614f276 100644 (file)
@@ -313,7 +313,7 @@ prism54_module_init(void)
 
        __bug_on_wrong_struct_sizes ();
 
-       return pci_module_init(&prism54_driver);
+       return pci_register_driver(&prism54_driver);
 }
 
 /* by the time prism54_module_exit() terminates, as a postcondition
index 61b83a5e737a719719646d37a4ff76d03b9fd949..8e112d139e297417548bf5cd7801509504d2104e 100644 (file)
@@ -52,8 +52,8 @@
 #include <pcmcia/ds.h>
 #include <pcmcia/mem_op.h>
 
-#include <net/ieee80211.h>
 #include <linux/wireless.h>
+#include <net/iw_handler.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
index 7f78b7801fb3de996a2ad1dff87cce905904efd7..bcc7038130f69a1355871e8abc5884ff2d386863 100644 (file)
@@ -242,7 +242,7 @@ spectrum_reset(struct pcmcia_device *link, int idle)
        u_int save_cor;
 
        /* Doing it if hardware is gone is guaranteed crash */
-       if (pcmcia_dev_present(link))
+       if (!pcmcia_dev_present(link))
                return -ENODEV;
 
        /* Save original COR value */
index 500314fc74d2abdf68d6af9cfa0614ce2cb436ec..6603ad5be63d09a3752913775034ce570c141797 100644 (file)
@@ -3,6 +3,7 @@ obj-$(CONFIG_ZD1211RW) += zd1211rw.o
 zd1211rw-objs := zd_chip.o zd_ieee80211.o \
                zd_mac.o zd_netdev.o \
                zd_rf_al2230.o zd_rf_rf2959.o \
+               zd_rf_al7230b.o \
                zd_rf.o zd_usb.o zd_util.o
 
 ifeq ($(CONFIG_ZD1211RW_DEBUG),y)
index da9d06bdb818a22089f623650e094a8e74c63b53..58419985e00fa156eb1e37623b711a6b69d68428 100644 (file)
@@ -42,12 +42,11 @@ void zd_chip_init(struct zd_chip *chip,
 
 void zd_chip_clear(struct zd_chip *chip)
 {
-       mutex_lock(&chip->mutex);
+       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
        zd_usb_clear(&chip->usb);
        zd_rf_clear(&chip->rf);
-       mutex_unlock(&chip->mutex);
        mutex_destroy(&chip->mutex);
-       memset(chip, 0, sizeof(*chip));
+       ZD_MEMCLEAR(chip, sizeof(*chip));
 }
 
 static int scnprint_mac_oui(const u8 *addr, char *buffer, size_t size)
@@ -68,10 +67,11 @@ static int scnprint_id(struct zd_chip *chip, char *buffer, size_t size)
        i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i);
        i += scnprintf(buffer+i, size-i, " ");
        i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i);
-       i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c", chip->pa_type,
+       i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c%c", chip->pa_type,
                chip->patch_cck_gain ? 'g' : '-',
                chip->patch_cr157 ? '7' : '-',
-               chip->patch_6m_band_edge ? '6' : '-');
+               chip->patch_6m_band_edge ? '6' : '-',
+               chip->new_phy_layout ? 'N' : '-');
        return i;
 }
 
@@ -330,13 +330,14 @@ static int read_pod(struct zd_chip *chip, u8 *rf_type)
        chip->patch_cck_gain = (value >> 8) & 0x1;
        chip->patch_cr157 = (value >> 13) & 0x1;
        chip->patch_6m_band_edge = (value >> 21) & 0x1;
+       chip->new_phy_layout = (value >> 31) & 0x1;
 
        dev_dbg_f(zd_chip_dev(chip),
                "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d "
-               "patch 6M %d\n",
+               "patch 6M %d new PHY %d\n",
                zd_rf_name(*rf_type), *rf_type,
                chip->pa_type, chip->patch_cck_gain,
-               chip->patch_cr157, chip->patch_6m_band_edge);
+               chip->patch_cr157, chip->patch_6m_band_edge, chip->new_phy_layout);
        return 0;
 error:
        *rf_type = 0;
@@ -344,6 +345,7 @@ error:
        chip->patch_cck_gain = 0;
        chip->patch_cr157 = 0;
        chip->patch_6m_band_edge = 0;
+       chip->new_phy_layout = 0;
        return r;
 }
 
@@ -717,7 +719,7 @@ static int zd1211b_hw_reset_phy(struct zd_chip *chip)
                { CR21,  0x0e }, { CR22,  0x23 }, { CR23,  0x90 },
                { CR24,  0x14 }, { CR25,  0x40 }, { CR26,  0x10 },
                { CR27,  0x10 }, { CR28,  0x7f }, { CR29,  0x80 },
-               { CR30,  0x49 }, /* jointly decoder, no ASIC */
+               { CR30,  0x4b }, /* ASIC/FWT, no jointly decoder */
                { CR31,  0x60 }, { CR32,  0x43 }, { CR33,  0x08 },
                { CR34,  0x06 }, { CR35,  0x0a }, { CR36,  0x00 },
                { CR37,  0x00 }, { CR38,  0x38 }, { CR39,  0x0c },
@@ -807,7 +809,6 @@ static int zd1211_hw_init_hmac(struct zd_chip *chip)
                { CR_ACK_TIMEOUT_EXT,           0x80 },
                { CR_ADDA_PWR_DWN,              0x00 },
                { CR_ACK_TIME_80211,            0x100 },
-               { CR_IFS_VALUE,                 0x547c032 },
                { CR_RX_PE_DELAY,               0x70 },
                { CR_PS_CTRL,                   0x10000000 },
                { CR_RTS_CTS_RATE,              0x02030203 },
@@ -854,11 +855,10 @@ static int zd1211b_hw_init_hmac(struct zd_chip *chip)
                { CR_ACK_TIMEOUT_EXT,           0x80 },
                { CR_ADDA_PWR_DWN,              0x00 },
                { CR_ACK_TIME_80211,            0x100 },
-               { CR_IFS_VALUE,                 0x547c032 },
                { CR_RX_PE_DELAY,               0x70 },
                { CR_PS_CTRL,                   0x10000000 },
                { CR_RTS_CTS_RATE,              0x02030203 },
-               { CR_RX_THRESHOLD,              0x000c0640 },
+               { CR_RX_THRESHOLD,              0x000c0eff, },
                { CR_AFTER_PNP,                 0x1 },
                { CR_WEP_PROTECT,               0x114 },
        };
@@ -970,10 +970,15 @@ static int hw_init(struct zd_chip *chip)
        r = hw_init_hmac(chip);
        if (r)
                return r;
-       r = set_beacon_interval(chip, 100);
+
+       /* Although the vendor driver defaults to a different value during
+        * init, it overwrites the IFS value with the following every time
+        * the channel changes. We should aim to be more intelligent... */
+       r = zd_iowrite32_locked(chip, IFS_VALUE_DEFAULT, CR_IFS_VALUE);
        if (r)
                return r;
-       return 0;
+
+       return set_beacon_interval(chip, 100);
 }
 
 #ifdef DEBUG
@@ -1613,3 +1618,34 @@ int zd_rfwritev_locked(struct zd_chip *chip,
 
        return 0;
 }
+
+/*
+ * We can optionally program the RF directly through CR regs, if supported by
+ * the hardware. This is much faster than the older method.
+ */
+int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value)
+{
+       struct zd_ioreq16 ioreqs[] = {
+               { CR244, (value >> 16) & 0xff },
+               { CR243, (value >>  8) & 0xff },
+               { CR242,  value        & 0xff },
+       };
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+int zd_rfwritev_cr_locked(struct zd_chip *chip,
+                         const u32 *values, unsigned int count)
+{
+       int r;
+       unsigned int i;
+
+       for (i = 0; i < count; i++) {
+               r = zd_rfwrite_cr_locked(chip, values[i]);
+               if (r)
+                       return r;
+       }
+
+       return 0;
+}
+
index 069d2b467339828d1213748cd591b4c3f0aa49a0..4b12508598972a65040a44987e43531912a71003 100644 (file)
 
 #define CR_ACK_TIMEOUT_EXT             CTL_REG(0x0690)
 #define CR_BCN_FIFO_SEMAPHORE          CTL_REG(0x0694)
+
 #define CR_IFS_VALUE                   CTL_REG(0x0698)
+#define IFS_VALUE_DIFS_SH              0
+#define IFS_VALUE_EIFS_SH              12
+#define IFS_VALUE_SIFS_SH              24
+#define IFS_VALUE_DEFAULT              ((  50 << IFS_VALUE_DIFS_SH) | \
+                                        (1148 << IFS_VALUE_EIFS_SH) | \
+                                        (  10 << IFS_VALUE_SIFS_SH))
+
 #define CR_RX_TIME_OUT                 CTL_REG(0x069C)
 #define CR_TOTAL_RX_FRM                        CTL_REG(0x06A0)
 #define CR_CRC32_CNT                   CTL_REG(0x06A4)
@@ -630,6 +638,7 @@ enum {
        LOAD_CODE_SIZE                  = 0xe, /* words */
        LOAD_VECT_SIZE                  = 0x10000 - 0xfff7, /* words */
        EEPROM_REGS_OFFSET              = LOAD_CODE_SIZE + LOAD_VECT_SIZE,
+       EEPROM_REGS_SIZE                = 0x7e, /* words */
        E2P_BASE_OFFSET                 = EEPROM_START_OFFSET +
                                          EEPROM_REGS_OFFSET,
 };
@@ -655,7 +664,7 @@ struct zd_chip {
        /* SetPointOFDM in the vendor driver */
        u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT];
        u8 pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
-          is_zd1211b:1;
+          new_phy_layout:1, is_zd1211b:1;
 };
 
 static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb)
@@ -739,8 +748,12 @@ static inline int zd_rfwrite_locked(struct zd_chip *chip, u32 value, u8 bits)
        return zd_usb_rfwrite(&chip->usb, value, bits);
 }
 
+int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value);
+
 int zd_rfwritev_locked(struct zd_chip *chip,
                       const u32* values, unsigned int count, u8 bits);
+int zd_rfwritev_cr_locked(struct zd_chip *chip,
+                         const u32* values, unsigned int count);
 
 /* Locking functions for reading and writing registers.
  * The different parameters are intentional.
index 465906812fc436b12f23c7d00c52c5bdde5dc19e..a13ec72eb3041ab8e8a4bc802f53ef9cde2d311d 100644 (file)
@@ -45,4 +45,10 @@ do { \
 #  define ZD_ASSERT(x) do { } while (0)
 #endif
 
+#ifdef DEBUG
+#  define ZD_MEMCLEAR(pointer, size) memset((pointer), 0xff, (size))
+#else
+#  define ZD_MEMCLEAR(pointer, size) do { } while (0)
+#endif
+
 #endif /* _ZD_DEF_H */
index d6f3e02a0b54e5925e67b08a3039ffdcb9136ccc..0eda534a648cf30ef2129a81985f1929fbfd22a5 100644 (file)
@@ -127,11 +127,9 @@ out:
 
 void zd_mac_clear(struct zd_mac *mac)
 {
-       /* Aquire the lock. */
-       spin_lock(&mac->lock);
-       spin_unlock(&mac->lock);
        zd_chip_clear(&mac->chip);
-       memset(mac, 0, sizeof(*mac));
+       ZD_ASSERT(!spin_is_locked(&mac->lock));
+       ZD_MEMCLEAR(mac, sizeof(struct zd_mac));
 }
 
 static int reset_mode(struct zd_mac *mac)
index 71e382c589ee5ce473d0b69ec95e3cad5b4f309b..082bcf8ec8dc6fd5d69ad4911892b75397a45c34 100644 (file)
@@ -121,9 +121,9 @@ enum mac_flags {
 };
 
 struct zd_mac {
-       struct net_device *netdev;
        struct zd_chip chip;
        spinlock_t lock;
+       struct net_device *netdev;
        /* Unlocked reading possible */
        struct iw_statistics iw_stats;
        u8 qual_average;
index 9df232c2c86311ada4a7fb60dad6d10714a40136..440ef24b5fd10a445c525093bf799a65c6d348c4 100644 (file)
@@ -72,10 +72,18 @@ static int iw_get_name(struct net_device *netdev,
                       struct iw_request_info *info,
                       union iwreq_data *req, char *extra)
 {
-       /* FIXME: check whether 802.11a will also supported, add also
-        *        zd1211B, if we support it.
-        */
-       strlcpy(req->name, "802.11g zd1211", IFNAMSIZ);
+       /* FIXME: check whether 802.11a will also supported */
+       strlcpy(req->name, "IEEE 802.11b/g", IFNAMSIZ);
+       return 0;
+}
+
+static int iw_get_nick(struct net_device *netdev,
+                      struct iw_request_info *info,
+                      union iwreq_data *req, char *extra)
+{
+       strcpy(extra, "zd1211");
+       req->data.length = strlen(extra) + 1;
+       req->data.flags = 1;
        return 0;
 }
 
@@ -181,6 +189,7 @@ static int iw_get_encodeext(struct net_device *netdev,
 
 static const iw_handler zd_standard_iw_handlers[] = {
        WX(SIOCGIWNAME)         = iw_get_name,
+       WX(SIOCGIWNICKN)        = iw_get_nick,
        WX(SIOCSIWFREQ)         = iw_set_freq,
        WX(SIOCGIWFREQ)         = iw_get_freq,
        WX(SIOCSIWMODE)         = iw_set_mode,
index d3770d2c61bca32bd40ca6b7f7e27fc51613714a..f50cff3db9164e26658b34302295f9cecbf70abe 100644 (file)
@@ -56,7 +56,7 @@ void zd_rf_init(struct zd_rf *rf)
 
 void zd_rf_clear(struct zd_rf *rf)
 {
-       memset(rf, 0, sizeof(*rf));
+       ZD_MEMCLEAR(rf, sizeof(*rf));
 }
 
 int zd_rf_init_hw(struct zd_rf *rf, u8 type)
@@ -76,6 +76,11 @@ int zd_rf_init_hw(struct zd_rf *rf, u8 type)
                if (r)
                        return r;
                break;
+       case AL7230B_RF:
+               r = zd_rf_init_al7230b(rf);
+               if (r)
+                       return r;
+               break;
        default:
                dev_err(zd_chip_dev(chip),
                        "RF %s %#x is not supported\n", zd_rf_name(type), type);
index ea30f693fcc8690512b7d25c4431c58ae3fe66d9..676b3734f1edd96e673a4aa7efbbd9269d0c78e5 100644 (file)
@@ -78,5 +78,6 @@ int zd_switch_radio_off(struct zd_rf *rf);
 
 int zd_rf_init_rf2959(struct zd_rf *rf);
 int zd_rf_init_al2230(struct zd_rf *rf);
+int zd_rf_init_al7230b(struct zd_rf *rf);
 
 #endif /* _ZD_RF_H */
index 0948b25f660d44e91277ad226ab4e7d25779f097..25323a13a3dbe97e2967ab253e8c1f01900135b3 100644 (file)
@@ -21,7 +21,7 @@
 #include "zd_usb.h"
 #include "zd_chip.h"
 
-static const u32 al2230_table[][3] = {
+static const u32 zd1211_al2230_table[][3] = {
        RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, },
        RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, },
        RF_CHANNEL( 3) = { 0x03e790, 0x033331, 0x00000d, },
@@ -38,6 +38,53 @@ static const u32 al2230_table[][3] = {
        RF_CHANNEL(14) = { 0x03e7c0, 0x066661, 0x00000d, },
 };
 
+static const u32 zd1211b_al2230_table[][3] = {
+       RF_CHANNEL( 1) = { 0x09efc0, 0x8cccc0, 0xb00000, },
+       RF_CHANNEL( 2) = { 0x09efc0, 0x8cccd0, 0xb00000, },
+       RF_CHANNEL( 3) = { 0x09e7c0, 0x8cccc0, 0xb00000, },
+       RF_CHANNEL( 4) = { 0x09e7c0, 0x8cccd0, 0xb00000, },
+       RF_CHANNEL( 5) = { 0x05efc0, 0x8cccc0, 0xb00000, },
+       RF_CHANNEL( 6) = { 0x05efc0, 0x8cccd0, 0xb00000, },
+       RF_CHANNEL( 7) = { 0x05e7c0, 0x8cccc0, 0xb00000, },
+       RF_CHANNEL( 8) = { 0x05e7c0, 0x8cccd0, 0xb00000, },
+       RF_CHANNEL( 9) = { 0x0defc0, 0x8cccc0, 0xb00000, },
+       RF_CHANNEL(10) = { 0x0defc0, 0x8cccd0, 0xb00000, },
+       RF_CHANNEL(11) = { 0x0de7c0, 0x8cccc0, 0xb00000, },
+       RF_CHANNEL(12) = { 0x0de7c0, 0x8cccd0, 0xb00000, },
+       RF_CHANNEL(13) = { 0x03efc0, 0x8cccc0, 0xb00000, },
+       RF_CHANNEL(14) = { 0x03e7c0, 0x866660, 0xb00000, },
+};
+
+static const struct zd_ioreq16 zd1211b_ioreqs_shared_1[] = {
+       { CR240, 0x57 }, { CR9,   0xe0 },
+};
+
+static int zd1211b_al2230_finalize_rf(struct zd_chip *chip)
+{
+       int r;
+       static const struct zd_ioreq16 ioreqs[] = {
+               { CR80,  0x30 }, { CR81,  0x30 }, { CR79,  0x58 },
+               { CR12,  0xf0 }, { CR77,  0x1b }, { CR78,  0x58 },
+               { CR203, 0x06 },
+               { },
+
+               { CR240, 0x80 },
+       };
+
+       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+       if (r)
+               return r;
+
+       /* related to antenna selection? */
+       if (chip->new_phy_layout) {
+               r = zd_iowrite16_locked(chip, 0xe1, CR9);
+               if (r)
+                       return r;
+       }
+
+       return zd_iowrite16_locked(chip, 0x06, CR203);
+}
+
 static int zd1211_al2230_init_hw(struct zd_rf *rf)
 {
        int r;
@@ -139,7 +186,7 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf)
                { CR47,  0x1e },
 
                /* ZD1211B 05.06.10 */
-               { CR48,  0x00 }, { CR49,  0x00 }, { CR51,  0x01 },
+               { CR48,  0x06 }, { CR49,  0xf9 }, { CR51,  0x01 },
                { CR52,  0x80 }, { CR53,  0x7e }, { CR65,  0x00 },
                { CR66,  0x00 }, { CR67,  0x00 }, { CR68,  0x00 },
                { CR69,  0x28 },
@@ -172,79 +219,78 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf)
                { CR137, 0x50 }, /* 5614 */
                { CR138, 0xa8 },
                { CR144, 0xac }, /* 5621 */
-               { CR150, 0x0d }, { CR252, 0x00 }, { CR253, 0x00 },
+               { CR150, 0x0d }, { CR252, 0x34 }, { CR253, 0x34 },
        };
 
        static const u32 rv1[] = {
-               /* channel 1 */
-               0x03f790,
-               0x033331,
-               0x00000d,
-
-               0x0b3331,
-               0x03b812,
-               0x00fff3,
-               0x0005a4,
-               0x0f4dc5, /* fix freq shift 0x044dc5 */
-               0x0805b6,
-               0x0146c7,
-               0x000688,
-               0x0403b9, /* External control TX power (CR31) */
-               0x00dbba,
-               0x00099b,
-               0x0bdffc,
-               0x00000d,
-               0x00580f,
+               0x8cccd0,
+               0x481dc0,
+               0xcfff00,
+               0x25a000,
+
+               /* To improve AL2230 yield, improve phase noise, 4713 */
+               0x25a000,
+               0xa3b2f0,
+
+               0x6da010, /* Reg6 update for MP versio */
+               0xe36280, /* Modified by jxiao for Bor-Chin on 2004/08/02 */
+               0x116000,
+               0x9dc020, /* External control TX power (CR31) */
+               0x5ddb00, /* RegA update for MP version */
+               0xd99000, /* RegB update for MP version */
+               0x3ffbd0, /* RegC update for MP version */
+               0xb00000, /* RegD update for MP version */
+
+               /* improve phase noise and remove phase calibration,4713 */
+               0xf01a00,
        };
 
        static const struct zd_ioreq16 ioreqs2[] = {
-               { CR47,  0x1e }, { CR_RFCFG, 0x03 },
+               { CR251, 0x2f }, /* shdnb(PLL_ON)=0 */
+               { CR251, 0x7f }, /* shdnb(PLL_ON)=1 */
        };
 
        static const u32 rv2[] = {
-               0x00880f,
-               0x00080f,
+               /* To improve AL2230 yield, 4713 */
+               0xf01b00,
+               0xf01e00,
+               0xf01a00,
        };
 
        static const struct zd_ioreq16 ioreqs3[] = {
-               { CR_RFCFG, 0x00 }, { CR47, 0x1e }, { CR251, 0x7f },
-       };
-
-       static const u32 rv3[] = {
-               0x00d80f,
-               0x00780f,
-               0x00580f,
-       };
-
-       static const struct zd_ioreq16 ioreqs4[] = {
-               { CR138, 0x28 }, { CR203, 0x06 },
+               /* related to 6M band edge patching, happens unconditionally */
+               { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 },
        };
 
+       r = zd_iowrite16a_locked(chip, zd1211b_ioreqs_shared_1,
+               ARRAY_SIZE(zd1211b_ioreqs_shared_1));
+       if (r)
+               return r;
        r = zd_iowrite16a_locked(chip, ioreqs1, ARRAY_SIZE(ioreqs1));
        if (r)
                return r;
-       r = zd_rfwritev_locked(chip, rv1, ARRAY_SIZE(rv1), RF_RV_BITS);
+       r = zd_rfwritev_cr_locked(chip, zd1211b_al2230_table[0], 3);
        if (r)
                return r;
-       r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2));
+       r = zd_rfwritev_cr_locked(chip, rv1, ARRAY_SIZE(rv1));
        if (r)
                return r;
-       r = zd_rfwritev_locked(chip, rv2, ARRAY_SIZE(rv2), RF_RV_BITS);
+       r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2));
        if (r)
                return r;
-       r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3));
+       r = zd_rfwritev_cr_locked(chip, rv2, ARRAY_SIZE(rv2));
        if (r)
                return r;
-       r = zd_rfwritev_locked(chip, rv3, ARRAY_SIZE(rv3), RF_RV_BITS);
+       r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3));
        if (r)
                return r;
-       return zd_iowrite16a_locked(chip, ioreqs4, ARRAY_SIZE(ioreqs4));
+       return zd1211b_al2230_finalize_rf(chip);
 }
 
-static int al2230_set_channel(struct zd_rf *rf, u8 channel)
+static int zd1211_al2230_set_channel(struct zd_rf *rf, u8 channel)
 {
        int r;
-       const u32 *rv = al2230_table[channel-1];
+       const u32 *rv = zd1211_al2230_table[channel-1];
        struct zd_chip *chip = zd_rf_to_chip(rf);
        static const struct zd_ioreq16 ioreqs[] = {
                { CR138, 0x28 },
@@ -257,6 +303,24 @@ static int al2230_set_channel(struct zd_rf *rf, u8 channel)
        return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
 }
 
+static int zd1211b_al2230_set_channel(struct zd_rf *rf, u8 channel)
+{
+       int r;
+       const u32 *rv = zd1211b_al2230_table[channel-1];
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       r = zd_iowrite16a_locked(chip, zd1211b_ioreqs_shared_1,
+               ARRAY_SIZE(zd1211b_ioreqs_shared_1));
+       if (r)
+               return r;
+
+       r = zd_rfwritev_cr_locked(chip, rv, 3);
+       if (r)
+               return r;
+
+       return zd1211b_al2230_finalize_rf(chip);
+}
+
 static int zd1211_al2230_switch_radio_on(struct zd_rf *rf)
 {
        struct zd_chip *chip = zd_rf_to_chip(rf);
@@ -294,13 +358,14 @@ int zd_rf_init_al2230(struct zd_rf *rf)
 {
        struct zd_chip *chip = zd_rf_to_chip(rf);
 
-       rf->set_channel = al2230_set_channel;
        rf->switch_radio_off = al2230_switch_radio_off;
        if (chip->is_zd1211b) {
                rf->init_hw = zd1211b_al2230_init_hw;
+               rf->set_channel = zd1211b_al2230_set_channel;
                rf->switch_radio_on = zd1211b_al2230_switch_radio_on;
        } else {
                rf->init_hw = zd1211_al2230_init_hw;
+               rf->set_channel = zd1211_al2230_set_channel;
                rf->switch_radio_on = zd1211_al2230_switch_radio_on;
        }
        rf->patch_6m_band_edge = 1;
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
new file mode 100644 (file)
index 0000000..a289f95
--- /dev/null
@@ -0,0 +1,274 @@
+/* zd_rf_al7230b.c: Functions for the AL7230B RF controller
+ *
+ * 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.
+ *
+ * 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
+ */
+
+#include <linux/kernel.h>
+
+#include "zd_rf.h"
+#include "zd_usb.h"
+#include "zd_chip.h"
+
+static const u32 chan_rv[][2] = {
+       RF_CHANNEL( 1) = { 0x09ec00, 0x8cccc8 },
+       RF_CHANNEL( 2) = { 0x09ec00, 0x8cccd8 },
+       RF_CHANNEL( 3) = { 0x09ec00, 0x8cccc0 },
+       RF_CHANNEL( 4) = { 0x09ec00, 0x8cccd0 },
+       RF_CHANNEL( 5) = { 0x05ec00, 0x8cccc8 },
+       RF_CHANNEL( 6) = { 0x05ec00, 0x8cccd8 },
+       RF_CHANNEL( 7) = { 0x05ec00, 0x8cccc0 },
+       RF_CHANNEL( 8) = { 0x05ec00, 0x8cccd0 },
+       RF_CHANNEL( 9) = { 0x0dec00, 0x8cccc8 },
+       RF_CHANNEL(10) = { 0x0dec00, 0x8cccd8 },
+       RF_CHANNEL(11) = { 0x0dec00, 0x8cccc0 },
+       RF_CHANNEL(12) = { 0x0dec00, 0x8cccd0 },
+       RF_CHANNEL(13) = { 0x03ec00, 0x8cccc8 },
+       RF_CHANNEL(14) = { 0x03ec00, 0x866660 },
+};
+
+static const u32 std_rv[] = {
+       0x4ff821,
+       0xc5fbfc,
+       0x21ebfe,
+       0xafd401, /* freq shift 0xaad401 */
+       0x6cf56a,
+       0xe04073,
+       0x193d76,
+       0x9dd844,
+       0x500007,
+       0xd8c010,
+};
+
+static int al7230b_init_hw(struct zd_rf *rf)
+{
+       int i, r;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       /* All of these writes are identical to AL2230 unless otherwise
+        * specified */
+       static const struct zd_ioreq16 ioreqs_1[] = {
+               /* This one is 7230-specific, and happens before the rest */
+               { CR240,  0x57 },
+               { },
+
+               { CR15,   0x20 }, { CR23,   0x40 }, { CR24,  0x20 },
+               { CR26,   0x11 }, { CR28,   0x3e }, { CR29,  0x00 },
+               { CR44,   0x33 },
+               /* This value is different for 7230 (was: 0x2a) */
+               { CR106,  0x22 },
+               { CR107,  0x1a }, { CR109,  0x09 }, { CR110,  0x27 },
+               { CR111,  0x2b }, { CR112,  0x2b }, { CR119,  0x0a },
+               /* This happened further down in AL2230,
+                * and the value changed (was: 0xe0) */
+               { CR122,  0xfc },
+               { CR10,   0x89 },
+               /* for newest (3rd cut) AL2300 */
+               { CR17,   0x28 },
+               { CR26,   0x93 }, { CR34,   0x30 },
+               /* for newest (3rd cut) AL2300 */
+               { CR35,   0x3e },
+               { CR41,   0x24 }, { CR44,   0x32 },
+               /* for newest (3rd cut) AL2300 */
+               { CR46,   0x96 },
+               { CR47,   0x1e }, { CR79,   0x58 }, { CR80,  0x30 },
+               { CR81,   0x30 }, { CR87,   0x0a }, { CR89,  0x04 },
+               { CR92,   0x0a }, { CR99,   0x28 },
+               /* This value is different for 7230 (was: 0x00) */
+               { CR100,  0x02 },
+               { CR101,  0x13 }, { CR102,  0x27 },
+               /* This value is different for 7230 (was: 0x24) */
+               { CR106,  0x22 },
+               /* This value is different for 7230 (was: 0x2a) */
+               { CR107,  0x3f },
+               { CR109,  0x09 },
+               /* This value is different for 7230 (was: 0x13) */
+               { CR110,  0x1f },
+               { CR111,  0x1f }, { CR112,  0x1f }, { CR113, 0x27 },
+               { CR114,  0x27 },
+               /* for newest (3rd cut) AL2300 */
+               { CR115,  0x24 },
+               /* This value is different for 7230 (was: 0x24) */
+               { CR116,  0x3f },
+               /* This value is different for 7230 (was: 0xf4) */
+               { CR117,  0xfa },
+               { CR118,  0xfc }, { CR119,  0x10 }, { CR120, 0x4f },
+               { CR121,  0x77 }, { CR137,  0x88 },
+               /* This one is 7230-specific */
+               { CR138,  0xa8 },
+               /* This value is different for 7230 (was: 0xff) */
+               { CR252,  0x34 },
+               /* This value is different for 7230 (was: 0xff) */
+               { CR253,  0x34 },
+
+               /* PLL_OFF */
+               { CR251, 0x2f },
+       };
+
+       static const struct zd_ioreq16 ioreqs_2[] = {
+               /* PLL_ON */
+               { CR251, 0x3f },
+               { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 },
+               { CR38, 0x38 }, { CR136, 0xdf },
+       };
+
+       r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1));
+       if (r)
+               return r;
+
+       r = zd_rfwrite_cr_locked(chip, 0x09ec04);
+       if (r)
+               return r;
+       r = zd_rfwrite_cr_locked(chip, 0x8cccc8);
+       if (r)
+               return r;
+
+       for (i = 0; i < ARRAY_SIZE(std_rv); i++) {
+               r = zd_rfwrite_cr_locked(chip, std_rv[i]);
+               if (r)
+                       return r;
+       }
+
+       r = zd_rfwrite_cr_locked(chip, 0x3c9000);
+       if (r)
+               return r;
+       r = zd_rfwrite_cr_locked(chip, 0xbfffff);
+       if (r)
+               return r;
+       r = zd_rfwrite_cr_locked(chip, 0x700000);
+       if (r)
+               return r;
+       r = zd_rfwrite_cr_locked(chip, 0xf15d58);
+       if (r)
+               return r;
+
+       r = zd_iowrite16a_locked(chip, ioreqs_2, ARRAY_SIZE(ioreqs_2));
+       if (r)
+               return r;
+
+       r = zd_rfwrite_cr_locked(chip, 0xf15d59);
+       if (r)
+               return r;
+       r = zd_rfwrite_cr_locked(chip, 0xf15d5c);
+       if (r)
+               return r;
+       r = zd_rfwrite_cr_locked(chip, 0xf15d58);
+       if (r)
+               return r;
+
+       r = zd_iowrite16_locked(chip, 0x06, CR203);
+       if (r)
+               return r;
+       r = zd_iowrite16_locked(chip, 0x80, CR240);
+       if (r)
+               return r;
+
+       return 0;
+}
+
+static int al7230b_set_channel(struct zd_rf *rf, u8 channel)
+{
+       int i, r;
+       const u32 *rv = chan_rv[channel-1];
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       struct zd_ioreq16 ioreqs_1[] = {
+               { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 },
+               { CR38,  0x38 }, { CR136, 0xdf },
+       };
+
+       struct zd_ioreq16 ioreqs_2[] = {
+               /* PLL_ON */
+               { CR251, 0x3f },
+               { CR203, 0x06 }, { CR240, 0x08 },
+       };
+
+       r = zd_iowrite16_locked(chip, 0x57, CR240);
+       if (r)
+               return r;
+
+       /* PLL_OFF */
+       r = zd_iowrite16_locked(chip, 0x2f, CR251);
+       if (r)
+               return r;
+
+       for (i = 0; i < ARRAY_SIZE(std_rv); i++) {
+               r = zd_rfwrite_cr_locked(chip, std_rv[i]);
+               if (r)
+                       return r;
+       }
+
+       r = zd_rfwrite_cr_locked(chip, 0x3c9000);
+       if (r)
+               return r;
+       r = zd_rfwrite_cr_locked(chip, 0xf15d58);
+       if (r)
+               return r;
+
+       r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1));
+       if (r)
+               return r;
+
+       for (i = 0; i < 2; i++) {
+               r = zd_rfwrite_cr_locked(chip, rv[i]);
+               if (r)
+                       return r;
+       }
+
+       r = zd_rfwrite_cr_locked(chip, 0x3c9000);
+       if (r)
+               return r;
+
+       return zd_iowrite16a_locked(chip, ioreqs_2, ARRAY_SIZE(ioreqs_2));
+}
+
+static int al7230b_switch_radio_on(struct zd_rf *rf)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+       static const struct zd_ioreq16 ioreqs[] = {
+               { CR11,  0x00 },
+               { CR251, 0x3f },
+       };
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int al7230b_switch_radio_off(struct zd_rf *rf)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+       static const struct zd_ioreq16 ioreqs[] = {
+               { CR11,  0x04 },
+               { CR251, 0x2f },
+       };
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+int zd_rf_init_al7230b(struct zd_rf *rf)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       if (chip->is_zd1211b) {
+               dev_err(zd_chip_dev(chip), "AL7230B is currently not "
+                       "supported for ZD1211B devices\n");
+               return -ENODEV;
+       }
+
+       rf->init_hw = al7230b_init_hw;
+       rf->set_channel = al7230b_set_channel;
+       rf->switch_radio_on = al7230b_switch_radio_on;
+       rf->switch_radio_off = al7230b_switch_radio_off;
+       rf->patch_6m_band_edge = 1;
+       return 0;
+}
index 6320984126c73adf63acf2cd55aee078b4f6f7da..47489fe8ab52a9fd202e2416a0540dc2e40d1242 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <asm/unaligned.h>
+#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/firmware.h>
@@ -39,9 +40,17 @@ static struct usb_device_id usb_ids[] = {
        { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 },
        { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 },
        { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x1740, 0x2000), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x157e, 0x3204), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x0586, 0x3402), .driver_info = DEVICE_ZD1211 },
        /* ZD1211B */
        { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B },
+       /* "Driverless" devices that need ejecting */
+       { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
        {}
 };
 
@@ -263,6 +272,39 @@ static char *get_fw_name(char *buffer, size_t size, u8 device_type,
        return buffer;
 }
 
+static int handle_version_mismatch(struct usb_device *udev, u8 device_type,
+       const struct firmware *ub_fw)
+{
+       const struct firmware *ur_fw = NULL;
+       int offset;
+       int r = 0;
+       char fw_name[128];
+
+       r = request_fw_file(&ur_fw,
+               get_fw_name(fw_name, sizeof(fw_name), device_type, "ur"),
+               &udev->dev);
+       if (r)
+               goto error;
+
+       r = upload_code(udev, ur_fw->data, ur_fw->size, FW_START_OFFSET,
+               REBOOT);
+       if (r)
+               goto error;
+
+       offset = ((EEPROM_REGS_OFFSET + EEPROM_REGS_SIZE) * sizeof(u16));
+       r = upload_code(udev, ub_fw->data + offset, ub_fw->size - offset,
+               E2P_BASE_OFFSET + EEPROM_REGS_SIZE, REBOOT);
+
+       /* At this point, the vendor driver downloads the whole firmware
+        * image, hacks around with version IDs, and uploads it again,
+        * completely overwriting the boot code. We do not do this here as
+        * it is not required on any tested devices, and it is suspected to
+        * cause problems. */
+error:
+       release_firmware(ur_fw);
+       return r;
+}
+
 static int upload_firmware(struct usb_device *udev, u8 device_type)
 {
        int r;
@@ -282,15 +324,17 @@ static int upload_firmware(struct usb_device *udev, u8 device_type)
 
        fw_bcdDevice = get_word(ub_fw->data, EEPROM_REGS_OFFSET);
 
-       /* FIXME: do we have any reason to perform the kludge that the vendor
-        * driver does when there is a version mismatch? (their driver uploads
-        * different firmwares and stuff)
-        */
        if (fw_bcdDevice != bcdDevice) {
                dev_info(&udev->dev,
-                       "firmware device id %#06x and actual device id "
-                       "%#06x differ, continuing anyway\n",
-                       fw_bcdDevice, bcdDevice);
+                       "firmware version %#06x and device bootcode version "
+                       "%#06x differ\n", fw_bcdDevice, bcdDevice);
+               if (bcdDevice <= 0x4313)
+                       dev_warn(&udev->dev, "device has old bootcode, please "
+                               "report success or failure\n");
+
+               r = handle_version_mismatch(udev, device_type, ub_fw);
+               if (r)
+                       goto error;
        } else {
                dev_dbg_f(&udev->dev,
                        "firmware device id %#06x is equal to the "
@@ -620,7 +664,7 @@ resubmit:
        usb_submit_urb(urb, GFP_ATOMIC);
 }
 
-struct urb *alloc_urb(struct zd_usb *usb)
+static struct urb *alloc_urb(struct zd_usb *usb)
 {
        struct usb_device *udev = zd_usb_to_usbdev(usb);
        struct urb *urb;
@@ -644,7 +688,7 @@ struct urb *alloc_urb(struct zd_usb *usb)
        return urb;
 }
 
-void free_urb(struct urb *urb)
+static void free_urb(struct urb *urb)
 {
        if (!urb)
                return;
@@ -864,7 +908,7 @@ void zd_usb_clear(struct zd_usb *usb)
 {
        usb_set_intfdata(usb->intf, NULL);
        usb_put_intf(usb->intf);
-       memset(usb, 0, sizeof(*usb));
+       ZD_MEMCLEAR(usb, sizeof(*usb));
        /* FIXME: usb_interrupt, usb_tx, usb_rx? */
 }
 
@@ -910,6 +954,55 @@ static void print_id(struct usb_device *udev)
 #define print_id(udev) do { } while (0)
 #endif
 
+static int eject_installer(struct usb_interface *intf)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct usb_host_interface *iface_desc = &intf->altsetting[0];
+       struct usb_endpoint_descriptor *endpoint;
+       unsigned char *cmd;
+       u8 bulk_out_ep;
+       int r;
+
+       /* Find bulk out endpoint */
+       endpoint = &iface_desc->endpoint[1].desc;
+       if ((endpoint->bEndpointAddress & USB_TYPE_MASK) == USB_DIR_OUT &&
+           (endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+           USB_ENDPOINT_XFER_BULK) {
+               bulk_out_ep = endpoint->bEndpointAddress;
+       } else {
+               dev_err(&udev->dev,
+                       "zd1211rw: Could not find bulk out endpoint\n");
+               return -ENODEV;
+       }
+
+       cmd = kzalloc(31, GFP_KERNEL);
+       if (cmd == NULL)
+               return -ENODEV;
+
+       /* USB bulk command block */
+       cmd[0] = 0x55;  /* bulk command signature */
+       cmd[1] = 0x53;  /* bulk command signature */
+       cmd[2] = 0x42;  /* bulk command signature */
+       cmd[3] = 0x43;  /* bulk command signature */
+       cmd[14] = 6;    /* command length */
+
+       cmd[15] = 0x1b; /* SCSI command: START STOP UNIT */
+       cmd[19] = 0x2;  /* eject disc */
+
+       dev_info(&udev->dev, "Ejecting virtual installer media...\n");
+       r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep),
+               cmd, 31, NULL, 2000);
+       kfree(cmd);
+       if (r)
+               return r;
+
+       /* At this point, the device disconnects and reconnects with the real
+        * ID numbers. */
+
+       usb_set_intfdata(intf, NULL);
+       return 0;
+}
+
 static int probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
        int r;
@@ -918,6 +1011,9 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id)
 
        print_id(udev);
 
+       if (id->driver_info & DEVICE_INSTALLER)
+               return eject_installer(intf);
+
        switch (udev->speed) {
        case USB_SPEED_LOW:
        case USB_SPEED_FULL:
@@ -983,6 +1079,11 @@ static void disconnect(struct usb_interface *intf)
        struct zd_mac *mac = zd_netdev_mac(netdev);
        struct zd_usb *usb = &mac->chip.usb;
 
+       /* Either something really bad happened, or we're just dealing with
+        * a DEVICE_INSTALLER. */
+       if (netdev == NULL)
+               return;
+
        dev_dbg_f(zd_usb_dev(usb), "\n");
 
        zd_netdev_disconnect(netdev);
@@ -998,7 +1099,6 @@ static void disconnect(struct usb_interface *intf)
         */
        usb_reset_device(interface_to_usbdev(intf));
 
-       /* If somebody still waits on this lock now, this is an error. */
        zd_netdev_free(netdev);
        dev_dbg(&intf->dev, "disconnected\n");
 }
index d6420283bd5ad031933370598e1623d2a886e2df..92746f76239aa1eab312e481e3a6cafafa5a338e 100644 (file)
@@ -30,6 +30,7 @@
 enum devicetype {
        DEVICE_ZD1211  = 0,
        DEVICE_ZD1211B = 1,
+       DEVICE_INSTALLER = 2,
 };
 
 enum endpoints {
index 8459a18254a4c4cbd67e368c6597965a6d6ed0db..b6b247433709c0d58baacbe7f105c5e0b8b2a813 100644 (file)
@@ -1434,7 +1434,7 @@ static int __init yellowfin_init (void)
 #ifdef MODULE
        printk(version);
 #endif
-       return pci_module_init (&yellowfin_driver);
+       return pci_register_driver(&yellowfin_driver);
 }
 
 
index 3fae77ffb2fac79d0029ed062114d0293c8dbaf5..3c148eaf2f4df691a87867d28b638d91fa95e624 100644 (file)
@@ -153,13 +153,6 @@ config HOTPLUG_PCI_SHPC_POLL_EVENT_MODE
 
          When in doubt, say N.
 
-config HOTPLUG_PCI_SHPC_PHPRM_LEGACY
-       bool "For AMD SHPC only: Use $HRT for resource/configuration"
-       depends on HOTPLUG_PCI_SHPC && !ACPI 
-       help
-         Say Y here for AMD SHPC. You have to select this option if you are 
-         using this driver on platform with AMD SHPC.
-
 config HOTPLUG_PCI_RPA
        tristate "RPA PCI Hotplug driver"
        depends on HOTPLUG_PCI && PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE
index ce89f5815861ed4a9a4c8a9f0502f8514ff7194d..eaea9d36a1bb2096104372b751decf81163efad7 100644 (file)
@@ -279,6 +279,11 @@ struct hpc_ops {
 
 
 #ifdef CONFIG_ACPI
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/actypes.h>
+#include <linux/pci-acpi.h>
+
 #define pciehp_get_hp_hw_control_from_firmware(dev) \
        pciehp_acpi_get_hp_hw_control_from_firmware(dev)
 static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
index 0d8fb6e607a1dd38a6f43c47ae650a3337fa6c78..6ab3b6cd2b54095fe3d1bdda65440b4e7c7129db 100644 (file)
 
 #include "../pci.h"
 #include "pciehp.h"
-#include <acpi/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/actypes.h>
-#include <linux/pci-acpi.h>
 #ifdef DEBUG
 #define DBG_K_TRACE_ENTRY      ((unsigned int)0x00000001)      /* On function entry */
 #define DBG_K_TRACE_EXIT       ((unsigned int)0x00000002)      /* On function exit */
index 4bf03fb67f8d46320e72a068e84aa4230a53d017..d8e9b95f0a1a374875c9574cb99af5b0ef5e4968 100644 (file)
@@ -1730,8 +1730,8 @@ dasd_flush_request_queue(struct dasd_device * device)
                req = elv_next_request(device->request_queue);
                if (req == NULL)
                        break;
-               dasd_end_request(req, 0);
                blkdev_dequeue_request(req);
+               dasd_end_request(req, 0);
        }
        spin_unlock_irq(&device->request_queue_lock);
 }
index 7f6fdac747068c84a22014b34ffa619643041d4e..9d0c6e1a0e664a87beb7764eb32653ff8c1614fc 100644 (file)
@@ -48,18 +48,20 @@ struct dasd_devmap {
 };
 
 /*
- * dasd_servermap is used to store the server_id of all storage servers
- * accessed by DASD device driver.
+ * dasd_server_ssid_map contains a globally unique storage server subsystem ID.
+ * dasd_server_ssid_list contains the list of all subsystem IDs accessed by
+ * the DASD device driver.
  */
-struct dasd_servermap {
+struct dasd_server_ssid_map {
        struct list_head list;
        struct server_id {
                char vendor[4];
                char serial[15];
        } sid;
+       __u16 ssid;
 };
 
-static struct list_head dasd_serverlist;
+static struct list_head dasd_server_ssid_list;
 
 /*
  * Parameter parsing functions for dasd= parameter. The syntax is:
@@ -89,7 +91,7 @@ static char *dasd[256];
 module_param_array(dasd, charp, NULL, 0);
 
 /*
- * Single spinlock to protect devmap structures and lists.
+ * Single spinlock to protect devmap and servermap structures and lists.
  */
 static DEFINE_SPINLOCK(dasd_devmap_lock);
 
@@ -264,8 +266,9 @@ dasd_parse_keyword( char *parsestring ) {
                if (dasd_page_cache)
                        return residual_str;
                dasd_page_cache =
-                       kmem_cache_create("dasd_page_cache", PAGE_SIZE, 0,
-                                         SLAB_CACHE_DMA, NULL, NULL );
+                       kmem_cache_create("dasd_page_cache", PAGE_SIZE,
+                                         PAGE_SIZE, SLAB_CACHE_DMA,
+                                         NULL, NULL );
                if (!dasd_page_cache)
                        MESSAGE(KERN_WARNING, "%s", "Failed to create slab, "
                                "fixed buffer mode disabled.");
@@ -858,39 +861,6 @@ static struct attribute_group dasd_attr_group = {
        .attrs = dasd_attrs,
 };
 
-/*
- * Check if the related storage server is already contained in the
- * dasd_serverlist. If server is not contained, create new entry.
- * Return 0 if server was already in serverlist,
- *       1 if the server was added successfully
- *      <0 in case of error.
- */
-static int
-dasd_add_server(struct dasd_uid *uid)
-{
-       struct dasd_servermap *new, *tmp;
-
-       /* check if server is already contained */
-       list_for_each_entry(tmp, &dasd_serverlist, list)
-         // normale cmp?
-               if (strncmp(tmp->sid.vendor, uid->vendor,
-                           sizeof(tmp->sid.vendor)) == 0
-                   && strncmp(tmp->sid.serial, uid->serial,
-                              sizeof(tmp->sid.serial)) == 0)
-                       return 0;
-
-       new = (struct dasd_servermap *)
-               kzalloc(sizeof(struct dasd_servermap), GFP_KERNEL);
-       if (!new)
-               return -ENOMEM;
-
-       strncpy(new->sid.vendor, uid->vendor, sizeof(new->sid.vendor));
-       strncpy(new->sid.serial, uid->serial, sizeof(new->sid.serial));
-       list_add(&new->list, &dasd_serverlist);
-       return 1;
-}
-
-
 /*
  * Return copy of the device unique identifier.
  */
@@ -910,6 +880,9 @@ dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
 
 /*
  * Register the given device unique identifier into devmap struct.
+ * In addition check if the related storage server subsystem ID is already
+ * contained in the dasd_server_ssid_list. If subsystem ID is not contained,
+ * create new entry.
  * Return 0 if server was already in serverlist,
  *       1 if the server was added successful
  *      <0 in case of error.
@@ -918,16 +891,39 @@ int
 dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
 {
        struct dasd_devmap *devmap;
-       int rc;
+       struct dasd_server_ssid_map *srv, *tmp;
 
        devmap = dasd_find_busid(cdev->dev.bus_id);
        if (IS_ERR(devmap))
                return PTR_ERR(devmap);
+
+       /* generate entry for server_ssid_map */
+       srv = (struct dasd_server_ssid_map *)
+               kzalloc(sizeof(struct dasd_server_ssid_map), GFP_KERNEL);
+       if (!srv)
+               return -ENOMEM;
+       strncpy(srv->sid.vendor, uid->vendor, sizeof(srv->sid.vendor) - 1);
+       strncpy(srv->sid.serial, uid->serial, sizeof(srv->sid.serial) - 1);
+       srv->ssid = uid->ssid;
+
+       /* server is already contained ? */
        spin_lock(&dasd_devmap_lock);
        devmap->uid = *uid;
-       rc = dasd_add_server(uid);
+       list_for_each_entry(tmp, &dasd_server_ssid_list, list) {
+               if (!memcmp(&srv->sid, &tmp->sid,
+                           sizeof(struct dasd_server_ssid_map))) {
+                       kfree(srv);
+                       srv = NULL;
+                       break;
+               }
+       }
+
+       /* add servermap to serverlist */
+       if (srv)
+               list_add(&srv->list, &dasd_server_ssid_list);
        spin_unlock(&dasd_devmap_lock);
-       return rc;
+
+       return (srv ? 1 : 0);
 }
 EXPORT_SYMBOL_GPL(dasd_set_uid);
 
@@ -995,7 +991,7 @@ dasd_devmap_init(void)
                INIT_LIST_HEAD(&dasd_hashlists[i]);
 
        /* Initialize servermap structure. */
-       INIT_LIST_HEAD(&dasd_serverlist);
+       INIT_LIST_HEAD(&dasd_server_ssid_list);
        return 0;
 }
 
index 39c2281371b5e75a1d7f15272e1de9ecf89f9a18..957ed5db98e4de714fb84caf485a1b88d48e362a 100644 (file)
@@ -468,11 +468,11 @@ dasd_eckd_generate_uid(struct dasd_device *device, struct dasd_uid *uid)
                return -ENODEV;
 
        memset(uid, 0, sizeof(struct dasd_uid));
-       strncpy(uid->vendor, confdata->ned1.HDA_manufacturer,
-               sizeof(uid->vendor) - 1);
+       memcpy(uid->vendor, confdata->ned1.HDA_manufacturer,
+              sizeof(uid->vendor) - 1);
        EBCASC(uid->vendor, sizeof(uid->vendor) - 1);
-       strncpy(uid->serial, confdata->ned1.HDA_location,
-               sizeof(uid->serial) - 1);
+       memcpy(uid->serial, confdata->ned1.HDA_location,
+              sizeof(uid->serial) - 1);
        EBCASC(uid->serial, sizeof(uid->serial) - 1);
        uid->ssid = confdata->neq.subsystemID;
        if (confdata->ned2.sneq.flags == 0x40) {
index 1140302ff11d852de1c1d20ba29069db84593dd6..ca7d51f7eccc276da0608dd6b8347a9887ae61a5 100644 (file)
 #define PRINT_ERR(x...)                printk(KERN_ERR XPRAM_NAME " error:" x)
 
 
-static struct sysdev_class xpram_sysclass = {
-       set_kset_name("xpram"),
-};
-
-static struct sys_device xpram_sys_device = {
-       .id     = 0,
-       .cls    = &xpram_sysclass,
-}; 
-
 typedef struct {
        unsigned int    size;           /* size of xpram segment in pages */
        unsigned int    offset;         /* start page of xpram segment */
@@ -451,8 +442,6 @@ static void __exit xpram_exit(void)
        }
        unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
        blk_cleanup_queue(xpram_queue);
-       sysdev_unregister(&xpram_sys_device);
-       sysdev_class_unregister(&xpram_sysclass);
 }
 
 static int __init xpram_init(void)
@@ -470,19 +459,7 @@ static int __init xpram_init(void)
        rc = xpram_setup_sizes(xpram_pages);
        if (rc)
                return rc;
-       rc = sysdev_class_register(&xpram_sysclass);
-       if (rc)
-               return rc;
-
-       rc = sysdev_register(&xpram_sys_device);
-       if (rc) {
-               sysdev_class_unregister(&xpram_sysclass);
-               return rc;
-       }
-       rc = xpram_setup_blkdev();
-       if (rc)
-               sysdev_unregister(&xpram_sys_device);
-       return rc;
+       return xpram_setup_blkdev();
 }
 
 module_init(xpram_init);
index 643b6d0785636783538d7d504c129c588bee3a2f..56b87618b100c1d33b8829d3f9bd184f7c80f7b6 100644 (file)
@@ -76,7 +76,7 @@ struct tape_class_device *register_tape_dev(
                                device,
                                "%s", tcd->device_name
                        );
-       rc = PTR_ERR(tcd->class_device);
+       rc = IS_ERR(tcd->class_device) ? PTR_ERR(tcd->class_device) : 0;
        if (rc)
                goto fail_with_cdev;
        rc = sysfs_create_link(
index 7a39e0b0386c63851d82147b7b47d907b82d2c11..6d91c2eb205b05b49afec7f9587f188ab55c5d0a 100644 (file)
@@ -772,6 +772,7 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event)
        stsch(sch->schid, &sch->schib);
 
        if (sch->schib.scsw.actl != 0 ||
+           (sch->schib.scsw.stctl & SCSW_STCTL_STATUS_PEND) ||
            (cdev->private->irb.scsw.stctl & SCSW_STCTL_STATUS_PEND)) {
                /*
                 * No final status yet or final status not yet delivered
index a60124264beec97583a150973f07550eb4845193..9e3de0bd59b5f3af9f6868356c5a8e23c019c07c 100644 (file)
@@ -263,6 +263,9 @@ ccw_device_wake_up(struct ccw_device *cdev, unsigned long ip, struct irb *irb)
        /* Abuse intparm for error reporting. */
        if (IS_ERR(irb))
                cdev->private->intparm = -EIO;
+       else if (irb->scsw.cc == 1)
+               /* Retry for deferred condition code. */
+               cdev->private->intparm = -EAGAIN;
        else if ((irb->scsw.dstat !=
                  (DEV_STAT_CHN_END|DEV_STAT_DEV_END)) ||
                 (irb->scsw.cstat != 0)) {
index 5fff1f93973ac26c85d746b6e045392de945f189..e1327b8fce003c31600452ded9814a50e5aa8001 100644 (file)
@@ -8510,9 +8510,9 @@ static int
 qeth_ipv6_init(void)
 {
        qeth_old_arp_constructor = arp_tbl.constructor;
-       write_lock(&arp_tbl.lock);
+       write_lock_bh(&arp_tbl.lock);
        arp_tbl.constructor = qeth_arp_constructor;
-       write_unlock(&arp_tbl.lock);
+       write_unlock_bh(&arp_tbl.lock);
 
        arp_direct_ops = (struct neigh_ops*)
                kmalloc(sizeof(struct neigh_ops), GFP_KERNEL);
@@ -8528,9 +8528,9 @@ qeth_ipv6_init(void)
 static void
 qeth_ipv6_uninit(void)
 {
-       write_lock(&arp_tbl.lock);
+       write_lock_bh(&arp_tbl.lock);
        arp_tbl.constructor = qeth_old_arp_constructor;
-       write_unlock(&arp_tbl.lock);
+       write_unlock_bh(&arp_tbl.lock);
        kfree(arp_direct_ops);
 }
 #endif /* CONFIG_QETH_IPV6 */
index 06d7601cdf565626c74bf196494b41cbb36809ca..d006a8cb4a7451fd439b97f6cd725efd3f5db001 100644 (file)
@@ -69,6 +69,7 @@ comment "The following drivers are not fully supported"
 config SCSI_CUMANA_1
        tristate "CumanaSCSI I support (EXPERIMENTAL)"
        depends on ARCH_ACORN && EXPERIMENTAL && SCSI
+       select SCSI_SPI_ATTRS
        help
          This enables support for the Cumana SCSI I card. If you have an
          Acorn system with one of these, say Y. If unsure, say N.
@@ -76,6 +77,7 @@ config SCSI_CUMANA_1
 config SCSI_ECOSCSI
        tristate "EcoScsi support (EXPERIMENTAL)"
        depends on ARCH_ACORN && EXPERIMENTAL && (ARCH_ARC || ARCH_A5K) && SCSI
+       select SCSI_SPI_ATTRS
        help
          This enables support for the EcoSCSI card -- a small card that sits
          in the Econet socket. If you have an Acorn system with one of these,
@@ -84,6 +86,7 @@ config SCSI_ECOSCSI
 config SCSI_OAK1
        tristate "Oak SCSI support (EXPERIMENTAL)"
        depends on ARCH_ACORN && EXPERIMENTAL && SCSI
+       select SCSI_SPI_ATTRS
        help
          This enables support for the Oak SCSI card. If you have an Acorn
          system with one of these, say Y. If unsure, say N.
index 6dd544a5eb56a207f9918f33c1d20ce00e0cd7bd..8c2600ffc6afec68e270f224ea4ba17a4d3fb7b4 100644 (file)
@@ -74,7 +74,7 @@ static inline void init_SCp(Scsi_Cmnd *SCpnt)
                unsigned long len = 0;
                int buf;
 
-               SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer;
+               SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer;
                SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
                SCpnt->SCp.ptr = (char *)
                         (page_address(SCpnt->SCp.buffer->page) +
index 19745a31072b17e2be64a3e432fe0940effb004a..5e8afc87698095710ed661bccc188fe07b94b1b9 100644 (file)
@@ -567,8 +567,8 @@ static int piix_sata_prereset(struct ata_port *ap)
                        present = 1;
        }
 
-       DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n",
-               ap->id, pcs, present_mask);
+       DPRINTK("ata%u: LEAVE, pcs=0x%x present=0x%x\n",
+               ap->id, pcs, present);
 
        if (!present) {
                ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n");
@@ -828,6 +828,7 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev,
                case IDE:
                        WARN_ON((i & 1) || map[i + 1] != IDE);
                        pinfo[i / 2] = piix_port_info[ich5_pata];
+                       pinfo[i / 2].private_data = hpriv;
                        i++;
                        printk(" IDE IDE");
                        break;
index 386e5f21e191894da37dbaa44d58d5ad6769fd81..16fc2dd8f2f7e3e7c17149c1764a153eea2c062a 100644 (file)
@@ -5185,28 +5185,6 @@ void ata_host_stop (struct ata_host_set *host_set)
                iounmap(host_set->mmio_base);
 }
 
-
-/**
- *     ata_host_remove - Unregister SCSI host structure with upper layers
- *     @ap: Port to unregister
- *     @do_unregister: 1 if we fully unregister, 0 to just stop the port
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-
-static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister)
-{
-       struct Scsi_Host *sh = ap->host;
-
-       DPRINTK("ENTER\n");
-
-       if (do_unregister)
-               scsi_remove_host(sh);
-
-       ap->ops->port_stop(ap);
-}
-
 /**
  *     ata_dev_init - Initialize an ata_device structure
  *     @dev: Device structure to initialize
@@ -5532,8 +5510,11 @@ int ata_device_add(const struct ata_probe_ent *ent)
 
 err_out:
        for (i = 0; i < count; i++) {
-               ata_host_remove(host_set->ports[i], 1);
-               scsi_host_put(host_set->ports[i]->host);
+               struct ata_port *ap = host_set->ports[i];
+               if (ap) {
+                       ap->ops->port_stop(ap);
+                       scsi_host_put(ap->host);
+               }
        }
 err_free_ret:
        kfree(host_set);
@@ -5558,7 +5539,7 @@ void ata_port_detach(struct ata_port *ap)
        int i;
 
        if (!ap->ops->error_handler)
-               return;
+               goto skip_eh;
 
        /* tell EH we're leaving & flush EH */
        spin_lock_irqsave(ap->lock, flags);
@@ -5594,6 +5575,7 @@ void ata_port_detach(struct ata_port *ap)
        cancel_delayed_work(&ap->hotplug_task);
        flush_workqueue(ata_aux_wq);
 
+ skip_eh:
        /* remove the associated SCSI host */
        scsi_remove_host(ap->host);
 }
@@ -5662,7 +5644,7 @@ int ata_scsi_release(struct Scsi_Host *host)
        DPRINTK("ENTER\n");
 
        ap->ops->port_disable(ap);
-       ata_host_remove(ap, 0);
+       ap->ops->port_stop(ap);
 
        DPRINTK("EXIT\n");
        return 1;
index 7ced41ecde860c0c4c58ce0c5cb7d9afc0d05051..e92c31d698ff6c983b7a817afe190d10a7f1de6c 100644 (file)
@@ -2353,6 +2353,19 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
                        ata_gen_ata_desc_sense(qc);
                }
 
+               /* SCSI EH automatically locks door if sdev->locked is
+                * set.  Sometimes door lock request continues to
+                * fail, for example, when no media is present.  This
+                * creates a loop - SCSI EH issues door lock which
+                * fails and gets invoked again to acquire sense data
+                * for the failed command.
+                *
+                * If door lock fails, always clear sdev->locked to
+                * avoid this infinite loop.
+                */
+               if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL)
+                       qc->dev->sdev->locked = 0;
+
                qc->scsicmd->result = SAM_STAT_CHECK_CONDITION;
                qc->scsidone(cmd);
                ata_qc_free(qc);
index 2e0f4a4076af6cd48a118c68b3640917116c158f..3f368c7d3ef90be120a98410ce842628ef201ef9 100644 (file)
@@ -1106,7 +1106,6 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        probe_ent->irq = pdev->irq;
        probe_ent->irq_flags = IRQF_SHARED;
-       probe_ent->mmio_base = port_base;
        probe_ent->private_data = hpriv;
 
        hpriv->host_base = host_base;
index 822914e2f43bbbe80a31616da47f40d3dfc06a4a..f7a975d5db097757965b758baf14612c86b72f62 100644 (file)
@@ -110,7 +110,6 @@ static void au1xxx_start_ohc(struct platform_device *dev)
 
        printk(KERN_DEBUG __FILE__
        ": Clock to USB host has been enabled \n");
-#endif
 }
 
 static void au1xxx_stop_ohc(struct platform_device *dev)
index 9e3f139033714b49c2c7ef101803d52a78e02112..044faa07e2976f49bf81bf8514f4c3b4575babbe 100644 (file)
@@ -597,9 +597,9 @@ static void atp_disconnect(struct usb_interface *iface)
        if (dev) {
                usb_kill_urb(dev->urb);
                input_unregister_device(dev->input);
-               usb_free_urb(dev->urb);
                usb_buffer_free(dev->udev, dev->datalen,
                                dev->data, dev->urb->transfer_dma);
+               usb_free_urb(dev->urb);
                kfree(dev);
        }
        printk(KERN_INFO "input: appletouch disconnected\n");
index 786e1dbe88ec4dbbd82484146ad77fa6d7444473..983e104dd4520653baa6f61c4ca2ccff10a16ba5 100644 (file)
@@ -1242,11 +1242,12 @@ done:
 static int ctrl_out (struct usbtest_dev *dev,
                unsigned count, unsigned length, unsigned vary)
 {
-       unsigned                i, j, len, retval;
+       unsigned                i, j, len;
+       int                     retval;
        u8                      *buf;
        char                    *what = "?";
        struct usb_device       *udev;
-       
+
        if (length < 1 || length > 0xffff || vary >= length)
                return -EINVAL;
 
index a20da8528a5f8b1826134b55be9ffdf00102d1b3..15945e806f032971abd692fc40bcc850f9133902 100644 (file)
@@ -306,6 +306,8 @@ static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = {
 
 
 static struct usb_device_id id_table_combined [] = {
+       { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) },
index 9f7343a45424494648f3d4341ed9f59249e09f9d..8888cd80a491a6da9b7adc40481d721101b488a5 100644 (file)
 #define FTDI_NF_RIC_PID        0x0001  /* Product Id */
 
 
+/* www.canusb.com Lawicel CANUSB device */
+#define FTDI_CANUSB_PID 0xFFA8 /* Product Id */
+
+/* AlphaMicro Components AMC-232USB01 device */
+#define FTDI_AMC232_PID 0xFF00 /* Product Id */
+
 /* ACT Solutions HomePro ZWave interface (http://www.act-solutions.com/HomePro.htm) */
 #define FTDI_ACTZWAVE_PID      0xF2D0
 
index 7e1bd5d6dfa0ca1502b22cdad8aa88d9925aa563..9840bade79f974acc9231665498500205ac0ff96 100644 (file)
@@ -251,6 +251,8 @@ static struct usb_device_id ipaq_id_table [] = {
        { USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */
        { USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */
        { USB_DEVICE(0x04DD, 0x9102) }, /* SHARP WS003SH USB Modem */
+       { USB_DEVICE(0x04DD, 0x9121) }, /* SHARP WS004SH USB Modem */
+       { USB_DEVICE(0x04DD, 0x9123) }, /* SHARP WS007SH USB Modem */
        { USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */
        { USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */
        { USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */
index 2793f9a912b4a7b6c2e05e136cc90c8eccc14905..fd158e063c0634bd89ca4791ea006bdc2f47a3be 100644 (file)
@@ -1240,6 +1240,16 @@ UNUSUAL_DEV(  0x0ed1, 0x7636, 0x0103, 0x0103,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_IGNORE_RESIDUE | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64),
 
+/* David Kuehling <dvdkhlng@gmx.de>:
+ * for MP3-Player AVOX WSX-300ER (bought in Japan).  Reports lots of SCSI
+ * errors when trying to write.
+ */
+UNUSUAL_DEV(  0x0f19, 0x0105, 0x0100, 0x0100,
+               "C-MEX",
+               "A-VOX",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_IGNORE_RESIDUE ),
+
 /* Reported by Michael Stattmann <michael@stattmann.com> */
 UNUSUAL_DEV(  0x0fce, 0xd008, 0x0000, 0x0000,
                "Sony Ericsson",
index c40b9b8b1e7e0e176554dd23a30fa4ef2bae9945..702eb933cf88bc9414ccbcb85e74de2dcfc18b08 100644 (file)
@@ -554,7 +554,7 @@ config FB_VESA
 
 config FB_IMAC
        bool "Intel-based Macintosh Framebuffer Support"
-       depends on (FB = y) && X86
+       depends on (FB = y) && X86 && EFI
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
index ff233b84dec4fc1a3c900b1896459e87446a623f..b485bece5fc921bc574544ee5a7dc7c408fad957 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/screen_info.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/dmi.h>
+#include <linux/efi.h>
 
 #include <asm/io.h>
 
@@ -28,7 +30,7 @@ typedef enum _MAC_TYPE {
        M_I20,
        M_MINI,
        M_MACBOOK,
-       M_NEW
+       M_UNKNOWN
 } MAC_TYPE;
 
 /* --------------------------------------------------------------------- */
@@ -52,10 +54,36 @@ static struct fb_fix_screeninfo imacfb_fix __initdata = {
 };
 
 static int inverse;
-static int model               = M_NEW;
+static int model               = M_UNKNOWN;
 static int manual_height;
 static int manual_width;
 
+static int set_system(struct dmi_system_id *id)
+{
+       printk(KERN_INFO "imacfb: %s detected - set system to %ld\n",
+               id->ident, (long)id->driver_data);
+
+       model = (long)id->driver_data;
+
+       return 0;
+}
+
+static struct dmi_system_id __initdata dmi_system_table[] = {
+       { set_system, "iMac4,1", {
+         DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
+         DMI_MATCH(DMI_BIOS_VERSION,"iMac4,1") }, (void*)M_I17},
+       { set_system, "MacBookPro1,1", {
+         DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
+         DMI_MATCH(DMI_BIOS_VERSION,"MacBookPro1,1") }, (void*)M_I17},
+       { set_system, "MacBook1,1", {
+         DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
+         DMI_MATCH(DMI_PRODUCT_NAME,"MacBook1,1")}, (void *)M_MACBOOK},
+       { set_system, "Macmini1,1", {
+         DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
+         DMI_MATCH(DMI_PRODUCT_NAME,"Macmini1,1")}, (void *)M_MINI},
+       {},
+};
+
 #define        DEFAULT_FB_MEM  1024*1024*16
 
 /* --------------------------------------------------------------------- */
@@ -149,7 +177,6 @@ static int __init imacfb_probe(struct platform_device *dev)
                screen_info.lfb_linelength = 1472 * 4;
                screen_info.lfb_base = 0x80010000;
                break;
-       case M_NEW:
        case M_I20:
                screen_info.lfb_width = 1680;
                screen_info.lfb_height = 1050;
@@ -207,6 +234,10 @@ static int __init imacfb_probe(struct platform_device *dev)
                size_remap = size_total;
        imacfb_fix.smem_len = size_remap;
 
+#ifndef __i386__
+       screen_info.imacpm_seg = 0;
+#endif
+
        if (!request_mem_region(imacfb_fix.smem_start, size_total, "imacfb")) {
                printk(KERN_WARNING
                       "imacfb: cannot reserve video memory at 0x%lx\n",
@@ -324,8 +355,16 @@ static int __init imacfb_init(void)
        int ret;
        char *option = NULL;
 
-       /* ignore error return of fb_get_options */
-       fb_get_options("imacfb", &option);
+       if (!efi_enabled)
+               return -ENODEV;
+       if (!dmi_check_system(dmi_system_table))
+               return -ENODEV;
+       if (model == M_UNKNOWN)
+               return -ENODEV;
+
+       if (fb_get_options("imacfb", &option))
+               return -ENODEV;
+
        imacfb_setup(option);
        ret = platform_driver_register(&imacfb_driver);
 
index ba1c88af49fee9e0c288479b06b3e774b19f6f8b..82011019494ccf6bbcefa838e28b5c130739470b 100644 (file)
@@ -308,7 +308,7 @@ static struct adfs_discmap *adfs_read_map(struct super_block *sb, struct adfs_di
        if (adfs_checkmap(sb, dm))
                return dm;
 
-       adfs_error(sb, NULL, "map corrupted");
+       adfs_error(sb, "map corrupted");
 
 error_free:
        while (--zone >= 0)
index 63614ed16336d7dec7bd4902a9c43d582e48842e..5c4fcd1dbf5908d29401aa3f83d1aac23a1d8244 100644 (file)
@@ -395,14 +395,16 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
        struct fuse_readpages_data data;
        int err;
 
+       err = -EIO;
        if (is_bad_inode(inode))
-               return -EIO;
+               goto clean_pages_up;
 
        data.file = file;
        data.inode = inode;
        data.req = fuse_get_req(fc);
+       err = PTR_ERR(data.req);
        if (IS_ERR(data.req))
-               return PTR_ERR(data.req);
+               goto clean_pages_up;
 
        err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
        if (!err) {
@@ -412,6 +414,10 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
                        fuse_put_request(fc, data.req);
        }
        return err;
+
+clean_pages_up:
+       put_pages_list(pages);
+       return err;
 }
 
 static size_t fuse_send_write(struct fuse_req *req, struct file *file,
index 43e3f566aad65fb26a4dcf92845675d561746601..a223cf4faa9b59e61f14e2ffc57712b9469017be 100644 (file)
@@ -168,16 +168,15 @@ void jfs_dirty_inode(struct inode *inode)
        set_cflag(COMMIT_Dirty, inode);
 }
 
-static int
-jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
-                       struct buffer_head *bh_result, int create)
+int jfs_get_block(struct inode *ip, sector_t lblock,
+                 struct buffer_head *bh_result, int create)
 {
        s64 lblock64 = lblock;
        int rc = 0;
        xad_t xad;
        s64 xaddr;
        int xflag;
-       s32 xlen = max_blocks;
+       s32 xlen = bh_result->b_size >> ip->i_blkbits;
 
        /*
         * Take appropriate lock on inode
@@ -188,7 +187,7 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
                IREAD_LOCK(ip);
 
        if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) &&
-           (!xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0)) &&
+           (!xtLookup(ip, lblock64, xlen, &xflag, &xaddr, &xlen, 0)) &&
            xaddr) {
                if (xflag & XAD_NOTRECORDED) {
                        if (!create)
@@ -255,13 +254,6 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
        return rc;
 }
 
-static int jfs_get_block(struct inode *ip, sector_t lblock,
-                        struct buffer_head *bh_result, int create)
-{
-       return jfs_get_blocks(ip, lblock, bh_result->b_size >> ip->i_blkbits,
-                       bh_result, create);
-}
-
 static int jfs_writepage(struct page *page, struct writeback_control *wbc)
 {
        return nobh_writepage(page, jfs_get_block, wbc);
index b5c7da6190dc0ac2364536650923941b8fa43ac8..1fc48df670c834f334f9620c4bd44c0a586145c7 100644 (file)
@@ -32,6 +32,7 @@ extern void jfs_truncate_nolock(struct inode *, loff_t);
 extern void jfs_free_zero_link(struct inode *);
 extern struct dentry *jfs_get_parent(struct dentry *dentry);
 extern void jfs_set_inode_flags(struct inode *);
+extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 extern const struct address_space_operations jfs_aops;
 extern struct inode_operations jfs_dir_inode_operations;
index 4f6cfebc82dbed167db0e5350613aec969f62f8e..143bcd1d5eaa42f0529596676c85c16304a3e995 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/moduleparam.h>
 #include <linux/kthread.h>
 #include <linux/posix_acl.h>
+#include <linux/buffer_head.h>
 #include <asm/uaccess.h>
 #include <linux/seq_file.h>
 
@@ -298,7 +299,7 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
                        break;
                }
 
-#if defined(CONFIG_QUOTA)
+#ifdef CONFIG_QUOTA
                case Opt_quota:
                case Opt_usrquota:
                        *flag |= JFS_USRQUOTA;
@@ -597,7 +598,7 @@ static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
        if (sbi->flag & JFS_NOINTEGRITY)
                seq_puts(seq, ",nointegrity");
 
-#if defined(CONFIG_QUOTA)
+#ifdef CONFIG_QUOTA
        if (sbi->flag & JFS_USRQUOTA)
                seq_puts(seq, ",usrquota");
 
@@ -608,6 +609,113 @@ static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
        return 0;
 }
 
+#ifdef CONFIG_QUOTA
+
+/* Read data from quotafile - avoid pagecache and such because we cannot afford
+ * acquiring the locks... As quota files are never truncated and quota code
+ * itself serializes the operations (and noone else should touch the files)
+ * we don't have to be afraid of races */
+static ssize_t jfs_quota_read(struct super_block *sb, int type, char *data,
+                             size_t len, loff_t off)
+{
+       struct inode *inode = sb_dqopt(sb)->files[type];
+       sector_t blk = off >> sb->s_blocksize_bits;
+       int err = 0;
+       int offset = off & (sb->s_blocksize - 1);
+       int tocopy;
+       size_t toread;
+       struct buffer_head tmp_bh;
+       struct buffer_head *bh;
+       loff_t i_size = i_size_read(inode);
+
+       if (off > i_size)
+               return 0;
+       if (off+len > i_size)
+               len = i_size-off;
+       toread = len;
+       while (toread > 0) {
+               tocopy = sb->s_blocksize - offset < toread ?
+                               sb->s_blocksize - offset : toread;
+
+               tmp_bh.b_state = 0;
+               tmp_bh.b_size = 1 << inode->i_blkbits;
+               err = jfs_get_block(inode, blk, &tmp_bh, 0);
+               if (err)
+                       return err;
+               if (!buffer_mapped(&tmp_bh))    /* A hole? */
+                       memset(data, 0, tocopy);
+               else {
+                       bh = sb_bread(sb, tmp_bh.b_blocknr);
+                       if (!bh)
+                               return -EIO;
+                       memcpy(data, bh->b_data+offset, tocopy);
+                       brelse(bh);
+               }
+               offset = 0;
+               toread -= tocopy;
+               data += tocopy;
+               blk++;
+       }
+       return len;
+}
+
+/* Write to quotafile */
+static ssize_t jfs_quota_write(struct super_block *sb, int type,
+                              const char *data, size_t len, loff_t off)
+{
+       struct inode *inode = sb_dqopt(sb)->files[type];
+       sector_t blk = off >> sb->s_blocksize_bits;
+       int err = 0;
+       int offset = off & (sb->s_blocksize - 1);
+       int tocopy;
+       size_t towrite = len;
+       struct buffer_head tmp_bh;
+       struct buffer_head *bh;
+
+       mutex_lock(&inode->i_mutex);
+       while (towrite > 0) {
+               tocopy = sb->s_blocksize - offset < towrite ?
+                               sb->s_blocksize - offset : towrite;
+
+               tmp_bh.b_state = 0;
+               tmp_bh.b_size = 1 << inode->i_blkbits;
+               err = jfs_get_block(inode, blk, &tmp_bh, 1);
+               if (err)
+                       goto out;
+               if (offset || tocopy != sb->s_blocksize)
+                       bh = sb_bread(sb, tmp_bh.b_blocknr);
+               else
+                       bh = sb_getblk(sb, tmp_bh.b_blocknr);
+               if (!bh) {
+                       err = -EIO;
+                       goto out;
+               }
+               lock_buffer(bh);
+               memcpy(bh->b_data+offset, data, tocopy);
+               flush_dcache_page(bh->b_page);
+               set_buffer_uptodate(bh);
+               mark_buffer_dirty(bh);
+               unlock_buffer(bh);
+               brelse(bh);
+               offset = 0;
+               towrite -= tocopy;
+               data += tocopy;
+               blk++;
+       }
+out:
+       if (len == towrite)
+               return err;
+       if (inode->i_size < off+len-towrite)
+               i_size_write(inode, off+len-towrite);
+       inode->i_version++;
+       inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+       mark_inode_dirty(inode);
+       mutex_unlock(&inode->i_mutex);
+       return len - towrite;
+}
+
+#endif
+
 static struct super_operations jfs_super_operations = {
        .alloc_inode    = jfs_alloc_inode,
        .destroy_inode  = jfs_destroy_inode,
@@ -621,7 +729,11 @@ static struct super_operations jfs_super_operations = {
        .unlockfs       = jfs_unlockfs,
        .statfs         = jfs_statfs,
        .remount_fs     = jfs_remount,
-       .show_options   = jfs_show_options
+       .show_options   = jfs_show_options,
+#ifdef CONFIG_QUOTA
+       .quota_read     = jfs_quota_read,
+       .quota_write    = jfs_quota_write,
+#endif
 };
 
 static struct export_operations jfs_export_operations = {
index b0b41a64e10bd86482b10a7ba44b36613a6d25e8..d7c53392cac12cf5b907d0122e1e504ca7a26f0e 100644 (file)
@@ -1421,8 +1421,9 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
        if (!leases_enable)
                goto out;
 
-       error = lease_alloc(filp, arg, &fl);
-       if (error)
+       error = -ENOMEM;
+       fl = locks_alloc_lock();
+       if (fl == NULL)
                goto out;
 
        locks_copy_lock(fl, lease);
@@ -1430,6 +1431,7 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
        locks_insert_lock(before, fl);
 
        *flp = fl;
+       error = 0;
 out:
        return error;
 }
index 1b8346dd0572ff349b3f01dc94140a9c8ed0557c..9503240ef0e50d46f413e46b62a665de3eec57bd 100644 (file)
@@ -2375,7 +2375,6 @@ leave:
        mlog(0, "returning %d\n", ret);
        return ret;
 }
-EXPORT_SYMBOL_GPL(dlm_migrate_lockres);
 
 int dlm_lock_basts_flushed(struct dlm_ctxt *dlm, struct dlm_lock *lock)
 {
index b0c3134f4f7089b016baaffcf54ed85e266d7f90..37be4b2e0d4a8801982e97a8636f61abd1360d4e 100644 (file)
@@ -155,7 +155,7 @@ static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm,
        else
                status = dlm_get_unlock_actions(dlm, res, lock, lksb, &actions);
 
-       if (status != DLM_NORMAL)
+       if (status != DLM_NORMAL && (status != DLM_CANCELGRANT || !master_node))
                goto leave;
 
        /* By now this has been masked out of cancel requests. */
@@ -183,8 +183,7 @@ static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm,
                spin_lock(&lock->spinlock);
                /* if the master told us the lock was already granted,
                 * let the ast handle all of these actions */
-               if (status == DLM_NORMAL &&
-                   lksb->status == DLM_CANCELGRANT) {
+               if (status == DLM_CANCELGRANT) {
                        actions &= ~(DLM_UNLOCK_REMOVE_LOCK|
                                     DLM_UNLOCK_REGRANT_LOCK|
                                     DLM_UNLOCK_CLEAR_CONVERT_TYPE);
@@ -349,14 +348,9 @@ static enum dlm_status dlm_send_remote_unlock_request(struct dlm_ctxt *dlm,
                                        vec, veclen, owner, &status);
        if (tmpret >= 0) {
                // successfully sent and received
-               if (status == DLM_CANCELGRANT)
-                       ret = DLM_NORMAL;
-               else if (status == DLM_FORWARD) {
+               if (status == DLM_FORWARD)
                        mlog(0, "master was in-progress.  retry\n");
-                       ret = DLM_FORWARD;
-               } else
-                       ret = status;
-               lksb->status = status;
+               ret = status;
        } else {
                mlog_errno(tmpret);
                if (dlm_is_host_down(tmpret)) {
@@ -372,7 +366,6 @@ static enum dlm_status dlm_send_remote_unlock_request(struct dlm_ctxt *dlm,
                        /* something bad.  this will BUG in ocfs2 */
                        ret = dlm_err_to_dlm_status(tmpret);
                }
-               lksb->status = ret;
        }
 
        return ret;
@@ -483,6 +476,10 @@ int dlm_unlock_lock_handler(struct o2net_msg *msg, u32 len, void *data)
 
        /* lock was found on queue */
        lksb = lock->lksb;
+       if (flags & (LKM_VALBLK|LKM_PUT_LVB) &&
+           lock->ml.type != LKM_EXMODE)
+               flags &= ~(LKM_VALBLK|LKM_PUT_LVB);
+
        /* unlockast only called on originating node */
        if (flags & LKM_PUT_LVB) {
                lksb->flags |= DLM_LKSB_PUT_LVB;
@@ -507,11 +504,8 @@ not_found:
                               "cookie=%u:%llu\n",
                               dlm_get_lock_cookie_node(unlock->cookie),
                               dlm_get_lock_cookie_seq(unlock->cookie));
-       else {
-               /* send the lksb->status back to the other node */
-               status = lksb->status;
+       else
                dlm_lock_put(lock);
-       }
 
 leave:
        if (res)
@@ -533,26 +527,22 @@ static enum dlm_status dlm_get_cancel_actions(struct dlm_ctxt *dlm,
 
        if (dlm_lock_on_list(&res->blocked, lock)) {
                /* cancel this outright */
-               lksb->status = DLM_NORMAL;
                status = DLM_NORMAL;
                *actions = (DLM_UNLOCK_CALL_AST |
                            DLM_UNLOCK_REMOVE_LOCK);
        } else if (dlm_lock_on_list(&res->converting, lock)) {
                /* cancel the request, put back on granted */
-               lksb->status = DLM_NORMAL;
                status = DLM_NORMAL;
                *actions = (DLM_UNLOCK_CALL_AST |
                            DLM_UNLOCK_REMOVE_LOCK |
                            DLM_UNLOCK_REGRANT_LOCK |
                            DLM_UNLOCK_CLEAR_CONVERT_TYPE);
        } else if (dlm_lock_on_list(&res->granted, lock)) {
-               /* too late, already granted.  DLM_CANCELGRANT */
-               lksb->status = DLM_CANCELGRANT;
-               status = DLM_NORMAL;
+               /* too late, already granted. */
+               status = DLM_CANCELGRANT;
                *actions = DLM_UNLOCK_CALL_AST;
        } else {
                mlog(ML_ERROR, "lock to cancel is not on any list!\n");
-               lksb->status = DLM_IVLOCKID;
                status = DLM_IVLOCKID;
                *actions = 0;
        }
@@ -569,13 +559,11 @@ static enum dlm_status dlm_get_unlock_actions(struct dlm_ctxt *dlm,
 
        /* unlock request */
        if (!dlm_lock_on_list(&res->granted, lock)) {
-               lksb->status = DLM_DENIED;
                status = DLM_DENIED;
                dlm_error(status);
                *actions = 0;
        } else {
                /* unlock granted lock */
-               lksb->status = DLM_NORMAL;
                status = DLM_NORMAL;
                *actions = (DLM_UNLOCK_FREE_LOCK |
                            DLM_UNLOCK_CALL_AST |
@@ -632,6 +620,8 @@ retry:
 
        spin_lock(&res->spinlock);
        is_master = (res->owner == dlm->node_num);
+       if (flags & LKM_VALBLK && lock->ml.type != LKM_EXMODE)
+               flags &= ~LKM_VALBLK;
        spin_unlock(&res->spinlock);
 
        if (is_master) {
@@ -665,7 +655,7 @@ retry:
        }
 
        if (call_ast) {
-               mlog(0, "calling unlockast(%p, %d)\n", data, lksb->status);
+               mlog(0, "calling unlockast(%p, %d)\n", data, status);
                if (is_master) {
                        /* it is possible that there is one last bast 
                         * pending.  make sure it is flushed, then
@@ -677,9 +667,12 @@ retry:
                        wait_event(dlm->ast_wq, 
                                   dlm_lock_basts_flushed(dlm, lock));
                }
-               (*unlockast)(data, lksb->status);
+               (*unlockast)(data, status);
        }
 
+       if (status == DLM_CANCELGRANT)
+               status = DLM_NORMAL;
+
        if (status == DLM_NORMAL) {
                mlog(0, "kicking the thread\n");
                dlm_kick_thread(dlm, res);
index 0d1973ea32b0a0b4d9d61e70a819022168cb1725..1f17a4d08287fbd6b1e02fc13c3aac997bdcd2c1 100644 (file)
@@ -840,6 +840,12 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
 
        mlog(0, "Allocating %u clusters for a new window.\n",
             ocfs2_local_alloc_window_bits(osb));
+
+       /* Instruct the allocation code to try the most recently used
+        * cluster group. We'll re-record the group used this pass
+        * below. */
+       ac->ac_last_group = osb->la_last_gd;
+
        /* we used the generic suballoc reserve function, but we set
         * everything up nicely, so there's no reason why we can't use
         * the more specific cluster api to claim bits. */
@@ -852,6 +858,8 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
                goto bail;
        }
 
+       osb->la_last_gd = ac->ac_last_group;
+
        la->la_bm_off = cpu_to_le32(cluster_off);
        alloc->id1.bitmap1.i_total = cpu_to_le32(cluster_count);
        /* just in case... In the future when we find space ourselves,
index cd4a6f253d13ac0a6bf7c70a50df905daccc6bec..0462a7f4e21b398300f3ed1bf8b80b6b7d30ce07 100644 (file)
@@ -197,7 +197,6 @@ struct ocfs2_super
        struct ocfs2_node_map recovery_map;
        struct ocfs2_node_map umount_map;
 
-       u32 num_clusters;
        u64 root_blkno;
        u64 system_dir_blkno;
        u64 bitmap_blkno;
@@ -237,6 +236,7 @@ struct ocfs2_super
 
        enum ocfs2_local_alloc_state local_alloc_state;
        struct buffer_head *local_alloc_bh;
+       u64 la_last_gd;
 
        /* Next two fields are for local node slot recovery during
         * mount. */
index 195523090c875cfd50a155f5a18df3e8269b786a..9d91e66f51a9fa4606a6f864e2bc7531e10c1a75 100644 (file)
@@ -70,12 +70,6 @@ static int ocfs2_block_group_search(struct inode *inode,
                                    struct buffer_head *group_bh,
                                    u32 bits_wanted, u32 min_bits,
                                    u16 *bit_off, u16 *bits_found);
-static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
-                             u32 bits_wanted,
-                             u32 min_bits,
-                             u16 *bit_off,
-                             unsigned int *num_bits,
-                             u64 *bg_blkno);
 static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
                                     struct ocfs2_alloc_context *ac,
                                     u32 bits_wanted,
@@ -85,11 +79,6 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
                                     u64 *bg_blkno);
 static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,
                                         int nr);
-static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb,
-                                            struct buffer_head *bg_bh,
-                                            unsigned int bits_wanted,
-                                            u16 *bit_off,
-                                            u16 *bits_found);
 static inline int ocfs2_block_group_set_bits(struct ocfs2_journal_handle *handle,
                                             struct inode *alloc_inode,
                                             struct ocfs2_group_desc *bg,
@@ -143,6 +132,64 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl)
        return (u32)le16_to_cpu(cl->cl_cpg) * (u32)le16_to_cpu(cl->cl_bpc);
 }
 
+/* somewhat more expensive than our other checks, so use sparingly. */
+static int ocfs2_check_group_descriptor(struct super_block *sb,
+                                       struct ocfs2_dinode *di,
+                                       struct ocfs2_group_desc *gd)
+{
+       unsigned int max_bits;
+
+       if (!OCFS2_IS_VALID_GROUP_DESC(gd)) {
+               OCFS2_RO_ON_INVALID_GROUP_DESC(sb, gd);
+               return -EIO;
+       }
+
+       if (di->i_blkno != gd->bg_parent_dinode) {
+               ocfs2_error(sb, "Group descriptor # %llu has bad parent "
+                           "pointer (%llu, expected %llu)",
+                           (unsigned long long)le64_to_cpu(gd->bg_blkno),
+                           (unsigned long long)le64_to_cpu(gd->bg_parent_dinode),
+                           (unsigned long long)le64_to_cpu(di->i_blkno));
+               return -EIO;
+       }
+
+       max_bits = le16_to_cpu(di->id2.i_chain.cl_cpg) * le16_to_cpu(di->id2.i_chain.cl_bpc);
+       if (le16_to_cpu(gd->bg_bits) > max_bits) {
+               ocfs2_error(sb, "Group descriptor # %llu has bit count of %u",
+                           (unsigned long long)le64_to_cpu(gd->bg_blkno),
+                           le16_to_cpu(gd->bg_bits));
+               return -EIO;
+       }
+
+       if (le16_to_cpu(gd->bg_chain) >=
+           le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) {
+               ocfs2_error(sb, "Group descriptor # %llu has bad chain %u",
+                           (unsigned long long)le64_to_cpu(gd->bg_blkno),
+                           le16_to_cpu(gd->bg_chain));
+               return -EIO;
+       }
+
+       if (le16_to_cpu(gd->bg_free_bits_count) > le16_to_cpu(gd->bg_bits)) {
+               ocfs2_error(sb, "Group descriptor # %llu has bit count %u but "
+                           "claims that %u are free",
+                           (unsigned long long)le64_to_cpu(gd->bg_blkno),
+                           le16_to_cpu(gd->bg_bits),
+                           le16_to_cpu(gd->bg_free_bits_count));
+               return -EIO;
+       }
+
+       if (le16_to_cpu(gd->bg_bits) > (8 * le16_to_cpu(gd->bg_size))) {
+               ocfs2_error(sb, "Group descriptor # %llu has bit count %u but "
+                           "max bitmap bits of %u",
+                           (unsigned long long)le64_to_cpu(gd->bg_blkno),
+                           le16_to_cpu(gd->bg_bits),
+                           8 * le16_to_cpu(gd->bg_size));
+               return -EIO;
+       }
+
+       return 0;
+}
+
 static int ocfs2_block_group_fill(struct ocfs2_journal_handle *handle,
                                  struct inode *alloc_inode,
                                  struct buffer_head *bg_bh,
@@ -663,6 +710,7 @@ static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,
 static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb,
                                             struct buffer_head *bg_bh,
                                             unsigned int bits_wanted,
+                                            unsigned int total_bits,
                                             u16 *bit_off,
                                             u16 *bits_found)
 {
@@ -679,10 +727,8 @@ static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb,
        found = start = best_offset = best_size = 0;
        bitmap = bg->bg_bitmap;
 
-       while((offset = ocfs2_find_next_zero_bit(bitmap,
-                                                le16_to_cpu(bg->bg_bits),
-                                                start)) != -1) {
-               if (offset == le16_to_cpu(bg->bg_bits))
+       while((offset = ocfs2_find_next_zero_bit(bitmap, total_bits, start)) != -1) {
+               if (offset == total_bits)
                        break;
 
                if (!ocfs2_test_bg_bit_allocatable(bg_bh, offset)) {
@@ -911,14 +957,35 @@ static int ocfs2_cluster_group_search(struct inode *inode,
 {
        int search = -ENOSPC;
        int ret;
-       struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) group_bh->b_data;
+       struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *) group_bh->b_data;
        u16 tmp_off, tmp_found;
+       unsigned int max_bits, gd_cluster_off;
 
        BUG_ON(!ocfs2_is_cluster_bitmap(inode));
 
-       if (bg->bg_free_bits_count) {
+       if (gd->bg_free_bits_count) {
+               max_bits = le16_to_cpu(gd->bg_bits);
+
+               /* Tail groups in cluster bitmaps which aren't cpg
+                * aligned are prone to partial extention by a failed
+                * fs resize. If the file system resize never got to
+                * update the dinode cluster count, then we don't want
+                * to trust any clusters past it, regardless of what
+                * the group descriptor says. */
+               gd_cluster_off = ocfs2_blocks_to_clusters(inode->i_sb,
+                                                         le64_to_cpu(gd->bg_blkno));
+               if ((gd_cluster_off + max_bits) >
+                   OCFS2_I(inode)->ip_clusters) {
+                       max_bits = OCFS2_I(inode)->ip_clusters - gd_cluster_off;
+                       mlog(0, "Desc %llu, bg_bits %u, clusters %u, use %u\n",
+                            (unsigned long long)le64_to_cpu(gd->bg_blkno),
+                            le16_to_cpu(gd->bg_bits),
+                            OCFS2_I(inode)->ip_clusters, max_bits);
+               }
+
                ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),
                                                        group_bh, bits_wanted,
+                                                       max_bits,
                                                        &tmp_off, &tmp_found);
                if (ret)
                        return ret;
@@ -951,17 +1018,109 @@ static int ocfs2_block_group_search(struct inode *inode,
        if (bg->bg_free_bits_count)
                ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),
                                                        group_bh, bits_wanted,
+                                                       le16_to_cpu(bg->bg_bits),
                                                        bit_off, bits_found);
 
        return ret;
 }
 
+static int ocfs2_alloc_dinode_update_counts(struct inode *inode,
+                                      struct ocfs2_journal_handle *handle,
+                                      struct buffer_head *di_bh,
+                                      u32 num_bits,
+                                      u16 chain)
+{
+       int ret;
+       u32 tmp_used;
+       struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;
+       struct ocfs2_chain_list *cl = (struct ocfs2_chain_list *) &di->id2.i_chain;
+
+       ret = ocfs2_journal_access(handle, inode, di_bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       tmp_used = le32_to_cpu(di->id1.bitmap1.i_used);
+       di->id1.bitmap1.i_used = cpu_to_le32(num_bits + tmp_used);
+       le32_add_cpu(&cl->cl_recs[chain].c_free, -num_bits);
+
+       ret = ocfs2_journal_dirty(handle, di_bh);
+       if (ret < 0)
+               mlog_errno(ret);
+
+out:
+       return ret;
+}
+
+static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
+                                 u32 bits_wanted,
+                                 u32 min_bits,
+                                 u16 *bit_off,
+                                 unsigned int *num_bits,
+                                 u64 gd_blkno,
+                                 u16 *bits_left)
+{
+       int ret;
+       u16 found;
+       struct buffer_head *group_bh = NULL;
+       struct ocfs2_group_desc *gd;
+       struct inode *alloc_inode = ac->ac_inode;
+       struct ocfs2_journal_handle *handle = ac->ac_handle;
+
+       ret = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb), gd_blkno,
+                              &group_bh, OCFS2_BH_CACHED, alloc_inode);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+
+       gd = (struct ocfs2_group_desc *) group_bh->b_data;
+       if (!OCFS2_IS_VALID_GROUP_DESC(gd)) {
+               OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, gd);
+               ret = -EIO;
+               goto out;
+       }
+
+       ret = ac->ac_group_search(alloc_inode, group_bh, bits_wanted, min_bits,
+                                 bit_off, &found);
+       if (ret < 0) {
+               if (ret != -ENOSPC)
+                       mlog_errno(ret);
+               goto out;
+       }
+
+       *num_bits = found;
+
+       ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh,
+                                              *num_bits,
+                                              le16_to_cpu(gd->bg_chain));
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_block_group_set_bits(handle, alloc_inode, gd, group_bh,
+                                        *bit_off, *num_bits);
+       if (ret < 0)
+               mlog_errno(ret);
+
+       *bits_left = le16_to_cpu(gd->bg_free_bits_count);
+
+out:
+       brelse(group_bh);
+
+       return ret;
+}
+
 static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
                              u32 bits_wanted,
                              u32 min_bits,
                              u16 *bit_off,
                              unsigned int *num_bits,
-                             u64 *bg_blkno)
+                             u64 *bg_blkno,
+                             u16 *bits_left)
 {
        int status;
        u16 chain, tmp_bits;
@@ -988,9 +1147,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
                goto bail;
        }
        bg = (struct ocfs2_group_desc *) group_bh->b_data;
-       if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
-               OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
-               status = -EIO;
+       status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, bg);
+       if (status) {
+               mlog_errno(status);
                goto bail;
        }
 
@@ -1018,9 +1177,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
                        goto bail;
                }
                bg = (struct ocfs2_group_desc *) group_bh->b_data;
-               if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
-                       OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
-                       status = -EIO;
+               status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, bg);
+               if (status) {
+                       mlog_errno(status);
                        goto bail;
                }
        }
@@ -1099,6 +1258,7 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
             (unsigned long long)fe->i_blkno);
 
        *bg_blkno = le64_to_cpu(bg->bg_blkno);
+       *bits_left = le16_to_cpu(bg->bg_free_bits_count);
 bail:
        if (group_bh)
                brelse(group_bh);
@@ -1120,6 +1280,8 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
 {
        int status;
        u16 victim, i;
+       u16 bits_left = 0;
+       u64 hint_blkno = ac->ac_last_group;
        struct ocfs2_chain_list *cl;
        struct ocfs2_dinode *fe;
 
@@ -1146,6 +1308,28 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
                goto bail;
        }
 
+       if (hint_blkno) {
+               /* Attempt to short-circuit the usual search mechanism
+                * by jumping straight to the most recently used
+                * allocation group. This helps us mantain some
+                * contiguousness across allocations. */
+               status = ocfs2_search_one_group(ac, bits_wanted, min_bits,
+                                               bit_off, num_bits,
+                                               hint_blkno, &bits_left);
+               if (!status) {
+                       /* Be careful to update *bg_blkno here as the
+                        * caller is expecting it to be filled in, and
+                        * ocfs2_search_one_group() won't do that for
+                        * us. */
+                       *bg_blkno = hint_blkno;
+                       goto set_hint;
+               }
+               if (status < 0 && status != -ENOSPC) {
+                       mlog_errno(status);
+                       goto bail;
+               }
+       }
+
        cl = (struct ocfs2_chain_list *) &fe->id2.i_chain;
 
        victim = ocfs2_find_victim_chain(cl);
@@ -1153,9 +1337,9 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
        ac->ac_allow_chain_relink = 1;
 
        status = ocfs2_search_chain(ac, bits_wanted, min_bits, bit_off,
-                                   num_bits, bg_blkno);
+                                   num_bits, bg_blkno, &bits_left);
        if (!status)
-               goto bail;
+               goto set_hint;
        if (status < 0 && status != -ENOSPC) {
                mlog_errno(status);
                goto bail;
@@ -1177,8 +1361,8 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
 
                ac->ac_chain = i;
                status = ocfs2_search_chain(ac, bits_wanted, min_bits,
-                                           bit_off, num_bits,
-                                           bg_blkno);
+                                           bit_off, num_bits, bg_blkno,
+                                           &bits_left);
                if (!status)
                        break;
                if (status < 0 && status != -ENOSPC) {
@@ -1186,8 +1370,19 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
                        goto bail;
                }
        }
-bail:
 
+set_hint:
+       if (status != -ENOSPC) {
+               /* If the next search of this group is not likely to
+                * yield a suitable extent, then we reset the last
+                * group hint so as to not waste a disk read */
+               if (bits_left < min_bits)
+                       ac->ac_last_group = 0;
+               else
+                       ac->ac_last_group = *bg_blkno;
+       }
+
+bail:
        mlog_exit(status);
        return status;
 }
@@ -1341,7 +1536,7 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb,
 {
        int status;
        unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
-       u64 bg_blkno;
+       u64 bg_blkno = 0;
        u16 bg_bit_off;
 
        mlog_entry_void();
@@ -1494,9 +1689,9 @@ static int ocfs2_free_suballoc_bits(struct ocfs2_journal_handle *handle,
        }
 
        group = (struct ocfs2_group_desc *) group_bh->b_data;
-       if (!OCFS2_IS_VALID_GROUP_DESC(group)) {
-               OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, group);
-               status = -EIO;
+       status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, group);
+       if (status) {
+               mlog_errno(status);
                goto bail;
        }
        BUG_ON((count + start_bit) > le16_to_cpu(group->bg_bits));
index a76c82a7ceac30bb69dfef2f818e9cac43c9353b..c787838d1052474d335b2754c88cf0a1d68f06c1 100644 (file)
@@ -49,6 +49,8 @@ struct ocfs2_alloc_context {
        u16    ac_chain;
        int    ac_allow_chain_relink;
        group_search_t *ac_group_search;
+
+       u64    ac_last_group;
 };
 
 void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac);
index 382706a67ffdce24decb8349851384739e2d05e3..d17e33e66a1e5228cead65463a3255adb383fa71 100644 (file)
@@ -1442,8 +1442,13 @@ static int ocfs2_initialize_super(struct super_block *sb,
 
        osb->bitmap_blkno = OCFS2_I(inode)->ip_blkno;
 
+       /* We don't have a cluster lock on the bitmap here because
+        * we're only interested in static information and the extra
+        * complexity at mount time isn't worht it. Don't pass the
+        * inode in to the read function though as we don't want it to
+        * be put in the cache. */
        status = ocfs2_read_block(osb, osb->bitmap_blkno, &bitmap_bh, 0,
-                                 inode);
+                                 NULL);
        iput(inode);
        if (status < 0) {
                mlog_errno(status);
@@ -1452,7 +1457,6 @@ static int ocfs2_initialize_super(struct super_block *sb,
 
        di = (struct ocfs2_dinode *) bitmap_bh->b_data;
        osb->bitmap_cpg = le16_to_cpu(di->id2.i_chain.cl_cpg);
-       osb->num_clusters = le32_to_cpu(di->id1.bitmap1.i_total);
        brelse(bitmap_bh);
        mlog(0, "cluster bitmap inode: %llu, clusters per group: %u\n",
             (unsigned long long)osb->bitmap_blkno, osb->bitmap_cpg);
index 4df822c881b69357038f96f0d91f6231f7da4a15..7de172efa0841eac8239b72b839138e0adab4146 100644 (file)
@@ -115,6 +115,13 @@ static struct inode *udf_alloc_inode(struct super_block *sb)
        ei = (struct udf_inode_info *)kmem_cache_alloc(udf_inode_cachep, SLAB_KERNEL);
        if (!ei)
                return NULL;
+
+       ei->i_unique = 0;
+       ei->i_lenExtents = 0;
+       ei->i_next_alloc_block = 0;
+       ei->i_next_alloc_goal = 0;
+       ei->i_strat4096 = 0;
+
        return &ei->vfs_inode;
 }
 
index eef6763f3a6732084ede458d4a8b38b5e01e3fd4..d2bbcd882a69578174110f3655e4aadf190a52f4 100644 (file)
@@ -1835,40 +1835,47 @@ xfs_alloc_fix_freelist(
                                &agbp)))
                        return error;
                if (!pag->pagf_init) {
+                       ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK);
+                       ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
                        args->agbp = NULL;
                        return 0;
                }
        } else
                agbp = NULL;
 
-       /* If this is a metadata preferred pag and we are user data
+       /*
+        * If this is a metadata preferred pag and we are user data
         * then try somewhere else if we are not being asked to
         * try harder at this point
         */
-       if (pag->pagf_metadata && args->userdata && flags) {
+       if (pag->pagf_metadata && args->userdata &&
+           (flags & XFS_ALLOC_FLAG_TRYLOCK)) {
+               ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
                args->agbp = NULL;
                return 0;
        }
 
-       need = XFS_MIN_FREELIST_PAG(pag, mp);
-       delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0;
-       /*
-        * If it looks like there isn't a long enough extent, or enough
-        * total blocks, reject it.
-        */
-       longest = (pag->pagf_longest > delta) ?
-               (pag->pagf_longest - delta) :
-               (pag->pagf_flcount > 0 || pag->pagf_longest > 0);
-       if (args->minlen + args->alignment + args->minalignslop - 1 > longest ||
-           (!(flags & XFS_ALLOC_FLAG_FREEING) &&
-            (int)(pag->pagf_freeblks + pag->pagf_flcount -
-                  need - args->total) <
-            (int)args->minleft)) {
-               if (agbp)
-                       xfs_trans_brelse(tp, agbp);
-               args->agbp = NULL;
-               return 0;
+       if (!(flags & XFS_ALLOC_FLAG_FREEING)) {
+               need = XFS_MIN_FREELIST_PAG(pag, mp);
+               delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0;
+               /*
+                * If it looks like there isn't a long enough extent, or enough
+                * total blocks, reject it.
+                */
+               longest = (pag->pagf_longest > delta) ?
+                       (pag->pagf_longest - delta) :
+                       (pag->pagf_flcount > 0 || pag->pagf_longest > 0);
+               if ((args->minlen + args->alignment + args->minalignslop - 1) >
+                               longest ||
+                   ((int)(pag->pagf_freeblks + pag->pagf_flcount -
+                          need - args->total) < (int)args->minleft)) {
+                       if (agbp)
+                               xfs_trans_brelse(tp, agbp);
+                       args->agbp = NULL;
+                       return 0;
+               }
        }
+
        /*
         * Get the a.g. freespace buffer.
         * Can fail if we're not blocking on locks, and it's held.
@@ -1878,6 +1885,8 @@ xfs_alloc_fix_freelist(
                                &agbp)))
                        return error;
                if (agbp == NULL) {
+                       ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK);
+                       ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
                        args->agbp = NULL;
                        return 0;
                }
@@ -1887,22 +1896,24 @@ xfs_alloc_fix_freelist(
         */
        agf = XFS_BUF_TO_AGF(agbp);
        need = XFS_MIN_FREELIST(agf, mp);
-       delta = need > be32_to_cpu(agf->agf_flcount) ?
-               (need - be32_to_cpu(agf->agf_flcount)) : 0;
        /*
         * If there isn't enough total or single-extent, reject it.
         */
-       longest = be32_to_cpu(agf->agf_longest);
-       longest = (longest > delta) ? (longest - delta) :
-               (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0);
-       if (args->minlen + args->alignment + args->minalignslop - 1 > longest ||
-            (!(flags & XFS_ALLOC_FLAG_FREEING) &&
-               (int)(be32_to_cpu(agf->agf_freeblks) +
-                  be32_to_cpu(agf->agf_flcount) - need - args->total) <
-            (int)args->minleft)) {
-               xfs_trans_brelse(tp, agbp);
-               args->agbp = NULL;
-               return 0;
+       if (!(flags & XFS_ALLOC_FLAG_FREEING)) {
+               delta = need > be32_to_cpu(agf->agf_flcount) ?
+                       (need - be32_to_cpu(agf->agf_flcount)) : 0;
+               longest = be32_to_cpu(agf->agf_longest);
+               longest = (longest > delta) ? (longest - delta) :
+                       (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0);
+               if ((args->minlen + args->alignment + args->minalignslop - 1) >
+                               longest ||
+                   ((int)(be32_to_cpu(agf->agf_freeblks) +
+                    be32_to_cpu(agf->agf_flcount) - need - args->total) <
+                               (int)args->minleft)) {
+                       xfs_trans_brelse(tp, agbp);
+                       args->agbp = NULL;
+                       return 0;
+               }
        }
        /*
         * Make the freelist shorter if it's too long.
@@ -1950,12 +1961,11 @@ xfs_alloc_fix_freelist(
                 * on a completely full ag.
                 */
                if (targs.agbno == NULLAGBLOCK) {
-                       if (!(flags & XFS_ALLOC_FLAG_FREEING)) {
-                               xfs_trans_brelse(tp, agflbp);
-                               args->agbp = NULL;
-                               return 0;
-                       }
-                       break;
+                       if (flags & XFS_ALLOC_FLAG_FREEING)
+                               break;
+                       xfs_trans_brelse(tp, agflbp);
+                       args->agbp = NULL;
+                       return 0;
                }
                /*
                 * Put each allocated block on the list.
@@ -2442,31 +2452,26 @@ xfs_free_extent(
        xfs_fsblock_t   bno,    /* starting block number of extent */
        xfs_extlen_t    len)    /* length of extent */
 {
-#ifdef DEBUG
-       xfs_agf_t       *agf;   /* a.g. freespace header */
-#endif
-       xfs_alloc_arg_t args;   /* allocation argument structure */
+       xfs_alloc_arg_t args;
        int             error;
 
        ASSERT(len != 0);
+       memset(&args, 0, sizeof(xfs_alloc_arg_t));
        args.tp = tp;
        args.mp = tp->t_mountp;
        args.agno = XFS_FSB_TO_AGNO(args.mp, bno);
        ASSERT(args.agno < args.mp->m_sb.sb_agcount);
        args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno);
-       args.alignment = 1;
-       args.minlen = args.minleft = args.minalignslop = 0;
        down_read(&args.mp->m_peraglock);
        args.pag = &args.mp->m_perag[args.agno];
        if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING)))
                goto error0;
 #ifdef DEBUG
        ASSERT(args.agbp != NULL);
-       agf = XFS_BUF_TO_AGF(args.agbp);
-       ASSERT(args.agbno + len <= be32_to_cpu(agf->agf_length));
+       ASSERT((args.agbno + len) <=
+               be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length));
 #endif
-       error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno,
-               len, 0);
+       error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0);
 error0:
        up_read(&args.mp->m_peraglock);
        return error;
index 8f7fd5cfec34f4c9fa0a39843ae443825f277fda..11cbdf81fd2e8f5113f1359660ce1f16eb1add91 100644 (file)
@@ -32,6 +32,7 @@
 #endif
 
 #ifndef __ASSEMBLY__
+#include <linux/cpumask.h>
 
 #ifdef CONFIG_KEXEC
 
@@ -109,7 +110,6 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
 
 #define MAX_NOTE_BYTES 1024
 
-#ifdef __powerpc64__
 extern void kexec_smp_wait(void);      /* get and clear naca physid, wait for
                                          master to copy new code to 0 */
 extern int crashing_cpu;
@@ -119,7 +119,6 @@ static inline int kexec_sr_activated(int cpu)
 {
        return cpu_isset(cpu,cpus_in_sr);
 }
-#endif /* __powerpc64 __ */
 
 struct kimage;
 struct pt_regs;
index a33c6acffa61f5c8bad8fbb007b1fc0dd0590563..82a27e9a041ff292eba8e103b4ebf7aca1ca27bf 100644 (file)
@@ -170,6 +170,7 @@ extern int rtas_get_sensor(int sensor, int index, int *state);
 extern int rtas_get_power_level(int powerdomain, int *level);
 extern int rtas_set_power_level(int powerdomain, int level, int *setlevel);
 extern int rtas_set_indicator(int indicator, int index, int new_value);
+extern int rtas_set_indicator_fast(int indicator, int index, int new_value);
 extern void rtas_progress(char *s, unsigned short hex);
 extern void rtas_initialize(void);
 
index c70344b910492d8633b98eb3d5f7b212264f80ae..f6a7ff04ffe5030a46092538ce31c99ac9478c3e 100644 (file)
@@ -1093,5 +1093,100 @@ typedef struct im_idma {
 
 #define FCC_PSMR_RMII  ((uint)0x00020000)      /* Use RMII interface */
 
+/* FCC iop & clock configuration. BSP code is responsible to define Fx_RXCLK & Fx_TXCLK
+ * in order to use clock-computing stuff below for the FCC x
+ */
+
+/* Automatically generates register configurations */
+#define PC_CLK(x)      ((uint)(1<<(x-1)))      /* FCC CLK I/O ports */
+
+#define CMXFCR_RF1CS(x)        ((uint)((x-5)<<27))     /* FCC1 Receive Clock Source */
+#define CMXFCR_TF1CS(x)        ((uint)((x-5)<<24))     /* FCC1 Transmit Clock Source */
+#define CMXFCR_RF2CS(x)        ((uint)((x-9)<<19))     /* FCC2 Receive Clock Source */
+#define CMXFCR_TF2CS(x) ((uint)((x-9)<<16))    /* FCC2 Transmit Clock Source */
+#define CMXFCR_RF3CS(x)        ((uint)((x-9)<<11))     /* FCC3 Receive Clock Source */
+#define CMXFCR_TF3CS(x) ((uint)((x-9)<<8))     /* FCC3 Transmit Clock Source */
+
+#define PC_F1RXCLK     PC_CLK(F1_RXCLK)
+#define PC_F1TXCLK     PC_CLK(F1_TXCLK)
+#define CMX1_CLK_ROUTE (CMXFCR_RF1CS(F1_RXCLK) | CMXFCR_TF1CS(F1_TXCLK))
+#define CMX1_CLK_MASK  ((uint)0xff000000)
+
+#define PC_F2RXCLK     PC_CLK(F2_RXCLK)
+#define PC_F2TXCLK     PC_CLK(F2_TXCLK)
+#define CMX2_CLK_ROUTE (CMXFCR_RF2CS(F2_RXCLK) | CMXFCR_TF2CS(F2_TXCLK))
+#define CMX2_CLK_MASK  ((uint)0x00ff0000)
+
+#define PC_F3RXCLK     PC_CLK(F3_RXCLK)
+#define PC_F3TXCLK     PC_CLK(F3_TXCLK)
+#define CMX3_CLK_ROUTE (CMXFCR_RF3CS(F3_RXCLK) | CMXFCR_TF3CS(F3_TXCLK))
+#define CMX3_CLK_MASK  ((uint)0x0000ff00)
+
+#define CPMUX_CLK_MASK (CMX3_CLK_MASK | CMX2_CLK_MASK)
+#define CPMUX_CLK_ROUTE (CMX3_CLK_ROUTE | CMX2_CLK_ROUTE)
+
+#define CLK_TRX (PC_F3TXCLK | PC_F3RXCLK | PC_F2TXCLK | PC_F2RXCLK)
+
+/* I/O Pin assignment for FCC1.  I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PA1_COL                0x00000001U
+#define PA1_CRS                0x00000002U
+#define PA1_TXER       0x00000004U
+#define PA1_TXEN       0x00000008U
+#define PA1_RXDV       0x00000010U
+#define PA1_RXER       0x00000020U
+#define PA1_TXDAT      0x00003c00U
+#define PA1_RXDAT      0x0003c000U
+#define PA1_PSORA0     (PA1_RXDAT | PA1_TXDAT)
+#define PA1_PSORA1     (PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
+               PA1_RXDV | PA1_RXER)
+#define PA1_DIRA0      (PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
+#define PA1_DIRA1      (PA1_TXDAT | PA1_TXEN | PA1_TXER)
+
+
+/* I/O Pin assignment for FCC2.  I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB2_TXER       0x00000001U
+#define PB2_RXDV       0x00000002U
+#define PB2_TXEN       0x00000004U
+#define PB2_RXER       0x00000008U
+#define PB2_COL                0x00000010U
+#define PB2_CRS                0x00000020U
+#define PB2_TXDAT      0x000003c0U
+#define PB2_RXDAT      0x00003c00U
+#define PB2_PSORB0     (PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
+               PB2_RXER | PB2_RXDV | PB2_TXER)
+#define PB2_PSORB1     (PB2_TXEN)
+#define PB2_DIRB0      (PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
+#define PB2_DIRB1      (PB2_TXDAT | PB2_TXEN | PB2_TXER)
+
+
+/* I/O Pin assignment for FCC3.  I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB3_RXDV       0x00004000U
+#define PB3_RXER       0x00008000U
+#define PB3_TXER       0x00010000U
+#define PB3_TXEN       0x00020000U
+#define PB3_COL                0x00040000U
+#define PB3_CRS                0x00080000U
+#define PB3_TXDAT      0x0f000000U
+#define PC3_TXDAT      0x00000010U
+#define PB3_RXDAT      0x00f00000U
+#define PB3_PSORB0     (PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
+               PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
+#define PB3_PSORB1     0
+#define PB3_DIRB0      (PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
+#define PB3_DIRB1      (PB3_TXDAT | PB3_TXEN | PB3_TXER)
+#define PC3_DIRC1      (PC3_TXDAT)
+
+/* Handy macro to specify mem for FCCs*/
+#define FCC_MEM_OFFSET(x) (CPM_FCC_SPECIAL_BASE + (x*128))
+#define FCC1_MEM_OFFSET FCC_MEM_OFFSET(0)
+#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(1)
+#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(2)
+
 #endif /* __CPM2__ */
 #endif /* __KERNEL__ */
index 4b93481e7679944d519e6862697c38f8c4fd906a..23579d4afae7549880454074171c4683b3e13fda 100644 (file)
@@ -82,6 +82,7 @@ enum ppc_sys_devices {
        MPC82xx_CPM_SMC2,
        MPC82xx_CPM_USB,
        MPC82xx_SEC1,
+       MPC82xx_MDIO_BB,
        NUM_PPC_SYS_DEVS,
 };
 
index adcce33f20ae7a6d3248510b3b5722f18b526c55..d3a2f2fe230c2181dcad280df11d0b8c20a58612 100644 (file)
@@ -110,6 +110,7 @@ enum ppc_sys_devices {
        MPC8xx_CPM_SMC1,
        MPC8xx_CPM_SMC2,
        MPC8xx_CPM_USB,
+       MPC8xx_MDIO_FEC,
        NUM_PPC_SYS_DEVS,
 };
 
index 4ad0673b199505b0f34c09dd2be80cc2a29c1d46..2f335e966011510df9944119d33daae9850580aa 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _LINUX_FB_H
 #define _LINUX_FB_H
 
-#include <linux/backlight.h>
 #include <asm/types.h>
 
 /* Definitions of frame buffers                                                */
@@ -381,6 +380,7 @@ struct fb_cursor {
 #include <linux/workqueue.h>
 #include <linux/notifier.h>
 #include <linux/list.h>
+#include <linux/backlight.h>
 #include <asm/io.h>
 
 struct vm_area_struct;
index 783c476b8674483ff11d415b30d991895667ddeb..74ed35a00a94db84cefdc6ddcf62715582d6006a 100644 (file)
@@ -69,34 +69,21 @@ enum fs_ioport {
        fsiop_porte,
 };
 
-struct fs_mii_bus_info {
-       int method;             /* mii method                  */
-       int id;                 /* the id of the mii_bus       */
-       int disable_aneg;       /* if the controller needs to negothiate speed & duplex */
-       int lpa;                /* the default board-specific vallues will be applied otherwise */
-
-       union {
-               struct {
-                       int duplex;
-                       int speed;
-               } fixed;
-
-               struct {
-                       /* nothing */
-               } fec;
-               
-               struct {
-                       /* nothing */
-               } scc;
-
-               struct {
-                       int mdio_port;  /* port & bit for MDIO */
-                       int mdio_bit;
-                       int mdc_port;   /* port & bit for MDC  */
-                       int mdc_bit;
-                       int delay;      /* delay in us         */
-               } bitbang;
-       } i;
+struct fs_mii_bit {
+       u32 offset;
+       u8 bit;
+       u8 polarity;
+};
+struct fs_mii_bb_platform_info {
+       struct fs_mii_bit       mdio_dir;
+       struct fs_mii_bit       mdio_dat;
+       struct fs_mii_bit       mdc_dat;
+       int mdio_port;  /* port & bit for MDIO */
+       int mdio_bit;
+       int mdc_port;   /* port & bit for MDC  */
+       int mdc_bit;
+       int delay;      /* delay in us         */
+       int irq[32];    /* irqs per phy's */
 };
 
 struct fs_platform_info {
@@ -119,6 +106,7 @@ struct fs_platform_info {
        u32 device_flags;
 
        int phy_addr;           /* the phy address (-1 no phy) */
+       const char*     bus_id;
        int phy_irq;            /* the phy irq (if it exists)  */
 
        const struct fs_mii_bus_info *bus_info;
@@ -130,6 +118,10 @@ struct fs_platform_info {
        int napi_weight;        /* NAPI weight                 */
 
        int use_rmii;           /* use RMII mode               */
+       int has_phy;            /* if the network is phy container as well...*/
+};
+struct fs_mii_fec_platform_info {
+       u32 irq[32];
+       u32 mii_speed;
 };
-
 #endif
index 383627ad328f383bfe07f78ddc77e09e37066d95..ab2740832742e85c6a6870384aa47bbe70c8a201 100644 (file)
@@ -155,6 +155,11 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb,
 {
        struct net_device_stats *stats;
 
+       if (skb_bond_should_drop(skb)) {
+               dev_kfree_skb_any(skb);
+               return NET_RX_DROP;
+       }
+
        skb->dev = grp->vlan_devices[vlan_tag & VLAN_VID_MASK];
        if (skb->dev == NULL) {
                dev_kfree_skb_any(skb);
index 181c69cad4e3a45dca58bd6c50c2ae3d3e95f5b1..851aa1bcfc1a25c65db7fd2829e1844fb6086e33 100644 (file)
@@ -210,6 +210,7 @@ extern enum system_states {
 extern void dump_stack(void);
 
 #ifdef DEBUG
+/* If you are writing a driver, please use dev_dbg instead */
 #define pr_debug(fmt,arg...) \
        printk(KERN_DEBUG fmt,##arg)
 #else
index 990957e0929f2319f217115df75977b3467ce5a4..f0b135cd86da1e54789bce46eb7bb8f6487edcaa 100644 (file)
@@ -336,6 +336,7 @@ static inline void init_page_count(struct page *page)
 }
 
 void put_page(struct page *page);
+void put_pages_list(struct list_head *pages);
 
 void split_page(struct page *page, unsigned int order);
 
index 75f02d8c6ed376b192858faff4de312c3b71e2ab..50a4719512ede141d2fbf045031ff2096227f98b 100644 (file)
@@ -320,6 +320,9 @@ struct net_device
 #define NETIF_F_TSO_ECN                (SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT)
 #define NETIF_F_TSO6           (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT)
 
+       /* List of features with software fallbacks. */
+#define NETIF_F_GSO_SOFTWARE   (NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6)
+
 #define NETIF_F_GEN_CSUM       (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
 #define NETIF_F_ALL_CSUM       (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
 
@@ -1012,6 +1015,30 @@ static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
                unlikely(skb->ip_summed != CHECKSUM_HW));
 }
 
+/* On bonding slaves other than the currently active slave, suppress
+ * duplicates except for 802.3ad ETH_P_SLOW and alb non-mcast/bcast.
+ */
+static inline int skb_bond_should_drop(struct sk_buff *skb)
+{
+       struct net_device *dev = skb->dev;
+       struct net_device *master = dev->master;
+
+       if (master &&
+           (dev->priv_flags & IFF_SLAVE_INACTIVE)) {
+               if (master->priv_flags & IFF_MASTER_ALB) {
+                       if (skb->pkt_type != PACKET_BROADCAST &&
+                           skb->pkt_type != PACKET_MULTICAST)
+                               return 0;
+               }
+               if (master->priv_flags & IFF_MASTER_8023AD &&
+                   skb->protocol == __constant_htons(ETH_P_SLOW))
+                       return 0;
+
+               return 1;
+       }
+       return 0;
+}
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_DEV_H */
index 331521a10a2d5072be85698afd37c1300016d53d..9447a57ee8a9fbf212d8ab6b242cb5cf26a3542a 100644 (file)
@@ -378,6 +378,7 @@ 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);
+struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id);
 
 extern struct bus_type mdio_bus_type;
 #endif /* __PHY_H */
index 19c96d498e20059b12fc0b07c6cf5d760cb79fcd..755e9cddac47eebe516751a55929f4339b576c5f 100644 (file)
@@ -1039,6 +1039,21 @@ static inline int pskb_trim(struct sk_buff *skb, unsigned int len)
        return (len < skb->len) ? __pskb_trim(skb, len) : 0;
 }
 
+/**
+ *     pskb_trim_unique - remove end from a paged unique (not cloned) buffer
+ *     @skb: buffer to alter
+ *     @len: new length
+ *
+ *     This is identical to pskb_trim except that the caller knows that
+ *     the skb is not cloned so we should never get an error due to out-
+ *     of-memory.
+ */
+static inline void pskb_trim_unique(struct sk_buff *skb, unsigned int len)
+{
+       int err = pskb_trim(skb, len);
+       BUG_ON(err);
+}
+
 /**
  *     skb_orphan - orphan a buffer
  *     @skb: buffer to orphan
@@ -1081,7 +1096,7 @@ static inline void __skb_queue_purge(struct sk_buff_head *list)
  *     the headroom they think they need without accounting for the
  *     built in space. The built in space is used for optimisations.
  *
- *     %NULL is returned in there is no free memory.
+ *     %NULL is returned if there is no free memory.
  */
 static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
                                              gfp_t gfp_mask)
@@ -1101,7 +1116,7 @@ static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
  *     the headroom they think they need without accounting for the
  *     built in space. The built in space is used for optimisations.
  *
- *     %NULL is returned in there is no free memory. Although this function
+ *     %NULL is returned if there is no free memory. Although this function
  *     allocates memory it can be called from an interrupt.
  */
 static inline struct sk_buff *dev_alloc_skb(unsigned int length)
index f8665326ed9fc2a62a683e35a5595b1bc9fdc9fe..600d61d7d2ab8e190b1c8a763cd6f107efa20d7d 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/device.h>
 #include <linux/mutex.h>
 #include <linux/compiler.h> /* need __user */
-#ifdef CONFIG_VIDEO_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 #include <linux/videodev.h>
 #else
 #include <linux/videodev2.h>
index ecc42864b001a400a5c8fe32a6de6a3feac92f81..b174ebb277a96668f058e469b0753503c34f164b 100644 (file)
@@ -240,6 +240,11 @@ struct ieee80211_snap_hdr {
 #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10)
 #define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
 
+/* 802.11g ERP information element */
+#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
+#define WLAN_ERP_USE_PROTECTION (1<<1)
+#define WLAN_ERP_BARKER_PREAMBLE (1<<2)
+
 /* Status codes */
 enum ieee80211_statuscode {
        WLAN_STATUS_SUCCESS = 0,
@@ -747,6 +752,8 @@ struct ieee80211_txb {
 #define NETWORK_HAS_IBSS_DFS            (1<<8)
 #define NETWORK_HAS_TPC_REPORT          (1<<9)
 
+#define NETWORK_HAS_ERP_VALUE           (1<<10)
+
 #define QOS_QUEUE_NUM                   4
 #define QOS_OUI_LEN                     3
 #define QOS_OUI_TYPE                    2
@@ -1252,6 +1259,8 @@ extern int ieee80211_tx_frame(struct ieee80211_device *ieee,
                              int total_len, int encrypt_mpdu);
 
 /* ieee80211_rx.c */
+extern void ieee80211_rx_any(struct ieee80211_device *ieee,
+                    struct sk_buff *skb, struct ieee80211_rx_stats *stats);
 extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                        struct ieee80211_rx_stats *rx_stats);
 /* make sure to set stats->len */
index 00ad810eb883090add39c82b60fd130cf97452c0..425b3a57ac74a01d12f8f3d714b66cd9d7dbcb04 100644 (file)
@@ -86,9 +86,6 @@ struct ieee80211softmac_assoc_info {
        
        /* BSSID we're trying to associate to */
        char bssid[ETH_ALEN];
-
-       /* Rates supported by the network */
-       struct ieee80211softmac_ratesinfo supported_rates;
        
        /* some flags.
         * static_essid is valid if the essid is constant,
@@ -103,6 +100,7 @@ struct ieee80211softmac_assoc_info {
         * bssfixed is used for SIOCSIWAP.
         */
        u8 static_essid:1,
+          short_preamble_available:1,
           associating:1,
           assoc_wait:1,
           bssvalid:1,
@@ -115,6 +113,19 @@ struct ieee80211softmac_assoc_info {
        struct work_struct timeout;
 };
 
+struct ieee80211softmac_bss_info {
+       /* Rates supported by the network */
+       struct ieee80211softmac_ratesinfo supported_rates;
+
+       /* This indicates whether frames can currently be transmitted with
+        * short preamble (only use this variable during TX at CCK rates) */
+       u8 short_preamble:1;
+
+       /* This indicates whether protection (e.g. self-CTS) should be used
+        * when transmitting with OFDM modulation */
+       u8 use_protection:1;
+};
+
 enum {
        IEEE80211SOFTMAC_AUTH_OPEN_REQUEST      = 1,
        IEEE80211SOFTMAC_AUTH_OPEN_RESPONSE     = 2,
@@ -157,6 +168,10 @@ struct ieee80211softmac_txrates {
 #define IEEE80211SOFTMAC_TXRATECHG_MCAST               (1 << 2) /* mcast_rate */
 #define IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST           (1 << 3) /* mgt_mcast_rate */
 
+#define IEEE80211SOFTMAC_BSSINFOCHG_RATES              (1 << 0) /* supported_rates */
+#define IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE     (1 << 1) /* short_preamble */
+#define IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION         (1 << 2) /* use_protection */
+
 struct ieee80211softmac_device {
        /* 802.11 structure for data stuff */
        struct ieee80211_device *ieee;
@@ -200,10 +215,16 @@ struct ieee80211softmac_device {
         * The driver just needs to read them.
         */
        struct ieee80211softmac_txrates txrates;
-       /* If the driver needs to do stuff on TX rate changes, assign this callback. */
+
+       /* If the driver needs to do stuff on TX rate changes, assign this
+        * callback. See IEEE80211SOFTMAC_TXRATECHG for change flags. */
        void (*txrates_change)(struct net_device *dev,
-                              u32 changes, /* see IEEE80211SOFTMAC_TXRATECHG flags */
-                              const struct ieee80211softmac_txrates *rates_before_change);
+                              u32 changes);
+
+       /* If the driver needs to do stuff when BSS properties change, assign
+        * this callback. see IEEE80211SOFTMAC_BSSINFOCHG for change flags. */
+       void (*bssinfo_change)(struct net_device *dev,
+                              u32 changes);
 
        /* private stuff follows */
        /* this lock protects this structure */
@@ -216,6 +237,7 @@ struct ieee80211softmac_device {
        
        struct ieee80211softmac_scaninfo *scaninfo;
        struct ieee80211softmac_assoc_info associnfo;
+       struct ieee80211softmac_bss_info bssinfo;
 
        struct list_head auth_queue;
        struct list_head events;
@@ -257,6 +279,14 @@ extern void ieee80211softmac_fragment_lost(struct net_device *dev,
  * Note that the rates need to be sorted. */
 extern void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates);
 
+/* Finds the highest rate which is:
+ *  1. Present in ri (optionally a basic rate)
+ *  2. Supported by the device
+ *  3. Less than or equal to the user-defined rate
+ */
+extern u8 ieee80211softmac_highest_supported_rate(struct ieee80211softmac_device *mac,
+       struct ieee80211softmac_ratesinfo *ri, int basic_only);
+
 /* Helper function which advises you the rate at which a frame should be
  * transmitted at. */
 static inline u8 ieee80211softmac_suggest_txrate(struct ieee80211softmac_device *mac,
@@ -279,6 +309,24 @@ static inline u8 ieee80211softmac_suggest_txrate(struct ieee80211softmac_device
                return txrates->mcast_rate;
 }
 
+/* Helper function which advises you when it is safe to transmit with short
+ * preamble.
+ * You should only call this function when transmitting at CCK rates. */
+static inline int ieee80211softmac_short_preamble_ok(struct ieee80211softmac_device *mac,
+                                                   int is_multicast,
+                                                   int is_mgt)
+{
+       return (is_multicast && is_mgt) ? 0 : mac->bssinfo.short_preamble;
+}
+
+/* Helper function which advises you whether protection (e.g. self-CTS) is
+ * needed. 1 = protection needed, 0 = no protection needed
+ * Only use this function when transmitting with OFDM modulation. */
+static inline int ieee80211softmac_protection_needed(struct ieee80211softmac_device *mac)
+{
+       return mac->bssinfo.use_protection;
+}
+
 /* Start the SoftMAC. Call this after you initialized the device
  * and it is ready to run.
  */
index c2b2e0b83abf520a5a170252e8d56e4659443448..d4633c588f33e417df960bff848ba5fa26eb78fe 100644 (file)
@@ -297,7 +297,7 @@ static int futex_handle_fault(unsigned long address, int attempt)
        struct vm_area_struct * vma;
        struct mm_struct *mm = current->mm;
 
-       if (attempt >= 2 || !(vma = find_vma(mm, address)) ||
+       if (attempt > 2 || !(vma = find_vma(mm, address)) ||
            vma->vm_start > address || !(vma->vm_flags & VM_WRITE))
                return -EFAULT;
 
@@ -747,8 +747,10 @@ retry:
                 */
                if (attempt++) {
                        if (futex_handle_fault((unsigned long)uaddr2,
-                                              attempt))
+                                               attempt)) {
+                               ret = -EFAULT;
                                goto out;
+                       }
                        goto retry;
                }
 
@@ -1322,9 +1324,10 @@ static int do_futex_lock_pi(u32 __user *uaddr, int detect, int trylock,
         * still holding the mmap_sem.
         */
        if (attempt++) {
-               if (futex_handle_fault((unsigned long)uaddr, attempt))
+               if (futex_handle_fault((unsigned long)uaddr, attempt)) {
+                       ret = -EFAULT;
                        goto out_unlock_release_sem;
-
+               }
                goto retry_locked;
        }
 
@@ -1506,9 +1509,10 @@ pi_faulted:
         * still holding the mmap_sem.
         */
        if (attempt++) {
-               if (futex_handle_fault((unsigned long)uaddr, attempt))
+               if (futex_handle_fault((unsigned long)uaddr, attempt)) {
+                       ret = -EFAULT;
                        goto out_unlock;
-
+               }
                goto retry_locked;
        }
 
index be989efc785612c6331393bbe3f204a86877f379..21c38a7e666ba74f373b9693770af4b22b63a685 100644 (file)
@@ -187,7 +187,7 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_base *base)
 {
        struct hrtimer_base *new_base;
 
-       new_base = &__get_cpu_var(hrtimer_bases[base->index]);
+       new_base = &__get_cpu_var(hrtimer_bases)[base->index];
 
        if (base != new_base) {
                /*
index d8a0bca21233e12d413fa9ab60c436b9b36e0db7..9b8dcfd1ca931e6f728c79655e4edead123a0f11 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/nmi.h>
 #include <linux/kexec.h>
+#include <linux/debug_locks.h>
 
 int panic_on_oops;
 int tainted;
index b650f04888ed6dbc6abb07adcee5c58a8f27c374..1d7dd6267c2de52206bb2f09ca981ff81db4b1a1 100644 (file)
@@ -1324,46 +1324,19 @@ asmlinkage long sys_getpid(void)
 }
 
 /*
- * Accessing ->group_leader->real_parent is not SMP-safe, it could
- * change from under us. However, rather than getting any lock
- * we can use an optimistic algorithm: get the parent
- * pid, and go back and check that the parent is still
- * the same. If it has changed (which is extremely unlikely
- * indeed), we just try again..
- *
- * NOTE! This depends on the fact that even if we _do_
- * get an old value of "parent", we can happily dereference
- * the pointer (it was and remains a dereferencable kernel pointer
- * no matter what): we just can't necessarily trust the result
- * until we know that the parent pointer is valid.
- *
- * NOTE2: ->group_leader never changes from under us.
+ * Accessing ->real_parent is not SMP-safe, it could
+ * change from under us. However, we can use a stale
+ * value of ->real_parent under rcu_read_lock(), see
+ * release_task()->call_rcu(delayed_put_task_struct).
  */
 asmlinkage long sys_getppid(void)
 {
        int pid;
-       struct task_struct *me = current;
-       struct task_struct *parent;
 
-       parent = me->group_leader->real_parent;
-       for (;;) {
-               pid = parent->tgid;
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
-{
-               struct task_struct *old = parent;
+       rcu_read_lock();
+       pid = rcu_dereference(current->real_parent)->tgid;
+       rcu_read_unlock();
 
-               /*
-                * Make sure we read the pid before re-reading the
-                * parent pointer:
-                */
-               smp_rmb();
-               parent = me->group_leader->real_parent;
-               if (old != parent)
-                       continue;
-}
-#endif
-               break;
-       }
        return pid;
 }
 
index 448e8f7b342d063e92704964ad87659e08014707..835fe28b87a8325c1cfb691de03dd7e2615ea943 100644 (file)
@@ -68,7 +68,7 @@ struct workqueue_struct {
 
 /* All the per-cpu workqueues on the system, for hotplug cpu to add/remove
    threads to each one as cpus come/go. */
-static DEFINE_SPINLOCK(workqueue_lock);
+static DEFINE_MUTEX(workqueue_mutex);
 static LIST_HEAD(workqueues);
 
 static int singlethread_cpu;
@@ -320,10 +320,10 @@ void fastcall flush_workqueue(struct workqueue_struct *wq)
        } else {
                int cpu;
 
-               lock_cpu_hotplug();
+               mutex_lock(&workqueue_mutex);
                for_each_online_cpu(cpu)
                        flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu));
-               unlock_cpu_hotplug();
+               mutex_unlock(&workqueue_mutex);
        }
 }
 EXPORT_SYMBOL_GPL(flush_workqueue);
@@ -371,8 +371,7 @@ struct workqueue_struct *__create_workqueue(const char *name,
        }
 
        wq->name = name;
-       /* We don't need the distraction of CPUs appearing and vanishing. */
-       lock_cpu_hotplug();
+       mutex_lock(&workqueue_mutex);
        if (singlethread) {
                INIT_LIST_HEAD(&wq->list);
                p = create_workqueue_thread(wq, singlethread_cpu);
@@ -381,9 +380,7 @@ struct workqueue_struct *__create_workqueue(const char *name,
                else
                        wake_up_process(p);
        } else {
-               spin_lock(&workqueue_lock);
                list_add(&wq->list, &workqueues);
-               spin_unlock(&workqueue_lock);
                for_each_online_cpu(cpu) {
                        p = create_workqueue_thread(wq, cpu);
                        if (p) {
@@ -393,7 +390,7 @@ struct workqueue_struct *__create_workqueue(const char *name,
                                destroy = 1;
                }
        }
-       unlock_cpu_hotplug();
+       mutex_unlock(&workqueue_mutex);
 
        /*
         * Was there any error during startup? If yes then clean up:
@@ -434,17 +431,15 @@ void destroy_workqueue(struct workqueue_struct *wq)
        flush_workqueue(wq);
 
        /* We don't need the distraction of CPUs appearing and vanishing. */
-       lock_cpu_hotplug();
+       mutex_lock(&workqueue_mutex);
        if (is_single_threaded(wq))
                cleanup_workqueue_thread(wq, singlethread_cpu);
        else {
                for_each_online_cpu(cpu)
                        cleanup_workqueue_thread(wq, cpu);
-               spin_lock(&workqueue_lock);
                list_del(&wq->list);
-               spin_unlock(&workqueue_lock);
        }
-       unlock_cpu_hotplug();
+       mutex_unlock(&workqueue_mutex);
        free_percpu(wq->cpu_wq);
        kfree(wq);
 }
@@ -515,11 +510,13 @@ int schedule_on_each_cpu(void (*func)(void *info), void *info)
        if (!works)
                return -ENOMEM;
 
+       mutex_lock(&workqueue_mutex);
        for_each_online_cpu(cpu) {
                INIT_WORK(per_cpu_ptr(works, cpu), func, info);
                __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu),
                                per_cpu_ptr(works, cpu));
        }
+       mutex_unlock(&workqueue_mutex);
        flush_workqueue(keventd_wq);
        free_percpu(works);
        return 0;
@@ -635,6 +632,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_UP_PREPARE:
+               mutex_lock(&workqueue_mutex);
                /* Create a new workqueue thread for it. */
                list_for_each_entry(wq, &workqueues, list) {
                        if (!create_workqueue_thread(wq, hotcpu)) {
@@ -653,6 +651,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
                        kthread_bind(cwq->thread, hotcpu);
                        wake_up_process(cwq->thread);
                }
+               mutex_unlock(&workqueue_mutex);
                break;
 
        case CPU_UP_CANCELED:
@@ -664,6 +663,15 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
                                     any_online_cpu(cpu_online_map));
                        cleanup_workqueue_thread(wq, hotcpu);
                }
+               mutex_unlock(&workqueue_mutex);
+               break;
+
+       case CPU_DOWN_PREPARE:
+               mutex_lock(&workqueue_mutex);
+               break;
+
+       case CPU_DOWN_FAILED:
+               mutex_unlock(&workqueue_mutex);
                break;
 
        case CPU_DEAD:
@@ -671,6 +679,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
                        cleanup_workqueue_thread(wq, hotcpu);
                list_for_each_entry(wq, &workqueues, list)
                        take_over_work(wq, hotcpu);
+               mutex_unlock(&workqueue_mutex);
                break;
        }
 
index 8fd095c4ae51b00b314e732ac9ea5547a5cd26b2..687686a61f7cb81cc75cd65a636ade65eb00d08d 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -54,6 +54,26 @@ void put_page(struct page *page)
 }
 EXPORT_SYMBOL(put_page);
 
+/**
+ * put_pages_list(): release a list of pages
+ *
+ * Release a list of pages which are strung together on page.lru.  Currently
+ * used by read_cache_pages() and related error recovery code.
+ *
+ * @pages: list of pages threaded on page->lru
+ */
+void put_pages_list(struct list_head *pages)
+{
+       while (!list_empty(pages)) {
+               struct page *victim;
+
+               victim = list_entry(pages->prev, struct page, lru);
+               list_del(&victim->lru);
+               page_cache_release(victim);
+       }
+}
+EXPORT_SYMBOL(put_pages_list);
+
 /*
  * Writeback is about to end against a page which has been marked for immediate
  * reclaim.  If it still appears to be reclaimable, move it to the tail of the
index 3f95b0886a6a659afd540ea8cb9f12011a03a3c5..91fe5f53ff112377755054d16ff82cd599dd54a5 100644 (file)
@@ -507,7 +507,7 @@ err_out:
        goto out;
 }
 
-void __exit atm_proc_exit(void)
+void atm_proc_exit(void)
 {
        atm_proc_dirs_remove();
 }
index f55ef682ef846e979b7e1b24569399a7c2fbd7da..b1211d5342f6cac5f43926a2c6a39f1651cb6761 100644 (file)
@@ -386,12 +386,17 @@ void br_features_recompute(struct net_bridge *br)
                        checksum = 0;
 
                if (feature & NETIF_F_GSO)
-                       feature |= NETIF_F_TSO;
+                       feature |= NETIF_F_GSO_SOFTWARE;
                feature |= NETIF_F_GSO;
 
                features &= feature;
        }
 
+       if (!(checksum & NETIF_F_ALL_CSUM))
+               features &= ~NETIF_F_SG;
+       if (!(features & NETIF_F_SG))
+               features &= ~NETIF_F_GSO_MASK;
+
        br->dev->features = features | checksum | NETIF_F_LLTX |
                            NETIF_F_GSO_ROBUST;
 }
index 02693a230dc1faae5d3252f62c4f9a2334ea3f00..9f950db3b76f5135cbb7e1ca7aca9022e5fbcc30 100644 (file)
@@ -74,6 +74,9 @@ static void ulog_send(unsigned int nlgroup)
        if (timer_pending(&ub->timer))
                del_timer(&ub->timer);
 
+       if (!ub->skb)
+               return;
+
        /* last nlmsg needs NLMSG_DONE */
        if (ub->qlen > 1)
                ub->lastnlh->nlmsg_type = NLMSG_DONE;
index d95e2626d944ea754731a3e78382c7f8156bb461..d4a1ec3bded5f6afa92c0cbb860101b509f0f338 100644 (file)
 #include <linux/audit.h>
 #include <linux/dmaengine.h>
 #include <linux/err.h>
+#include <linux/ctype.h>
 
 /*
  *     The list of packet types we will receive (as opposed to discard)
@@ -632,14 +633,22 @@ struct net_device * dev_get_by_flags(unsigned short if_flags, unsigned short mas
  *     @name: name string
  *
  *     Network device names need to be valid file names to
- *     to allow sysfs to work
+ *     to allow sysfs to work.  We also disallow any kind of
+ *     whitespace.
  */
 int dev_valid_name(const char *name)
 {
-       return !(*name == '\0' 
-                || !strcmp(name, ".")
-                || !strcmp(name, "..")
-                || strchr(name, '/'));
+       if (*name == '\0')
+               return 0;
+       if (!strcmp(name, ".") || !strcmp(name, ".."))
+               return 0;
+
+       while (*name) {
+               if (*name == '/' || isspace(*name))
+                       return 0;
+               name++;
+       }
+       return 1;
 }
 
 /**
@@ -1619,26 +1628,10 @@ static inline struct net_device *skb_bond(struct sk_buff *skb)
        struct net_device *dev = skb->dev;
 
        if (dev->master) {
-               /*
-                * On bonding slaves other than the currently active
-                * slave, suppress duplicates except for 802.3ad
-                * ETH_P_SLOW and alb non-mcast/bcast.
-                */
-               if (dev->priv_flags & IFF_SLAVE_INACTIVE) {
-                       if (dev->master->priv_flags & IFF_MASTER_ALB) {
-                               if (skb->pkt_type != PACKET_BROADCAST &&
-                                   skb->pkt_type != PACKET_MULTICAST)
-                                       goto keep;
-                       }
-
-                       if (dev->master->priv_flags & IFF_MASTER_8023AD &&
-                           skb->protocol == __constant_htons(ETH_P_SLOW))
-                               goto keep;
-               
+               if (skb_bond_should_drop(skb)) {
                        kfree_skb(skb);
                        return NULL;
                }
-keep:
                skb->dev = dev->master;
        }
 
index 470c05bc4cb2bd513f1ba37002a81f46266c8905..1a5e49da0e77bdaaaaebf5369a97153ff75f4918 100644 (file)
@@ -95,12 +95,11 @@ static void dst_run_gc(unsigned long dummy)
                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",
               atomic_read(&dst_total), delayed,  dst_gc_timer_expires);
 #endif
-       add_timer(&dst_gc_timer);
+       mod_timer(&dst_gc_timer, jiffies + dst_gc_timer_expires);
 
 out:
        spin_unlock(&dst_lock);
index 67ed14ddabd2b83a32bef68b002c67298bcc2f42..6a7320b39ed0c21fd104afc543e961e758f993d3 100644 (file)
@@ -2149,6 +2149,8 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
        skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
        skb->dev = odev;
        skb->pkt_type = PACKET_HOST;
+       skb->nh.iph = iph;
+       skb->h.uh = udph;
 
        if (pkt_dev->nfrags <= 0)
                pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
@@ -2460,6 +2462,8 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
        skb->protocol = protocol;
        skb->dev = odev;
        skb->pkt_type = PACKET_HOST;
+       skb->nh.ipv6h = iph;
+       skb->h.uh = udph;
 
        if (pkt_dev->nfrags <= 0)
                pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
index 20e5bb73f147b6c0f6d84d02e562560e8b500f63..30cc1ba6ed5c46259bc939e425b88b0402e2a436 100644 (file)
@@ -394,6 +394,9 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        }
 
        if (ida[IFLA_ADDRESS - 1]) {
+               struct sockaddr *sa;
+               int len;
+
                if (!dev->set_mac_address) {
                        err = -EOPNOTSUPP;
                        goto out;
@@ -405,7 +408,17 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
                if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len))
                        goto out;
 
-               err = dev->set_mac_address(dev, RTA_DATA(ida[IFLA_ADDRESS - 1]));
+               len = sizeof(sa_family_t) + dev->addr_len;
+               sa = kmalloc(len, GFP_KERNEL);
+               if (!sa) {
+                       err = -ENOMEM;
+                       goto out;
+               }
+               sa->sa_family = dev->type;
+               memcpy(sa->sa_data, RTA_DATA(ida[IFLA_ADDRESS - 1]),
+                      dev->addr_len);
+               err = dev->set_mac_address(dev, sa);
+               kfree(sa);
                if (err)
                        goto out;
                send_addr_notify = 1;
index 022d8894c11de1ef21839988f5b233ca878db1ef..c54f3664bce5b0e868928df71c392dc18f89f2a0 100644 (file)
@@ -268,8 +268,10 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
        struct sk_buff *skb;
 
        skb = alloc_skb(length + NET_SKB_PAD, gfp_mask);
-       if (likely(skb))
+       if (likely(skb)) {
                skb_reserve(skb, NET_SKB_PAD);
+               skb->dev = dev;
+       }
        return skb;
 }
 
index 4f96f389243d7d6322288609f6477c74eab5ac09..e31c90e055941e73f020e07adcd92360e81960da 100644 (file)
@@ -130,12 +130,13 @@ void __init net_random_init(void)
 static int net_random_reseed(void)
 {
        int i;
-       unsigned long seed[NR_CPUS];
+       unsigned long seed;
 
-       get_random_bytes(seed, sizeof(seed));
        for_each_possible_cpu(i) {
                struct nrnd_state *state = &per_cpu(net_rand_state,i);
-               __net_srandom(state, seed[i]);
+
+               get_random_bytes(&seed, sizeof(seed));
+               __net_srandom(state, seed);
        }
        return 0;
 }
index 72d4d4e04d426b26d8f323f4522432337f4691e7..d60358d702d714946d17d9881c4d068d76608c2c 100644 (file)
@@ -779,33 +779,44 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
        return 0;
 }
 
-/* Filter out unrelated packets, call ieee80211_rx[_mgt] */
-int ieee80211_rx_any(struct ieee80211_device *ieee,
+/* Filter out unrelated packets, call ieee80211_rx[_mgt]
+ * This function takes over the skb, it should not be used again after calling
+ * this function. */
+void ieee80211_rx_any(struct ieee80211_device *ieee,
                     struct sk_buff *skb, struct ieee80211_rx_stats *stats)
 {
        struct ieee80211_hdr_4addr *hdr;
        int is_packet_for_us;
        u16 fc;
 
-       if (ieee->iw_mode == IW_MODE_MONITOR)
-               return ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL;
+       if (ieee->iw_mode == IW_MODE_MONITOR) {
+               if (!ieee80211_rx(ieee, skb, stats))
+                       dev_kfree_skb_irq(skb);
+               return;
+       }
+
+       if (skb->len < sizeof(struct ieee80211_hdr))
+               goto drop_free;
 
        hdr = (struct ieee80211_hdr_4addr *)skb->data;
        fc = le16_to_cpu(hdr->frame_ctl);
 
        if ((fc & IEEE80211_FCTL_VERS) != 0)
-               return -EINVAL;
+               goto drop_free;
                
        switch (fc & IEEE80211_FCTL_FTYPE) {
        case IEEE80211_FTYPE_MGMT:
+               if (skb->len < sizeof(struct ieee80211_hdr_3addr))
+                       goto drop_free;
                ieee80211_rx_mgt(ieee, hdr, stats);
-               return 0;
+               dev_kfree_skb_irq(skb);
+               return;
        case IEEE80211_FTYPE_DATA:
                break;
        case IEEE80211_FTYPE_CTL:
-               return 0;
+               return;
        default:
-               return -EINVAL;
+               return;
        }
 
        is_packet_for_us = 0;
@@ -849,8 +860,14 @@ int ieee80211_rx_any(struct ieee80211_device *ieee,
        }
 
        if (is_packet_for_us)
-               return (ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL);
-       return 0;
+               if (!ieee80211_rx(ieee, skb, stats))
+                       dev_kfree_skb_irq(skb);
+       return;
+
+drop_free:
+       dev_kfree_skb_irq(skb);
+       ieee->stats.rx_dropped++;
+       return;
 }
 
 #define MGMT_FRAME_FIXED_PART_LENGTH           0x24
@@ -1166,6 +1183,7 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
 
                case MFIE_TYPE_ERP_INFO:
                        network->erp_value = info_element->data[0];
+                       network->flags |= NETWORK_HAS_ERP_VALUE;
                        IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
                                             network->erp_value);
                        break;
@@ -1729,5 +1747,6 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
        }
 }
 
+EXPORT_SYMBOL_GPL(ieee80211_rx_any);
 EXPORT_SYMBOL(ieee80211_rx_mgt);
 EXPORT_SYMBOL(ieee80211_rx);
index 44215ce64d4e9db3c9abb54edbfd35c154590bfd..589f6d2c548a7ba0167598def59daab5b7eb13c4 100644 (file)
@@ -96,7 +96,7 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac)
        mac->associated = 0;
        mac->associnfo.bssvalid = 0;
        mac->associnfo.associating = 0;
-       ieee80211softmac_init_txrates(mac);
+       ieee80211softmac_init_bss(mac);
        ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
        spin_unlock_irqrestore(&mac->lock, flags);
 }
@@ -334,11 +334,19 @@ ieee80211softmac_associated(struct ieee80211softmac_device *mac,
        struct ieee80211_assoc_response * resp,
        struct ieee80211softmac_network *net)
 {
+       u16 cap = le16_to_cpu(resp->capability);
+       u8 erp_value = net->erp_value;
+
        mac->associnfo.associating = 0;
-       mac->associnfo.supported_rates = net->supported_rates;
+       mac->bssinfo.supported_rates = net->supported_rates;
        ieee80211softmac_recalc_txrates(mac);
 
        mac->associated = 1;
+
+       mac->associnfo.short_preamble_available =
+               (cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0;
+       ieee80211softmac_process_erp(mac, erp_value);
+
        if (mac->set_bssid_filter)
                mac->set_bssid_filter(mac->dev, net->bssid);
        memcpy(mac->ieee->bssid, net->bssid, ETH_ALEN);
@@ -351,9 +359,9 @@ ieee80211softmac_associated(struct ieee80211softmac_device *mac,
 int
 ieee80211softmac_handle_assoc_response(struct net_device * dev,
                                       struct ieee80211_assoc_response * resp,
-                                      struct ieee80211_network * _ieee80211_network_do_not_use)
+                                      struct ieee80211_network * _ieee80211_network)
 {
-       /* NOTE: the network parameter has to be ignored by
+       /* NOTE: the network parameter has to be mostly ignored by
         *       this code because it is the ieee80211's pointer
         *       to the struct, not ours (we made a copy)
         */
@@ -385,6 +393,11 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev,
        /* now that we know it was for us, we can cancel the timeout */
        cancel_delayed_work(&mac->associnfo.timeout);
 
+       /* if the association response included an ERP IE, update our saved
+        * copy */
+       if (_ieee80211_network->flags & NETWORK_HAS_ERP_VALUE)
+               network->erp_value = _ieee80211_network->erp_value;
+
        switch (status) {
                case 0:
                        dprintk(KERN_INFO PFX "associated!\n");
index 6ae5a1dc79564742f1bfd024ae9e2b37058fb4c0..82bfddbf33a28e999b944d86660f21560206438b 100644 (file)
@@ -467,3 +467,17 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
        kfree(pkt);
        return 0;
 }
+
+/* Beacon handling */
+int ieee80211softmac_handle_beacon(struct net_device *dev,
+       struct ieee80211_beacon *beacon,
+       struct ieee80211_network *network)
+{
+       struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+
+       if (mac->associated && memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0)
+               ieee80211softmac_process_erp(mac, network->erp_value);
+
+       return 0;
+}
+
index 4b2e57d12418a901185b6124ac3104dbd0e8d69a..addea1cf73ae3f5ba9f2787af8503bb354b97778 100644 (file)
@@ -44,6 +44,7 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv)
        softmac->ieee->handle_assoc_response = ieee80211softmac_handle_assoc_response;
        softmac->ieee->handle_reassoc_request = ieee80211softmac_handle_reassoc_req;
        softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc;
+       softmac->ieee->handle_beacon = ieee80211softmac_handle_beacon;
        softmac->scaninfo = NULL;
 
        softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
@@ -178,21 +179,14 @@ int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo
        return 0;
 }
 
-/* Finds the highest rate which is:
- *  1. Present in ri (optionally a basic rate)
- *  2. Supported by the device
- *  3. Less than or equal to the user-defined rate
- */
-static u8 highest_supported_rate(struct ieee80211softmac_device *mac,
+u8 ieee80211softmac_highest_supported_rate(struct ieee80211softmac_device *mac,
        struct ieee80211softmac_ratesinfo *ri, int basic_only)
 {
        u8 user_rate = mac->txrates.user_rate;
        int i;
 
-       if (ri->count == 0) {
-               dprintk(KERN_ERR PFX "empty ratesinfo?\n");
+       if (ri->count == 0)
                return IEEE80211_CCK_RATE_1MB;
-       }
 
        for (i = ri->count - 1; i >= 0; i--) {
                u8 rate = ri->rates[i];
@@ -208,36 +202,61 @@ static u8 highest_supported_rate(struct ieee80211softmac_device *mac,
        /* If we haven't found a suitable rate by now, just trust the user */
        return user_rate;
 }
+EXPORT_SYMBOL_GPL(ieee80211softmac_highest_supported_rate);
+
+void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac,
+       u8 erp_value)
+{
+       int use_protection;
+       int short_preamble;
+       u32 changes = 0;
+
+       /* Barker preamble mode */
+       short_preamble = ((erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0
+                         && mac->associnfo.short_preamble_available) ? 1 : 0;
+
+       /* Protection needed? */
+       use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
+
+       if (mac->bssinfo.short_preamble != short_preamble) {
+               changes |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE;
+               mac->bssinfo.short_preamble = short_preamble;
+       }
+
+       if (mac->bssinfo.use_protection != use_protection) {
+               changes |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION;
+               mac->bssinfo.use_protection = use_protection;
+       }
+
+       if (mac->bssinfo_change && changes)
+               mac->bssinfo_change(mac->dev, changes);
+}
 
 void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac)
 {
        struct ieee80211softmac_txrates *txrates = &mac->txrates;
-       struct ieee80211softmac_txrates oldrates;
        u32 change = 0;
 
-       if (mac->txrates_change)
-               oldrates = mac->txrates;
-
        change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
-       txrates->default_rate = highest_supported_rate(mac, &mac->associnfo.supported_rates, 0);
+       txrates->default_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 0);
 
        change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
        txrates->default_fallback = lower_rate(mac, txrates->default_rate);
 
        change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
-       txrates->mcast_rate = highest_supported_rate(mac, &mac->associnfo.supported_rates, 1);
+       txrates->mcast_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 1);
 
        if (mac->txrates_change)
-               mac->txrates_change(mac->dev, change, &oldrates);
+               mac->txrates_change(mac->dev, change);
 
 }
 
-void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac)
+void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac)
 {
        struct ieee80211_device *ieee = mac->ieee;
        u32 change = 0;
        struct ieee80211softmac_txrates *txrates = &mac->txrates;
-       struct ieee80211softmac_txrates oldrates;
+       struct ieee80211softmac_bss_info *bssinfo = &mac->bssinfo;
 
        /* TODO: We need some kind of state machine to lower the default rates
         *       if we loose too many packets.
@@ -245,8 +264,6 @@ void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac)
        /* Change the default txrate to the highest possible value.
         * The txrate machine will lower it, if it is too high.
         */
-       if (mac->txrates_change)
-               oldrates = mac->txrates;
        /* FIXME: We don't correctly handle backing down to lower
           rates, so 801.11g devices start off at 11M for now. People
           can manually change it if they really need to, but 11M is
@@ -272,7 +289,23 @@ void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac)
        change |= IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST;
 
        if (mac->txrates_change)
-               mac->txrates_change(mac->dev, change, &oldrates);
+               mac->txrates_change(mac->dev, change);
+
+       change = 0;
+
+       bssinfo->supported_rates.count = 0;
+       memset(bssinfo->supported_rates.rates, 0,
+               sizeof(bssinfo->supported_rates.rates));
+       change |= IEEE80211SOFTMAC_BSSINFOCHG_RATES;
+
+       bssinfo->short_preamble = 0;
+       change |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE;
+
+       bssinfo->use_protection = 0;
+       change |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION;
+
+       if (mac->bssinfo_change)
+               mac->bssinfo_change(mac->dev, change);
 
        mac->running = 1;
 }
@@ -282,7 +315,7 @@ void ieee80211softmac_start(struct net_device *dev)
        struct ieee80211softmac_device *mac = ieee80211_priv(dev);
 
        ieee80211softmac_start_check_rates(mac);
-       ieee80211softmac_init_txrates(mac);
+       ieee80211softmac_init_bss(mac);
 }
 EXPORT_SYMBOL_GPL(ieee80211softmac_start);
 
@@ -335,7 +368,6 @@ u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rat
 static void ieee80211softmac_add_txrates_badness(struct ieee80211softmac_device *mac,
                                                 int amount)
 {
-       struct ieee80211softmac_txrates oldrates;
        u8 default_rate = mac->txrates.default_rate;
        u8 default_fallback = mac->txrates.default_fallback;
        u32 changes = 0;
@@ -348,8 +380,6 @@ printk("badness %d\n", mac->txrate_badness);
        mac->txrate_badness += amount;
        if (mac->txrate_badness <= -1000) {
                /* Very small badness. Try a faster bitrate. */
-               if (mac->txrates_change)
-                       memcpy(&oldrates, &mac->txrates, sizeof(oldrates));
                default_rate = raise_rate(mac, default_rate);
                changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
                default_fallback = get_fallback_rate(mac, default_rate);
@@ -358,8 +388,6 @@ printk("badness %d\n", mac->txrate_badness);
 printk("Bitrate raised to %u\n", default_rate);
        } else if (mac->txrate_badness >= 10000) {
                /* Very high badness. Try a slower bitrate. */
-               if (mac->txrates_change)
-                       memcpy(&oldrates, &mac->txrates, sizeof(oldrates));
                default_rate = lower_rate(mac, default_rate);
                changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
                default_fallback = get_fallback_rate(mac, default_rate);
@@ -372,7 +400,7 @@ printk("Bitrate lowered to %u\n", default_rate);
        mac->txrates.default_fallback = default_fallback;
 
        if (changes && mac->txrates_change)
-               mac->txrates_change(mac->dev, changes, &oldrates);
+               mac->txrates_change(mac->dev, changes);
 }
 
 void ieee80211softmac_fragment_lost(struct net_device *dev,
@@ -416,7 +444,11 @@ ieee80211softmac_create_network(struct ieee80211softmac_device *mac,
        memcpy(&softnet->supported_rates.rates[softnet->supported_rates.count], net->rates_ex, net->rates_ex_len);
        softnet->supported_rates.count += net->rates_ex_len;
        sort(softnet->supported_rates.rates, softnet->supported_rates.count, sizeof(softnet->supported_rates.rates[0]), rate_cmp, NULL);
-       
+
+       /* we save the ERP value because it is needed at association time, and
+        * many AP's do not include an ERP IE in the association response. */
+       softnet->erp_value = net->erp_value;
+
        softnet->capabilities = net->capability;
        return softnet;
 }
index fa1f8e3acfc07f0370567e026bef2d4379eeeedc..0642e090b8a7a177ce0bf63a56a3692e2e57c0a8 100644 (file)
@@ -116,9 +116,11 @@ ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac,
        struct ieee80211softmac_essid *essid);
 
 /* Rates related */
+void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac,
+       u8 erp_value);
 int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate);
 u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta);
-void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac);
+void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac);
 void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac);
 static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) {
        return ieee80211softmac_lower_rate_delta(mac, rate, 1);
@@ -133,6 +135,9 @@ static inline u8 get_fallback_rate(struct ieee80211softmac_device *mac, u8 rate)
 /*** prototypes from _io.c */
 int ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
        void* ptrarg, u32 type, u32 arg);
+int ieee80211softmac_handle_beacon(struct net_device *dev,
+       struct ieee80211_beacon *beacon,
+       struct ieee80211_network *network);
 
 /*** prototypes from _auth.c */
 /* do these have to go into the public header? */
@@ -189,6 +194,7 @@ struct ieee80211softmac_network {
            authenticated:1,
            auth_desynced_once:1;
 
+       u8 erp_value;                           /* Saved ERP value */
        u16 capabilities;                       /* Capabilities bitfield */
        u8 challenge_len;                       /* Auth Challenge length */
        char *challenge;                        /* Challenge Text */
index 9be53a8e72c338d7865dadcc747d6003cd1c8b20..51738000f3dc4c12c5db72063548b8535f7517e6 100644 (file)
@@ -159,7 +159,7 @@ void free_fib_info(struct fib_info *fi)
 
 void fib_release_info(struct fib_info *fi)
 {
-       write_lock(&fib_info_lock);
+       write_lock_bh(&fib_info_lock);
        if (fi && --fi->fib_treeref == 0) {
                hlist_del(&fi->fib_hash);
                if (fi->fib_prefsrc)
@@ -172,7 +172,7 @@ void fib_release_info(struct fib_info *fi)
                fi->fib_dead = 1;
                fib_info_put(fi);
        }
-       write_unlock(&fib_info_lock);
+       write_unlock_bh(&fib_info_lock);
 }
 
 static __inline__ int nh_comp(const struct fib_info *fi, const struct fib_info *ofi)
@@ -598,7 +598,7 @@ static void fib_hash_move(struct hlist_head *new_info_hash,
        unsigned int old_size = fib_hash_size;
        unsigned int i, bytes;
 
-       write_lock(&fib_info_lock);
+       write_lock_bh(&fib_info_lock);
        old_info_hash = fib_info_hash;
        old_laddrhash = fib_info_laddrhash;
        fib_hash_size = new_size;
@@ -639,7 +639,7 @@ static void fib_hash_move(struct hlist_head *new_info_hash,
        }
        fib_info_laddrhash = new_laddrhash;
 
-       write_unlock(&fib_info_lock);
+       write_unlock_bh(&fib_info_lock);
 
        bytes = old_size * sizeof(struct hlist_head *);
        fib_hash_free(old_info_hash, bytes);
@@ -820,7 +820,7 @@ link_it:
 
        fi->fib_treeref++;
        atomic_inc(&fi->fib_clntref);
-       write_lock(&fib_info_lock);
+       write_lock_bh(&fib_info_lock);
        hlist_add_head(&fi->fib_hash,
                       &fib_info_hash[fib_info_hashfn(fi)]);
        if (fi->fib_prefsrc) {
@@ -839,7 +839,7 @@ link_it:
                head = &fib_info_devhash[hash];
                hlist_add_head(&nh->nh_hash, head);
        } endfor_nexthops(fi)
-       write_unlock(&fib_info_lock);
+       write_unlock_bh(&fib_info_lock);
        return fi;
 
 err_inval:
index 9f4b752f5a337e7dfae09970d5112dc4bc6dc54b..8e8117c19e4db24ad74d55cfe540fb0d4c9816f3 100644 (file)
@@ -1793,29 +1793,35 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
        struct in_device *in_dev;
        u32 group = imr->imr_multiaddr.s_addr;
        u32 ifindex;
+       int ret = -EADDRNOTAVAIL;
 
        rtnl_lock();
        in_dev = ip_mc_find_dev(imr);
-       if (!in_dev) {
-               rtnl_unlock();
-               return -ENODEV;
-       }
        ifindex = imr->imr_ifindex;
        for (imlp = &inet->mc_list; (iml = *imlp) != NULL; imlp = &iml->next) {
-               if (iml->multi.imr_multiaddr.s_addr == group &&
-                   iml->multi.imr_ifindex == ifindex) {
-                       (void) ip_mc_leave_src(sk, iml, in_dev);
+               if (iml->multi.imr_multiaddr.s_addr != group)
+                       continue;
+               if (ifindex) {
+                       if (iml->multi.imr_ifindex != ifindex)
+                               continue;
+               } else if (imr->imr_address.s_addr && imr->imr_address.s_addr !=
+                               iml->multi.imr_address.s_addr)
+                       continue;
+
+               (void) ip_mc_leave_src(sk, iml, in_dev);
 
-                       *imlp = iml->next;
+               *imlp = iml->next;
 
+               if (in_dev)
                        ip_mc_dec_group(in_dev, group);
-                       rtnl_unlock();
-                       sock_kfree_s(sk, iml, sizeof(*iml));
-                       return 0;
-               }
+               rtnl_unlock();
+               sock_kfree_s(sk, iml, sizeof(*iml));
+               return 0;
        }
+       if (!in_dev)
+               ret = -ENODEV;
        rtnl_unlock();
-       return -EADDRNOTAVAIL;
+       return ret;
 }
 
 int ip_mc_source(int add, int omode, struct sock *sk, struct
@@ -2199,13 +2205,13 @@ void ip_mc_drop_socket(struct sock *sk)
                struct in_device *in_dev;
                inet->mc_list = iml->next;
 
-               if ((in_dev = inetdev_by_index(iml->multi.imr_ifindex)) != NULL) {
-                       (void) ip_mc_leave_src(sk, iml, in_dev);
+               in_dev = inetdev_by_index(iml->multi.imr_ifindex);
+               (void) ip_mc_leave_src(sk, iml, in_dev);
+               if (in_dev != NULL) {
                        ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);
                        in_dev_put(in_dev);
                }
                sock_kfree_s(sk, iml, sizeof(*iml));
-
        }
        rtnl_unlock();
 }
index 9bf307a2978355bd68fb66d663630b79720db85c..4c20f5546893dc104afd7cdf32dc4f148b38821b 100644 (file)
@@ -947,7 +947,7 @@ alloc_new_skb:
                                skb_prev->csum = csum_sub(skb_prev->csum,
                                                          skb->csum);
                                data += fraggap;
-                               skb_trim(skb_prev, maxfraglen);
+                               pskb_trim_unique(skb_prev, maxfraglen);
                        }
 
                        copy = datalen - transhdrlen - fraggap;
@@ -1142,7 +1142,7 @@ ssize_t   ip_append_page(struct sock *sk, struct page *page,
                                        data, fraggap, 0);
                                skb_prev->csum = csum_sub(skb_prev->csum,
                                                          skb->csum);
-                               skb_trim(skb_prev, maxfraglen);
+                               pskb_trim_unique(skb_prev, maxfraglen);
                        }
 
                        /*
index 80c73ca90116f51ecff0cc2e52b8e4201f747920..df4854cf598bbea46da6b19b6c2bb0ffdc0436fe 100644 (file)
@@ -1170,21 +1170,34 @@ static int __init arp_tables_init(void)
 {
        int ret;
 
-       xt_proto_init(NF_ARP);
+       ret = xt_proto_init(NF_ARP);
+       if (ret < 0)
+               goto err1;
 
        /* Noone else will be downing sem now, so we won't sleep */
-       xt_register_target(&arpt_standard_target);
-       xt_register_target(&arpt_error_target);
+       ret = xt_register_target(&arpt_standard_target);
+       if (ret < 0)
+               goto err2;
+       ret = xt_register_target(&arpt_error_target);
+       if (ret < 0)
+               goto err3;
 
        /* Register setsockopt */
        ret = nf_register_sockopt(&arpt_sockopts);
-       if (ret < 0) {
-               duprintf("Unable to register sockopts.\n");
-               return ret;
-       }
+       if (ret < 0)
+               goto err4;
 
        printk("arp_tables: (C) 2002 David S. Miller\n");
        return 0;
+
+err4:
+       xt_unregister_target(&arpt_error_target);
+err3:
+       xt_unregister_target(&arpt_standard_target);
+err2:
+       xt_proto_fini(NF_ARP);
+err1:
+       return ret;
 }
 
 static void __exit arp_tables_fini(void)
index 33891bb1fde438a97c5d85516b3c25bb826d1ba4..0d4cc92391fa54a23d26e64564c7b58b7e250d2f 100644 (file)
@@ -415,21 +415,18 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
                        cb->args[0], *id);
 
        read_lock_bh(&ip_conntrack_lock);
+       last = (struct ip_conntrack *)cb->args[1];
        for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++) {
 restart:
-               last = (struct ip_conntrack *)cb->args[1];
                list_for_each_prev(i, &ip_conntrack_hash[cb->args[0]]) {
                        h = (struct ip_conntrack_tuple_hash *) i;
                        if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
                                continue;
                        ct = tuplehash_to_ctrack(h);
-                       if (last != NULL) {
-                               if (ct == last) {
-                                       ip_conntrack_put(last);
-                                       cb->args[1] = 0;
-                                       last = NULL;
-                               } else
+                       if (cb->args[1]) {
+                               if (ct != last)
                                        continue;
+                               cb->args[1] = 0;
                        }
                        if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
                                                cb->nlh->nlmsg_seq,
@@ -440,17 +437,17 @@ restart:
                                goto out;
                        }
                }
-               if (last != NULL) {
-                       ip_conntrack_put(last);
+               if (cb->args[1]) {
                        cb->args[1] = 0;
                        goto restart;
                }
        }
 out:
        read_unlock_bh(&ip_conntrack_lock);
+       if (last)
+               ip_conntrack_put(last);
 
        DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
-
        return skb->len;
 }
 
index fc5bdd5eb7d35aa7de0f4fd5a2c7a8bc794dd643..048514f15f2ffe116dcbebc0aa1672eae54045f4 100644 (file)
@@ -230,7 +230,7 @@ ipt_do_table(struct sk_buff **pskb,
        const char *indev, *outdev;
        void *table_base;
        struct ipt_entry *e, *back;
-       struct xt_table_info *private = table->private;
+       struct xt_table_info *private;
 
        /* Initialization */
        ip = (*pskb)->nh.iph;
@@ -247,6 +247,7 @@ ipt_do_table(struct sk_buff **pskb,
 
        read_lock_bh(&table->lock);
        IP_NF_ASSERT(table->valid_hooks & (1 << hook));
+       private = table->private;
        table_base = (void *)private->entries[smp_processor_id()];
        e = get_entry(table_base, private->hook_entry[hook]);
 
@@ -2239,22 +2240,39 @@ static int __init ip_tables_init(void)
 {
        int ret;
 
-       xt_proto_init(AF_INET);
+       ret = xt_proto_init(AF_INET);
+       if (ret < 0)
+               goto err1;
 
        /* Noone else will be downing sem now, so we won't sleep */
-       xt_register_target(&ipt_standard_target);
-       xt_register_target(&ipt_error_target);
-       xt_register_match(&icmp_matchstruct);
+       ret = xt_register_target(&ipt_standard_target);
+       if (ret < 0)
+               goto err2;
+       ret = xt_register_target(&ipt_error_target);
+       if (ret < 0)
+               goto err3;
+       ret = xt_register_match(&icmp_matchstruct);
+       if (ret < 0)
+               goto err4;
 
        /* Register setsockopt */
        ret = nf_register_sockopt(&ipt_sockopts);
-       if (ret < 0) {
-               duprintf("Unable to register sockopts.\n");
-               return ret;
-       }
+       if (ret < 0)
+               goto err5;
 
        printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n");
        return 0;
+
+err5:
+       xt_unregister_match(&icmp_matchstruct);
+err4:
+       xt_unregister_target(&ipt_error_target);
+err3:
+       xt_unregister_target(&ipt_standard_target);
+err2:
+       xt_proto_fini(AF_INET);
+err1:
+       return ret;
 }
 
 static void __exit ip_tables_fini(void)
index d7dd7fe7051ca4413de76da6e631403499b67925..d46fd677fa11f8f48f30e136d843cb95f3ae8c45 100644 (file)
@@ -115,6 +115,11 @@ static void ulog_send(unsigned int nlgroupnum)
                del_timer(&ub->timer);
        }
 
+       if (!ub->skb) {
+               DEBUGP("ipt_ULOG: ulog_send: nothing to send\n");
+               return;
+       }
+
        /* last nlmsg needs NLMSG_DONE */
        if (ub->qlen > 1)
                ub->lastnlh->nlmsg_type = NLMSG_DONE;
index 6b662449e8253579fc9e87112590d1ac55f7e238..3bd2368e1fc9757da9cb6f21a60aea872a0ecb1f 100644 (file)
@@ -454,15 +454,12 @@ hashlimit_match(const struct sk_buff *skb,
                dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * 
                                                        hinfo->cfg.burst);
                dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
-
-               spin_unlock_bh(&hinfo->lock);
-               return 1;
+       } else {
+               /* update expiration timeout */
+               dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
+               rateinfo_recalc(dh, now);
        }
 
-       /* update expiration timeout */
-       dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
-
-       rateinfo_recalc(dh, now);
        if (dh->rateinfo.credit >= dh->rateinfo.cost) {
                /* We're underlimit. */
                dh->rateinfo.credit -= dh->rateinfo.cost;
index 19bd49d69d9ffbc3f34a97a3d151356001519d7a..b873cbcdd0b8f2e2745b2be633febeabccde1db1 100644 (file)
@@ -3157,7 +3157,7 @@ int __init ip_rt_init(void)
                                        rhash_entries,
                                        (num_physpages >= 128 * 1024) ?
                                        15 : 17,
-                                       HASH_HIGHMEM,
+                                       0,
                                        &rt_hash_log,
                                        &rt_hash_mask,
                                        0);
index 5c08ea20a18dfb8fa965fc23070729c176aba4f0..507adefbc17cdf18d1b7a814630711fbaca5cf81 100644 (file)
@@ -466,7 +466,8 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
        if (skb->len != tcp_header_size)
                tcp_event_data_sent(tp, skb, sk);
 
-       TCP_INC_STATS(TCP_MIB_OUTSEGS);
+       if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq)
+               TCP_INC_STATS(TCP_MIB_OUTSEGS);
 
        err = icsk->icsk_af_ops->queue_xmit(skb, 0);
        if (likely(err <= 0))
@@ -2157,10 +2158,9 @@ int tcp_connect(struct sock *sk)
        skb_shinfo(buff)->gso_size = 0;
        skb_shinfo(buff)->gso_type = 0;
        buff->csum = 0;
+       tp->snd_nxt = tp->write_seq;
        TCP_SKB_CB(buff)->seq = tp->write_seq++;
        TCP_SKB_CB(buff)->end_seq = tp->write_seq;
-       tp->snd_nxt = tp->write_seq;
-       tp->pushed_seq = tp->write_seq;
 
        /* Send it off. */
        TCP_SKB_CB(buff)->when = tcp_time_stamp;
@@ -2170,6 +2170,12 @@ int tcp_connect(struct sock *sk)
        sk_charge_skb(sk, buff);
        tp->packets_out += tcp_skb_pcount(buff);
        tcp_transmit_skb(sk, buff, 1, GFP_KERNEL);
+
+       /* We change tp->snd_nxt after the tcp_transmit_skb() call
+        * in order to make this packet get counted in tcpOutSegs.
+        */
+       tp->snd_nxt = tp->write_seq;
+       tp->pushed_seq = tp->write_seq;
        TCP_INC_STATS(TCP_MIB_ACTIVEOPENS);
 
        /* Timer for repeating the SYN until an answer. */
index b3435324b573fb468f429bb3db805158d8aac2ae..dab37d2f65fcf09a820bce52300d7f335ab5066c 100644 (file)
@@ -130,11 +130,12 @@ static ssize_t tcpprobe_read(struct file *file, char __user *buf,
        error = wait_event_interruptible(tcpw.wait,
                                         __kfifo_len(tcpw.fifo) != 0);
        if (error)
-               return error;
+               goto out_free;
 
        cnt = kfifo_get(tcpw.fifo, tbuf, len);
        error = copy_to_user(buf, tbuf, cnt);
 
+out_free:
        vfree(tbuf);
 
        return error ? error : cnt;
index 8ea1e36bf8ebbe7b5b9f161272a66cf28c35c3bb..0c5042e7380d391769f8e484132157735cb35e6e 100644 (file)
@@ -1909,11 +1909,11 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
        ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags);
 
        if (!IS_ERR(ifp)) {
-               spin_lock(&ifp->lock);
+               spin_lock_bh(&ifp->lock);
                ifp->valid_lft = valid_lft;
                ifp->prefered_lft = prefered_lft;
                ifp->tstamp = jiffies;
-               spin_unlock(&ifp->lock);
+               spin_unlock_bh(&ifp->lock);
 
                addrconf_dad_start(ifp, 0);
                in6_ifa_put(ifp);
index 1044b6fce0d5d472b11b0eef3a2e261650869e5e..3d6e9a351150294376557616ab29c72a783ed2c4 100644 (file)
@@ -712,6 +712,11 @@ discard_it:
        return 0;
 }
 
+/*
+ * Special lock-class for __icmpv6_socket:
+ */
+static struct lock_class_key icmpv6_socket_sk_dst_lock_key;
+
 int __init icmpv6_init(struct net_proto_family *ops)
 {
        struct sock *sk;
@@ -730,6 +735,14 @@ int __init icmpv6_init(struct net_proto_family *ops)
 
                sk = per_cpu(__icmpv6_socket, i)->sk;
                sk->sk_allocation = GFP_ATOMIC;
+               /*
+                * Split off their lock-class, because sk->sk_dst_lock
+                * gets used from softirqs, which is safe for
+                * __icmpv6_socket (because those never get directly used
+                * via userspace syscalls), but unsafe for normal sockets.
+                */
+               lockdep_set_class(&sk->sk_dst_lock,
+                                 &icmpv6_socket_sk_dst_lock_key);
 
                /* Enough space for 2 64K ICMP packets, including
                 * sk_buff struct overhead.
index 69451af6abe7dd2aaff636498eb1894e45f43fc7..4fb47a25291313ea0851a6539bed48a73a97c1c8 100644 (file)
@@ -1095,7 +1095,7 @@ alloc_new_skb:
                                skb_prev->csum = csum_sub(skb_prev->csum,
                                                          skb->csum);
                                data += fraggap;
-                               skb_trim(skb_prev, maxfraglen);
+                               pskb_trim_unique(skb_prev, maxfraglen);
                        }
                        copy = datalen - transhdrlen - fraggap;
                        if (copy < 0) {
index 9d697d4dcffccde33651b99a5e9b7fe9b37ddf48..639eb20c9f1fd08181c104593f3f39bc8bad3e0d 100644 (file)
@@ -268,13 +268,14 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
                        if ((dev = dev_get_by_index(mc_lst->ifindex)) != NULL) {
                                struct inet6_dev *idev = in6_dev_get(dev);
 
+                               (void) ip6_mc_leave_src(sk, mc_lst, idev);
                                if (idev) {
-                                       (void) ip6_mc_leave_src(sk,mc_lst,idev);
                                        __ipv6_dev_mc_dec(idev, &mc_lst->addr);
                                        in6_dev_put(idev);
                                }
                                dev_put(dev);
-                       }
+                       } else
+                               (void) ip6_mc_leave_src(sk, mc_lst, NULL);
                        sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
                        return 0;
                }
@@ -334,13 +335,14 @@ void ipv6_sock_mc_close(struct sock *sk)
                if (dev) {
                        struct inet6_dev *idev = in6_dev_get(dev);
 
+                       (void) ip6_mc_leave_src(sk, mc_lst, idev);
                        if (idev) {
-                               (void) ip6_mc_leave_src(sk, mc_lst, idev);
                                __ipv6_dev_mc_dec(idev, &mc_lst->addr);
                                in6_dev_put(idev);
                        }
                        dev_put(dev);
-               }
+               } else
+                       (void) ip6_mc_leave_src(sk, mc_lst, NULL);
 
                sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
 
index f26898b003475cb1358d6ab5dc9e7c831bca21c9..c9d6b23cd3f7141ff91b8cf11c3fff6e622a9e9c 100644 (file)
@@ -1398,23 +1398,39 @@ static int __init ip6_tables_init(void)
 {
        int ret;
 
-       xt_proto_init(AF_INET6);
+       ret = xt_proto_init(AF_INET6);
+       if (ret < 0)
+               goto err1;
 
        /* Noone else will be downing sem now, so we won't sleep */
-       xt_register_target(&ip6t_standard_target);
-       xt_register_target(&ip6t_error_target);
-       xt_register_match(&icmp6_matchstruct);
+       ret = xt_register_target(&ip6t_standard_target);
+       if (ret < 0)
+               goto err2;
+       ret = xt_register_target(&ip6t_error_target);
+       if (ret < 0)
+               goto err3;
+       ret = xt_register_match(&icmp6_matchstruct);
+       if (ret < 0)
+               goto err4;
 
        /* Register setsockopt */
        ret = nf_register_sockopt(&ip6t_sockopts);
-       if (ret < 0) {
-               duprintf("Unable to register sockopts.\n");
-               xt_proto_fini(AF_INET6);
-               return ret;
-       }
+       if (ret < 0)
+               goto err5;
 
        printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n");
        return 0;
+
+err5:
+       xt_unregister_match(&icmp6_matchstruct);
+err4:
+       xt_unregister_target(&ip6t_error_target);
+err3:
+       xt_unregister_target(&ip6t_standard_target);
+err2:
+       xt_proto_fini(AF_INET6);
+err1:
+       return ret;
 }
 
 static void __exit ip6_tables_fini(void)
index aa34ff4b707ca9a4151c6ce783761370901eaf4c..bef3f61569f76470248a9993a0ed4aae6ef1e8dc 100644 (file)
@@ -1642,13 +1642,17 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
        if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
                goto out;
 
-       ipx             = ipx_hdr(skb);
-       ipx_pktsize     = ntohs(ipx->ipx_pktsize);
+       if (!pskb_may_pull(skb, sizeof(struct ipxhdr)))
+               goto drop;
+
+       ipx_pktsize = ntohs(ipx_hdr(skb)->ipx_pktsize);
        
        /* Too small or invalid header? */
-       if (ipx_pktsize < sizeof(struct ipxhdr) || ipx_pktsize > skb->len)
+       if (ipx_pktsize < sizeof(struct ipxhdr) ||
+           !pskb_may_pull(skb, ipx_pktsize))
                goto drop;
                         
+       ipx = ipx_hdr(skb);
        if (ipx->ipx_checksum != IPX_NO_CHECKSUM &&
           ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize))
                goto drop;
index 42eb0c3a97804aa3726999107da0cf65a8cd16a5..61cb8cf7d1532a4d4b1abd51244e863fc7e8b887 100644 (file)
@@ -330,6 +330,9 @@ static void llc_sap_mcast(struct llc_sap *sap,
                if (llc->laddr.lsap != laddr->lsap)
                        continue;
 
+               if (llc->dev != skb->dev)
+                       continue;
+
                skb1 = skb_clone(skb, GFP_ATOMIC);
                if (!skb1)
                        break;
index af4845971f70606d568e731093118b74c0fbf104..6527d4e048d81395f1e5263eb3103f6d65ed2114 100644 (file)
@@ -429,9 +429,9 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
                        cb->args[0], *id);
 
        read_lock_bh(&nf_conntrack_lock);
+       last = (struct nf_conn *)cb->args[1];
        for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) {
 restart:
-               last = (struct nf_conn *)cb->args[1];
                list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) {
                        h = (struct nf_conntrack_tuple_hash *) i;
                        if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
@@ -442,13 +442,10 @@ restart:
                         * then dump everything. */
                        if (l3proto && L3PROTO(ct) != l3proto)
                                continue;
-                       if (last != NULL) {
-                               if (ct == last) {
-                                       nf_ct_put(last);
-                                       cb->args[1] = 0;
-                                       last = NULL;
-                               } else
+                       if (cb->args[1]) {
+                               if (ct != last)
                                        continue;
+                               cb->args[1] = 0;
                        }
                        if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
                                                cb->nlh->nlmsg_seq,
@@ -459,17 +456,17 @@ restart:
                                goto out;
                        }
                }
-               if (last != NULL) {
-                       nf_ct_put(last);
+               if (cb->args[1]) {
                        cb->args[1] = 0;
                        goto restart;
                }
        }
 out:
        read_unlock_bh(&nf_conntrack_lock);
+       if (last)
+               nf_ct_put(last);
 
        DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
-
        return skb->len;
 }
 
index 61cdda4e5d3ba8b25f02af19a7bbb634fc9a0d84..b59d3b2bde21815ad8c20f8fe758c226eff566f4 100644 (file)
@@ -366,6 +366,9 @@ __nfulnl_send(struct nfulnl_instance *inst)
        if (timer_pending(&inst->timer))
                del_timer(&inst->timer);
 
+       if (!inst->skb)
+               return 0;
+
        if (inst->qlen > 1)
                inst->lastnlh->nlmsg_type = NLMSG_DONE;
 
index a9f4f6f3c628225e9720d0cefad672a598fa00c9..63a96546746575979e2200b87d9a557c774e6970 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/module.h>
 #include <linux/skbuff.h>
+#include <linux/netfilter_bridge.h>
 #include <linux/netfilter/xt_physdev.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_bridge.h>
index d8e3891b5f8bd0aa9287fd8a7af88d4a6514a6e9..275330fcdaaab9dfebba281e3baf5e80671c884c 100644 (file)
@@ -37,7 +37,7 @@ static int match(const struct sk_buff *skb,
 
        return (skb_find_text((struct sk_buff *)skb, conf->from_offset, 
                             conf->to_offset, conf->config, &state) 
-                            != UINT_MAX) && !conf->invert;
+                            != UINT_MAX) conf->invert;
 }
 
 #define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m)
index eea3669667400868ccde06397175a6bf48fe50a5..0a6cfa0005bed31627f6ec8de3c7ffc3763abe36 100644 (file)
@@ -796,7 +796,7 @@ static int __init init_u32(void)
 {
        printk("u32 classifier\n");
 #ifdef CONFIG_CLS_U32_PERF
-       printk("    Perfomance counters on\n");
+       printk("    Performance counters on\n");
 #endif
 #ifdef CONFIG_NET_CLS_POLICE
        printk("    OLD policer on \n");
index f35bc676128c1a1f5f836816b285fe59af3f070e..3da67ca2c3ce9890b9774e4d2757d3f33928c493 100644 (file)
@@ -1134,12 +1134,33 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
 }
 EXPORT_SYMBOL(__xfrm_route_forward);
 
+/* Optimize later using cookies and generation ids. */
+
 static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie)
 {
-       /* If it is marked obsolete, which is how we even get here,
-        * then we have purged it from the policy bundle list and we
-        * did that for a good reason.
+       /* Code (such as __xfrm4_bundle_create()) sets dst->obsolete
+        * to "-1" to force all XFRM destinations to get validated by
+        * dst_ops->check on every use.  We do this because when a
+        * normal route referenced by an XFRM dst is obsoleted we do
+        * not go looking around for all parent referencing XFRM dsts
+        * so that we can invalidate them.  It is just too much work.
+        * Instead we make the checks here on every use.  For example:
+        *
+        *      XFRM dst A --> IPv4 dst X
+        *
+        * X is the "xdst->route" of A (X is also the "dst->path" of A
+        * in this example).  If X is marked obsolete, "A" will not
+        * notice.  That's what we are validating here via the
+        * stale_bundle() check.
+        *
+        * When a policy's bundle is pruned, we dst_free() the XFRM
+        * dst which causes it's ->obsolete field to be set to a
+        * positive non-zero integer.  If an XFRM dst has been pruned
+        * like this, we want to force a new route lookup.
         */
+       if (dst->obsolete < 0 && !stale_bundle(dst))
+               return dst;
+
        return NULL;
 }
 
index 44312926b84934f3b68e12e0bda278f3824cc4ed..e2de650d3dbff82ea73de953aec6edffc63f28e5 100644 (file)
@@ -391,7 +391,7 @@ static void do_input(char *alias,
        unsigned int i;
 
        for (i = min; i < max; i++)
-               if (arr[i / BITS_PER_LONG] & (1 << (i%BITS_PER_LONG)))
+               if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG)))
                        sprintf(alias + strlen(alias), "%X,*", i);
 }
 
index f4980ca5c05c86d9f4cbd8c86c885f2bd35af09c..1b7c3dfc2b41352c24e9fd6833dcb90a2d19beca 100644 (file)
@@ -31,7 +31,7 @@ config SOUND_EMU10K1
          For more information on this driver and the degree of support for
          the different card models please check:
 
-               <http://sourceforge.net/projects/emu10k1/>
+               <http://sourceforge.net/projects/emu10k1/>
 
          It is now possible to load dsp microcode patches into the EMU10K1
          chip.  These patches are used to implement real time sound
@@ -140,7 +140,7 @@ config SOUND_TRIDENT
          system support" and "Sysctl support", and after the /proc file
          system has been mounted, executing the command
 
-               command                 what is enabled
+               command                 what is enabled
 
          echo 0>/proc/ALi5451  pcm out is also set to S/PDIF out. (Default).
 
@@ -838,7 +838,7 @@ config SOUND_WAVEARTIST
 
 config SOUND_TVMIXER
        tristate "TV card (bt848) mixer support"
-       depends on SOUND_PRIME && I2C
+       depends on SOUND_PRIME && I2C && VIDEO_V4L1
        help
          Support for audio mixer facilities on the BT848 TV frame-grabber
          card.
index d7ad32f514da5f20f38f159fd96d40cc47d1c86a..e49c0fe21b0d13d12283c5fe908e7cc60e74df6d 100644 (file)
@@ -16,16 +16,16 @@ config SND_AD1889
          will be called snd-ad1889.
 
 config SND_ALS300
-        tristate "Avance Logic ALS300/ALS300+"
-        depends on SND
-        select SND_PCM
-        select SND_AC97_CODEC
-        select SND_OPL3_LIB
-        help
-          Say 'Y' or 'M' to include support for Avance Logic ALS300/ALS300+
+       tristate "Avance Logic ALS300/ALS300+"
+       depends on SND
+       select SND_PCM
+       select SND_AC97_CODEC
+       select SND_OPL3_LIB
+       help
+         Say 'Y' or 'M' to include support for Avance Logic ALS300/ALS300+
 
-          To compile this driver as a module, choose M here: the module
-          will be called snd-als300
+         To compile this driver as a module, choose M here: the module
+         will be called snd-als300
 
 config SND_ALS4000
        tristate "Avance Logic ALS4000"
@@ -78,49 +78,49 @@ config SND_ATIIXP_MODEM
          will be called snd-atiixp-modem.
 
 config SND_AU8810
-        tristate "Aureal Advantage"
-        depends on SND
+       tristate "Aureal Advantage"
+       depends on SND
        select SND_MPU401_UART
        select SND_AC97_CODEC
-        help
+       help
          Say Y here to include support for Aureal Advantage soundcards.
 
          Supported features: Hardware Mixer, SRC, EQ and SPDIF output.
-          3D support code is in place, but not yet useable. For more info, 
-          email the ALSA developer list, or <mjander@users.sourceforge.net>.
+         3D support code is in place, but not yet useable. For more info,
+         email the ALSA developer list, or <mjander@users.sourceforge.net>.
 
          To compile this driver as a module, choose M here: the module
          will be called snd-au8810.
+
 config SND_AU8820
-        tristate "Aureal Vortex"
-        depends on SND
+       tristate "Aureal Vortex"
+       depends on SND
        select SND_MPU401_UART
        select SND_AC97_CODEC
-        help
+       help
          Say Y here to include support for Aureal Vortex soundcards.
 
-          Supported features: Hardware Mixer and SRC. For more info, email 
-          the ALSA developer list, or <mjander@users.sourceforge.net>.
+         Supported features: Hardware Mixer and SRC. For more info, email
+         the ALSA developer list, or <mjander@users.sourceforge.net>.
 
          To compile this driver as a module, choose M here: the module
          will be called snd-au8820.
+
 config SND_AU8830
-        tristate "Aureal Vortex 2"
-        depends on SND
+       tristate "Aureal Vortex 2"
+       depends on SND
        select SND_MPU401_UART
        select SND_AC97_CODEC
-        help
+       help
          Say Y here to include support for Aureal Vortex 2 soundcards.
 
-          Supported features: Hardware Mixer, SRC, EQ and SPDIF output.
-          3D support code is in place, but not yet useable. For more info, 
-          email the ALSA developer list, or <mjander@users.sourceforge.net>.
+         Supported features: Hardware Mixer, SRC, EQ and SPDIF output.
+         3D support code is in place, but not yet useable. For more info,
+         email the ALSA developer list, or <mjander@users.sourceforge.net>.
 
          To compile this driver as a module, choose M here: the module
          will be called snd-au8830.
+
 config SND_AZT3328
        tristate "Aztech AZF3328 / PCI168 (EXPERIMENTAL)"
        depends on SND && EXPERIMENTAL
@@ -135,10 +135,10 @@ config SND_AZT3328
          will be called snd-azt3328.
 
 config SND_BT87X
-        tristate "Bt87x Audio Capture"
-        depends on SND
+       tristate "Bt87x Audio Capture"
+       depends on SND
        select SND_PCM
-        help
+       help
          If you want to record audio from TV cards based on
          Brooktree Bt878/Bt879 chips, say Y here and read
          <file:Documentation/sound/alsa/Bt87x.txt>.
@@ -209,7 +209,7 @@ config SND_CS46XX
 config SND_CS46XX_NEW_DSP
        bool "Cirrus Logic (Sound Fusion) New DSP support"
        depends on SND_CS46XX
-        default y
+       default y
        help
          Say Y here to use a new DSP image for SPDIF and dual codecs.
 
@@ -225,7 +225,7 @@ config SND_CS5535AUDIO
          referred to as NS CS5535 IO or AMD CS5535 IO companion in
          various literature. This driver also supports the CS5536 audio
          device. However, for both chips, on certain boards, you may
-         need to use ac97_quirk=hp_only if your board has physically 
+         need to use ac97_quirk=hp_only if your board has physically
          mapped headphone out to master output. If that works for you,
          send lspci -vvv output to the mailing list so that your board
          can be identified in the quirks list.
@@ -468,11 +468,13 @@ config SND_FM801_TEA575X_BOOL
          FM801 chip with a TEA5757 tuner connected to GPIO1-3 pins (Media
          Forte SF256-PCS-02) into the snd-fm801 driver.
 
+         This will enable support for the old V4L1 API.
+
 config SND_FM801_TEA575X
        tristate
        depends on SND_FM801_TEA575X_BOOL
        default SND_FM801
-       select VIDEO_DEV
+       select VIDEO_V4L1
 
 config SND_HDA_INTEL
        tristate "Intel HD Audio"
index e93824269da2aeebdd99c41aebda07a0eb0e5993..5b31c0b61c76a908a42f3b42b8868f3a4de06536 100644 (file)
@@ -35,6 +35,9 @@ quiet_cmd_initfs = GEN     $@
       cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input)
 
 targets := initramfs_data.cpio.gz
+# do not try to update files included in initramfs
+$(deps_initramfs): ;
+
 $(deps_initramfs): klibcdirs
 # We rebuild initramfs_data.cpio.gz if:
 # 1) Any included file is newer then initramfs_data.cpio.gz