Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/shaggy...
authorLinus Torvalds <torvalds@g5.osdl.org>
Mon, 20 Mar 2006 18:32:33 +0000 (10:32 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 20 Mar 2006 18:32:33 +0000 (10:32 -0800)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/shaggy/jfs-2.6:
  JFS: add uid, gid, and umask mount options
  JFS: Take logsync lock before testing mp->lsn
  JFS: kzalloc conversion
  JFS: Add missing file from fa3241d24cf1182b0ffb6e4d412c3bc2a2ab7bf6
  JFS: Use the kthread_ API
  JFS: Fix regression.  fsck complains if symlinks do not have INLINEEA attribute
  JFS: ext2 inode attributes for jfs
  JFS: semaphore to mutex conversion.
  JFS: make buddy table static
  JFS: Add back directory i_size calculations for legacy partitions

242 files changed:
CREDITS
Documentation/DocBook/Makefile
Documentation/DocBook/sis900.tmpl [deleted file]
Documentation/cpusets.txt
Documentation/feature-removal-schedule.txt
Documentation/networking/00-INDEX
Documentation/networking/README.ipw2100
Documentation/networking/README.ipw2200
Documentation/networking/sis900.txt [deleted file]
Documentation/vm/page_migration
MAINTAINERS
Makefile
arch/arm/common/locomo.c
arch/arm/kernel/compat.c
arch/arm/kernel/compat.h [new file with mode: 0644]
arch/arm/kernel/process.c
arch/arm/kernel/ptrace.c
arch/arm/kernel/setup.c
arch/arm/mach-s3c2410/devs.c
arch/i386/kernel/smpboot.c
arch/mips/Makefile
arch/mips/arc/misc.c
arch/mips/au1000/common/reset.c
arch/mips/kernel/time.c
arch/mips/mm/c-r4k.c
arch/mips/mm/c-tx39.c
arch/mips/sibyte/sb1250/time.c
arch/mips/sibyte/swarm/setup.c
arch/powerpc/Kconfig
arch/powerpc/boot/crt0.S
arch/powerpc/configs/cell_defconfig
arch/powerpc/configs/iseries_defconfig
arch/powerpc/configs/maple_defconfig
arch/powerpc/configs/mpc834x_sys_defconfig
arch/powerpc/configs/pmac32_defconfig
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/kernel/pci_64.c
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/rtas-rtc.c
arch/powerpc/kernel/rtas_pci.c
arch/powerpc/kernel/time.c
arch/powerpc/mm/pgtable_32.c
arch/powerpc/platforms/powermac/feature.c
arch/powerpc/platforms/powermac/setup.c
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/pci_dlpar.c
arch/ppc/platforms/hdpu.c
block/as-iosched.c
block/cfq-iosched.c
block/deadline-iosched.c
block/elevator.c
block/ll_rw_blk.c
drivers/block/loop.c
drivers/block/pktcdvd.c
drivers/block/umem.c
drivers/md/dm-stripe.c
drivers/md/dm.c
drivers/md/md.c
drivers/media/video/cx88/Kconfig
drivers/media/video/em28xx/em28xx-video.c
drivers/net/3c509.c
drivers/net/3c523.c
drivers/net/3c59x.c
drivers/net/7990.c
drivers/net/8139cp.c
drivers/net/8139too.c
drivers/net/82596.c
drivers/net/Kconfig
drivers/net/apne.c
drivers/net/arcnet/Kconfig
drivers/net/arcnet/arc-rawmode.c
drivers/net/arcnet/arc-rimi.c
drivers/net/arcnet/arcnet.c
drivers/net/arcnet/com90xx.c
drivers/net/arcnet/rfc1051.c
drivers/net/arcnet/rfc1201.c
drivers/net/arm/etherh.c
drivers/net/bnx2.c
drivers/net/bnx2_fw.h
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_sysfs.c
drivers/net/bonding/bonding.h
drivers/net/chelsio/espi.c
drivers/net/chelsio/sge.c
drivers/net/chelsio/subr.c
drivers/net/dgrs.c
drivers/net/dgrs_firmware.c
drivers/net/dl2k.c
drivers/net/e100.c
drivers/net/e1000/e1000.h
drivers/net/e1000/e1000_ethtool.c
drivers/net/e1000/e1000_hw.c
drivers/net/e1000/e1000_hw.h
drivers/net/e1000/e1000_main.c
drivers/net/e1000/e1000_param.c
drivers/net/eepro100.c
drivers/net/epic100.c
drivers/net/eth16i.c
drivers/net/fealnx.c
drivers/net/forcedeth.c
drivers/net/hamachi.c
drivers/net/hamradio/baycom_epp.c
drivers/net/hp100.c
drivers/net/ibm_emac/ibm_emac_core.c
drivers/net/ibm_emac/ibm_emac_core.h
drivers/net/ibm_emac/ibm_emac_debug.c
drivers/net/ibm_emac/ibm_emac_rgmii.h
drivers/net/ibm_emac/ibm_emac_zmii.c
drivers/net/ibm_emac/ibm_emac_zmii.h
drivers/net/irda/Kconfig
drivers/net/macsonic.c
drivers/net/mv643xx_eth.c
drivers/net/mv643xx_eth.h
drivers/net/natsemi.c
drivers/net/ne-h8300.c
drivers/net/ne.c
drivers/net/ne2.c
drivers/net/ne2k-pci.c
drivers/net/ns83820.c
drivers/net/oaknet.c
drivers/net/pcmcia/3c574_cs.c
drivers/net/pcmcia/3c589_cs.c
drivers/net/pcmcia/fmvj18x_cs.c
drivers/net/pcmcia/nmclan_cs.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/pcmcia/smc91c92_cs.c
drivers/net/pcmcia/xirc2ps_cs.c
drivers/net/pcnet32.c
drivers/net/phy/phy.c
drivers/net/plip.c
drivers/net/ppp_async.c
drivers/net/ppp_synctty.c
drivers/net/r8169.c
drivers/net/s2io.c
drivers/net/s2io.h
drivers/net/sb1000.c
drivers/net/sb1250-mac.c
drivers/net/seeq8005.c
drivers/net/sgiseeq.c
drivers/net/shaper.c
drivers/net/sis190.c
drivers/net/sis900.c
drivers/net/sk98lin/h/skaddr.h
drivers/net/sk98lin/h/skcsum.h
drivers/net/sk98lin/h/skgeinit.h
drivers/net/sk98lin/h/skgepnmi.h
drivers/net/sk98lin/h/skgesirq.h
drivers/net/sk98lin/h/ski2c.h
drivers/net/sk98lin/h/skvpd.h
drivers/net/sk98lin/skaddr.c
drivers/net/sk98lin/skgeinit.c
drivers/net/sk98lin/skgemib.c
drivers/net/sk98lin/skgepnmi.c
drivers/net/sk98lin/skgesirq.c
drivers/net/sk98lin/ski2c.c
drivers/net/sk98lin/sklm80.c
drivers/net/sk98lin/skrlmt.c
drivers/net/sk98lin/skvpd.c
drivers/net/sk98lin/skxmac2.c
drivers/net/skfp/fplustm.c
drivers/net/skfp/pcmplc.c
drivers/net/skfp/skfddi.c
drivers/net/starfire.c
drivers/net/sundance.c
drivers/net/sungem_phy.c
drivers/net/tg3.c
drivers/net/tg3.h
drivers/net/tokenring/lanstreamer.c
drivers/net/tokenring/olympic.c
drivers/net/tulip/de2104x.c
drivers/net/tulip/pnic.c
drivers/net/tulip/winbond-840.c
drivers/net/tulip/xircom_cb.c
drivers/net/typhoon.c
drivers/net/wan/Kconfig
drivers/net/wan/hostess_sv11.c
drivers/net/wan/sealevel.c
drivers/net/wireless/Kconfig
drivers/net/wireless/airo.c
drivers/net/wireless/atmel.c
drivers/net/wireless/ipw2100.c
drivers/net/wireless/ipw2100.h
drivers/net/wireless/ipw2200.c
drivers/net/wireless/ipw2200.h
drivers/net/wireless/netwave_cs.c
drivers/net/wireless/strip.c
drivers/net/wireless/wavelan.p.h
drivers/net/wireless/wavelan_cs.p.h
drivers/net/yellowfin.c
drivers/net/zorro8390.c
drivers/s390/block/dcssblk.c
drivers/s390/cio/css.c
fs/9p/vfs_dir.c
fs/buffer.c
fs/direct-io.c
fs/ext2/dir.c
fs/namespace.c
fs/nfsctl.c
include/asm-arm/system.h
include/asm-mips/cpu-features.h
include/asm-mips/cpu-info.h
include/asm-mips/hazards.h
include/asm-mips/io.h
include/asm-mips/r4kcache.h
include/asm-mips/sibyte/sb1250.h
include/asm-mips/sibyte/sb1250_scd.h
include/asm-powerpc/ppc-pci.h
include/linux/arcdevice.h
include/linux/blkdev.h
include/linux/elevator.h
include/linux/if.h
include/linux/if_ether.h
include/linux/mv643xx.h
include/linux/pci_ids.h
include/net/ax25.h
include/net/ieee80211.h
include/net/ieee80211_crypt.h
include/net/sock.h
kernel/exit.c
kernel/fork.c
kernel/posix-timers.c
kernel/timer.c
mm/memory.c
mm/mempolicy.c
mm/swap.c
mm/vmscan.c
net/Kconfig
net/ax25/sysctl_net_ax25.c
net/core/Makefile
net/core/dev.c
net/ieee80211/ieee80211_crypt.c
net/ieee80211/ieee80211_crypt_ccmp.c
net/ieee80211/ieee80211_crypt_tkip.c
net/ieee80211/ieee80211_crypt_wep.c
net/ieee80211/ieee80211_geo.c
net/ieee80211/ieee80211_module.c
net/ieee80211/ieee80211_rx.c
net/ieee80211/ieee80211_tx.c
net/ieee80211/ieee80211_wx.c
net/socket.c
scripts/mod/modpost.c

diff --git a/CREDITS b/CREDITS
index 64511e2..1f171f1 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -120,7 +120,6 @@ D: Author of lil (Linux Interrupt Latency benchmark)
 D: Fixed the shm swap deallocation at swapoff time (try_to_unuse message)
 D: VM hacker
 D: Various other kernel hacks
-S: Via Cicalini 26
 S: Imola 40026
 S: Italy
 
index 1c95588..2975291 100644 (file)
@@ -9,7 +9,7 @@
 DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
            kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
            procfs-guide.xml writing_usb_driver.xml \
-           sis900.xml kernel-api.xml journal-api.xml lsm.xml usb.xml \
+           kernel-api.xml journal-api.xml lsm.xml usb.xml \
            gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml
 
 ###
diff --git a/Documentation/DocBook/sis900.tmpl b/Documentation/DocBook/sis900.tmpl
deleted file mode 100644 (file)
index 6c2cbac..0000000
+++ /dev/null
@@ -1,585 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-       "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="SiS900Guide">
-
-<bookinfo>
-
-<title>SiS 900/7016 Fast Ethernet Device Driver</title>
-
-<authorgroup>
-<author>
-<firstname>Ollie</firstname>
-<surname>Lho</surname>
-</author>
-
-<author>
-<firstname>Lei Chun</firstname>
-<surname>Chang</surname>
-</author>
-</authorgroup>
-
-<edition>Document Revision: 0.3 for SiS900 driver v1.06 &amp; v1.07</edition>
-<pubdate>November 16, 2000</pubdate>
-
-<copyright>
- <year>1999</year>
- <holder>Silicon Integrated System Corp.</holder>
-</copyright>
-
-<legalnotice>
- <para>
-       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.
- </para>
-
- <para>
-       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.
- </para>
-
- <para>
-       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
- </para>
-</legalnotice>
-
-<abstract>
-<para>
-This document gives some information on installation and usage of SiS 900/7016
-device driver under Linux.
-</para>
-</abstract>
-
-</bookinfo>
-
-<toc></toc>
-
-<chapter id="intro">
- <title>Introduction</title>
-
-<para>
-This document describes the revision 1.06 and 1.07 of SiS 900/7016 Fast Ethernet 
-device driver under Linux. The driver is developed by Silicon Integrated
-System Corp. and distributed freely under the GNU General Public License (GPL).
-The driver can be compiled as a loadable module and used under Linux kernel 
-version 2.2.x. (rev. 1.06)
-With minimal changes, the driver can also be used under 2.3.x and 2.4.x kernel 
-(rev. 1.07), please see 
-<xref linkend="install"/>. If you are intended to
-use the driver for earlier kernels, you are on your own.
-</para>
-
-<para>
-The driver is tested with usual TCP/IP applications including
-FTP, Telnet, Netscape etc. and is used constantly by the developers.
-</para>
-
-<para>
-Please send all comments/fixes/questions to
-<ulink url="mailto:lcchang@sis.com.tw">Lei-Chun Chang</ulink>.
-</para>
-</chapter>
-
-<chapter id="changes">
- <title>Changes</title>
-
-<para>
-Changes made in Revision 1.07
-
-<orderedlist>
-<listitem>
-<para>
-Separation of sis900.c and sis900.h in order to move most 
-constant definition to sis900.h (many of those constants were
-corrected)
-</para>
-</listitem>
-
-<listitem>
-<para>
-Clean up PCI detection, the pci-scan from Donald Becker were not used,
-just simple pci&lowbar;find&lowbar;*.
-</para>
-</listitem>
-
-<listitem>
-<para>
-MII detection is modified to support multiple mii transceiver.
-</para>
-</listitem>
-
-<listitem>
-<para>
-Bugs in read&lowbar;eeprom, mdio&lowbar;* were removed.
-</para>
-</listitem>
-
-<listitem>
-<para>
-Lot of sis900 irrelevant comments were removed/changed and
-more comments were added to reflect the real situation.
-</para>
-</listitem>
-
-<listitem>
-<para>
-Clean up of physical/virtual address space mess in buffer 
-descriptors.
-</para>
-</listitem>
-
-<listitem>
-<para>
-Better transmit/receive error handling.
-</para>
-</listitem>
-
-<listitem>
-<para>
-The driver now uses zero-copy single buffer management
-scheme to improve performance.
-</para>
-</listitem>
-
-<listitem>
-<para>
-Names of variables were changed to be more consistent.
-</para>
-</listitem>
-
-<listitem>
-<para>
-Clean up of auo-negotiation and timer code.
-</para>
-</listitem>
-
-<listitem>
-<para>
-Automatic detection and change of PHY on the fly.
-</para>
-</listitem>
-
-<listitem>
-<para>
-Bug in mac probing fixed.
-</para>
-</listitem>
-
-<listitem>
-<para>
-Fix 630E equalier problem by modifying the equalizer workaround rule.
-</para>
-</listitem>
-
-<listitem>
-<para>
-Support for ICS1893 10/100 Interated PHYceiver.
-</para>
-</listitem>
-
-<listitem>
-<para>
-Support for media select by ifconfig.
-</para>
-</listitem>
-
-<listitem>
-<para>
-Added kernel-doc extratable documentation.
-</para>
-</listitem>
-
-</orderedlist>
-</para>
-</chapter>
-
-<chapter id="tested">
- <title>Tested Environment</title>
-
-<para>
-This driver is developed on the following hardware
-
-<itemizedlist>
-<listitem>
-
-<para>
-Intel Celeron 500 with SiS 630 (rev 02) chipset
-</para>
-</listitem>
-<listitem>
-
-<para>
-SiS 900 (rev 01) and SiS 7016/7014 Fast Ethernet Card
-</para>
-</listitem>
-
-</itemizedlist>
-
-and tested with these software environments
-
-<itemizedlist>
-<listitem>
-
-<para>
-Red Hat Linux version 6.2
-</para>
-</listitem>
-<listitem>
-
-<para>
-Linux kernel version 2.4.0
-</para>
-</listitem>
-<listitem>
-
-<para>
-Netscape version 4.6
-</para>
-</listitem>
-<listitem>
-
-<para>
-NcFTP 3.0.0 beta 18
-</para>
-</listitem>
-<listitem>
-
-<para>
-Samba version 2.0.3
-</para>
-</listitem>
-
-</itemizedlist>
-
-</para>
-
-</chapter>
-
-<chapter id="files">
-<title>Files in This Package</title>
-
-<para>
-In the package you can find these files:
-</para>
-
-<para>
-<variablelist>
-
-<varlistentry>
-<term>sis900.c</term>
-<listitem>
-<para>
-Driver source file in C 
-</para>
-</listitem>
-</varlistentry>
-
-<varlistentry>
-<term>sis900.h</term>
-<listitem>
-<para>
-Header file for sis900.c
-</para>
-</listitem>
-</varlistentry>
-
-<varlistentry>
-<term>sis900.sgml</term>
-<listitem>
-<para>
-DocBook SGML source of the document
-</para>
-</listitem>
-</varlistentry>
-
-<varlistentry>
-<term>sis900.txt</term>
-<listitem>
-<para>
-Driver document in plain text
-</para>
-</listitem>
-</varlistentry>
-
-</variablelist>
-</para>
-</chapter>
-
-<chapter id="install">
- <title>Installation</title>
-
-<para>
-Silicon Integrated System Corp. is cooperating closely with core Linux Kernel
-developers. The revisions of SiS 900 driver are distributed by the usuall channels
-for kernel tar files and patches. Those kernel tar files for official kernel and
-patches for kernel pre-release can be download at 
-<ulink url="http://ftp.kernel.org/pub/linux/kernel/">official kernel ftp site</ulink>
-and its mirrors.
-The 1.06 revision can be found in kernel version later than 2.3.15 and pre-2.2.14, 
-and 1.07 revision can be found in kernel version 2.4.0.
-If you have no prior experience in networking under Linux, please read
-<ulink url="http://www.tldp.org/">Ethernet HOWTO</ulink> and
-<ulink url="http://www.tldp.org/">Networking HOWTO</ulink> available from
-Linux Documentation Project (LDP).
-</para>
-
-<para>
-The driver is bundled in release later than 2.2.11 and 2.3.15 so this 
-is the most easy case. 
-Be sure you have the appropriate packages for compiling kernel source.
-Those packages are listed in Document/Changes in kernel source 
-distribution. If you have to install the driver other than those bundled
-in kernel release, you should have your driver file 
-<filename>sis900.c</filename> and <filename>sis900.h</filename> 
-copied into <filename class="directory">/usr/src/linux/drivers/net/</filename> first.
-There are two alternative ways to install the driver
-</para>
-
-<sect1>
-<title>Building the driver as loadable module</title>
-
-<para>
-To build the driver as a loadable kernel module you have to reconfigure
-the kernel to activate network support by
-</para>
-
-<para><screen>
-make menuconfig
-</screen></para>
-
-<para>
-Choose <quote>Loadable module support  ---></quote>, 
-then select <quote>Enable loadable module support</quote>.
-</para>
-
-<para>
-Choose <quote>Network Device Support  ---></quote>, select 
-<quote>Ethernet (10 or 100Mbit)</quote>.
-Then select <quote>EISA, VLB, PCI and on board controllers</quote>, 
-and choose <quote>SiS 900/7016 PCI Fast Ethernet Adapter support</quote> 
-to <quote>M</quote>.
-</para>
-
-<para>
-After reconfiguring the kernel, you can make the driver module by
-</para>
-
-<para><screen>
-make modules
-</screen></para>
-
-<para>
-The driver should be compiled with no errors. After compiling the driver,
-the driver can be installed to proper place by
-</para>
-
-<para><screen>
-make modules_install
-</screen></para>
-
-<para>
-Load the driver into kernel by
-</para>
-
-<para><screen>
-insmod sis900
-</screen></para>
-
-<para>
-When loading the driver into memory, some information message can be view by
-</para>
-
-<para>
-<screen>
-dmesg
-</screen>
-
-or
-
-<screen>
-cat /var/log/message
-</screen>
-</para>
-
-<para>
-If the driver is loaded properly you will have messages similar to this:
-</para>
-
-<para><screen>
-sis900.c: v1.07.06  11/07/2000
-eth0: SiS 900 PCI Fast Ethernet at 0xd000, IRQ 10, 00:00:e8:83:7f:a4.
-eth0: SiS 900 Internal MII PHY transceiver found at address 1.
-eth0: Using SiS 900 Internal MII PHY as default
-</screen></para>
-
-<para>
-showing the version of the driver and the results of probing routine.
-</para>
-
-<para>
-Once the driver is loaded, network can be brought up by
-</para>
-
-<para><screen>
-/sbin/ifconfig eth0 IPADDR broadcast BROADCAST netmask NETMASK media TYPE
-</screen></para>
-
-<para>
-where IPADDR, BROADCAST, NETMASK are your IP address, broadcast address and
-netmask respectively. TYPE is used to set medium type used by the device. 
-Typical values are "10baseT"(twisted-pair 10Mbps Ethernet) or "100baseT"
-(twisted-pair 100Mbps Ethernet). For more information on how to configure 
-network interface, please refer to  
-<ulink url="http://www.tldp.org/">Networking HOWTO</ulink>.
-</para>
-
-<para>
-The link status is also shown by kernel messages. For example, after the
-network interface is activated, you may have the message:
-</para>
-
-<para><screen>
-eth0: Media Link On 100mbps full-duplex
-</screen></para>
-
-<para>
-If you try to unplug the twist pair (TP) cable you will get
-</para>
-
-<para><screen>
-eth0: Media Link Off
-</screen></para>
-
-<para>
-indicating that the link is failed.
-</para>
-</sect1>
-
-<sect1>
-<title>Building the driver into kernel</title>
-
-<para>
-If you want to make the driver into kernel, choose <quote>Y</quote> 
-rather than <quote>M</quote> on 
-<quote>SiS 900/7016 PCI Fast Ethernet Adapter support</quote> 
-when configuring the kernel. Build the kernel image in the usual way
-</para>
-
-<para><screen>
-make clean
-
-make bzlilo
-</screen></para>
-
-<para>
-Next time the system reboot, you have the driver in memory.
-</para>
-
-</sect1>
-</chapter>
-
-<chapter id="problems">
- <title>Known Problems and Bugs</title>
-
-<para>
-There are some known problems and bugs. If you find any other bugs please 
-mail to <ulink url="mailto:lcchang@sis.com.tw">lcchang@sis.com.tw</ulink>
-
-<orderedlist>
-
-<listitem>
-<para>
-AM79C901 HomePNA PHY is not thoroughly tested, there may be some 
-bugs in the <quote>on the fly</quote> change of transceiver. 
-</para>
-</listitem>
-
-<listitem>
-<para>
-A bug is hidden somewhere in the receive buffer management code, 
-the bug causes NULL pointer reference in the kernel. This fault is 
-caught before bad things happen and reported with the message:
-
-<computeroutput>
-eth0: NULL pointer encountered in Rx ring, skipping 
-</computeroutput>
-
-which can be viewed with <literal remap="tt">dmesg</literal> or
-<literal remap="tt">cat /var/log/message</literal>.
-</para>
-</listitem>
-
-<listitem>
-<para>
-The media type change from 10Mbps to 100Mbps twisted-pair ethernet 
-by ifconfig causes the media link down.
-</para>
-</listitem>
-
-</orderedlist>
-</para>
-</chapter>
-
-<chapter id="RHistory">
- <title>Revision History</title>
-
-<para>
-<itemizedlist>
-
-<listitem>
-<para>
-November 13, 2000, Revision 1.07, seventh release, 630E problem fixed 
-and further clean up.
-</para>
-</listitem>
-
-<listitem>
-<para>
-November 4, 1999, Revision 1.06, Second release, lots of clean up
-and optimization.
-</para>
-</listitem>
-
-<listitem>
-<para>
-August 8, 1999, Revision 1.05, Initial Public Release
-</para>
-</listitem>
-
-</itemizedlist>
-</para>
-</chapter>
-
-<chapter id="acknowledgements">
- <title>Acknowledgements</title>
-
-<para>
-This driver was originally derived form 
-<ulink url="mailto:becker@cesdis1.gsfc.nasa.gov">Donald Becker</ulink>'s
-<ulink url="ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/kern-2.3/pci-skeleton.c"
->pci-skeleton</ulink> and
-<ulink url="ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/kern-2.3/rtl8139.c"
->rtl8139</ulink> drivers. Donald also provided various suggestion
-regarded with improvements made in revision 1.06.
-</para>
-
-<para>
-The 1.05 revision was created by 
-<ulink url="mailto:cmhuang@sis.com.tw">Jim Huang</ulink>, AMD 79c901
-support was added by <ulink url="mailto:lcs@sis.com.tw">Chin-Shan Li</ulink>.
-</para>
-</chapter>
-
-<chapter id="functions">
-<title>List of Functions</title>
-!Idrivers/net/sis900.c
-</chapter>
-
-</book>
index 990998e..30c4145 100644 (file)
@@ -4,8 +4,9 @@
 Copyright (C) 2004 BULL SA.
 Written by Simon.Derr@bull.net
 
-Portions Copyright (c) 2004 Silicon Graphics, Inc.
+Portions Copyright (c) 2004-2006 Silicon Graphics, Inc.
 Modified by Paul Jackson <pj@sgi.com>
+Modified by Christoph Lameter <clameter@sgi.com>
 
 CONTENTS:
 =========
@@ -90,7 +91,8 @@ This can be especially valuable on:
 
 These subsets, or "soft partitions" must be able to be dynamically
 adjusted, as the job mix changes, without impacting other concurrently
-executing jobs.
+executing jobs. The location of the running jobs pages may also be moved
+when the memory locations are changed.
 
 The kernel cpuset patch provides the minimum essential kernel
 mechanisms required to efficiently implement such subsets.  It
@@ -102,8 +104,8 @@ memory allocator code.
 1.3 How are cpusets implemented ?
 ---------------------------------
 
-Cpusets provide a Linux kernel (2.6.7 and above) mechanism to constrain
-which CPUs and Memory Nodes are used by a process or set of processes.
+Cpusets provide a Linux kernel mechanism to constrain which CPUs and
+Memory Nodes are used by a process or set of processes.
 
 The Linux kernel already has a pair of mechanisms to specify on which
 CPUs a task may be scheduled (sched_setaffinity) and on which Memory
@@ -371,22 +373,17 @@ cpusets memory placement policy 'mems' subsequently changes.
 If the cpuset flag file 'memory_migrate' is set true, then when
 tasks are attached to that cpuset, any pages that task had
 allocated to it on nodes in its previous cpuset are migrated
-to the tasks new cpuset.  Depending on the implementation,
-this migration may either be done by swapping the page out,
-so that the next time the page is referenced, it will be paged
-into the tasks new cpuset, usually on the node where it was
-referenced, or this migration may be done by directly copying
-the pages from the tasks previous cpuset to the new cpuset,
-where possible to the same node, relative to the new cpuset,
-as the node that held the page, relative to the old cpuset.
+to the tasks new cpuset. The relative placement of the page within
+the cpuset is preserved during these migration operations if possible.
+For example if the page was on the second valid node of the prior cpuset
+then the page will be placed on the second valid node of the new cpuset.
+
 Also if 'memory_migrate' is set true, then if that cpusets
 'mems' file is modified, pages allocated to tasks in that
 cpuset, that were on nodes in the previous setting of 'mems',
-will be moved to nodes in the new setting of 'mems.'  Again,
-depending on the implementation, this might be done by swapping,
-or by direct copying.  In either case, pages that were not in
-the tasks prior cpuset, or in the cpusets prior 'mems' setting,
-will not be moved.
+will be moved to nodes in the new setting of 'mems.'
+Pages that were not in the tasks prior cpuset, or in the cpusets
+prior 'mems' setting, will not be moved.
 
 There is an exception to the above.  If hotplug functionality is used
 to remove all the CPUs that are currently assigned to a cpuset,
@@ -434,16 +431,6 @@ and then start a subshell 'sh' in that cpuset:
   # The next line should display '/Charlie'
   cat /proc/self/cpuset
 
-In the case that a change of cpuset includes wanting to move already
-allocated memory pages, consider further the work of IWAMOTO
-Toshihiro <iwamoto@valinux.co.jp> for page remapping and memory
-hotremoval, which can be found at:
-
-  http://people.valinux.co.jp/~iwamoto/mh.html
-
-The integration of cpusets with such memory migration is not yet
-available.
-
 In the future, a C library interface to cpusets will likely be
 available.  For now, the only way to query or modify cpusets is
 via the cpuset file system, using the various cd, mkdir, echo, cat,
index 81bc513..28a31c5 100644 (file)
@@ -151,6 +151,13 @@ Who:       Ralf Baechle <ralf@linux-mips.org>
 
 ---------------------------
 
+What:   eepro100 network driver
+When:   January 2007
+Why:    replaced by the e100 driver
+Who:    Adrian Bunk <bunk@stusta.de>
+
+---------------------------
+
 What:  Legacy /proc/pci interface (PCI_LEGACY_PROC)
 When:  March 2006
 Why:   deprecated since 2.5.53 in favor of lspci(8)
index 5b01d5c..b1181ce 100644 (file)
@@ -92,8 +92,6 @@ routing.txt
        - the new routing mechanism
 shaper.txt
        - info on the module that can shape/limit transmitted traffic.
-sis900.txt
-       - SiS 900/7016 Fast Ethernet device driver info.
 sk98lin.txt
        - Marvell Yukon Chipset / SysKonnect SK-98xx compliant Gigabit
          Ethernet Adapter family driver info
index 3ab4037..f3fcaa4 100644 (file)
@@ -3,18 +3,18 @@ Intel(R) PRO/Wireless 2100 Driver for Linux in support of:
 
 Intel(R) PRO/Wireless 2100 Network Connection
 
-Copyright (C) 2003-2005, Intel Corporation
+Copyright (C) 2003-2006, Intel Corporation
 
 README.ipw2100
 
-Version: 1.1.3
-Date   : October 17, 2005
+Version: git-1.1.5
+Date   : January 25, 2006
 
 Index
 -----------------------------------------------
 0. IMPORTANT INFORMATION BEFORE USING THIS DRIVER
 1. Introduction
-2. Release 1.1.3 Current Features
+2. Release git-1.1.5 Current Features
 3. Command Line Parameters
 4. Sysfs Helper Files
 5. Radio Kill Switch
@@ -89,7 +89,7 @@ potential fixes and patches, as well as links to the development mailing list
 for the driver project.
 
 
-2. Release 1.1.3 Current Supported Features
+2. Release git-1.1.5 Current Supported Features
 -----------------------------------------------
 - Managed (BSS) and Ad-Hoc (IBSS)
 - WEP (shared key and open)
@@ -270,7 +270,7 @@ For installation support on the ipw2100 1.1.0 driver on Linux kernels
 9. License
 -----------------------------------------------
 
-  Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved.
 
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License (version 2) as 
index c6492d3..acb30c5 100644 (file)
@@ -10,7 +10,7 @@ both hardware adapters listed above. In this document the Intel(R)
 PRO/Wireless 2915ABG Driver for Linux will be used to reference the
 unified driver.
 
-Copyright (C) 2004-2005, Intel Corporation
+Copyright (C) 2004-2006, Intel Corporation
 
 README.ipw2200
 
@@ -26,9 +26,11 @@ Index
 1.2. Module parameters
 1.3. Wireless Extension Private Methods
 1.4. Sysfs Helper Files
+1.5. Supported channels
 2.   Ad-Hoc Networking
 3.   Interacting with Wireless Tools
 3.1. iwconfig mode
+3.2. iwconfig sens
 4.   About the Version Numbers
 5.   Firmware installation
 6.   Support
@@ -314,6 +316,35 @@ For the device level files, see /sys/bus/pci/drivers/ipw2200:
        running ifconfig and is therefore disabled by default.
 
 
+1.5. Supported channels
+-----------------------------------------------
+
+Upon loading the Intel(R) PRO/Wireless 2915ABG Driver for Linux, a
+message stating the detected geography code and the number of 802.11
+channels supported by the card will be displayed in the log.
+
+The geography code corresponds to a regulatory domain as shown in the
+table below.
+
+                                         Supported channels
+Code   Geography                       802.11bg        802.11a
+
+---    Restricted                      11               0
+ZZF    Custom US/Canada                11               8
+ZZD    Rest of World                   13               0
+ZZA    Custom USA & Europe & High      11              13
+ZZB    Custom NA & Europe              11              13
+ZZC    Custom Japan                    11               4
+ZZM    Custom                          11               0
+ZZE    Europe                          13              19
+ZZJ    Custom Japan                    14               4
+ZZR    Rest of World                   14               0
+ZZH    High Band                       13               4
+ZZG    Custom Europe                   13               4
+ZZK    Europe                          13              24
+ZZL    Europe                          11              13
+
+
 2.   Ad-Hoc Networking
 -----------------------------------------------
 
@@ -353,6 +384,15 @@ When configuring the mode of the adapter, all run-time configured parameters
 are reset to the value used when the module was loaded.  This includes
 channels, rates, ESSID, etc.
 
+3.2 iwconfig sens
+-----------------------------------------------
+
+The 'iwconfig ethX sens XX' command will not set the signal sensitivity
+threshold, as described in iwconfig documentation, but rather the number
+of consecutive missed beacons that will trigger handover, i.e. roaming
+to another access point. At the same time, it will set the disassociation
+threshold to 3 times the given value.
+
 
 4.   About the Version Numbers
 -----------------------------------------------
@@ -408,7 +448,7 @@ For general information and support, go to:
 7.  License
 -----------------------------------------------
 
-  Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved.
 
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License version 2 as 
diff --git a/Documentation/networking/sis900.txt b/Documentation/networking/sis900.txt
deleted file mode 100644 (file)
index bddffd7..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-
-SiS 900/7016 Fast Ethernet Device Driver
-
-Ollie Lho
-
-Lei Chun Chang
-
-   Copyright Â© 1999 by Silicon Integrated System Corp.
-   
-   This document gives some information on installation and usage of SiS
-   900/7016 device driver under Linux.
-   
-   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
-     _________________________________________________________________
-   
-   Table of Contents
-   1. Introduction
-   2. Changes
-   3. Tested Environment
-   4. Files in This Package
-   5. Installation
-          
-        Building the driver as loadable module
-        Building the driver into kernel
-                
-   6. Known Problems and Bugs
-   7. Revision History
-   8. Acknowledgements
-     _________________________________________________________________
-   
-Chapter 1. Introduction
-
-   This document describes the revision 1.06 and 1.07 of SiS 900/7016
-   Fast Ethernet device driver under Linux. The driver is developed by
-   Silicon Integrated System Corp. and distributed freely under the GNU
-   General Public License (GPL). The driver can be compiled as a loadable
-   module and used under Linux kernel version 2.2.x. (rev. 1.06) With
-   minimal changes, the driver can also be used under 2.3.x and 2.4.x
-   kernel (rev. 1.07), please see Chapter 5. If you are intended to use
-   the driver for earlier kernels, you are on your own.
-   
-   The driver is tested with usual TCP/IP applications including FTP,
-   Telnet, Netscape etc. and is used constantly by the developers.
-   
-   Please send all comments/fixes/questions to Lei-Chun Chang.
-     _________________________________________________________________
-   
-Chapter 2. Changes
-
-   Changes made in Revision 1.07
-   
-    1. Separation of sis900.c and sis900.h in order to move most constant
-       definition to sis900.h (many of those constants were corrected)
-    2. Clean up PCI detection, the pci-scan from Donald Becker were not
-       used, just simple pci_find_*.
-    3. MII detection is modified to support multiple mii transceiver.
-    4. Bugs in read_eeprom, mdio_* were removed.
-    5. Lot of sis900 irrelevant comments were removed/changed and more
-       comments were added to reflect the real situation.
-    6. Clean up of physical/virtual address space mess in buffer
-       descriptors.
-    7. Better transmit/receive error handling.
-    8. The driver now uses zero-copy single buffer management scheme to
-       improve performance.
-    9. Names of variables were changed to be more consistent.
-   10. Clean up of auo-negotiation and timer code.
-   11. Automatic detection and change of PHY on the fly.
-   12. Bug in mac probing fixed.
-   13. Fix 630E equalier problem by modifying the equalizer workaround
-       rule.
-   14. Support for ICS1893 10/100 Interated PHYceiver.
-   15. Support for media select by ifconfig.
-   16. Added kernel-doc extratable documentation.
-     _________________________________________________________________
-   
-Chapter 3. Tested Environment
-
-   This driver is developed on the following hardware
-   
-     * Intel Celeron 500 with SiS 630 (rev 02) chipset
-     * SiS 900 (rev 01) and SiS 7016/7014 Fast Ethernet Card
-       
-   and tested with these software environments
-   
-     * Red Hat Linux version 6.2
-     * Linux kernel version 2.4.0
-     * Netscape version 4.6
-     * NcFTP 3.0.0 beta 18
-     * Samba version 2.0.3
-     _________________________________________________________________
-   
-Chapter 4. Files in This Package
-
-   In the package you can find these files:
-   
-   sis900.c
-          Driver source file in C
-          
-   sis900.h
-          Header file for sis900.c
-          
-   sis900.sgml
-          DocBook SGML source of the document
-          
-   sis900.txt
-          Driver document in plain text
-     _________________________________________________________________
-   
-Chapter 5. Installation
-
-   Silicon Integrated System Corp. is cooperating closely with core Linux
-   Kernel developers. The revisions of SiS 900 driver are distributed by
-   the usuall channels for kernel tar files and patches. Those kernel tar
-   files for official kernel and patches for kernel pre-release can be
-   download at official kernel ftp site and its mirrors. The 1.06
-   revision can be found in kernel version later than 2.3.15 and
-   pre-2.2.14, and 1.07 revision can be found in kernel version 2.4.0. If
-   you have no prior experience in networking under Linux, please read
-   Ethernet HOWTO and Networking HOWTO available from Linux Documentation
-   Project (LDP).
-   
-   The driver is bundled in release later than 2.2.11 and 2.3.15 so this
-   is the most easy case. Be sure you have the appropriate packages for
-   compiling kernel source. Those packages are listed in Document/Changes
-   in kernel source distribution. If you have to install the driver other
-   than those bundled in kernel release, you should have your driver file
-   sis900.c and sis900.h copied into /usr/src/linux/drivers/net/ first.
-   There are two alternative ways to install the driver
-     _________________________________________________________________
-   
-Building the driver as loadable module
-
-   To build the driver as a loadable kernel module you have to
-   reconfigure the kernel to activate network support by
-   
-make menuconfig
-
-   Choose "Loadable module support --->", then select "Enable loadable
-   module support".
-   
-   Choose "Network Device Support --->", select "Ethernet (10 or
-   100Mbit)". Then select "EISA, VLB, PCI and on board controllers", and
-   choose "SiS 900/7016 PCI Fast Ethernet Adapter support" to "M".
-   
-   After reconfiguring the kernel, you can make the driver module by
-   
-make modules
-
-   The driver should be compiled with no errors. After compiling the
-   driver, the driver can be installed to proper place by
-   
-make modules_install
-
-   Load the driver into kernel by
-   
-insmod sis900
-
-   When loading the driver into memory, some information message can be
-   view by
-   
-dmesg
-
-   or
-cat /var/log/message
-
-   If the driver is loaded properly you will have messages similar to
-   this:
-   
-sis900.c: v1.07.06  11/07/2000
-eth0: SiS 900 PCI Fast Ethernet at 0xd000, IRQ 10, 00:00:e8:83:7f:a4.
-eth0: SiS 900 Internal MII PHY transceiver found at address 1.
-eth0: Using SiS 900 Internal MII PHY as default
-
-   showing the version of the driver and the results of probing routine.
-   
-   Once the driver is loaded, network can be brought up by
-   
-/sbin/ifconfig eth0 IPADDR broadcast BROADCAST netmask NETMASK media TYPE
-
-   where IPADDR, BROADCAST, NETMASK are your IP address, broadcast
-   address and netmask respectively. TYPE is used to set medium type used
-   by the device. Typical values are "10baseT"(twisted-pair 10Mbps
-   Ethernet) or "100baseT" (twisted-pair 100Mbps Ethernet). For more
-   information on how to configure network interface, please refer to
-   Networking HOWTO.
-   
-   The link status is also shown by kernel messages. For example, after
-   the network interface is activated, you may have the message:
-   
-eth0: Media Link On 100mbps full-duplex
-
-   If you try to unplug the twist pair (TP) cable you will get
-   
-eth0: Media Link Off
-
-   indicating that the link is failed.
-     _________________________________________________________________
-   
-Building the driver into kernel
-
-   If you want to make the driver into kernel, choose "Y" rather than "M"
-   on "SiS 900/7016 PCI Fast Ethernet Adapter support" when configuring
-   the kernel. Build the kernel image in the usual way
-   
-make clean
-
-make bzlilo
-
-   Next time the system reboot, you have the driver in memory.
-     _________________________________________________________________
-   
-Chapter 6. Known Problems and Bugs
-
-   There are some known problems and bugs. If you find any other bugs
-   please mail to lcchang@sis.com.tw
-   
-    1. AM79C901 HomePNA PHY is not thoroughly tested, there may be some
-       bugs in the "on the fly" change of transceiver.
-    2. A bug is hidden somewhere in the receive buffer management code,
-       the bug causes NULL pointer reference in the kernel. This fault is
-       caught before bad things happen and reported with the message:
-       eth0: NULL pointer encountered in Rx ring, skipping which can be
-       viewed with dmesg or cat /var/log/message.
-    3. The media type change from 10Mbps to 100Mbps twisted-pair ethernet
-       by ifconfig causes the media link down.
-     _________________________________________________________________
-   
-Chapter 7. Revision History
-
-     * November 13, 2000, Revision 1.07, seventh release, 630E problem
-       fixed and further clean up.
-     * November 4, 1999, Revision 1.06, Second release, lots of clean up
-       and optimization.
-     * August 8, 1999, Revision 1.05, Initial Public Release
-     _________________________________________________________________
-   
-Chapter 8. Acknowledgements
-
-   This driver was originally derived form Donald Becker's pci-skeleton
-   and rtl8139 drivers. Donald also provided various suggestion regarded
-   with improvements made in revision 1.06.
-   
-   The 1.05 revision was created by Jim Huang, AMD 79c901 support was
-   added by Chin-Shan Li.
index c52820f..0dd4ef3 100644 (file)
@@ -12,12 +12,18 @@ is running.
 
 Page migration allows a process to manually relocate the node on which its
 pages are located through the MF_MOVE and MF_MOVE_ALL options while setting
-a new memory policy. The pages of process can also be relocated
+a new memory policy via mbind(). The pages of process can also be relocated
 from another process using the sys_migrate_pages() function call. The
 migrate_pages function call takes two sets of nodes and moves pages of a
 process that are located on the from nodes to the destination nodes.
-
-Manual migration is very useful if for example the scheduler has relocated
+Page migration functions are provided by the numactl package by Andi Kleen
+(a version later than 0.9.3 is required. Get it from
+ftp://ftp.suse.com/pub/people/ak). numactl provided libnuma which
+provides an interface similar to other numa functionality for page migration.
+cat /proc/<pid>/numa_maps allows an easy review of where the pages of
+a process are located. See also the numa_maps manpage in the numactl package.
+
+Manual migration is useful if for example the scheduler has relocated
 a process to a processor on a distant node. A batch scheduler or an
 administrator may detect the situation and move the pages of the process
 nearer to the new processor. At some point in the future we may have
@@ -25,10 +31,12 @@ some mechanism in the scheduler that will automatically move the pages.
 
 Larger installations usually partition the system using cpusets into
 sections of nodes. Paul Jackson has equipped cpusets with the ability to
-move pages when a task is moved to another cpuset. This allows automatic
-control over locality of a process. If a task is moved to a new cpuset
-then also all its pages are moved with it so that the performance of the
-process does not sink dramatically (as is the case today).
+move pages when a task is moved to another cpuset (See ../cpusets.txt).
+Cpusets allows the automation of process locality. If a task is moved to
+a new cpuset then also all its pages are moved with it so that the
+performance of the process does not sink dramatically. Also the pages
+of processes in a cpuset are moved if the allowed memory nodes of a
+cpuset are changed.
 
 Page migration allows the preservation of the relative location of pages
 within a group of nodes for all migration techniques which will preserve a
@@ -37,22 +45,26 @@ process. This is necessary in order to preserve the memory latencies.
 Processes will run with similar performance after migration.
 
 Page migration occurs in several steps. First a high level
-description for those trying to use migrate_pages() and then
-a low level description of how the low level details work.
+description for those trying to use migrate_pages() from the kernel
+(for userspace usage see the Andi Kleen's numactl package mentioned above)
+and then a low level description of how the low level details work.
 
-A. Use of migrate_pages()
--------------------------
+A. In kernel use of migrate_pages()
+-----------------------------------
 
 1. Remove pages from the LRU.
 
    Lists of pages to be migrated are generated by scanning over
    pages and moving them into lists. This is done by
-   calling isolate_lru_page() or __isolate_lru_page().
+   calling isolate_lru_page().
    Calling isolate_lru_page increases the references to the page
-   so that it cannot vanish under us.
+   so that it cannot vanish while the page migration occurs.
+   It also prevents the swapper or other scans to encounter
+   the page.
 
-2. Generate a list of newly allocates page to move the contents
-   of the first list to.
+2. Generate a list of newly allocates page. These pages will contain the
+   contents of the pages from the first list after page migration is
+   complete.
 
 3. The migrate_pages() function is called which attempts
    to do the migration. It returns the moved pages in the
@@ -63,13 +75,17 @@ A. Use of migrate_pages()
 4. The leftover pages of various types are returned
    to the LRU using putback_to_lru_pages() or otherwise
    disposed of. The pages will still have the refcount as
-   increased by isolate_lru_pages()!
+   increased by isolate_lru_pages() if putback_to_lru_pages() is not
+   used! The kernel may want to handle the various cases of failures in
+   different ways.
 
-B. Operation of migrate_pages()
---------------------------------
+B. How migrate_pages() works
+----------------------------
 
-migrate_pages does several passes over its list of pages. A page is moved
-if all references to a page are removable at the time.
+migrate_pages() does several passes over its list of pages. A page is moved
+if all references to a page are removable at the time. The page has
+already been removed from the LRU via isolate_lru_page() and the refcount
+is increased so that the page cannot be freed while page migration occurs.
 
 Steps:
 
@@ -79,36 +95,40 @@ Steps:
 
 3. Make sure that the page has assigned swap cache entry if
    it is an anonyous page. The swap cache reference is necessary
-   to preserve the information contain in the page table maps.
+   to preserve the information contain in the page table maps while
+   page migration occurs.
 
 4. Prep the new page that we want to move to. It is locked
    and set to not being uptodate so that all accesses to the new
-   page immediately lock while we are moving references.
+   page immediately lock while the move is in progress.
 
-5. All the page table references to the page are either dropped (file backed)
-   or converted to swap references (anonymous pages). This should decrease the
-   reference count.
+5. All the page table references to the page are either dropped (file
+   backed pages) or converted to swap references (anonymous pages).
+   This should decrease the reference count.
 
-6. The radix tree lock is taken
+6. The radix tree lock is taken. This will cause all processes trying
+   to reestablish a pte to block on the radix tree spinlock.
 
 7. The refcount of the page is examined and we back out if references remain
    otherwise we know that we are the only one referencing this page.
 
 8. The radix tree is checked and if it does not contain the pointer to this
-   page then we back out.
+   page then we back out because someone else modified the mapping first.
 
 9. The mapping is checked. If the mapping is gone then a truncate action may
    be in progress and we back out.
 
-10. The new page is prepped with some settings from the old page so that accesses
-   to the new page will be discovered to have the correct settings.
+10. The new page is prepped with some settings from the old page so that
+   accesses to the new page will be discovered to have the correct settings.
 
 11. The radix tree is changed to point to the new page.
 
-12. The reference count of the old page is dropped because the reference has now
-    been removed.
+12. The reference count of the old page is dropped because the radix tree
+    reference is gone.
 
-13. The radix tree lock is dropped.
+13. The radix tree lock is dropped. With that lookups become possible again
+    and other processes will move from spinning on the tree lock to sleeping on
+    the locked new page.
 
 14. The page contents are copied to the new page.
 
@@ -119,11 +139,37 @@ Steps:
 
 17. Queued up writeback on the new page is triggered.
 
-18. If swap pte's were generated for the page then remove them again.
+18. If swap pte's were generated for the page then replace them with real
+    ptes. This will reenable access for processes not blocked by the page lock.
+
+19. The page locks are dropped from the old and new page.
+    Processes waiting on the page lock can continue.
+
+20. The new page is moved to the LRU and can be scanned by the swapper
+    etc again.
+
+TODO list
+---------
+
+- Page migration requires the use of swap handles to preserve the
+  information of the anonymous page table entries. This means that swap
+  space is reserved but never used. The maximum number of swap handles used
+  is determined by CHUNK_SIZE (see mm/mempolicy.c) per ongoing migration.
+  Reservation of pages could be avoided by having a special type of swap
+  handle that does not require swap space and that would only track the page
+  references. Something like that was proposed by Marcelo Tosatti in the
+  past (search for migration cache on lkml or linux-mm@kvack.org).
 
-19. The locks are dropped from the old and new page.
+- Page migration unmaps ptes for file backed pages and requires page
+  faults to reestablish these ptes. This could be optimized by somehow
+  recording the references before migration and then reestablish them later.
+  However, there are several locking challenges that have to be overcome
+  before this is possible.
 
-20. The new page is moved to the LRU.
+- Page migration generates read ptes for anonymous pages. Dirty page
+  faults are required to make the pages writable again. It may be possible
+  to generate a pte marked dirty if it is known that the page is dirty and
+  that this process has the only reference to that page.
 
-Christoph Lameter, December 19, 2005.
+Christoph Lameter, March 8, 2006.
 
index 3d7d30d..8db5c33 100644 (file)
@@ -1752,7 +1752,8 @@ P:        Ralf Baechle
 M:     ralf@linux-mips.org
 W:     http://www.linux-mips.org/
 L:     linux-mips@linux-mips.org
-S:     Maintained
+T:     git www.linux-mips.org:/pub/scm/linux.git
+S:     Supported
 
 MISCELLANEOUS MCA-SUPPORT
 P:     James Bottomley
index ac54c03..cb57905 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 16
-EXTRAVERSION =-rc6
+EXTRAVERSION =
 NAME=Sliding Snow Leopard
 
 # *DOCUMENTATION*
index 159ad7e..d31b1cb 100644 (file)
@@ -629,6 +629,22 @@ static int locomo_resume(struct platform_device *dev)
 }
 #endif
 
+
+#define LCM_ALC_EN     0x8000
+
+void frontlight_set(struct locomo *lchip, int duty, int vr, int bpwf)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&lchip->lock, flags);
+       locomo_writel(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
+       udelay(100);
+       locomo_writel(duty, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
+       locomo_writel(bpwf | LCM_ALC_EN, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
+       spin_unlock_irqrestore(&lchip->lock, flags);
+}
+
+
 /**
  *     locomo_probe - probe for a single LoCoMo chip.
  *     @phys_addr: physical address of device.
@@ -688,6 +704,11 @@ __locomo_probe(struct device *me, struct resource *mem, int irq)
        /* FrontLight */
        locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
        locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
+
+       /* Same constants can be used for collie and poodle
+          (depending on CONFIG options in original sharp code)? */
+       frontlight_set(lchip, 163, 0, 148);
+
        /* Longtime timer */
        locomo_writel(0, lchip->base + LOCOMO_LTINT);
        /* SPI */
index 7195add..60cfa7f 100644 (file)
@@ -27,6 +27,8 @@
 
 #include <asm/mach/arch.h>
 
+#include "compat.h"
+
 /*
  * Usage:
  *  - do not go blindly adding fields, add them at the end
diff --git a/arch/arm/kernel/compat.h b/arch/arm/kernel/compat.h
new file mode 100644 (file)
index 0000000..27e61a6
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ *  linux/arch/arm/kernel/compat.h
+ *
+ *  Copyright (C) 2001 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+extern void convert_to_tag_list(struct tag *tags);
+
+extern void squash_mem_tags(struct tag *tag);
index 4b4e4cf..489c069 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/kallsyms.h>
 #include <linux/init.h>
 #include <linux/cpu.h>
+#include <linux/elfcore.h>
 
 #include <asm/leds.h>
 #include <asm/processor.h>
@@ -83,7 +84,7 @@ EXPORT_SYMBOL(pm_power_off);
  * This is our default idle handler.  We need to disable
  * interrupts here to ensure we don't miss a wakeup call.
  */
-void default_idle(void)
+static void default_idle(void)
 {
        if (hlt_counter)
                cpu_relax();
index bc9e2f8..a1d1b29 100644 (file)
@@ -628,7 +628,7 @@ static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp)
        if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT))
                return -EACCES;
        iwmmxt_task_release(thread);  /* force a reload */
-       return copy_from_user(&thead->fpstate.iwmmxt, ufp, IWMMXT_SIZE)
+       return copy_from_user(&thread->fpstate.iwmmxt, ufp, IWMMXT_SIZE)
                ? -EFAULT : 0;
 }
 
index 68273b4..08974cb 100644 (file)
@@ -37,6 +37,8 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
+#include "compat.h"
+
 #ifndef MEM_SIZE
 #define MEM_SIZE       (16*1024*1024)
 #endif
@@ -53,10 +55,7 @@ static int __init fpe_setup(char *line)
 __setup("fpe=", fpe_setup);
 #endif
 
-extern unsigned int mem_fclk_21285;
 extern void paging_init(struct meminfo *, struct machine_desc *desc);
-extern void convert_to_tag_list(struct tag *tags);
-extern void squash_mem_tags(struct tag *tag);
 extern void reboot_setup(char *str);
 extern int root_mountflags;
 extern void _stext, _text, _etext, __data_start, _edata, _end;
index 0a47d38..ca09ba5 100644 (file)
@@ -334,11 +334,17 @@ static struct resource s3c_spi0_resource[] = {
 
 };
 
+static u64 s3c_device_spi0_dmamask = 0xffffffffUL;
+
 struct platform_device s3c_device_spi0 = {
        .name             = "s3c2410-spi",
        .id               = 0,
        .num_resources    = ARRAY_SIZE(s3c_spi0_resource),
        .resource         = s3c_spi0_resource,
+        .dev              = {
+                .dma_mask = &s3c_device_spi0_dmamask,
+                .coherent_dma_mask = 0xffffffffUL
+        }
 };
 
 EXPORT_SYMBOL(s3c_device_spi0);
@@ -359,11 +365,17 @@ static struct resource s3c_spi1_resource[] = {
 
 };
 
+static u64 s3c_device_spi1_dmamask = 0xffffffffUL;
+
 struct platform_device s3c_device_spi1 = {
        .name             = "s3c2410-spi",
        .id               = 1,
        .num_resources    = ARRAY_SIZE(s3c_spi1_resource),
        .resource         = s3c_spi1_resource,
+        .dev              = {
+                .dma_mask = &s3c_device_spi1_dmamask,
+                .coherent_dma_mask = 0xffffffffUL
+        }
 };
 
 EXPORT_SYMBOL(s3c_device_spi1);
index eba7f53..7007e17 100644 (file)
@@ -1029,6 +1029,16 @@ int __devinit smp_prepare_cpu(int cpu)
        int     apicid, ret;
 
        lock_cpu_hotplug();
+
+       /*
+        * On x86, CPU0 is never offlined.  Trying to bring up an
+        * already-booted CPU will hang.  So check for that case.
+        */
+       if (cpu_online(cpu)) {
+               ret = -EINVAL;
+               goto exit;
+       }
+
        apicid = x86_cpu_to_apicid[cpu];
        if (apicid == BAD_APICID) {
                ret = -ENODEV;
index fe9da16..3d8dac6 100644 (file)
@@ -108,7 +108,8 @@ MODFLAGS                    += -mlong-calls
 cflags-$(CONFIG_CPU_BIG_ENDIAN)                += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB)
 cflags-$(CONFIG_CPU_LITTLE_ENDIAN)     += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL)
 
-cflags-$(CONFIG_SB1XXX_CORELIS)        += -mno-sched-prolog -fno-omit-frame-pointer
+cflags-$(CONFIG_SB1XXX_CORELIS)        += $(call cc-option,-mno-sched-prolog) \
+                                  -fno-omit-frame-pointer
 
 #
 # Use: $(call set_gccflags,<cpu0>,<isa0>,<cpu1>,<isa1>,<isa2>)
index 84867de..b2e10b9 100644 (file)
@@ -9,7 +9,6 @@
  * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
  * Copyright (C) 1999 Silicon Graphics, Inc.
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 
 #include <asm/bootinfo.h>
 #include <asm/system.h>
 
-extern void *sgiwd93_host;
-extern void reset_wd33c93(void *instance);
-
 VOID
 ArcHalt(VOID)
 {
        bc_disable();
        local_irq_disable();
-#ifdef CONFIG_SCSI_SGIWD93
-       reset_wd33c93(sgiwd93_host);
-#endif
        ARC_CALL0(halt);
 never: goto never;
 }
@@ -40,9 +33,6 @@ ArcPowerDown(VOID)
 {
        bc_disable();
        local_irq_disable();
-#ifdef CONFIG_SCSI_SGIWD93
-       reset_wd33c93(sgiwd93_host);
-#endif
        ARC_CALL0(pdown);
 never: goto never;
 }
@@ -53,9 +43,6 @@ ArcRestart(VOID)
 {
        bc_disable();
        local_irq_disable();
-#ifdef CONFIG_SCSI_SGIWD93
-       reset_wd33c93(sgiwd93_host);
-#endif
        ARC_CALL0(restart);
 never: goto never;
 }
@@ -65,9 +52,6 @@ ArcReboot(VOID)
 {
        bc_disable();
        local_irq_disable();
-#ifdef CONFIG_SCSI_SGIWD93
-       reset_wd33c93(sgiwd93_host);
-#endif
        ARC_CALL0(reboot);
 never: goto never;
 }
@@ -77,9 +61,6 @@ ArcEnterInteractiveMode(VOID)
 {
        bc_disable();
        local_irq_disable();
-#ifdef CONFIG_SCSI_SGIWD93
-       reset_wd33c93(sgiwd93_host);
-#endif
        ARC_CALL0(imode);
 never: goto never;
 }
index 4ffcced..c93af22 100644 (file)
@@ -164,17 +164,20 @@ void au1000_restart(char *command)
 
 void au1000_halt(void)
 {
-#if defined(CONFIG_MIPS_PB1550)
+#if defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_DB1550)
        /* power off system */
-       printk("\n** Powering off Pb1550\n");
+       printk("\n** Powering off...\n");
        au_writew(au_readw(0xAF00001C) | (3<<14), 0xAF00001C);
        au_sync();
        while(1); /* should not get here */
-#endif
+#else
        printk(KERN_NOTICE "\n** You can safely turn off the power\n");
 #ifdef CONFIG_MIPS_MIRAGE
        au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT);
 #endif
+#ifdef CONFIG_MIPS_DB1200
+       au_writew(au_readw(0xB980001C) | (1<<14), 0xB980001C);
+#endif
 #ifdef CONFIG_PM
        au_sleep();
 
@@ -187,6 +190,7 @@ void au1000_halt(void)
                        "wait\n\t"
                        ".set\tmips0");
 #endif
+#endif /* defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_DB1550) */
 }
 
 void au1000_power_off(void)
index 42c94c7..51273b7 100644 (file)
@@ -424,6 +424,8 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        unsigned long j;
        unsigned int count;
 
+       write_seqlock(&xtime_lock);
+
        count = mips_hpt_read();
        mips_timer_ack();
 
@@ -441,7 +443,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
         * CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be
         * called as close as possible to 500 ms before the new second starts.
         */
-       write_seqlock(&xtime_lock);
        if (ntp_synced() &&
            xtime.tv_sec > last_rtc_update + 660 &&
            (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
@@ -453,7 +454,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        last_rtc_update = xtime.tv_sec - 600;
                }
        }
-       write_sequnlock(&xtime_lock);
 
        /*
         * If jiffies has overflown in this timer_interrupt, we must
@@ -496,6 +496,8 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                }
        }
 
+       write_sequnlock(&xtime_lock);
+
        /*
         * In UP mode, we call local_timer_interrupt() to do profiling
         * and process accouting.
index 0668e9b..9572ed4 100644 (file)
@@ -375,6 +375,7 @@ static void r4k_flush_cache_mm(struct mm_struct *mm)
 struct flush_cache_page_args {
        struct vm_area_struct *vma;
        unsigned long addr;
+       unsigned long pfn;
 };
 
 static inline void local_r4k_flush_cache_page(void *args)
@@ -382,6 +383,7 @@ static inline void local_r4k_flush_cache_page(void *args)
        struct flush_cache_page_args *fcp_args = args;
        struct vm_area_struct *vma = fcp_args->vma;
        unsigned long addr = fcp_args->addr;
+       unsigned long paddr = fcp_args->pfn << PAGE_SHIFT;
        int exec = vma->vm_flags & VM_EXEC;
        struct mm_struct *mm = vma->vm_mm;
        pgd_t *pgdp;
@@ -431,11 +433,12 @@ static inline void local_r4k_flush_cache_page(void *args)
         * Do indexed flush, too much work to get the (possible) TLB refills
         * to work correctly.
         */
-       addr = INDEX_BASE + (addr & (dcache_size - 1));
        if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
-               r4k_blast_dcache_page_indexed(addr);
-               if (exec && !cpu_icache_snoops_remote_store)
-                       r4k_blast_scache_page_indexed(addr);
+               r4k_blast_dcache_page_indexed(cpu_has_pindexed_dcache ?
+                                             paddr : addr);
+               if (exec && !cpu_icache_snoops_remote_store) {
+                       r4k_blast_scache_page_indexed(paddr);
+               }
        }
        if (exec) {
                if (cpu_has_vtag_icache) {
@@ -455,6 +458,7 @@ static void r4k_flush_cache_page(struct vm_area_struct *vma,
 
        args.vma = vma;
        args.addr = addr;
+       args.pfn = pfn;
 
        on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1);
 }
@@ -956,6 +960,7 @@ static void __init probe_pcache(void)
        switch (c->cputype) {
        case CPU_20KC:
        case CPU_25KF:
+               c->dcache.flags |= MIPS_CACHE_PINDEX;
        case CPU_R10000:
        case CPU_R12000:
        case CPU_SB1:
index 7c572be..fe232e3 100644 (file)
@@ -210,7 +210,6 @@ static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page
         * Do indexed flush, too much work to get the (possible) TLB refills
         * to work correctly.
         */
-       page = (KSEG0 + (page & (dcache_size - 1)));
        if (cpu_has_dc_aliases || exec)
                tx39_blast_dcache_page_indexed(page);
        if (exec)
index 511c89d..1588f6d 100644 (file)
 #define IMR_IP3_VAL    K_INT_MAP_I1
 #define IMR_IP4_VAL    K_INT_MAP_I2
 
+#define SB1250_HPT_NUM         3
+#define SB1250_HPT_VALUE       M_SCD_TIMER_CNT /* max value */
+#define SB1250_HPT_SHIFT       ((sizeof(unsigned int)*8)-V_SCD_TIMER_WIDTH)
+
+
 extern int sb1250_steal_irq(int irq);
 
+static unsigned int sb1250_hpt_read(void);
+static void sb1250_hpt_init(unsigned int);
+
+static unsigned int hpt_offset;
+
+void __init sb1250_hpt_setup(void)
+{
+       int cpu = smp_processor_id();
+
+       if (!cpu) {
+               /* Setup hpt using timer #3 but do not enable irq for it */
+               __raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG)));
+               __raw_writeq(SB1250_HPT_VALUE,
+                            IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_INIT)));
+               __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
+                            IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG)));
+
+               /*
+                * we need to fill 32 bits, so just use the upper 23 bits and pretend
+                * the timer is going 512Mhz instead of 1Mhz
+                */
+               mips_hpt_frequency = V_SCD_TIMER_FREQ << SB1250_HPT_SHIFT;
+               mips_hpt_init = sb1250_hpt_init;
+               mips_hpt_read = sb1250_hpt_read;
+       }
+}
+
+
 void sb1250_time_init(void)
 {
        int cpu = smp_processor_id();
        int irq = K_INT_TIMER_0+cpu;
 
-       /* Only have 4 general purpose timers */
-       if (cpu > 3) {
+       /* Only have 4 general purpose timers, and we use last one as hpt */
+       if (cpu > 2) {
                BUG();
        }
 
-       if (!cpu) {
-               /* Use our own gettimeoffset() routine */
-               do_gettimeoffset = sb1250_gettimeoffset;
-       }
-
        sb1250_mask_irq(cpu, irq);
 
        /* Map the timer interrupt to ip[4] of this cpu */
@@ -75,10 +103,10 @@ void sb1250_time_init(void)
        /* Disable the timer and set up the count */
        __raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
 #ifdef CONFIG_SIMULATION
-       __raw_writeq(50000 / HZ,
+       __raw_writeq((50000 / HZ) - 1,
                     IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
 #else
-       __raw_writeq(1000000 / HZ,
+       __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1,
                     IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
 #endif
 
@@ -103,7 +131,7 @@ void sb1250_timer_interrupt(struct pt_regs *regs)
        int cpu = smp_processor_id();
        int irq = K_INT_TIMER_0 + cpu;
 
-       /* Reset the timer */
+       /* ACK interrupt */
        ____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
                       IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
 
@@ -122,15 +150,26 @@ void sb1250_timer_interrupt(struct pt_regs *regs)
 }
 
 /*
- * We use our own do_gettimeoffset() instead of the generic one,
- * because the generic one does not work for SMP case.
- * In addition, since we use general timer 0 for system time,
- * we can get accurate intra-jiffy offset without calibration.
+ * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over
+ * again. There's no easy way to set to a specific value so store init value
+ * in hpt_offset and subtract each time.
+ *
+ * Note: Timer isn't full 32bits so shift it into the upper part making
+ *       it appear to run at a higher frequency.
  */
-unsigned long sb1250_gettimeoffset(void)
+static unsigned int sb1250_hpt_read(void)
 {
-       unsigned long count =
-               __raw_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)));
+       unsigned int count;
 
-       return 1000000/HZ - count;
- }
+       count = G_SCD_TIMER_CNT(__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CNT))));
+
+       count = (SB1250_HPT_VALUE - count) << SB1250_HPT_SHIFT;
+
+       return count - hpt_offset;
+}
+
+static void sb1250_hpt_init(unsigned int count)
+{
+       hpt_offset = count;
+       return;
+}
index b614ca0..b661d24 100644 (file)
@@ -70,6 +70,12 @@ const char *get_system_type(void)
        return "SiByte " SIBYTE_BOARD_NAME;
 }
 
+void __init swarm_time_init(void)
+{
+       /* Setup HPT */
+       sb1250_hpt_setup();
+}
+
 void __init swarm_timer_setup(struct irqaction *irq)
 {
         /*
@@ -109,6 +115,7 @@ void __init plat_setup(void)
 
        panic_timeout = 5;  /* For debug.  */
 
+       board_time_init = swarm_time_init;
        board_timer_setup = swarm_timer_setup;
        board_be_handler = swarm_be_handler;
 
index a834f9e..dfba817 100644 (file)
@@ -580,7 +580,7 @@ config KEXEC
          strongly in flux, so no good recommendation can be made.
 
 config CRASH_DUMP
-       bool "kernel crash dumps (EXPERIMENTAL)"
+       bool "Build a kdump crash kernel (EXPERIMENTAL)"
        depends on PPC_MULTIPLATFORM && PPC64 && EXPERIMENTAL
        help
          Build a kernel suitable for use as a kdump capture kernel.
index e0192c2..70e65b1 100644 (file)
@@ -45,7 +45,8 @@ _zimage_start:
        bdnz    2b
 
        /* Do a cache flush for our text, in case OF didn't */
-3:     lis     r9,_start@h
+3:     lis     r9,_start@ha
+       addi    r9,r9,_start@l
        add     r9,r0,r9
        lis     r8,_etext@ha
        addi    r8,r8,_etext@l
@@ -53,7 +54,7 @@ _zimage_start:
 4:     dcbf    r0,r9
        icbi    r0,r9
        addi    r9,r9,0x20
-       cmplwi  0,r9,8
+       cmplw   cr0,r9,r8
        blt     4b
        sync
        isync
index 063b84f..3c2acab 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.15-rc5
-# Tue Dec 20 15:59:26 2005
+# Linux kernel version: 2.6.16-rc6
+# Wed Mar 15 16:19:48 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -16,6 +16,10 @@ CONFIG_COMPAT=y
 CONFIG_SYSVIPC_COMPAT=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+# CONFIG_DEFAULT_UIMAGE is not set
 
 #
 # Processor support
@@ -33,7 +37,6 @@ CONFIG_NR_CPUS=4
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -48,8 +51,6 @@ CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_CPUSETS is not set
 CONFIG_INITRAMFS_SOURCE=""
@@ -58,8 +59,10 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -68,8 +71,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -111,7 +116,6 @@ CONFIG_PPC_MULTIPLATFORM=y
 # CONFIG_PPC_PMAC is not set
 # CONFIG_PPC_MAPLE is not set
 CONFIG_PPC_CELL=y
-CONFIG_PPC_OF=y
 # CONFIG_U3_DART is not set
 CONFIG_PPC_RTAS=y
 # CONFIG_RTAS_ERROR_LOGGING is not set
@@ -120,10 +124,14 @@ CONFIG_RTAS_FLASH=y
 CONFIG_MMIO_NVRAM=y
 CONFIG_CELL_IIC=y
 # CONFIG_PPC_MPC106 is not set
-# CONFIG_GENERIC_TBSYNC is not set
 # CONFIG_CPU_FREQ is not set
 # CONFIG_WANT_EARLY_SERIAL is not set
 
+#
+# Cell Broadband Engine options
+#
+CONFIG_SPU_FS=y
+
 #
 # Kernel options
 #
@@ -140,6 +148,7 @@ CONFIG_BINFMT_ELF=y
 CONFIG_FORCE_MAX_ZONEORDER=13
 # CONFIG_IOMMU_VMERGE is not set
 CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
 CONFIG_IRQ_ALL_CPUS=y
 # CONFIG_NUMA is not set
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
@@ -191,6 +200,7 @@ CONFIG_NET=y
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -234,6 +244,25 @@ CONFIG_NETFILTER=y
 # Core Netfilter Configuration
 #
 # CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 
 #
 # IP: Netfilter Configuration
@@ -251,37 +280,23 @@ CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_PPTP is not set
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
 CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
 CONFIG_IP_NF_MATCH_RECENT=m
 CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_DSCP=m
 CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
 CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_REALM=m
-CONFIG_IP_NF_MATCH_SCTP=m
-# CONFIG_IP_NF_MATCH_DCCP is not set
-CONFIG_IP_NF_MATCH_COMMENT=m
 CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_STRING=m
+CONFIG_IP_NF_MATCH_POLICY=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_TARGET_NFQUEUE=m
 CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -297,11 +312,8 @@ CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_CLASSIFY=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
@@ -311,7 +323,6 @@ CONFIG_IP_NF_ARP_MANGLE=m
 #
 # CONFIG_IP6_NF_QUEUE is not set
 # CONFIG_IP6_NF_IPTABLES is not set
-# CONFIG_IP6_NF_TARGET_NFQUEUE is not set
 
 #
 # DCCP Configuration (EXPERIMENTAL)
@@ -322,6 +333,11 @@ CONFIG_IP_NF_ARP_MANGLE=m
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -540,9 +556,11 @@ CONFIG_E1000=m
 # CONFIG_R8169 is not set
 # CONFIG_SIS190 is not set
 CONFIG_SKGE=m
+# CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_SPIDER_NET=y
 # CONFIG_MV643XX_ETH is not set
 
 #
@@ -628,13 +646,16 @@ CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
 CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
 # CONFIG_ROCKETPORT is not set
 # CONFIG_CYCLADES is not set
 # CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
 # CONFIG_MOXA_SMARTIO is not set
 # CONFIG_ISI is not set
 # CONFIG_SYNCLINK is not set
 # CONFIG_SYNCLINKMP is not set
+# CONFIG_SYNCLINK_GT is not set
 # CONFIG_N_HDLC is not set
 # CONFIG_SPECIALIX is not set
 # CONFIG_SX is not set
@@ -646,6 +667,7 @@ CONFIG_SERIAL_NONSTANDARD=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
@@ -755,6 +777,12 @@ CONFIG_I2C_ALGOBIT=y
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
 #
 # Dallas's 1-wire bus
 #
@@ -827,7 +855,7 @@ CONFIG_USB_ARCH_HAS_OHCI=y
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
@@ -847,6 +875,7 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
@@ -886,6 +915,7 @@ CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
 # CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -951,6 +981,7 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
 CONFIG_EFI_PARTITION=y
 
 #
@@ -1021,18 +1052,20 @@ CONFIG_TEXTSEARCH_FSM=m
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=15
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_MUTEXES is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
+# CONFIG_FORCED_INLINING is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
@@ -1040,6 +1073,11 @@ CONFIG_DEBUGGER=y
 # CONFIG_XMON is not set
 CONFIG_IRQSTACKS=y
 # CONFIG_BOOTX_TEXT is not set
+# 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
 
 #
 # Security options
index c775027..1816a46 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.15-rc5
-# Tue Dec 20 15:59:32 2005
+# Linux kernel version: 2.6.16-rc6
+# Wed Mar 15 16:19:52 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -16,6 +16,10 @@ CONFIG_COMPAT=y
 CONFIG_SYSVIPC_COMPAT=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+# CONFIG_PPC_UDBG_16550 is not set
+# CONFIG_GENERIC_TBSYNC is not set
+# CONFIG_DEFAULT_UIMAGE is not set
 
 #
 # Processor support
@@ -33,7 +37,6 @@ CONFIG_NR_CPUS=32
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -49,8 +52,6 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_SYSCTL=y
 CONFIG_AUDIT=y
 CONFIG_AUDITSYSCALL=y
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
@@ -60,8 +61,10 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -70,8 +73,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -113,7 +118,6 @@ CONFIG_PPC_ISERIES=y
 # CONFIG_MMIO_NVRAM is not set
 CONFIG_IBMVIO=y
 # CONFIG_PPC_MPC106 is not set
-# CONFIG_GENERIC_TBSYNC is not set
 # CONFIG_CPU_FREQ is not set
 # CONFIG_WANT_EARLY_SERIAL is not set
 
@@ -183,6 +187,7 @@ CONFIG_NET=y
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -220,6 +225,28 @@ CONFIG_NETFILTER=y
 # Core Netfilter Configuration
 #
 # CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 
 #
 # IP: Netfilter Configuration
@@ -237,39 +264,23 @@ CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_PPTP is not set
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
 CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
 CONFIG_IP_NF_MATCH_RECENT=m
 CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_DSCP=m
 CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
 CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_REALM=m
-CONFIG_IP_NF_MATCH_SCTP=m
-# CONFIG_IP_NF_MATCH_DCCP is not set
-CONFIG_IP_NF_MATCH_COMMENT=m
-CONFIG_IP_NF_MATCH_CONNMARK=m
-CONFIG_IP_NF_MATCH_CONNBYTES=m
 CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_STRING=m
+CONFIG_IP_NF_MATCH_POLICY=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_TARGET_NFQUEUE=m
 CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -285,13 +296,9 @@ CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_CLASSIFY=m
 CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_TARGET_CONNMARK=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
@@ -305,6 +312,11 @@ CONFIG_IP_NF_ARP_MANGLE=m
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -451,13 +463,7 @@ CONFIG_SCSI_IBMVSCSI=m
 # CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -574,6 +580,7 @@ CONFIG_E1000=m
 # CONFIG_R8169 is not set
 # CONFIG_SIS190 is not set
 # CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
@@ -722,6 +729,12 @@ CONFIG_MAX_RAW_DEVS=256
 #
 # CONFIG_I2C is not set
 
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
 #
 # Dallas's 1-wire bus
 #
@@ -788,7 +801,7 @@ CONFIG_USB_ARCH_HAS_OHCI=y
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
@@ -825,6 +838,7 @@ CONFIG_XFS_EXPORT=y
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
 # CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
@@ -865,6 +879,7 @@ CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -993,31 +1008,36 @@ CONFIG_TEXTSEARCH_FSM=m
 #
 # Instrumentation Support
 #
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
 # CONFIG_KPROBES is not set
 
 #
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+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_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
+# CONFIG_FORCED_INLINING is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 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
 
 #
 # Security options
index 68194c0..80a0db4 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.15-rc5
-# Tue Dec 20 15:59:36 2005
+# Linux kernel version: 2.6.16-rc6
+# Wed Mar 15 16:19:54 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -16,6 +16,10 @@ CONFIG_COMPAT=y
 CONFIG_SYSVIPC_COMPAT=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_PPC_UDBG_16550=y
+CONFIG_GENERIC_TBSYNC=y
+# CONFIG_DEFAULT_UIMAGE is not set
 
 #
 # Processor support
@@ -32,7 +36,6 @@ CONFIG_NR_CPUS=2
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -47,8 +50,6 @@ CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
@@ -58,8 +59,10 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -68,8 +71,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -111,14 +116,12 @@ CONFIG_PPC_MULTIPLATFORM=y
 # CONFIG_PPC_PMAC is not set
 CONFIG_PPC_MAPLE=y
 # CONFIG_PPC_CELL is not set
-CONFIG_PPC_OF=y
 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_GENERIC_TBSYNC=y
 # CONFIG_CPU_FREQ is not set
 # CONFIG_WANT_EARLY_SERIAL is not set
 
@@ -138,6 +141,7 @@ CONFIG_BINFMT_ELF=y
 CONFIG_FORCE_MAX_ZONEORDER=13
 CONFIG_IOMMU_VMERGE=y
 CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
 CONFIG_IRQ_ALL_CPUS=y
 # CONFIG_NUMA is not set
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
@@ -189,6 +193,7 @@ CONFIG_NET=y
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -226,6 +231,11 @@ CONFIG_TCP_CONG_BIC=y
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -461,6 +471,7 @@ CONFIG_E1000=y
 # CONFIG_R8169 is not set
 # CONFIG_SIS190 is not set
 # CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
@@ -553,6 +564,7 @@ CONFIG_HW_CONSOLE=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
@@ -650,6 +662,12 @@ CONFIG_I2C_AMD8111=y
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
 #
 # Dallas's 1-wire bus
 #
@@ -738,12 +756,14 @@ CONFIG_USB_UHCI_HCD=y
 # may also be needed; see USB_STORAGE Help for more information
 #
 # CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Input Devices
 #
 CONFIG_USB_HID=y
 CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 # CONFIG_USB_HIDDEV is not set
 # CONFIG_USB_AIPTEK is not set
@@ -757,6 +777,7 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
 
@@ -797,6 +818,7 @@ CONFIG_USB_SERIAL_GENERIC=y
 # CONFIG_USB_SERIAL_AIRPRIME is not set
 # CONFIG_USB_SERIAL_ANYDATA is not set
 # CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
 # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
 # CONFIG_USB_SERIAL_CP2101 is not set
 CONFIG_USB_SERIAL_CYPRESS_M8=m
@@ -873,7 +895,7 @@ CONFIG_USB_EZUSB=y
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
@@ -891,6 +913,7 @@ CONFIG_JBD=y
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
@@ -927,6 +950,7 @@ CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
 # CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -988,6 +1012,7 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 
 #
@@ -1053,18 +1078,20 @@ CONFIG_ZLIB_INFLATE=y
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_MUTEXES is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
+# CONFIG_FORCED_INLINING is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
@@ -1073,6 +1100,11 @@ CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
 # CONFIG_IRQSTACKS is not set
 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
 
 #
 # Security options
index 3bff761..5078b04 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.15-g461d4edf-dirty
-# Fri Jan 13 11:01:47 2006
+# Linux kernel version: 2.6.16-rc6
+# Wed Mar 15 16:19:56 2006
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -43,7 +43,6 @@ CONFIG_PPC_STD_MMU_32=y
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -189,6 +188,7 @@ CONFIG_NET=y
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -226,6 +226,11 @@ CONFIG_TCP_CONG_BIC=y
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -511,6 +516,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -614,6 +620,12 @@ CONFIG_I2C_MPC=y
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
 #
 # Dallas's 1-wire bus
 #
@@ -632,6 +644,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_ATXP1 is not set
 # CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_FSCPOS is not set
 # CONFIG_SENSORS_GL518SM is not set
@@ -716,7 +729,7 @@ CONFIG_USB_ARCH_HAS_OHCI=y
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
@@ -826,6 +839,7 @@ CONFIG_PARTITION_ADVANCED=y
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 
 #
@@ -899,13 +913,3 @@ CONFIG_CRYPTO_DES=y
 #
 # Hardware crypto devices
 #
-
-#
-# SEC2.x Options
-#
-CONFIG_MPC8349E_SEC2x=y
-
-#
-# SEC2.x Test Options
-#
-CONFIG_MPC8349E_SEC2xTEST=y
index 2ace57d..57a0279 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.15
-# Sat Jan 14 16:26:08 2006
+# Linux kernel version: 2.6.16-rc6
+# Wed Mar 15 16:21:32 2006
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -17,8 +17,8 @@ CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 CONFIG_PPC_OF=y
 # CONFIG_PPC_UDBG_16550 is not set
-# CONFIG_CRASH_DUMP is not set
 # CONFIG_GENERIC_TBSYNC is not set
+# CONFIG_DEFAULT_UIMAGE is not set
 
 #
 # Processor support
@@ -43,7 +43,6 @@ CONFIG_PPC_STD_MMU_32=y
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -236,6 +235,7 @@ CONFIG_NET=y
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -271,6 +271,25 @@ CONFIG_NETFILTER=y
 # Core Netfilter Configuration
 #
 # CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 
 #
 # IP: Netfilter Configuration
@@ -288,37 +307,22 @@ CONFIG_IP_NF_AMANDA=m
 CONFIG_IP_NF_PPTP=m
 # CONFIG_IP_NF_QUEUE is not set
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
 CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
 CONFIG_IP_NF_MATCH_RECENT=m
 CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_DSCP=m
 CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
 CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
 CONFIG_IP_NF_MATCH_OWNER=m
-# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
-# CONFIG_IP_NF_MATCH_REALM is not set
-# CONFIG_IP_NF_MATCH_SCTP is not set
-CONFIG_IP_NF_MATCH_DCCP=m
-# CONFIG_IP_NF_MATCH_COMMENT is not set
-# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
-CONFIG_IP_NF_MATCH_STRING=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
-# CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_IP_NF_TARGET_TCPMSS=m
-# CONFIG_IP_NF_TARGET_NFQUEUE is not set
 CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -331,9 +335,12 @@ CONFIG_IP_NF_NAT_FTP=m
 CONFIG_IP_NF_NAT_TFTP=m
 CONFIG_IP_NF_NAT_AMANDA=m
 CONFIG_IP_NF_NAT_PPTP=m
-# CONFIG_IP_NF_MANGLE is not set
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
@@ -360,6 +367,11 @@ CONFIG_IP_DCCP_TFRC_LIB=m
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -377,6 +389,7 @@ CONFIG_IP_DCCP_TFRC_LIB=m
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
 
 #
 # Network testing
@@ -568,7 +581,6 @@ CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
 CONFIG_BLK_DEV_PDC202XX_NEW=y
-# CONFIG_PDC202XX_FORCE is not set
 # CONFIG_BLK_DEV_SVWKS is not set
 # CONFIG_BLK_DEV_SIIMAGE is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
@@ -654,8 +666,7 @@ CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set
+# CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -991,6 +1002,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 #
 CONFIG_SERIAL_CORE=m
 CONFIG_SERIAL_PMACZILOG=m
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -1097,6 +1109,12 @@ CONFIG_I2C_POWERMAC=y
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
 #
 # Dallas's 1-wire bus
 #
@@ -1348,6 +1366,7 @@ CONFIG_USB_PRINTER=m
 #
 CONFIG_USB_HID=y
 CONFIG_USB_HIDINPUT=y
+CONFIG_USB_HIDINPUT_POWERBOOK=y
 # CONFIG_HID_FF is not set
 # CONFIG_USB_HIDDEV is not set
 # CONFIG_USB_AIPTEK is not set
@@ -1488,7 +1507,7 @@ CONFIG_USB_EZUSB=y
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
@@ -1609,6 +1628,7 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 
 #
@@ -1692,6 +1712,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
+# CONFIG_FORCED_INLINING is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
index 0362a70..395e498 100644 (file)
@@ -407,7 +407,7 @@ CONFIG_IDEPCI_SHARE_IRQ=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_SL82C105=y
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
index c367520..ba92bab 100644 (file)
@@ -589,7 +589,6 @@ void __devinit scan_phb(struct pci_controller *hose)
 #endif /* CONFIG_PPC_MULTIPLATFORM */
        if (mode == PCI_PROBE_NORMAL)
                hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
-       pci_bus_add_devices(bus);
 }
 
 static int __init pcibios_init(void)
@@ -608,8 +607,10 @@ static int __init pcibios_init(void)
        printk("PCI: Probing PCI hardware\n");
 
        /* Scan all of the recorded PCI controllers.  */
-       list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
                scan_phb(hose);
+               pci_bus_add_devices(hose->bus);
+       }
 
 #ifndef CONFIG_PPC_ISERIES
        if (pci_probe_only)
index 8a731ea..63ecbec 100644 (file)
@@ -110,15 +110,6 @@ EXPORT_SYMBOL(_insw_ns);
 EXPORT_SYMBOL(_outsw_ns);
 EXPORT_SYMBOL(_insl_ns);
 EXPORT_SYMBOL(_outsl_ns);
-EXPORT_SYMBOL(ioremap);
-#ifdef CONFIG_44x
-EXPORT_SYMBOL(ioremap64);
-#endif
-EXPORT_SYMBOL(__ioremap);
-EXPORT_SYMBOL(iounmap);
-#ifdef CONFIG_PPC32
-EXPORT_SYMBOL(ioremap_bot);    /* aka VMALLOC_END */
-#endif
 
 #if defined(CONFIG_PPC32) && (defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE))
 EXPORT_SYMBOL(ppc_ide_md);
@@ -161,7 +152,6 @@ EXPORT_SYMBOL(__flush_icache_range);
 EXPORT_SYMBOL(flush_dcache_range);
 
 #ifdef CONFIG_SMP
-EXPORT_SYMBOL(smp_call_function);
 #ifdef CONFIG_PPC32
 EXPORT_SYMBOL(smp_hw_index);
 #endif
index 635d3b9..34d073f 100644 (file)
@@ -52,7 +52,7 @@ void rtas_get_rtc_time(struct rtc_time *rtc_tm)
                error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
                if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) {
                        if (in_interrupt() && printk_ratelimit()) {
-                               memset(&rtc_tm, 0, sizeof(struct rtc_time));
+                               memset(rtc_tm, 0, sizeof(struct rtc_time));
                                printk(KERN_WARNING "error: reading clock"
                                       " would delay interrupt\n");
                                return; /* delay not allowed */
index 5579f65..7442775 100644 (file)
@@ -280,8 +280,7 @@ static int phb_set_bus_ranges(struct device_node *dev,
        return 0;
 }
 
-static int __devinit setup_phb(struct device_node *dev,
-                              struct pci_controller *phb)
+int __devinit setup_phb(struct device_node *dev, struct pci_controller *phb)
 {
        if (is_python(dev))
                python_countermeasures(dev);
@@ -359,27 +358,6 @@ unsigned long __init find_and_init_phbs(void)
        return 0;
 }
 
-struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
-{
-       struct pci_controller *phb;
-       int primary;
-
-       primary = list_empty(&hose_list);
-       phb = pcibios_alloc_controller(dn);
-       if (!phb)
-               return NULL;
-       setup_phb(dn, phb);
-       pci_process_bridge_OF_ranges(phb, dn, primary);
-
-       pci_setup_phb_io_dynamic(phb, primary);
-
-       pci_devs_phb_init_dynamic(phb);
-       scan_phb(phb);
-
-       return phb;
-}
-EXPORT_SYMBOL(init_phb_dynamic);
-
 /* RPA-specific bits for removing PHBs */
 int pcibios_remove_root_bus(struct pci_controller *phb)
 {
index 2a7ddc5..86f7e3d 100644 (file)
@@ -283,9 +283,9 @@ static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec,
         * the two values of tb_update_count match and are even then the
         * tb_to_xs and stamp_xsec values are consistent.  If not, then it
         * loops back and reads them again until this criteria is met.
+        * We expect the caller to have done the first increment of
+        * vdso_data->tb_update_count already.
         */
-       ++(vdso_data->tb_update_count);
-       smp_wmb();
        vdso_data->tb_orig_stamp = new_tb_stamp;
        vdso_data->stamp_xsec = new_stamp_xsec;
        vdso_data->tb_to_xs = new_tb_to_xs;
@@ -310,20 +310,15 @@ static __inline__ void timer_recalc_offset(u64 cur_tb)
        unsigned long offset;
        u64 new_stamp_xsec;
        u64 tlen, t2x;
+       u64 tb, xsec_old, xsec_new;
+       struct gettimeofday_vars *varp;
 
        if (__USE_RTC())
                return;
        tlen = current_tick_length();
        offset = cur_tb - do_gtod.varp->tb_orig_stamp;
-       if (tlen == last_tick_len && offset < 0x80000000u) {
-               /* check that we're still in sync; if not, resync */
-               struct timeval tv;
-               __do_gettimeofday(&tv, cur_tb);
-               if (tv.tv_sec <= xtime.tv_sec &&
-                   (tv.tv_sec < xtime.tv_sec ||
-                    tv.tv_usec * 1000 <= xtime.tv_nsec))
-                       return;
-       }
+       if (tlen == last_tick_len && offset < 0x80000000u)
+               return;
        if (tlen != last_tick_len) {
                t2x = mulhdu(tlen << TICKLEN_SHIFT, ticklen_to_xs);
                last_tick_len = tlen;
@@ -332,6 +327,21 @@ static __inline__ void timer_recalc_offset(u64 cur_tb)
        new_stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC;
        do_div(new_stamp_xsec, 1000000000);
        new_stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC;
+
+       ++vdso_data->tb_update_count;
+       smp_mb();
+
+       /*
+        * Make sure time doesn't go backwards for userspace gettimeofday.
+        */
+       tb = get_tb();
+       varp = do_gtod.varp;
+       xsec_old = mulhdu(tb - varp->tb_orig_stamp, varp->tb_to_xs)
+               + varp->stamp_xsec;
+       xsec_new = mulhdu(tb - cur_tb, t2x) + new_stamp_xsec;
+       if (xsec_new < xsec_old)
+               new_stamp_xsec += xsec_old - xsec_new;
+
        update_gtod(cur_tb, new_stamp_xsec, t2x);
 }
 
@@ -564,6 +574,10 @@ int do_settimeofday(struct timespec *tv)
        }
 #endif
 
+       /* Make userspace gettimeofday spin until we're done. */
+       ++vdso_data->tb_update_count;
+       smp_mb();
+
        /*
         * Subtract off the number of nanoseconds since the
         * beginning of the last tick.
@@ -724,10 +738,16 @@ void __init time_init(void)
         * It is computed as:
         * ticklen_to_xs = 2^N / (tb_ticks_per_jiffy * 1e9)
         * where N = 64 + 20 - TICKLEN_SCALE - TICKLEN_SHIFT
-        * so as to give the result as a 0.64 fixed-point fraction.
+        * which turns out to be N = 51 - SHIFT_HZ.
+        * This gives the result as a 0.64 fixed-point fraction.
+        * That value is reduced by an offset amounting to 1 xsec per
+        * 2^31 timebase ticks to avoid problems with time going backwards
+        * by 1 xsec when we do timer_recalc_offset due to losing the
+        * fractional xsec.  That offset is equal to ppc_tb_freq/2^51
+        * since there are 2^20 xsec in a second.
         */
-       div128_by_32(1ULL << (64 + 20 - TICKLEN_SCALE - TICKLEN_SHIFT), 0,
-                    tb_ticks_per_jiffy, &res);
+       div128_by_32((1ULL << 51) - ppc_tb_freq, 0,
+                    tb_ticks_per_jiffy << SHIFT_HZ, &res);
        div128_by_32(res.result_high, res.result_low, NSEC_PER_SEC, &res);
        ticklen_to_xs = res.result_low;
 
index f4e5ac1..d296eb6 100644 (file)
@@ -37,6 +37,7 @@
 
 unsigned long ioremap_base;
 unsigned long ioremap_bot;
+EXPORT_SYMBOL(ioremap_bot);    /* aka VMALLOC_END */
 int io_bat_index;
 
 #if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
@@ -153,6 +154,7 @@ ioremap64(unsigned long long addr, unsigned long size)
 {
        return __ioremap(addr, size, _PAGE_NO_CACHE);
 }
+EXPORT_SYMBOL(ioremap64);
 
 void __iomem *
 ioremap(phys_addr_t addr, unsigned long size)
@@ -162,6 +164,7 @@ ioremap(phys_addr_t addr, unsigned long size)
        return ioremap64(addr64, size);
 }
 #endif /* CONFIG_PHYS_64BIT */
+EXPORT_SYMBOL(ioremap);
 
 void __iomem *
 __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags)
@@ -247,6 +250,7 @@ __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags)
 out:
        return (void __iomem *) (v + ((unsigned long)addr & ~PAGE_MASK));
 }
+EXPORT_SYMBOL(__ioremap);
 
 void iounmap(volatile void __iomem *addr)
 {
@@ -259,6 +263,7 @@ void iounmap(volatile void __iomem *addr)
        if (addr > high_memory && (unsigned long) addr < ioremap_bot)
                vunmap((void *) (PAGE_MASK & (unsigned long)addr));
 }
+EXPORT_SYMBOL(iounmap);
 
 void __iomem *ioport_map(unsigned long port, unsigned int len)
 {
index 34714d3..bbe7948 100644 (file)
@@ -2491,9 +2491,7 @@ found:
                        pmac_mb.model_id = PMAC_TYPE_COMET;
                iounmap(mach_id_ptr);
        }
-#endif /* CONFIG_POWER4 */
 
-#ifdef CONFIG_6xx
        /* Set default value of powersave_nap on machines that support it.
         * It appears that uninorth rev 3 has a problem with it, we don't
         * enable it on those. In theory, the flush-on-lock property is
@@ -2522,10 +2520,11 @@ found:
         * NAP mode
         */
        powersave_lowspeed = 1;
-#endif /* CONFIG_6xx */
-#ifdef CONFIG_POWER4
+
+#else /* CONFIG_POWER4 */
        powersave_nap = 1;
-#endif
+#endif  /* CONFIG_POWER4 */
+
        /* Check for "mobile" machine */
        if (model && (strncmp(model, "PowerBook", 9) == 0
                   || strncmp(model, "iBook", 5) == 0))
index 1955462..29c2946 100644 (file)
@@ -621,10 +621,6 @@ static void __init pmac_init_early(void)
        /* Probe motherboard chipset */
        pmac_feature_init();
 
-       /* We can NAP */
-       powersave_nap = 1;
-       printk(KERN_INFO "Using native/NAP idle loop\n");
-
        /* Initialize debug stuff */
        udbg_scc_init(!!strstr(cmd_line, "sccdbg"));
        udbg_adb_init(!!strstr(cmd_line, "btextdbg"));
index 4e5c8f8..a57032c 100644 (file)
@@ -19,7 +19,7 @@ config SCANLOG
        depends on RTAS_PROC && PPC_PSERIES
 
 config LPARCFG
-       tristate "LPAR Configuration Data"
+       bool "LPAR Configuration Data"
        depends on PPC_PSERIES || PPC_ISERIES
        help
        Provide system capacity information via human readable
index f3bad90..44abdeb 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <linux/pci.h>
 #include <asm/pci-bridge.h>
+#include <asm/ppc-pci.h>
 
 static struct pci_bus *
 find_bus_among_children(struct pci_bus *bus,
@@ -179,3 +180,30 @@ pcibios_add_pci_devices(struct pci_bus * bus)
        }
 }
 EXPORT_SYMBOL_GPL(pcibios_add_pci_devices);
+
+struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
+{
+       struct pci_controller *phb;
+       int primary;
+
+       primary = list_empty(&hose_list);
+       phb = pcibios_alloc_controller(dn);
+       if (!phb)
+               return NULL;
+       setup_phb(dn, phb);
+       pci_process_bridge_OF_ranges(phb, dn, 0);
+
+       pci_setup_phb_io_dynamic(phb, primary);
+
+       pci_devs_phb_init_dynamic(phb);
+
+       if (dn->child)
+               eeh_add_device_tree_early(dn);
+
+       scan_phb(phb);
+       pcibios_fixup_new_pci_devices(phb->bus, 0);
+       pci_bus_add_devices(phb->bus);
+
+       return phb;
+}
+EXPORT_SYMBOL_GPL(init_phb_dynamic);
index 50039a2..f945416 100644 (file)
@@ -319,11 +319,10 @@ static void __init hdpu_fixup_eth_pdata(struct platform_device *pd)
        struct mv643xx_eth_platform_data *eth_pd;
        eth_pd = pd->dev.platform_data;
 
-       eth_pd->port_serial_control =
-           mv64x60_read(&bh, MV643XX_ETH_PORT_SERIAL_CONTROL_REG(pd->id) & ~1);
-
        eth_pd->force_phy_addr = 1;
        eth_pd->phy_addr = pd->id;
+       eth_pd->speed = SPEED_100;
+       eth_pd->duplex = DUPLEX_FULL;
        eth_pd->tx_queue_size = 400;
        eth_pd->rx_queue_size = 800;
 }
index 8da3cf6..296708c 100644 (file)
@@ -182,6 +182,9 @@ struct as_rq {
 
 static kmem_cache_t *arq_pool;
 
+static atomic_t ioc_count = ATOMIC_INIT(0);
+static struct completion *ioc_gone;
+
 static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq);
 static void as_antic_stop(struct as_data *ad);
 
@@ -193,6 +196,15 @@ static void as_antic_stop(struct as_data *ad);
 static void free_as_io_context(struct as_io_context *aic)
 {
        kfree(aic);
+       if (atomic_dec_and_test(&ioc_count) && ioc_gone)
+               complete(ioc_gone);
+}
+
+static void as_trim(struct io_context *ioc)
+{
+       if (ioc->aic)
+               free_as_io_context(ioc->aic);
+       ioc->aic = NULL;
 }
 
 /* Called when the task exits */
@@ -220,6 +232,7 @@ static struct as_io_context *alloc_as_io_context(void)
                ret->seek_total = 0;
                ret->seek_samples = 0;
                ret->seek_mean = 0;
+               atomic_inc(&ioc_count);
        }
 
        return ret;
@@ -1696,11 +1709,6 @@ static int as_init_queue(request_queue_t *q, elevator_t *e)
 /*
  * sysfs parts below
  */
-struct as_fs_entry {
-       struct attribute attr;
-       ssize_t (*show)(struct as_data *, char *);
-       ssize_t (*store)(struct as_data *, const char *, size_t);
-};
 
 static ssize_t
 as_var_show(unsigned int var, char *page)
@@ -1717,8 +1725,9 @@ as_var_store(unsigned long *var, const char *page, size_t count)
        return count;
 }
 
-static ssize_t as_est_show(struct as_data *ad, char *page)
+static ssize_t est_time_show(elevator_t *e, char *page)
 {
+       struct as_data *ad = e->elevator_data;
        int pos = 0;
 
        pos += sprintf(page+pos, "%lu %% exit probability\n",
@@ -1734,21 +1743,23 @@ static ssize_t as_est_show(struct as_data *ad, char *page)
 }
 
 #define SHOW_FUNCTION(__FUNC, __VAR)                           \
-static ssize_t __FUNC(struct as_data *ad, char *page)          \
+static ssize_t __FUNC(elevator_t *e, char *page)               \
 {                                                              \
+       struct as_data *ad = e->elevator_data;                  \
        return as_var_show(jiffies_to_msecs((__VAR)), (page));  \
 }
-SHOW_FUNCTION(as_readexpire_show, ad->fifo_expire[REQ_SYNC]);
-SHOW_FUNCTION(as_writeexpire_show, ad->fifo_expire[REQ_ASYNC]);
-SHOW_FUNCTION(as_anticexpire_show, ad->antic_expire);
-SHOW_FUNCTION(as_read_batchexpire_show, ad->batch_expire[REQ_SYNC]);
-SHOW_FUNCTION(as_write_batchexpire_show, ad->batch_expire[REQ_ASYNC]);
+SHOW_FUNCTION(as_read_expire_show, ad->fifo_expire[REQ_SYNC]);
+SHOW_FUNCTION(as_write_expire_show, ad->fifo_expire[REQ_ASYNC]);
+SHOW_FUNCTION(as_antic_expire_show, ad->antic_expire);
+SHOW_FUNCTION(as_read_batch_expire_show, ad->batch_expire[REQ_SYNC]);
+SHOW_FUNCTION(as_write_batch_expire_show, ad->batch_expire[REQ_ASYNC]);
 #undef SHOW_FUNCTION
 
 #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX)                                \
-static ssize_t __FUNC(struct as_data *ad, const char *page, size_t count)      \
+static ssize_t __FUNC(elevator_t *e, const char *page, size_t count)   \
 {                                                                      \
-       int ret = as_var_store(__PTR, (page), count);           \
+       struct as_data *ad = e->elevator_data;                          \
+       int ret = as_var_store(__PTR, (page), count);                   \
        if (*(__PTR) < (MIN))                                           \
                *(__PTR) = (MIN);                                       \
        else if (*(__PTR) > (MAX))                                      \
@@ -1756,90 +1767,26 @@ static ssize_t __FUNC(struct as_data *ad, const char *page, size_t count)       \
        *(__PTR) = msecs_to_jiffies(*(__PTR));                          \
        return ret;                                                     \
 }
-STORE_FUNCTION(as_readexpire_store, &ad->fifo_expire[REQ_SYNC], 0, INT_MAX);
-STORE_FUNCTION(as_writeexpire_store, &ad->fifo_expire[REQ_ASYNC], 0, INT_MAX);
-STORE_FUNCTION(as_anticexpire_store, &ad->antic_expire, 0, INT_MAX);
-STORE_FUNCTION(as_read_batchexpire_store,
+STORE_FUNCTION(as_read_expire_store, &ad->fifo_expire[REQ_SYNC], 0, INT_MAX);
+STORE_FUNCTION(as_write_expire_store, &ad->fifo_expire[REQ_ASYNC], 0, INT_MAX);
+STORE_FUNCTION(as_antic_expire_store, &ad->antic_expire, 0, INT_MAX);
+STORE_FUNCTION(as_read_batch_expire_store,
                        &ad->batch_expire[REQ_SYNC], 0, INT_MAX);
-STORE_FUNCTION(as_write_batchexpire_store,
+STORE_FUNCTION(as_write_batch_expire_store,
                        &ad->batch_expire[REQ_ASYNC], 0, INT_MAX);
 #undef STORE_FUNCTION
 
-static struct as_fs_entry as_est_entry = {
-       .attr = {.name = "est_time", .mode = S_IRUGO },
-       .show = as_est_show,
-};
-static struct as_fs_entry as_readexpire_entry = {
-       .attr = {.name = "read_expire", .mode = S_IRUGO | S_IWUSR },
-       .show = as_readexpire_show,
-       .store = as_readexpire_store,
-};
-static struct as_fs_entry as_writeexpire_entry = {
-       .attr = {.name = "write_expire", .mode = S_IRUGO | S_IWUSR },
-       .show = as_writeexpire_show,
-       .store = as_writeexpire_store,
-};
-static struct as_fs_entry as_anticexpire_entry = {
-       .attr = {.name = "antic_expire", .mode = S_IRUGO | S_IWUSR },
-       .show = as_anticexpire_show,
-       .store = as_anticexpire_store,
-};
-static struct as_fs_entry as_read_batchexpire_entry = {
-       .attr = {.name = "read_batch_expire", .mode = S_IRUGO | S_IWUSR },
-       .show = as_read_batchexpire_show,
-       .store = as_read_batchexpire_store,
-};
-static struct as_fs_entry as_write_batchexpire_entry = {
-       .attr = {.name = "write_batch_expire", .mode = S_IRUGO | S_IWUSR },
-       .show = as_write_batchexpire_show,
-       .store = as_write_batchexpire_store,
-};
-
-static struct attribute *default_attrs[] = {
-       &as_est_entry.attr,
-       &as_readexpire_entry.attr,
-       &as_writeexpire_entry.attr,
-       &as_anticexpire_entry.attr,
-       &as_read_batchexpire_entry.attr,
-       &as_write_batchexpire_entry.attr,
-       NULL,
-};
-
-#define to_as(atr) container_of((atr), struct as_fs_entry, attr)
-
-static ssize_t
-as_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
-{
-       elevator_t *e = container_of(kobj, elevator_t, kobj);
-       struct as_fs_entry *entry = to_as(attr);
-
-       if (!entry->show)
-               return -EIO;
-
-       return entry->show(e->elevator_data, page);
-}
-
-static ssize_t
-as_attr_store(struct kobject *kobj, struct attribute *attr,
-                   const char *page, size_t length)
-{
-       elevator_t *e = container_of(kobj, elevator_t, kobj);
-       struct as_fs_entry *entry = to_as(attr);
-
-       if (!entry->store)
-               return -EIO;
-
-       return entry->store(e->elevator_data, page, length);
-}
-
-static struct sysfs_ops as_sysfs_ops = {
-       .show   = as_attr_show,
-       .store  = as_attr_store,
-};
-
-static struct kobj_type as_ktype = {
-       .sysfs_ops      = &as_sysfs_ops,
-       .default_attrs  = default_attrs,
+#define AS_ATTR(name) \
+       __ATTR(name, S_IRUGO|S_IWUSR, as_##name##_show, as_##name##_store)
+
+static struct elv_fs_entry as_attrs[] = {
+       __ATTR_RO(est_time),
+       AS_ATTR(read_expire),
+       AS_ATTR(write_expire),
+       AS_ATTR(antic_expire),
+       AS_ATTR(read_batch_expire),
+       AS_ATTR(write_batch_expire),
+       __ATTR_NULL
 };
 
 static struct elevator_type iosched_as = {
@@ -1860,9 +1807,10 @@ static struct elevator_type iosched_as = {
                .elevator_may_queue_fn =        as_may_queue,
                .elevator_init_fn =             as_init_queue,
                .elevator_exit_fn =             as_exit_queue,
+               .trim =                         as_trim,
        },
 
-       .elevator_ktype = &as_ktype,
+       .elevator_attrs = as_attrs,
        .elevator_name = "anticipatory",
        .elevator_owner = THIS_MODULE,
 };
@@ -1893,7 +1841,13 @@ static int __init as_init(void)
 
 static void __exit as_exit(void)
 {
+       DECLARE_COMPLETION(all_gone);
        elv_unregister(&iosched_as);
+       ioc_gone = &all_gone;
+       barrier();
+       if (atomic_read(&ioc_count))
+               complete(ioc_gone);
+       synchronize_rcu();
        kmem_cache_destroy(arq_pool);
 }
 
index c8dbe38..c4a0d5d 100644 (file)
@@ -6,21 +6,13 @@
  *
  *  Copyright (C) 2003 Jens Axboe <axboe@suse.de>
  */
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/blkdev.h>
-#include <linux/elevator.h>
-#include <linux/bio.h>
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/compiler.h>
+#include <linux/blkdev.h>
+#include <linux/elevator.h>
 #include <linux/hash.h>
 #include <linux/rbtree.h>
-#include <linux/mempool.h>
 #include <linux/ioprio.h>
-#include <linux/writeback.h>
 
 /*
  * tunables
@@ -47,6 +39,8 @@ static int cfq_slice_idle = HZ / 100;
  */
 static const int cfq_max_depth = 2;
 
+static DEFINE_RWLOCK(cfq_exit_lock);
+
 /*
  * for the hash of cfqq inside the cfqd
  */
@@ -89,6 +83,9 @@ static kmem_cache_t *crq_pool;
 static kmem_cache_t *cfq_pool;
 static kmem_cache_t *cfq_ioc_pool;
 
+static atomic_t ioc_count = ATOMIC_INIT(0);
+static struct completion *ioc_gone;
+
 #define CFQ_PRIO_LISTS         IOPRIO_BE_NR
 #define cfq_class_idle(cfqq)   ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE)
 #define cfq_class_be(cfqq)     ((cfqq)->ioprio_class == IOPRIO_CLASS_BE)
@@ -109,7 +106,6 @@ static kmem_cache_t *cfq_ioc_pool;
  * Per block device queue structure
  */
 struct cfq_data {
-       atomic_t ref;
        request_queue_t *queue;
 
        /*
@@ -175,6 +171,8 @@ struct cfq_data {
        unsigned int cfq_slice_async_rq;
        unsigned int cfq_slice_idle;
        unsigned int cfq_max_depth;
+
+       struct list_head cic_list;
 };
 
 /*
@@ -288,7 +286,7 @@ CFQ_CRQ_FNS(is_sync);
 
 static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short);
 static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *);
-static void cfq_put_cfqd(struct cfq_data *cfqd);
+static struct cfq_queue *cfq_get_queue(struct cfq_data *cfqd, unsigned int key, struct task_struct *tsk, gfp_t gfp_mask);
 
 #define process_sync(tsk)      ((tsk)->flags & PF_SYNCWRITE)
 
@@ -1160,8 +1158,6 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
        if (unlikely(cfqd->active_queue == cfqq))
                __cfq_slice_expired(cfqd, cfqq, 0);
 
-       cfq_put_cfqd(cfqq->cfqd);
-
        /*
         * it's on the empty list and still hashed
         */
@@ -1179,7 +1175,7 @@ __cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned int prio,
 
        hlist_for_each_safe(entry, next, hash_list) {
                struct cfq_queue *__cfqq = list_entry_qhash(entry);
-               const unsigned short __p = IOPRIO_PRIO_VALUE(__cfqq->ioprio_class, __cfqq->ioprio);
+               const unsigned short __p = IOPRIO_PRIO_VALUE(__cfqq->org_ioprio_class, __cfqq->org_ioprio);
 
                if (__cfqq->key == key && (__p == prio || prio == CFQ_KEY_ANY))
                        return __cfqq;
@@ -1198,13 +1194,24 @@ static void cfq_free_io_context(struct cfq_io_context *cic)
 {
        struct cfq_io_context *__cic;
        struct list_head *entry, *next;
+       int freed = 1;
 
        list_for_each_safe(entry, next, &cic->list) {
                __cic = list_entry(entry, struct cfq_io_context, list);
                kmem_cache_free(cfq_ioc_pool, __cic);
+               freed++;
        }
 
        kmem_cache_free(cfq_ioc_pool, cic);
+       if (atomic_sub_and_test(freed, &ioc_count) && ioc_gone)
+               complete(ioc_gone);
+}
+
+static void cfq_trim(struct io_context *ioc)
+{
+       ioc->set_ioprio = NULL;
+       if (ioc->cic)
+               cfq_free_io_context(ioc->cic);
 }
 
 /*
@@ -1212,25 +1219,37 @@ static void cfq_free_io_context(struct cfq_io_context *cic)
  */
 static void cfq_exit_single_io_context(struct cfq_io_context *cic)
 {
-       struct cfq_data *cfqd = cic->cfqq->cfqd;
-       request_queue_t *q = cfqd->queue;
+       struct cfq_data *cfqd = cic->key;
+       request_queue_t *q;
+
+       if (!cfqd)
+               return;
+
+       q = cfqd->queue;
 
        WARN_ON(!irqs_disabled());
 
        spin_lock(q->queue_lock);
 
-       if (unlikely(cic->cfqq == cfqd->active_queue))
-               __cfq_slice_expired(cfqd, cic->cfqq, 0);
+       if (cic->cfqq[ASYNC]) {
+               if (unlikely(cic->cfqq[ASYNC] == cfqd->active_queue))
+                       __cfq_slice_expired(cfqd, cic->cfqq[ASYNC], 0);
+               cfq_put_queue(cic->cfqq[ASYNC]);
+               cic->cfqq[ASYNC] = NULL;
+       }
+
+       if (cic->cfqq[SYNC]) {
+               if (unlikely(cic->cfqq[SYNC] == cfqd->active_queue))
+                       __cfq_slice_expired(cfqd, cic->cfqq[SYNC], 0);
+               cfq_put_queue(cic->cfqq[SYNC]);
+               cic->cfqq[SYNC] = NULL;
+       }
 
-       cfq_put_queue(cic->cfqq);
-       cic->cfqq = NULL;
+       cic->key = NULL;
+       list_del_init(&cic->queue_list);
        spin_unlock(q->queue_lock);
 }
 
-/*
- * Another task may update the task cic list, if it is doing a queue lookup
- * on its behalf. cfq_cic_lock excludes such concurrent updates
- */
 static void cfq_exit_io_context(struct cfq_io_context *cic)
 {
        struct cfq_io_context *__cic;
@@ -1242,12 +1261,14 @@ static void cfq_exit_io_context(struct cfq_io_context *cic)
        /*
         * put the reference this task is holding to the various queues
         */
+       read_lock(&cfq_exit_lock);
        list_for_each(entry, &cic->list) {
                __cic = list_entry(entry, struct cfq_io_context, list);
                cfq_exit_single_io_context(__cic);
        }
 
        cfq_exit_single_io_context(cic);
+       read_unlock(&cfq_exit_lock);
        local_irq_restore(flags);
 }
 
@@ -1258,7 +1279,8 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
 
        if (cic) {
                INIT_LIST_HEAD(&cic->list);
-               cic->cfqq = NULL;
+               cic->cfqq[ASYNC] = NULL;
+               cic->cfqq[SYNC] = NULL;
                cic->key = NULL;
                cic->last_end_request = jiffies;
                cic->ttime_total = 0;
@@ -1266,6 +1288,8 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
                cic->ttime_mean = 0;
                cic->dtor = cfq_free_io_context;
                cic->exit = cfq_exit_io_context;
+               INIT_LIST_HEAD(&cic->queue_list);
+               atomic_inc(&ioc_count);
        }
 
        return cic;
@@ -1318,14 +1342,27 @@ static void cfq_init_prio_data(struct cfq_queue *cfqq)
        cfq_clear_cfqq_prio_changed(cfqq);
 }
 
-static inline void changed_ioprio(struct cfq_queue *cfqq)
+static inline void changed_ioprio(struct cfq_io_context *cic)
 {
-       if (cfqq) {
-               struct cfq_data *cfqd = cfqq->cfqd;
-
+       struct cfq_data *cfqd = cic->key;
+       struct cfq_queue *cfqq;
+       if (cfqd) {
                spin_lock(cfqd->queue->queue_lock);
-               cfq_mark_cfqq_prio_changed(cfqq);
-               cfq_init_prio_data(cfqq);
+               cfqq = cic->cfqq[ASYNC];
+               if (cfqq) {
+                       struct cfq_queue *new_cfqq;
+                       new_cfqq = cfq_get_queue(cfqd, CFQ_KEY_ASYNC,
+                                               cic->ioc->task, GFP_ATOMIC);
+                       if (new_cfqq) {
+                               cic->cfqq[ASYNC] = new_cfqq;
+                               cfq_put_queue(cfqq);
+                       }
+               }
+               cfqq = cic->cfqq[SYNC];
+               if (cfqq) {
+                       cfq_mark_cfqq_prio_changed(cfqq);
+                       cfq_init_prio_data(cfqq);
+               }
                spin_unlock(cfqd->queue->queue_lock);
        }
 }
@@ -1335,24 +1372,32 @@ static inline void changed_ioprio(struct cfq_queue *cfqq)
  */
 static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio)
 {
-       struct cfq_io_context *cic = ioc->cic;
+       struct cfq_io_context *cic;
+
+       write_lock(&cfq_exit_lock);
+
+       cic = ioc->cic;
 
-       changed_ioprio(cic->cfqq);
+       changed_ioprio(cic);
 
        list_for_each_entry(cic, &cic->list, list)
-               changed_ioprio(cic->cfqq);
+               changed_ioprio(cic);
+
+       write_unlock(&cfq_exit_lock);
 
        return 0;
 }
 
 static struct cfq_queue *
-cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio,
+cfq_get_queue(struct cfq_data *cfqd, unsigned int key, struct task_struct *tsk,
              gfp_t gfp_mask)
 {
        const int hashval = hash_long(key, CFQ_QHASH_SHIFT);
        struct cfq_queue *cfqq, *new_cfqq = NULL;
+       unsigned short ioprio;
 
 retry:
+       ioprio = tsk->ioprio;
        cfqq = __cfq_find_cfq_hash(cfqd, key, ioprio, hashval);
 
        if (!cfqq) {
@@ -1381,7 +1426,6 @@ retry:
                hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]);
                atomic_set(&cfqq->ref, 0);
                cfqq->cfqd = cfqd;
-               atomic_inc(&cfqd->ref);
                cfqq->service_last = 0;
                /*
                 * set ->slice_left to allow preemption for a new process
@@ -1419,6 +1463,7 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
        if (!ioc)
                return NULL;
 
+restart:
        if ((cic = ioc->cic) == NULL) {
                cic = cfq_alloc_io_context(cfqd, gfp_mask);
 
@@ -1429,11 +1474,13 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
                 * manually increment generic io_context usage count, it
                 * cannot go away since we are already holding one ref to it
                 */
-               ioc->cic = cic;
-               ioc->set_ioprio = cfq_ioc_set_ioprio;
                cic->ioc = ioc;
                cic->key = cfqd;
-               atomic_inc(&cfqd->ref);
+               read_lock(&cfq_exit_lock);
+               ioc->set_ioprio = cfq_ioc_set_ioprio;
+               ioc->cic = cic;
+               list_add(&cic->queue_list, &cfqd->cic_list);
+               read_unlock(&cfq_exit_lock);
        } else {
                struct cfq_io_context *__cic;
 
@@ -1443,6 +1490,20 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
                if (cic->key == cfqd)
                        goto out;
 
+               if (unlikely(!cic->key)) {
+                       read_lock(&cfq_exit_lock);
+                       if (list_empty(&cic->list))
+                               ioc->cic = NULL;
+                       else
+                               ioc->cic = list_entry(cic->list.next,
+                                                     struct cfq_io_context,
+                                                     list);
+                       read_unlock(&cfq_exit_lock);
+                       kmem_cache_free(cfq_ioc_pool, cic);
+                       atomic_dec(&ioc_count);
+                       goto restart;
+               }
+
                /*
                 * cic exists, check if we already are there. linear search
                 * should be ok here, the list will usually not be more than
@@ -1457,6 +1518,14 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
                                cic = __cic;
                                goto out;
                        }
+                       if (unlikely(!__cic->key)) {
+                               read_lock(&cfq_exit_lock);
+                               list_del(&__cic->list);
+                               read_unlock(&cfq_exit_lock);
+                               kmem_cache_free(cfq_ioc_pool, __cic);
+                               atomic_dec(&ioc_count);
+                               goto restart;
+                       }
                }
 
                /*
@@ -1469,8 +1538,10 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
 
                __cic->ioc = ioc;
                __cic->key = cfqd;
-               atomic_inc(&cfqd->ref);
+               read_lock(&cfq_exit_lock);
                list_add(&__cic->list, &cic->list);
+               list_add(&__cic->queue_list, &cfqd->cic_list);
+               read_unlock(&cfq_exit_lock);
                cic = __cic;
        }
 
@@ -1890,6 +1961,7 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
        struct cfq_queue *cfqq;
        struct cfq_rq *crq;
        unsigned long flags;
+       int is_sync = key != CFQ_KEY_ASYNC;
 
        might_sleep_if(gfp_mask & __GFP_WAIT);
 
@@ -1900,14 +1972,14 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
        if (!cic)
                goto queue_fail;
 
-       if (!cic->cfqq) {
-               cfqq = cfq_get_queue(cfqd, key, tsk->ioprio, gfp_mask);
+       if (!cic->cfqq[is_sync]) {
+               cfqq = cfq_get_queue(cfqd, key, tsk, gfp_mask);
                if (!cfqq)
                        goto queue_fail;
 
-               cic->cfqq = cfqq;
+               cic->cfqq[is_sync] = cfqq;
        } else
-               cfqq = cic->cfqq;
+               cfqq = cic->cfqq[is_sync];
 
        cfqq->allocated[rw]++;
        cfq_clear_cfqq_must_alloc(cfqq);
@@ -1924,7 +1996,7 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
                crq->cfq_queue = cfqq;
                crq->io_context = cic;
 
-               if (rw == READ || process_sync(tsk))
+               if (is_sync)
                        cfq_mark_crq_is_sync(crq);
                else
                        cfq_clear_crq_is_sync(crq);
@@ -2055,15 +2127,35 @@ static void cfq_shutdown_timer_wq(struct cfq_data *cfqd)
        blk_sync_queue(cfqd->queue);
 }
 
-static void cfq_put_cfqd(struct cfq_data *cfqd)
+static void cfq_exit_queue(elevator_t *e)
 {
+       struct cfq_data *cfqd = e->elevator_data;
        request_queue_t *q = cfqd->queue;
 
-       if (!atomic_dec_and_test(&cfqd->ref))
-               return;
+       cfq_shutdown_timer_wq(cfqd);
+       write_lock(&cfq_exit_lock);
+       spin_lock_irq(q->queue_lock);
+       if (cfqd->active_queue)
+               __cfq_slice_expired(cfqd, cfqd->active_queue, 0);
+       while(!list_empty(&cfqd->cic_list)) {
+               struct cfq_io_context *cic = list_entry(cfqd->cic_list.next,
+                                                       struct cfq_io_context,
+                                                       queue_list);
+               if (cic->cfqq[ASYNC]) {
+                       cfq_put_queue(cic->cfqq[ASYNC]);
+                       cic->cfqq[ASYNC] = NULL;
+               }
+               if (cic->cfqq[SYNC]) {
+                       cfq_put_queue(cic->cfqq[SYNC]);
+                       cic->cfqq[SYNC] = NULL;
+               }
+               cic->key = NULL;
+               list_del_init(&cic->queue_list);
+       }
+       spin_unlock_irq(q->queue_lock);
+       write_unlock(&cfq_exit_lock);
 
        cfq_shutdown_timer_wq(cfqd);
-       blk_put_queue(q);
 
        mempool_destroy(cfqd->crq_pool);
        kfree(cfqd->crq_hash);
@@ -2071,14 +2163,6 @@ static void cfq_put_cfqd(struct cfq_data *cfqd)
        kfree(cfqd);
 }
 
-static void cfq_exit_queue(elevator_t *e)
-{
-       struct cfq_data *cfqd = e->elevator_data;
-
-       cfq_shutdown_timer_wq(cfqd);
-       cfq_put_cfqd(cfqd);
-}
-
 static int cfq_init_queue(request_queue_t *q, elevator_t *e)
 {
        struct cfq_data *cfqd;
@@ -2097,6 +2181,7 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
        INIT_LIST_HEAD(&cfqd->cur_rr);
        INIT_LIST_HEAD(&cfqd->idle_rr);
        INIT_LIST_HEAD(&cfqd->empty_list);
+       INIT_LIST_HEAD(&cfqd->cic_list);
 
        cfqd->crq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL);
        if (!cfqd->crq_hash)
@@ -2118,7 +2203,6 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
        e->elevator_data = cfqd;
 
        cfqd->queue = q;
-       atomic_inc(&q->refcnt);
 
        cfqd->max_queued = q->nr_requests / 4;
        q->nr_batching = cfq_queued;
@@ -2133,8 +2217,6 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
 
        INIT_WORK(&cfqd->unplug_work, cfq_kick_queue, q);
 
-       atomic_set(&cfqd->ref, 1);
-
        cfqd->cfq_queued = cfq_queued;
        cfqd->cfq_quantum = cfq_quantum;
        cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0];
@@ -2193,11 +2275,6 @@ fail:
 /*
  * sysfs parts below -->
  */
-struct cfq_fs_entry {
-       struct attribute attr;
-       ssize_t (*show)(struct cfq_data *, char *);
-       ssize_t (*store)(struct cfq_data *, const char *, size_t);
-};
 
 static ssize_t
 cfq_var_show(unsigned int var, char *page)
@@ -2215,8 +2292,9 @@ cfq_var_store(unsigned int *var, const char *page, size_t count)
 }
 
 #define SHOW_FUNCTION(__FUNC, __VAR, __CONV)                           \
-static ssize_t __FUNC(struct cfq_data *cfqd, char *page)               \
+static ssize_t __FUNC(elevator_t *e, char *page)                       \
 {                                                                      \
+       struct cfq_data *cfqd = e->elevator_data;                       \
        unsigned int __data = __VAR;                                    \
        if (__CONV)                                                     \
                __data = jiffies_to_msecs(__data);                      \
@@ -2226,8 +2304,8 @@ SHOW_FUNCTION(cfq_quantum_show, cfqd->cfq_quantum, 0);
 SHOW_FUNCTION(cfq_queued_show, cfqd->cfq_queued, 0);
 SHOW_FUNCTION(cfq_fifo_expire_sync_show, cfqd->cfq_fifo_expire[1], 1);
 SHOW_FUNCTION(cfq_fifo_expire_async_show, cfqd->cfq_fifo_expire[0], 1);
-SHOW_FUNCTION(cfq_back_max_show, cfqd->cfq_back_max, 0);
-SHOW_FUNCTION(cfq_back_penalty_show, cfqd->cfq_back_penalty, 0);
+SHOW_FUNCTION(cfq_back_seek_max_show, cfqd->cfq_back_max, 0);
+SHOW_FUNCTION(cfq_back_seek_penalty_show, cfqd->cfq_back_penalty, 0);
 SHOW_FUNCTION(cfq_slice_idle_show, cfqd->cfq_slice_idle, 1);
 SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1);
 SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1);
@@ -2236,8 +2314,9 @@ SHOW_FUNCTION(cfq_max_depth_show, cfqd->cfq_max_depth, 0);
 #undef SHOW_FUNCTION
 
 #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV)                        \
-static ssize_t __FUNC(struct cfq_data *cfqd, const char *page, size_t count)   \
+static ssize_t __FUNC(elevator_t *e, const char *page, size_t count)   \
 {                                                                      \
+       struct cfq_data *cfqd = e->elevator_data;                       \
        unsigned int __data;                                            \
        int ret = cfq_var_store(&__data, (page), count);                \
        if (__data < (MIN))                                             \
@@ -2254,8 +2333,8 @@ STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, UINT_MAX, 0);
 STORE_FUNCTION(cfq_queued_store, &cfqd->cfq_queued, 1, UINT_MAX, 0);
 STORE_FUNCTION(cfq_fifo_expire_sync_store, &cfqd->cfq_fifo_expire[1], 1, UINT_MAX, 1);
 STORE_FUNCTION(cfq_fifo_expire_async_store, &cfqd->cfq_fifo_expire[0], 1, UINT_MAX, 1);
-STORE_FUNCTION(cfq_back_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0);
-STORE_FUNCTION(cfq_back_penalty_store, &cfqd->cfq_back_penalty, 1, UINT_MAX, 0);
+STORE_FUNCTION(cfq_back_seek_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0);
+STORE_FUNCTION(cfq_back_seek_penalty_store, &cfqd->cfq_back_penalty, 1, UINT_MAX, 0);
 STORE_FUNCTION(cfq_slice_idle_store, &cfqd->cfq_slice_idle, 0, UINT_MAX, 1);
 STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1);
 STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1);
@@ -2263,112 +2342,22 @@ STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX,
 STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0);
 #undef STORE_FUNCTION
 
-static struct cfq_fs_entry cfq_quantum_entry = {
-       .attr = {.name = "quantum", .mode = S_IRUGO | S_IWUSR },
-       .show = cfq_quantum_show,
-       .store = cfq_quantum_store,
-};
-static struct cfq_fs_entry cfq_queued_entry = {
-       .attr = {.name = "queued", .mode = S_IRUGO | S_IWUSR },
-       .show = cfq_queued_show,
-       .store = cfq_queued_store,
-};
-static struct cfq_fs_entry cfq_fifo_expire_sync_entry = {
-       .attr = {.name = "fifo_expire_sync", .mode = S_IRUGO | S_IWUSR },
-       .show = cfq_fifo_expire_sync_show,
-       .store = cfq_fifo_expire_sync_store,
-};
-static struct cfq_fs_entry cfq_fifo_expire_async_entry = {
-       .attr = {.name = "fifo_expire_async", .mode = S_IRUGO | S_IWUSR },
-       .show = cfq_fifo_expire_async_show,
-       .store = cfq_fifo_expire_async_store,
-};
-static struct cfq_fs_entry cfq_back_max_entry = {
-       .attr = {.name = "back_seek_max", .mode = S_IRUGO | S_IWUSR },
-       .show = cfq_back_max_show,
-       .store = cfq_back_max_store,
-};
-static struct cfq_fs_entry cfq_back_penalty_entry = {
-       .attr = {.name = "back_seek_penalty", .mode = S_IRUGO | S_IWUSR },
-       .show = cfq_back_penalty_show,
-       .store = cfq_back_penalty_store,
-};
-static struct cfq_fs_entry cfq_slice_sync_entry = {
-       .attr = {.name = "slice_sync", .mode = S_IRUGO | S_IWUSR },
-       .show = cfq_slice_sync_show,
-       .store = cfq_slice_sync_store,
-};
-static struct cfq_fs_entry cfq_slice_async_entry = {
-       .attr = {.name = "slice_async", .mode = S_IRUGO | S_IWUSR },
-       .show = cfq_slice_async_show,
-       .store = cfq_slice_async_store,
-};
-static struct cfq_fs_entry cfq_slice_async_rq_entry = {
-       .attr = {.name = "slice_async_rq", .mode = S_IRUGO | S_IWUSR },
-       .show = cfq_slice_async_rq_show,
-       .store = cfq_slice_async_rq_store,
-};
-static struct cfq_fs_entry cfq_slice_idle_entry = {
-       .attr = {.name = "slice_idle", .mode = S_IRUGO | S_IWUSR },
-       .show = cfq_slice_idle_show,
-       .store = cfq_slice_idle_store,
-};
-static struct cfq_fs_entry cfq_max_depth_entry = {
-       .attr = {.name = "max_depth", .mode = S_IRUGO | S_IWUSR },
-       .show = cfq_max_depth_show,
-       .store = cfq_max_depth_store,
-};
-
-static struct attribute *default_attrs[] = {
-       &cfq_quantum_entry.attr,
-       &cfq_queued_entry.attr,
-       &cfq_fifo_expire_sync_entry.attr,
-       &cfq_fifo_expire_async_entry.attr,
-       &cfq_back_max_entry.attr,
-       &cfq_back_penalty_entry.attr,
-       &cfq_slice_sync_entry.attr,
-       &cfq_slice_async_entry.attr,
-       &cfq_slice_async_rq_entry.attr,
-       &cfq_slice_idle_entry.attr,
-       &cfq_max_depth_entry.attr,
-       NULL,
-};
-
-#define to_cfq(atr) container_of((atr), struct cfq_fs_entry, attr)
-
-static ssize_t
-cfq_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
-{
-       elevator_t *e = container_of(kobj, elevator_t, kobj);
-       struct cfq_fs_entry *entry = to_cfq(attr);
-
-       if (!entry->show)
-               return -EIO;
-
-       return entry->show(e->elevator_data, page);
-}
-
-static ssize_t
-cfq_attr_store(struct kobject *kobj, struct attribute *attr,
-              const char *page, size_t length)
-{
-       elevator_t *e = container_of(kobj, elevator_t, kobj);
-       struct cfq_fs_entry *entry = to_cfq(attr);
-
-       if (!entry->store)
-               return -EIO;
-
-       return entry->store(e->elevator_data, page, length);
-}
-
-static struct sysfs_ops cfq_sysfs_ops = {
-       .show   = cfq_attr_show,
-       .store  = cfq_attr_store,
-};
-
-static struct kobj_type cfq_ktype = {
-       .sysfs_ops      = &cfq_sysfs_ops,
-       .default_attrs  = default_attrs,
+#define CFQ_ATTR(name) \
+       __ATTR(name, S_IRUGO|S_IWUSR, cfq_##name##_show, cfq_##name##_store)
+
+static struct elv_fs_entry cfq_attrs[] = {
+       CFQ_ATTR(quantum),
+       CFQ_ATTR(queued),
+       CFQ_ATTR(fifo_expire_sync),
+       CFQ_ATTR(fifo_expire_async),
+       CFQ_ATTR(back_seek_max),
+       CFQ_ATTR(back_seek_penalty),
+       CFQ_ATTR(slice_sync),
+       CFQ_ATTR(slice_async),
+       CFQ_ATTR(slice_async_rq),
+       CFQ_ATTR(slice_idle),
+       CFQ_ATTR(max_depth),
+       __ATTR_NULL
 };
 
 static struct elevator_type iosched_cfq = {
@@ -2389,8 +2378,9 @@ static struct elevator_type iosched_cfq = {
                .elevator_may_queue_fn =        cfq_may_queue,
                .elevator_init_fn =             cfq_init_queue,
                .elevator_exit_fn =             cfq_exit_queue,
+               .trim =                         cfq_trim,
        },
-       .elevator_ktype =       &cfq_ktype,
+       .elevator_attrs =       cfq_attrs,
        .elevator_name =        "cfq",
        .elevator_owner =       THIS_MODULE,
 };
@@ -2419,7 +2409,13 @@ static int __init cfq_init(void)
 
 static void __exit cfq_exit(void)
 {
+       DECLARE_COMPLETION(all_gone);
        elv_unregister(&iosched_cfq);
+       ioc_gone = &all_gone;
+       barrier();
+       if (atomic_read(&ioc_count))
+               complete(ioc_gone);
+       synchronize_rcu();
        cfq_slab_kill();
 }
 
index 27e494b..399fa1e 100644 (file)
@@ -694,11 +694,6 @@ deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
 /*
  * sysfs parts below
  */
-struct deadline_fs_entry {
-       struct attribute attr;
-       ssize_t (*show)(struct deadline_data *, char *);
-       ssize_t (*store)(struct deadline_data *, const char *, size_t);
-};
 
 static ssize_t
 deadline_var_show(int var, char *page)
@@ -716,23 +711,25 @@ deadline_var_store(int *var, const char *page, size_t count)
 }
 
 #define SHOW_FUNCTION(__FUNC, __VAR, __CONV)                           \
-static ssize_t __FUNC(struct deadline_data *dd, char *page)            \
+static ssize_t __FUNC(elevator_t *e, char *page)                       \
 {                                                                      \
-       int __data = __VAR;                                     \
+       struct deadline_data *dd = e->elevator_data;                    \
+       int __data = __VAR;                                             \
        if (__CONV)                                                     \
                __data = jiffies_to_msecs(__data);                      \
        return deadline_var_show(__data, (page));                       \
 }
-SHOW_FUNCTION(deadline_readexpire_show, dd->fifo_expire[READ], 1);
-SHOW_FUNCTION(deadline_writeexpire_show, dd->fifo_expire[WRITE], 1);
-SHOW_FUNCTION(deadline_writesstarved_show, dd->writes_starved, 0);
-SHOW_FUNCTION(deadline_frontmerges_show, dd->front_merges, 0);
-SHOW_FUNCTION(deadline_fifobatch_show, dd->fifo_batch, 0);
+SHOW_FUNCTION(deadline_read_expire_show, dd->fifo_expire[READ], 1);
+SHOW_FUNCTION(deadline_write_expire_show, dd->fifo_expire[WRITE], 1);
+SHOW_FUNCTION(deadline_writes_starved_show, dd->writes_starved, 0);
+SHOW_FUNCTION(deadline_front_merges_show, dd->front_merges, 0);
+SHOW_FUNCTION(deadline_fifo_batch_show, dd->fifo_batch, 0);
 #undef SHOW_FUNCTION
 
 #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV)                        \
-static ssize_t __FUNC(struct deadline_data *dd, const char *page, size_t count)        \
+static ssize_t __FUNC(elevator_t *e, const char *page, size_t count)   \
 {                                                                      \
+       struct deadline_data *dd = e->elevator_data;                    \
        int __data;                                                     \
        int ret = deadline_var_store(&__data, (page), count);           \
        if (__data < (MIN))                                             \
@@ -745,83 +742,24 @@ static ssize_t __FUNC(struct deadline_data *dd, const char *page, size_t count)
                *(__PTR) = __data;                                      \
        return ret;                                                     \
 }
-STORE_FUNCTION(deadline_readexpire_store, &dd->fifo_expire[READ], 0, INT_MAX, 1);
-STORE_FUNCTION(deadline_writeexpire_store, &dd->fifo_expire[WRITE], 0, INT_MAX, 1);
-STORE_FUNCTION(deadline_writesstarved_store, &dd->writes_starved, INT_MIN, INT_MAX, 0);
-STORE_FUNCTION(deadline_frontmerges_store, &dd->front_merges, 0, 1, 0);
-STORE_FUNCTION(deadline_fifobatch_store, &dd->fifo_batch, 0, INT_MAX, 0);
+STORE_FUNCTION(deadline_read_expire_store, &dd->fifo_expire[READ], 0, INT_MAX, 1);
+STORE_FUNCTION(deadline_write_expire_store, &dd->fifo_expire[WRITE], 0, INT_MAX, 1);
+STORE_FUNCTION(deadline_writes_starved_store, &dd->writes_starved, INT_MIN, INT_MAX, 0);
+STORE_FUNCTION(deadline_front_merges_store, &dd->front_merges, 0, 1, 0);
+STORE_FUNCTION(deadline_fifo_batch_store, &dd->fifo_batch, 0, INT_MAX, 0);
 #undef STORE_FUNCTION
 
-static struct deadline_fs_entry deadline_readexpire_entry = {
-       .attr = {.name = "read_expire", .mode = S_IRUGO | S_IWUSR },
-       .show = deadline_readexpire_show,
-       .store = deadline_readexpire_store,
-};
-static struct deadline_fs_entry deadline_writeexpire_entry = {
-       .attr = {.name = "write_expire", .mode = S_IRUGO | S_IWUSR },
-       .show = deadline_writeexpire_show,
-       .store = deadline_writeexpire_store,
-};
-static struct deadline_fs_entry deadline_writesstarved_entry = {
-       .attr = {.name = "writes_starved", .mode = S_IRUGO | S_IWUSR },
-       .show = deadline_writesstarved_show,
-       .store = deadline_writesstarved_store,
-};
-static struct deadline_fs_entry deadline_frontmerges_entry = {
-       .attr = {.name = "front_merges", .mode = S_IRUGO | S_IWUSR },
-       .show = deadline_frontmerges_show,
-       .store = deadline_frontmerges_store,
-};
-static struct deadline_fs_entry deadline_fifobatch_entry = {
-       .attr = {.name = "fifo_batch", .mode = S_IRUGO | S_IWUSR },
-       .show = deadline_fifobatch_show,
-       .store = deadline_fifobatch_store,
-};
-
-static struct attribute *default_attrs[] = {
-       &deadline_readexpire_entry.attr,
-       &deadline_writeexpire_entry.attr,
-       &deadline_writesstarved_entry.attr,
-       &deadline_frontmerges_entry.attr,
-       &deadline_fifobatch_entry.attr,
-       NULL,
-};
-
-#define to_deadline(atr) container_of((atr), struct deadline_fs_entry, attr)
-
-static ssize_t
-deadline_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
-{
-       elevator_t *e = container_of(kobj, elevator_t, kobj);
-       struct deadline_fs_entry *entry = to_deadline(attr);
-
-       if (!entry->show)
-               return -EIO;
-
-       return entry->show(e->elevator_data, page);
-}
-
-static ssize_t
-deadline_attr_store(struct kobject *kobj, struct attribute *attr,
-                   const char *page, size_t length)
-{
-       elevator_t *e = container_of(kobj, elevator_t, kobj);
-       struct deadline_fs_entry *entry = to_deadline(attr);
-
-       if (!entry->store)
-               return -EIO;
-
-       return entry->store(e->elevator_data, page, length);
-}
-
-static struct sysfs_ops deadline_sysfs_ops = {
-       .show   = deadline_attr_show,
-       .store  = deadline_attr_store,
-};
-
-static struct kobj_type deadline_ktype = {
-       .sysfs_ops      = &deadline_sysfs_ops,
-       .default_attrs  = default_attrs,
+#define DD_ATTR(name) \
+       __ATTR(name, S_IRUGO|S_IWUSR, deadline_##name##_show, \
+                                     deadline_##name##_store)
+
+static struct elv_fs_entry deadline_attrs[] = {
+       DD_ATTR(read_expire),
+       DD_ATTR(write_expire),
+       DD_ATTR(writes_starved),
+       DD_ATTR(front_merges),
+       DD_ATTR(fifo_batch),
+       __ATTR_NULL
 };
 
 static struct elevator_type iosched_deadline = {
@@ -840,7 +778,7 @@ static struct elevator_type iosched_deadline = {
                .elevator_exit_fn =             deadline_exit_queue,
        },
 
-       .elevator_ktype = &deadline_ktype,
+       .elevator_attrs = deadline_attrs,
        .elevator_name = "deadline",
        .elevator_owner = THIS_MODULE,
 };
index 24b702d..db3d0d8 100644 (file)
@@ -120,15 +120,10 @@ static struct elevator_type *elevator_get(const char *name)
        return e;
 }
 
-static int elevator_attach(request_queue_t *q, struct elevator_type *e,
-                          struct elevator_queue *eq)
+static int elevator_attach(request_queue_t *q, struct elevator_queue *eq)
 {
        int ret = 0;
 
-       memset(eq, 0, sizeof(*eq));
-       eq->ops = &e->ops;
-       eq->elevator_type = e;
-
        q->elevator = eq;
 
        if (eq->ops->elevator_init_fn)
@@ -154,6 +149,32 @@ static int __init elevator_setup(char *str)
 
 __setup("elevator=", elevator_setup);
 
+static struct kobj_type elv_ktype;
+
+static elevator_t *elevator_alloc(struct elevator_type *e)
+{
+       elevator_t *eq = kmalloc(sizeof(elevator_t), GFP_KERNEL);
+       if (eq) {
+               memset(eq, 0, sizeof(*eq));
+               eq->ops = &e->ops;
+               eq->elevator_type = e;
+               kobject_init(&eq->kobj);
+               snprintf(eq->kobj.name, KOBJ_NAME_LEN, "%s", "iosched");
+               eq->kobj.ktype = &elv_ktype;
+               mutex_init(&eq->sysfs_lock);
+       } else {
+               elevator_put(e);
+       }
+       return eq;
+}
+
+static void elevator_release(struct kobject *kobj)
+{
+       elevator_t *e = container_of(kobj, elevator_t, kobj);
+       elevator_put(e->elevator_type);
+       kfree(e);
+}
+
 int elevator_init(request_queue_t *q, char *name)
 {
        struct elevator_type *e = NULL;
@@ -176,29 +197,26 @@ int elevator_init(request_queue_t *q, char *name)
                e = elevator_get("noop");
        }
 
-       eq = kmalloc(sizeof(struct elevator_queue), GFP_KERNEL);
-       if (!eq) {
-               elevator_put(e);
+       eq = elevator_alloc(e);
+       if (!eq)
                return -ENOMEM;
-       }
 
-       ret = elevator_attach(q, e, eq);
-       if (ret) {
-               kfree(eq);
-               elevator_put(e);
-       }
+       ret = elevator_attach(q, eq);
+       if (ret)
+               kobject_put(&eq->kobj);
 
        return ret;
 }
 
 void elevator_exit(elevator_t *e)
 {
+       mutex_lock(&e->sysfs_lock);
        if (e->ops->elevator_exit_fn)
                e->ops->elevator_exit_fn(e);
+       e->ops = NULL;
+       mutex_unlock(&e->sysfs_lock);
 
-       elevator_put(e->elevator_type);
-       e->elevator_type = NULL;
-       kfree(e);
+       kobject_put(&e->kobj);
 }
 
 /*
@@ -627,26 +645,79 @@ void elv_completed_request(request_queue_t *q, struct request *rq)
        }
 }
 
-int elv_register_queue(struct request_queue *q)
+#define to_elv(atr) container_of((atr), struct elv_fs_entry, attr)
+
+static ssize_t
+elv_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
 {
-       elevator_t *e = q->elevator;
+       elevator_t *e = container_of(kobj, elevator_t, kobj);
+       struct elv_fs_entry *entry = to_elv(attr);
+       ssize_t error;
 
-       e->kobj.parent = kobject_get(&q->kobj);
-       if (!e->kobj.parent)
-               return -EBUSY;
+       if (!entry->show)
+               return -EIO;
 
-       snprintf(e->kobj.name, KOBJ_NAME_LEN, "%s", "iosched");
-       e->kobj.ktype = e->elevator_type->elevator_ktype;
+       mutex_lock(&e->sysfs_lock);
+       error = e->ops ? entry->show(e, page) : -ENOENT;
+       mutex_unlock(&e->sysfs_lock);
+       return error;
+}
+
+static ssize_t
+elv_attr_store(struct kobject *kobj, struct attribute *attr,
+              const char *page, size_t length)
+{
+       elevator_t *e = container_of(kobj, elevator_t, kobj);
+       struct elv_fs_entry *entry = to_elv(attr);
+       ssize_t error;
+
+       if (!entry->store)
+               return -EIO;
+
+       mutex_lock(&e->sysfs_lock);
+       error = e->ops ? entry->store(e, page, length) : -ENOENT;
+       mutex_unlock(&e->sysfs_lock);
+       return error;
+}
+
+static struct sysfs_ops elv_sysfs_ops = {
+       .show   = elv_attr_show,
+       .store  = elv_attr_store,
+};
+
+static struct kobj_type elv_ktype = {
+       .sysfs_ops      = &elv_sysfs_ops,
+       .release        = elevator_release,
+};
 
-       return kobject_register(&e->kobj);
+int elv_register_queue(struct request_queue *q)
+{
+       elevator_t *e = q->elevator;
+       int error;
+
+       e->kobj.parent = &q->kobj;
+
+       error = kobject_add(&e->kobj);
+       if (!error) {
+               struct elv_fs_entry *attr = e->elevator_type->elevator_attrs;
+               if (attr) {
+                       while (attr->attr.name) {
+                               if (sysfs_create_file(&e->kobj, &attr->attr))
+                                       break;
+                               attr++;
+                       }
+               }
+               kobject_uevent(&e->kobj, KOBJ_ADD);
+       }
+       return error;
 }
 
 void elv_unregister_queue(struct request_queue *q)
 {
        if (q) {
                elevator_t *e = q->elevator;
-               kobject_unregister(&e->kobj);
-               kobject_put(&q->kobj);
+               kobject_uevent(&e->kobj, KOBJ_REMOVE);
+               kobject_del(&e->kobj);
        }
 }
 
@@ -675,21 +746,15 @@ void elv_unregister(struct elevator_type *e)
        /*
         * Iterate every thread in the process to remove the io contexts.
         */
-       read_lock(&tasklist_lock);
-       do_each_thread(g, p) {
-               struct io_context *ioc = p->io_context;
-               if (ioc && ioc->cic) {
-                       ioc->cic->exit(ioc->cic);
-                       ioc->cic->dtor(ioc->cic);
-                       ioc->cic = NULL;
-               }
-               if (ioc && ioc->aic) {
-                       ioc->aic->exit(ioc->aic);
-                       ioc->aic->dtor(ioc->aic);
-                       ioc->aic = NULL;
-               }
-       } while_each_thread(g, p);
-       read_unlock(&tasklist_lock);
+       if (e->ops.trim) {
+               read_lock(&tasklist_lock);
+               do_each_thread(g, p) {
+                       task_lock(p);
+                       e->ops.trim(p->io_context);
+                       task_unlock(p);
+               } while_each_thread(g, p);
+               read_unlock(&tasklist_lock);
+       }
 
        spin_lock_irq(&elv_list_lock);
        list_del_init(&e->list);
@@ -703,16 +768,16 @@ EXPORT_SYMBOL_GPL(elv_unregister);
  * need for the new one. this way we have a chance of going back to the old
  * one, if the new one fails init for some reason.
  */
-static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
+static int elevator_switch(request_queue_t *q, struct elevator_type *new_e)
 {
        elevator_t *old_elevator, *e;
 
        /*
         * Allocate new elevator
         */
-       e = kmalloc(sizeof(elevator_t), GFP_KERNEL);
+       e = elevator_alloc(new_e);
        if (!e)
-               goto error;
+               return 0;
 
        /*
         * Turn on BYPASS and drain all requests w/ elevator private data
@@ -743,7 +808,7 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
        /*
         * attach and start new elevator
         */
-       if (elevator_attach(q, new_e, e))
+       if (elevator_attach(q, e))
                goto fail;
 
        if (elv_register_queue(q))
@@ -754,7 +819,7 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
         */
        elevator_exit(old_elevator);
        clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
-       return;
+       return 1;
 
 fail_register:
        /*
@@ -767,10 +832,9 @@ fail:
        q->elevator = old_elevator;
        elv_register_queue(q);
        clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
-       kfree(e);
-error:
-       elevator_put(new_e);
-       printk(KERN_ERR "elevator: switch to %s failed\n",new_e->elevator_name);
+       if (e)
+               kobject_put(&e->kobj);
+       return 0;
 }
 
 ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count)
@@ -797,7 +861,8 @@ ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count)
                return count;
        }
 
-       elevator_switch(q, e);
+       if (!elevator_switch(q, e))
+               printk(KERN_ERR "elevator: switch to %s failed\n",elevator_name);
        return count;
 }
 
index 0ef2971..6c793b1 100644 (file)
@@ -1740,16 +1740,11 @@ EXPORT_SYMBOL(blk_run_queue);
  *     Hopefully the low level driver will have finished any
  *     outstanding requests first...
  **/
-void blk_cleanup_queue(request_queue_t * q)
+static void blk_release_queue(struct kobject *kobj)
 {
+       request_queue_t *q = container_of(kobj, struct request_queue, kobj);
        struct request_list *rl = &q->rq;
 
-       if (!atomic_dec_and_test(&q->refcnt))
-               return;
-
-       if (q->elevator)
-               elevator_exit(q->elevator);
-
        blk_sync_queue(q);
 
        if (rl->rq_pool)
@@ -1761,6 +1756,24 @@ void blk_cleanup_queue(request_queue_t * q)
        kmem_cache_free(requestq_cachep, q);
 }
 
+void blk_put_queue(request_queue_t *q)
+{
+       kobject_put(&q->kobj);
+}
+EXPORT_SYMBOL(blk_put_queue);
+
+void blk_cleanup_queue(request_queue_t * q)
+{
+       mutex_lock(&q->sysfs_lock);
+       set_bit(QUEUE_FLAG_DEAD, &q->queue_flags);
+       mutex_unlock(&q->sysfs_lock);
+
+       if (q->elevator)
+               elevator_exit(q->elevator);
+
+       blk_put_queue(q);
+}
+
 EXPORT_SYMBOL(blk_cleanup_queue);
 
 static int blk_init_free_list(request_queue_t *q)
@@ -1788,6 +1801,8 @@ request_queue_t *blk_alloc_queue(gfp_t gfp_mask)
 }
 EXPORT_SYMBOL(blk_alloc_queue);
 
+static struct kobj_type queue_ktype;
+
 request_queue_t *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
 {
        request_queue_t *q;
@@ -1798,11 +1813,16 @@ request_queue_t *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
 
        memset(q, 0, sizeof(*q));
        init_timer(&q->unplug_timer);
-       atomic_set(&q->refcnt, 1);
+
+       snprintf(q->kobj.name, KOBJ_NAME_LEN, "%s", "queue");
+       q->kobj.ktype = &queue_ktype;
+       kobject_init(&q->kobj);
 
        q->backing_dev_info.unplug_io_fn = blk_backing_dev_unplug;
        q->backing_dev_info.unplug_io_data = q;
 
+       mutex_init(&q->sysfs_lock);
+
        return q;
 }
 EXPORT_SYMBOL(blk_alloc_queue_node);
@@ -1854,8 +1874,10 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
                return NULL;
 
        q->node = node_id;
-       if (blk_init_free_list(q))
-               goto out_init;
+       if (blk_init_free_list(q)) {
+               kmem_cache_free(requestq_cachep, q);
+               return NULL;
+       }
 
        /*
         * if caller didn't supply a lock, they get per-queue locking with
@@ -1891,9 +1913,7 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
                return q;
        }
 
-       blk_cleanup_queue(q);
-out_init:
-       kmem_cache_free(requestq_cachep, q);
+       blk_put_queue(q);
        return NULL;
 }
 EXPORT_SYMBOL(blk_init_queue_node);
@@ -1901,7 +1921,7 @@ EXPORT_SYMBOL(blk_init_queue_node);
 int blk_get_queue(request_queue_t *q)
 {
        if (likely(!test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) {
-               atomic_inc(&q->refcnt);
+               kobject_get(&q->kobj);
                return 0;
        }
 
@@ -3477,10 +3497,12 @@ void put_io_context(struct io_context *ioc)
        BUG_ON(atomic_read(&ioc->refcount) == 0);
 
        if (atomic_dec_and_test(&ioc->refcount)) {
+               rcu_read_lock();
                if (ioc->aic && ioc->aic->dtor)
                        ioc->aic->dtor(ioc->aic);
                if (ioc->cic && ioc->cic->dtor)
                        ioc->cic->dtor(ioc->cic);
+               rcu_read_unlock();
 
                kmem_cache_free(iocontext_cachep, ioc);
        }
@@ -3614,10 +3636,13 @@ static ssize_t
 queue_requests_store(struct request_queue *q, const char *page, size_t count)
 {
        struct request_list *rl = &q->rq;
+       unsigned long nr;
+       int ret = queue_var_store(&nr, page, count);
+       if (nr < BLKDEV_MIN_RQ)
+               nr = BLKDEV_MIN_RQ;
 
-       int ret = queue_var_store(&q->nr_requests, page, count);
-       if (q->nr_requests < BLKDEV_MIN_RQ)
-               q->nr_requests = BLKDEV_MIN_RQ;
+       spin_lock_irq(q->queue_lock);
+       q->nr_requests = nr;
        blk_queue_congestion_threshold(q);
 
        if (rl->count[READ] >= queue_congestion_on_threshold(q))
@@ -3643,6 +3668,7 @@ queue_requests_store(struct request_queue *q, const char *page, size_t count)
                blk_clear_queue_full(q, WRITE);
                wake_up(&rl->wait[WRITE]);
        }
+       spin_unlock_irq(q->queue_lock);
        return ret;
 }
 
@@ -3758,13 +3784,19 @@ static ssize_t
 queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
 {
        struct queue_sysfs_entry *entry = to_queue(attr);
-       struct request_queue *q;
+       request_queue_t *q = container_of(kobj, struct request_queue, kobj);
+       ssize_t res;
 
-       q = container_of(kobj, struct request_queue, kobj);
        if (!entry->show)
                return -EIO;
-
-       return entry->show(q, page);
+       mutex_lock(&q->sysfs_lock);
+       if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)) {
+               mutex_unlock(&q->sysfs_lock);
+               return -ENOENT;
+       }
+       res = entry->show(q, page);
+       mutex_unlock(&q->sysfs_lock);
+       return res;
 }
 
 static ssize_t
@@ -3772,13 +3804,20 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
                    const char *page, size_t length)
 {
        struct queue_sysfs_entry *entry = to_queue(attr);
-       struct request_queue *q;
+       request_queue_t *q = container_of(kobj, struct request_queue, kobj);
+
+       ssize_t res;
 
-       q = container_of(kobj, struct request_queue, kobj);
        if (!entry->store)
                return -EIO;
-
-       return entry->store(q, page, length);
+       mutex_lock(&q->sysfs_lock);
+       if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)) {
+               mutex_unlock(&q->sysfs_lock);
+               return -ENOENT;
+       }
+       res = entry->store(q, page, length);
+       mutex_unlock(&q->sysfs_lock);
+       return res;
 }
 
 static struct sysfs_ops queue_sysfs_ops = {
@@ -3789,6 +3828,7 @@ static struct sysfs_ops queue_sysfs_ops = {
 static struct kobj_type queue_ktype = {
        .sysfs_ops      = &queue_sysfs_ops,
        .default_attrs  = default_attrs,
+       .release        = blk_release_queue,
 };
 
 int blk_register_queue(struct gendisk *disk)
@@ -3801,19 +3841,17 @@ int blk_register_queue(struct gendisk *disk)
                return -ENXIO;
 
        q->kobj.parent = kobject_get(&disk->kobj);
-       if (!q->kobj.parent)
-               return -EBUSY;
 
-       snprintf(q->kobj.name, KOBJ_NAME_LEN, "%s", "queue");
-       q->kobj.ktype = &queue_ktype;
-
-       ret = kobject_register(&q->kobj);
+       ret = kobject_add(&q->kobj);
        if (ret < 0)
                return ret;
 
+       kobject_uevent(&q->kobj, KOBJ_ADD);
+
        ret = elv_register_queue(q);
        if (ret) {
-               kobject_unregister(&q->kobj);
+               kobject_uevent(&q->kobj, KOBJ_REMOVE);
+               kobject_del(&q->kobj);
                return ret;
        }
 
@@ -3827,7 +3865,8 @@ void blk_unregister_queue(struct gendisk *disk)
        if (q && q->request_fn) {
                elv_unregister_queue(q);
 
-               kobject_unregister(&q->kobj);
+               kobject_uevent(&q->kobj, KOBJ_REMOVE);
+               kobject_del(&q->kobj);
                kobject_put(&disk->kobj);
        }
 }
index 5f6d1a5..0010704 100644 (file)
@@ -1307,7 +1307,7 @@ static int __init loop_init(void)
 
 out_mem4:
        while (i--)
-               blk_put_queue(loop_dev[i].lo_queue);
+               blk_cleanup_queue(loop_dev[i].lo_queue);
        devfs_remove("loop");
        i = max_loop;
 out_mem3:
@@ -1328,7 +1328,7 @@ static void loop_exit(void)
 
        for (i = 0; i < max_loop; i++) {
                del_gendisk(disks[i]);
-               blk_put_queue(loop_dev[i].lo_queue);
+               blk_cleanup_queue(loop_dev[i].lo_queue);
                put_disk(disks[i]);
        }
        devfs_remove("loop");
index bc9b2bc..476a5b5 100644 (file)
@@ -2514,7 +2514,7 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
        return 0;
 
 out_new_dev:
-       blk_put_queue(disk->queue);
+       blk_cleanup_queue(disk->queue);
 out_mem2:
        put_disk(disk);
 out_mem:
@@ -2555,7 +2555,7 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd)
        DPRINTK("pktcdvd: writer %s unmapped\n", pd->name);
 
        del_gendisk(pd->disk);
-       blk_put_queue(pd->disk->queue);
+       blk_cleanup_queue(pd->disk->queue);
        put_disk(pd->disk);
 
        pkt_devs[idx] = NULL;
index 4ada126..c16e66b 100644 (file)
@@ -1131,7 +1131,7 @@ static void mm_pci_remove(struct pci_dev *dev)
                pci_free_consistent(card->dev, PAGE_SIZE*2,
                                    card->mm_pages[1].desc,
                                    card->mm_pages[1].page_dma);
-       blk_put_queue(card->queue);
+       blk_cleanup_queue(card->queue);
 }
 
 static const struct pci_device_id mm_pci_ids[] = { {
index ab89278..697aaca 100644 (file)
@@ -103,9 +103,15 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                return -EINVAL;
        }
 
+       if (((uint32_t)ti->len) & (chunk_size - 1)) {
+               ti->error = "dm-stripe: Target length not divisible by "
+                   "chunk size";
+               return -EINVAL;
+       }
+
        width = ti->len;
        if (sector_div(width, stripes)) {
-               ti->error = "dm-stripe: Target length not divisable by "
+               ti->error = "dm-stripe: Target length not divisible by "
                    "number of stripes";
                return -EINVAL;
        }
index 745ca1f..88d6020 100644 (file)
@@ -840,7 +840,7 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent)
  bad3:
        mempool_destroy(md->io_pool);
  bad2:
-       blk_put_queue(md->queue);
+       blk_cleanup_queue(md->queue);
        free_minor(minor);
  bad1:
        kfree(md);
@@ -860,7 +860,7 @@ static void free_dev(struct mapped_device *md)
        del_gendisk(md->disk);
        free_minor(minor);
        put_disk(md->disk);
-       blk_put_queue(md->queue);
+       blk_cleanup_queue(md->queue);
        kfree(md);
 }
 
index d05e312..5ed2228 100644 (file)
@@ -213,8 +213,11 @@ static void mddev_put(mddev_t *mddev)
                return;
        if (!mddev->raid_disks && list_empty(&mddev->disks)) {
                list_del(&mddev->all_mddevs);
-               blk_put_queue(mddev->queue);
+               /* that blocks */
+               blk_cleanup_queue(mddev->queue);
+               /* that also blocks */
                kobject_unregister(&mddev->kobj);
+               /* result blows... */
        }
        spin_unlock(&all_mddevs_lock);
 }
index e99dfbb..87d79df 100644 (file)
@@ -15,20 +15,6 @@ config VIDEO_CX88
          To compile this driver as a module, choose M here: the
          module will be called cx8800
 
-config VIDEO_CX88_DVB
-       tristate "DVB/ATSC Support for cx2388x based TV cards"
-       depends on VIDEO_CX88 && DVB_CORE
-       select VIDEO_BUF_DVB
-       ---help---
-         This adds support for DVB/ATSC cards based on the
-         Connexant 2388x chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cx88-dvb.
-
-         You must also select one or more DVB/ATSC demodulators.
-         If you are unsure which you need, choose all of them.
-
 config VIDEO_CX88_ALSA
        tristate "ALSA DMA audio support"
        depends on VIDEO_CX88 && SND && EXPERIMENTAL
@@ -44,6 +30,20 @@ config VIDEO_CX88_ALSA
          To compile this driver as a module, choose M here: the
          module will be called cx88-alsa.
 
+config VIDEO_CX88_DVB
+       tristate "DVB/ATSC Support for cx2388x based TV cards"
+       depends on VIDEO_CX88 && DVB_CORE
+       select VIDEO_BUF_DVB
+       ---help---
+         This adds support for DVB/ATSC cards based on the
+         Connexant 2388x chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx88-dvb.
+
+         You must also select one or more DVB/ATSC demodulators.
+         If you are unsure which you need, choose all of them.
+
 config VIDEO_CX88_DVB_ALL_FRONTENDS
        bool "Build all supported frontends for cx2388x based TV cards"
        default y
index 94a14a2..5b26780 100644 (file)
@@ -367,6 +367,9 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
        em28xx_capture_start(dev, 1);
        em28xx_resolution_set(dev);
 
+       /* device needs to be initialized before isoc transfer */
+       video_mux(dev, 0);
+
        /* start the transfer */
        errCode = em28xx_init_isoc(dev);
        if (errCode)
index 830528d..dc845f3 100644 (file)
@@ -100,6 +100,10 @@ static int max_interrupt_work = 10;
 static char versionA[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
 static char versionB[] __initdata = "http://www.scyld.com/network/3c509.html\n";
 
+#if defined(CONFIG_PM) && (defined(CONFIG_MCA) || defined(CONFIG_EISA))
+#define EL3_SUSPEND
+#endif
+
 #ifdef EL3_DEBUG
 static int el3_debug = EL3_DEBUG;
 #else
@@ -174,9 +178,6 @@ struct el3_private {
        /* skb send-queue */
        int head, size;
        struct sk_buff *queue[SKB_QUEUE_SIZE];
-#ifdef CONFIG_PM_LEGACY
-       struct pm_dev *pmdev;
-#endif
        enum {
                EL3_MCA,
                EL3_PNP,
@@ -201,11 +202,15 @@ static void el3_tx_timeout (struct net_device *dev);
 static void el3_down(struct net_device *dev);
 static void el3_up(struct net_device *dev);
 static struct ethtool_ops ethtool_ops;
-#ifdef CONFIG_PM_LEGACY
-static int el3_suspend(struct pm_dev *pdev);
-static int el3_resume(struct pm_dev *pdev);
-static int el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data);
+#ifdef EL3_SUSPEND
+static int el3_suspend(struct device *, pm_message_t);
+static int el3_resume(struct device *);
+#else
+#define el3_suspend NULL
+#define el3_resume NULL
 #endif
+
+
 /* generic device remove for all device types */
 #if defined(CONFIG_EISA) || defined(CONFIG_MCA)
 static int el3_device_remove (struct device *device);
@@ -229,7 +234,9 @@ static struct eisa_driver el3_eisa_driver = {
                .driver   = {
                                .name    = "3c509",
                                .probe   = el3_eisa_probe,
-                               .remove  = __devexit_p (el3_device_remove)
+                               .remove  = __devexit_p (el3_device_remove),
+                               .suspend = el3_suspend,
+                               .resume  = el3_resume,
                }
 };
 #endif
@@ -262,6 +269,8 @@ static struct mca_driver el3_mca_driver = {
                                .bus = &mca_bus_type,
                                .probe = el3_mca_probe,
                                .remove = __devexit_p(el3_device_remove),
+                               .suspend = el3_suspend,
+                               .resume  = el3_resume,
                },
 };
 #endif /* CONFIG_MCA */
@@ -362,10 +371,6 @@ static void el3_common_remove (struct net_device *dev)
        struct el3_private *lp = netdev_priv(dev);
 
        (void) lp;                              /* Keep gcc quiet... */
-#ifdef CONFIG_PM_LEGACY
-       if (lp->pmdev)
-               pm_unregister(lp->pmdev);
-#endif
 #if defined(__ISAPNP__)
        if (lp->type == EL3_PNP)
                pnp_device_detach(to_pnp_dev(lp->dev));
@@ -572,16 +577,6 @@ no_pnp:
        if (err)
                goto out1;
 
-#ifdef CONFIG_PM_LEGACY
-       /* register power management */
-       lp->pmdev = pm_register(PM_ISA_DEV, card_idx, el3_pm_callback);
-       if (lp->pmdev) {
-               struct pm_dev *p;
-               p = lp->pmdev;
-               p->data = (struct net_device *)dev;
-       }
-#endif
-
        el3_cards++;
        lp->next_dev = el3_root_dev;
        el3_root_dev = dev;
@@ -1480,20 +1475,17 @@ el3_up(struct net_device *dev)
 }
 
 /* Power Management support functions */
-#ifdef CONFIG_PM_LEGACY
+#ifdef EL3_SUSPEND
 
 static int
-el3_suspend(struct pm_dev *pdev)
+el3_suspend(struct device *pdev, pm_message_t state)
 {
        unsigned long flags;
        struct net_device *dev;
        struct el3_private *lp;
        int ioaddr;
        
-       if (!pdev && !pdev->data)
-               return -EINVAL;
-
-       dev = (struct net_device *)pdev->data;
+       dev = pdev->driver_data;
        lp = netdev_priv(dev);
        ioaddr = dev->base_addr;
 
@@ -1510,17 +1502,14 @@ el3_suspend(struct pm_dev *pdev)
 }
 
 static int
-el3_resume(struct pm_dev *pdev)
+el3_resume(struct device *pdev)
 {
        unsigned long flags;
        struct net_device *dev;
        struct el3_private *lp;
        int ioaddr;
        
-       if (!pdev && !pdev->data)
-               return -EINVAL;
-
-       dev = (struct net_device *)pdev->data;
+       dev = pdev->driver_data;
        lp = netdev_priv(dev);
        ioaddr = dev->base_addr;
 
@@ -1536,20 +1525,7 @@ el3_resume(struct pm_dev *pdev)
        return 0;
 }
 
-static int
-el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data)
-{
-       switch (rqst) {
-               case PM_SUSPEND:
-                       return el3_suspend(pdev);
-
-               case PM_RESUME:
-                       return el3_resume(pdev);
-       }
-       return 0;
-}
-
-#endif /* CONFIG_PM_LEGACY */
+#endif /* EL3_SUSPEND */
 
 /* Parameters that may be passed into the module. */
 static int debug = -1;
index 9e1fe2e..b40885d 100644 (file)
 #include <linux/mca-legacy.h>
 #include <linux/ethtool.h>
 #include <linux/bitops.h>
+#include <linux/jiffies.h>
 
 #include <asm/uaccess.h>
 #include <asm/processor.h>
@@ -658,7 +659,7 @@ static int init586(struct net_device *dev)
 
        s = jiffies;            /* warning: only active with interrupts on !! */
        while (!(cfg_cmd->cmd_status & STAT_COMPL)) {
-               if (jiffies - s > 30*HZ/100)
+               if (time_after(jiffies, s + 30*HZ/100))
                        break;
        }
 
@@ -684,7 +685,7 @@ static int init586(struct net_device *dev)
 
        s = jiffies;
        while (!(ias_cmd->cmd_status & STAT_COMPL)) {
-               if (jiffies - s > 30*HZ/100)
+               if (time_after(jiffies, s + 30*HZ/100))
                        break;
        }
 
@@ -709,7 +710,7 @@ static int init586(struct net_device *dev)
 
        s = jiffies;
        while (!(tdr_cmd->cmd_status & STAT_COMPL)) {
-               if (jiffies - s > 30*HZ/100) {
+               if (time_after(jiffies, s + 30*HZ/100)) {
                        printk(KERN_WARNING "%s: %d Problems while running the TDR.\n", dev->name, __LINE__);
                        result = 1;
                        break;
@@ -798,7 +799,7 @@ static int init586(struct net_device *dev)
                        elmc_id_attn586();
                        s = jiffies;
                        while (!(mc_cmd->cmd_status & STAT_COMPL)) {
-                               if (jiffies - s > 30*HZ/100)
+                               if (time_after(jiffies, s + 30*HZ/100))
                                        break;
                        }
                        if (!(mc_cmd->cmd_status & STAT_COMPL)) {
index 7f47124..5d11a06 100644 (file)
@@ -258,6 +258,7 @@ static int vortex_debug = 1;
 #include <linux/highmem.h>
 #include <linux/eisa.h>
 #include <linux/bitops.h>
+#include <linux/jiffies.h>
 #include <asm/irq.h>                   /* For NR_IRQS only. */
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -841,7 +842,7 @@ enum xcvr_types {
        XCVR_100baseFx, XCVR_MII=6, XCVR_NWAY=8, XCVR_ExtMII=9, XCVR_Default=10,
 };
 
-static struct media_table {
+static const struct media_table {
        char *name;
        unsigned int media_bits:16,             /* Bits to set in Wn4_Media register. */
                mask:8,                                         /* The transceiver-present bit in Wn3_Config.*/
@@ -1445,7 +1446,7 @@ static int __devinit vortex_probe1(struct device *gendev,
        }
 
        {
-               static const char * ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
+               static const char * const ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
                unsigned int config;
                EL3WINDOW(3);
                vp->available_media = ioread16(ioaddr + Wn3_Options);
@@ -2724,7 +2725,7 @@ boomerang_rx(struct net_device *dev)
                        skb = dev_alloc_skb(PKT_BUF_SZ);
                        if (skb == NULL) {
                                static unsigned long last_jif;
-                               if ((jiffies - last_jif) > 10 * HZ) {
+                               if (time_after(jiffies, last_jif + 10 * HZ)) {
                                        printk(KERN_WARNING "%s: memory shortage\n", dev->name);
                                        last_jif = jiffies;
                                }
index 18b027e..86633c5 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
-#include <linux/irq.h>
+#include <asm/irq.h>
 /* Used for the temporal inet entries and routing */
 #include <linux/socket.h>
 #include <linux/bitops.h>
index dd41049..ce99845 100644 (file)
@@ -1276,7 +1276,7 @@ static int cp_change_mtu(struct net_device *dev, int new_mtu)
 }
 #endif /* BROKEN */
 
-static char mii_2_8139_map[8] = {
+static const char mii_2_8139_map[8] = {
        BasicModeCtrl,
        BasicModeStatus,
        0,
index 2beac55..e58d4c5 100644 (file)
@@ -229,7 +229,7 @@ typedef enum {
 
 
 /* indexed by board_t, above */
-static struct {
+static const struct {
        const char *name;
        u32 hw_flags;
 } board_info[] __devinitdata = {
@@ -1192,7 +1192,7 @@ static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_l
 #define mdio_delay()   RTL_R8(Config4)
 
 
-static char mii_2_8139_map[8] = {
+static const char mii_2_8139_map[8] = {
        BasicModeCtrl,
        BasicModeStatus,
        0,
index 13b745b..da0c878 100644 (file)
@@ -614,7 +614,7 @@ static void rebuild_rx_bufs(struct net_device *dev)
 static int init_i596_mem(struct net_device *dev)
 {
        struct i596_private *lp = dev->priv;
-#if !defined(ENABLE_MVME16x_NET) && !defined(ENABLE_BVME6000_NET)
+#if !defined(ENABLE_MVME16x_NET) && !defined(ENABLE_BVME6000_NET) || defined(ENABLE_APRICOT)
        short ioaddr = dev->base_addr;
 #endif
        unsigned long flags;
index aa633fa..e0b1109 100644 (file)
@@ -66,7 +66,7 @@ config BONDING
          'Trunking' by Sun, 802.3ad by the IEEE, and 'Bonding' in Linux.
 
          The driver supports multiple bonding modes to allow for both high
-         perfomance and high availability operation.
+         performance and high availability operation.
 
          Refer to <file:Documentation/networking/bonding.txt> for more
          information.
@@ -698,8 +698,8 @@ config VORTEX
        depends on NET_VENDOR_3COM && (PCI || EISA)
        select MII
        ---help---
-         This option enables driver support for a large number of 10mbps and
-         10/100mbps EISA, PCI and PCMCIA 3Com network cards:
+         This option enables driver support for a large number of 10Mbps and
+         10/100Mbps EISA, PCI and PCMCIA 3Com network cards:
 
          "Vortex"    (Fast EtherLink 3c590/3c592/3c595/3c597) EISA and PCI
          "Boomerang" (EtherLink XL 3c900 or 3c905)            PCI
@@ -1021,7 +1021,7 @@ config EEXPRESS_PRO
        depends on NET_ISA
        ---help---
          If you have a network (Ethernet) card of this type, say Y. This
-         driver supports intel i82595{FX,TX} based boards. Note however
+         driver supports Intel i82595{FX,TX} based boards. Note however
          that the EtherExpress PRO/100 Ethernet card has its own separate
          driver.  Please read the Ethernet-HOWTO, available from
          <http://www.tldp.org/docs.html#howto>.
@@ -1208,7 +1208,7 @@ config IBM_EMAC_RX_SKB_HEADROOM
        help
          Additional receive skb headroom. Note, that driver
          will always reserve at least 2 bytes to make IP header
-         aligned, so usualy there is no need to add any additional
+         aligned, so usually there is no need to add any additional
          headroom.
          
          If unsure, set to 0.
@@ -1372,8 +1372,8 @@ config B44
          called b44.
 
 config FORCEDETH
-       tristate "Reverse Engineered nForce Ethernet support (EXPERIMENTAL)"
-       depends on NET_PCI && PCI && EXPERIMENTAL
+       tristate "nForce Ethernet support"
+       depends on NET_PCI && PCI
        help
          If you have a network (Ethernet) controller of this type, say Y and
          read the Ethernet-HOWTO, available from
@@ -1614,11 +1614,7 @@ config SIS900
        ---help---
          This is a driver for the Fast Ethernet PCI network cards based on
          the SiS 900 and SiS 7016 chips. The SiS 900 core is also embedded in
-         SiS 630 and SiS 540 chipsets.  If you have one of those, say Y and
-         read the Ethernet-HOWTO, available at
-         <http://www.tldp.org/docs.html#howto>.  Please read
-         <file:Documentation/networking/sis900.txt> and comments at the
-         beginning of <file:drivers/net/sis900.c> for more information.
+         SiS 630 and SiS 540 chipsets.
 
          This driver also supports AMD 79C901 HomePNA so that you can use
          your phone line as a network cable.
@@ -1934,7 +1930,7 @@ config MYRI_SBUS
          will be called myri_sbus.  This is recommended.
 
 config NS83820
-       tristate "National Semiconduct DP83820 support"
+       tristate "National Semiconductor DP83820 support"
        depends on PCI
        help
          This is a driver for the National Semiconductor DP83820 series
@@ -2195,6 +2191,7 @@ config GFAR_NAPI
 config MV643XX_ETH
        tristate "MV-643XX Ethernet support"
        depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MOMENCO_OCELOT_3 || PPC_MULTIPLATFORM
+       select MII
        help
          This driver supports the gigabit Ethernet on the Marvell MV643XX
          chipset which is used in the Momenco Ocelot C and Jaguar ATX and
@@ -2514,7 +2511,7 @@ config PPP_FILTER
          Say Y here if you want to be able to filter the packets passing over
          PPP interfaces.  This allows you to control which packets count as
          activity (i.e. which packets will reset the idle timer or bring up
-         a demand-dialled link) and which packets are to be dropped entirely.
+         a demand-dialed link) and which packets are to be dropped entirely.
          You need to say Y here if you wish to use the pass-filter and
          active-filter options to pppd.
 
@@ -2702,8 +2699,8 @@ config SHAPER
          <file:Documentation/networking/shaper.txt> for more information.
 
          An alternative to this traffic shaper is the experimental
-         Class-Based Queueing (CBQ) scheduling support which you get if you
-         say Y to "QoS and/or fair queueing" above.
+         Class-Based Queuing (CBQ) scheduling support which you get if you
+         say Y to "QoS and/or fair queuing" above.
 
          To compile this driver as a module, choose M here: the module
          will be called shaper.  If unsure, say N.
index a94216b..b9820b8 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/jiffies.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -216,7 +217,7 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr)
        outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
 
        while ((inb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
-               if (jiffies - reset_start_time > 2*HZ/100) {
+               if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
                        printk(" not found (no reset ack).\n");
                        return -ENODEV;
                }
@@ -382,7 +383,7 @@ apne_reset_8390(struct net_device *dev)
 
     /* This check _should_not_ be necessary, omit eventually. */
     while ((inb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0)
-       if (jiffies - reset_start_time > 2*HZ/100) {
+       if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
            printk("%s: ne_reset_8390() did not complete.\n", dev->name);
            break;
        }
@@ -530,7 +531,7 @@ apne_block_output(struct net_device *dev, int count,
     dma_start = jiffies;
 
     while ((inb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
-       if (jiffies - dma_start > 2*HZ/100) {           /* 20ms */
+       if (time_after(jiffies, dma_start + 2*HZ/100)) {        /* 20ms */
                printk("%s: timeout waiting for Tx RDC.\n", dev->name);
                apne_reset_8390(dev);
                NS8390_init(dev,1);
index 948de25..7284cca 100644 (file)
@@ -68,10 +68,10 @@ config ARCNET_CAP
           packet is stuffed with an extra 4 byte "cookie" which doesn't
           actually appear on the network. After transmit the driver will send
           back a packet with protocol byte 0 containing the status of the
-          transmition:
+          transmission:
              0=no hardware acknowledge
              1=excessive nak
-             2=transmition accepted by the reciever hardware
+             2=transmission accepted by the receiver hardware
 
           Received packets are also stuffed with the extra 4 bytes but it will
           be random data.
index e1ea29b..e7555d4 100644 (file)
@@ -42,7 +42,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
 static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
                      int bufnum);
 
-struct ArcProto rawmode_proto =
+static struct ArcProto rawmode_proto =
 {
        .suffix         = 'r',
        .mtu            = XMTU,
index 38c3f03..8c8d6c4 100644 (file)
@@ -97,25 +97,44 @@ static int __init arcrimi_probe(struct net_device *dev)
                       "must specify the shmem and irq!\n");
                return -ENODEV;
        }
+       if (dev->dev_addr[0] == 0) {
+               BUGMSG(D_NORMAL, "You need to specify your card's station "
+                      "ID!\n");
+               return -ENODEV;
+       }
        /*
-        * Grab the memory region at mem_start for BUFFER_SIZE bytes.
+        * Grab the memory region at mem_start for MIRROR_SIZE bytes.
         * Later in arcrimi_found() the real size will be determined
         * and this reserve will be released and the correct size
         * will be taken.
         */
-       if (!request_mem_region(dev->mem_start, BUFFER_SIZE, "arcnet (90xx)")) {
+       if (!request_mem_region(dev->mem_start, MIRROR_SIZE, "arcnet (90xx)")) {
                BUGMSG(D_NORMAL, "Card memory already allocated\n");
                return -ENODEV;
        }
-       if (dev->dev_addr[0] == 0) {
-               release_mem_region(dev->mem_start, BUFFER_SIZE);
-               BUGMSG(D_NORMAL, "You need to specify your card's station "
-                      "ID!\n");
-               return -ENODEV;
-       }
        return arcrimi_found(dev);
 }
 
+static int check_mirror(unsigned long addr, size_t size)
+{
+       void __iomem *p;
+       int res = -1;
+
+       if (!request_mem_region(addr, size, "arcnet (90xx)"))
+               return -1;
+
+       p = ioremap(addr, size);
+       if (p) {
+               if (readb(p) == TESTvalue)
+                       res = 1;
+               else
+                       res = 0;
+               iounmap(p);
+       }
+
+       release_mem_region(addr, size);
+       return res;
+}
 
 /*
  * Set up the struct net_device associated with this card.  Called after
@@ -125,19 +144,28 @@ static int __init arcrimi_found(struct net_device *dev)
 {
        struct arcnet_local *lp;
        unsigned long first_mirror, last_mirror, shmem;
+       void __iomem *p;
        int mirror_size;
        int err;
 
+       p = ioremap(dev->mem_start, MIRROR_SIZE);
+       if (!p) {
+               release_mem_region(dev->mem_start, MIRROR_SIZE);
+               BUGMSG(D_NORMAL, "Can't ioremap\n");
+               return -ENODEV;
+       }
+
        /* reserve the irq */
        if (request_irq(dev->irq, &arcnet_interrupt, 0, "arcnet (RIM I)", dev)) {
-               release_mem_region(dev->mem_start, BUFFER_SIZE);
+               iounmap(p);
+               release_mem_region(dev->mem_start, MIRROR_SIZE);
                BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
                return -ENODEV;
        }
 
        shmem = dev->mem_start;
-       isa_writeb(TESTvalue, shmem);
-       isa_writeb(dev->dev_addr[0], shmem + 1);        /* actually the node ID */
+       writeb(TESTvalue, p);
+       writeb(dev->dev_addr[0], p + 1);        /* actually the node ID */
 
        /* find the real shared memory start/end points, including mirrors */
 
@@ -146,17 +174,18 @@ static int __init arcrimi_found(struct net_device *dev)
         * 2k (or there are no mirrors at all) but on some, it's 4k.
         */
        mirror_size = MIRROR_SIZE;
-       if (isa_readb(shmem) == TESTvalue
-           && isa_readb(shmem - mirror_size) != TESTvalue
-           && isa_readb(shmem - 2 * mirror_size) == TESTvalue)
-               mirror_size *= 2;
+       if (readb(p) == TESTvalue
+           && check_mirror(shmem - MIRROR_SIZE, MIRROR_SIZE) == 0
+           && check_mirror(shmem - 2 * MIRROR_SIZE, MIRROR_SIZE) == 1)
+               mirror_size = 2 * MIRROR_SIZE;
 
-       first_mirror = last_mirror = shmem;
-       while (isa_readb(first_mirror) == TESTvalue)
+       first_mirror = shmem - mirror_size;
+       while (check_mirror(first_mirror, mirror_size) == 1)
                first_mirror -= mirror_size;
        first_mirror += mirror_size;
 
-       while (isa_readb(last_mirror) == TESTvalue)
+       last_mirror = shmem + mirror_size;
+       while (check_mirror(last_mirror, mirror_size) == 1)
                last_mirror += mirror_size;
        last_mirror -= mirror_size;
 
@@ -181,7 +210,8 @@ static int __init arcrimi_found(struct net_device *dev)
         * with the correct size.  There is a VERY slim chance this could
         * fail.
         */
-       release_mem_region(shmem, BUFFER_SIZE);
+       iounmap(p);
+       release_mem_region(shmem, MIRROR_SIZE);
        if (!request_mem_region(dev->mem_start,
                                dev->mem_end - dev->mem_start + 1,
                                "arcnet (90xx)")) {
index 12ef52c..64e2caf 100644 (file)
@@ -52,6 +52,7 @@
 #include <net/arp.h>
 #include <linux/init.h>
 #include <linux/arcdevice.h>
+#include <linux/jiffies.h>
 
 /* "do nothing" functions for protocol drivers */
 static void null_rx(struct net_device *dev, int bufnum,
@@ -61,6 +62,7 @@ static int null_build_header(struct sk_buff *skb, struct net_device *dev,
 static int null_prepare_tx(struct net_device *dev, struct archdr *pkt,
                           int length, int bufnum);
 
+static void arcnet_rx(struct net_device *dev, int bufnum);
 
 /*
  * one ArcProto per possible proto ID.  None of the elements of
@@ -71,7 +73,7 @@ static int null_prepare_tx(struct net_device *dev, struct archdr *pkt,
  struct ArcProto *arc_proto_map[256], *arc_proto_default,
    *arc_bcast_proto, *arc_raw_proto;
 
-struct ArcProto arc_proto_null =
+static struct ArcProto arc_proto_null =
 {
        .suffix         = '?',
        .mtu            = XMTU,
@@ -90,7 +92,6 @@ EXPORT_SYMBOL(arc_proto_map);
 EXPORT_SYMBOL(arc_proto_default);
 EXPORT_SYMBOL(arc_bcast_proto);
 EXPORT_SYMBOL(arc_raw_proto);
-EXPORT_SYMBOL(arc_proto_null);
 EXPORT_SYMBOL(arcnet_unregister_proto);
 EXPORT_SYMBOL(arcnet_debug);
 EXPORT_SYMBOL(alloc_arcdev);
@@ -118,7 +119,7 @@ static int __init arcnet_init(void)
 
        arcnet_debug = debug;
 
-       printk(VERSION);
+       printk("arcnet loaded.\n");
 
 #ifdef ALPHA_WARNING
        BUGLVL(D_EXTRA) {
@@ -178,8 +179,8 @@ EXPORT_SYMBOL(arcnet_dump_skb);
  * Dump the contents of an ARCnet buffer
  */
 #if (ARCNET_DEBUG_MAX & (D_RX | D_TX))
-void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc,
-                       int take_arcnet_lock)
+static void arcnet_dump_packet(struct net_device *dev, int bufnum,
+                              char *desc, int take_arcnet_lock)
 {
        struct arcnet_local *lp = dev->priv;
        int i, length;
@@ -208,7 +209,10 @@ void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc,
 
 }
 
-EXPORT_SYMBOL(arcnet_dump_packet);
+#else
+
+#define arcnet_dump_packet(dev, bufnum, desc,take_arcnet_lock) do { } while (0)
+
 #endif
 
 
@@ -733,7 +737,7 @@ static void arcnet_timeout(struct net_device *dev)
        
        spin_unlock_irqrestore(&lp->lock, flags);
 
-       if (jiffies - lp->last_timeout > 10*HZ) {
+       if (time_after(jiffies, lp->last_timeout + 10*HZ)) {
                BUGMSG(D_EXTRA, "tx timed out%s (status=%Xh, intmask=%Xh, dest=%02Xh)\n",
                       msg, status, lp->intmask, lp->lasttrans_dest);
                lp->last_timeout = jiffies;
@@ -996,7 +1000,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  * This is a generic packet receiver that calls arcnet??_rx depending on the
  * protocol ID found.
  */
-void arcnet_rx(struct net_device *dev, int bufnum)
+static void arcnet_rx(struct net_device *dev, int bufnum)
 {
        struct arcnet_local *lp = dev->priv;
        struct archdr pkt;
index 6c2c9b9..43150b2 100644 (file)
@@ -53,7 +53,7 @@
 
 
 /* Internal function declarations */
-static int com90xx_found(int ioaddr, int airq, u_long shmem);
+static int com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem *);
 static void com90xx_command(struct net_device *dev, int command);
 static int com90xx_status(struct net_device *dev);
 static void com90xx_setmask(struct net_device *dev, int mask);
@@ -116,14 +116,26 @@ static void __init com90xx_probe(void)
        unsigned long airqmask;
        int ports[(0x3f0 - 0x200) / 16 + 1] =
        {0};
-       u_long shmems[(0xFF800 - 0xA0000) / 2048 + 1] =
-       {0};
+       unsigned long *shmems;
+       void __iomem **iomem;
        int numports, numshmems, *port;
        u_long *p;
+       int index;
 
        if (!io && !irq && !shmem && !*device && com90xx_skip_probe)
                return;
 
+       shmems = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(unsigned long),
+                        GFP_KERNEL);
+       if (!shmems)
+               return;
+       iomem = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(void __iomem *),
+                        GFP_KERNEL);
+       if (!iomem) {
+               kfree(shmems);
+               return;
+       }
+
        BUGLVL(D_NORMAL) printk(VERSION);
 
        /* set up the arrays where we'll store the possible probe addresses */
@@ -179,6 +191,8 @@ static void __init com90xx_probe(void)
 
        if (!numports) {
                BUGMSG2(D_NORMAL, "S1: No ARCnet cards found.\n");
+               kfree(shmems);
+               kfree(iomem);
                return;
        }
        /* Stage 2: we have now reset any possible ARCnet cards, so we can't
@@ -202,8 +216,8 @@ static void __init com90xx_probe(void)
         * 0xD1 byte in the right place, or are read-only.
         */
        numprint = -1;
-       for (p = &shmems[0]; p < shmems + numshmems; p++) {
-               u_long ptr = *p;
+       for (index = 0, p = &shmems[0]; index < numshmems; p++, index++) {
+               void __iomem *base;
 
                numprint++;
                numprint %= 8;
@@ -213,38 +227,49 @@ static void __init com90xx_probe(void)
                }
                BUGMSG2(D_INIT, "%lXh ", *p);
 
-               if (!request_mem_region(*p, BUFFER_SIZE, "arcnet (90xx)")) {
+               if (!request_mem_region(*p, MIRROR_SIZE, "arcnet (90xx)")) {
                        BUGMSG2(D_INIT_REASONS, "(request_mem_region)\n");
                        BUGMSG2(D_INIT_REASONS, "Stage 3: ");
                        BUGLVL(D_INIT_REASONS) numprint = 0;
-                       *p-- = shmems[--numshmems];
-                       continue;
+                       goto out;
+               }
+               base = ioremap(*p, MIRROR_SIZE);
+               if (!base) {
+                       BUGMSG2(D_INIT_REASONS, "(ioremap)\n");
+                       BUGMSG2(D_INIT_REASONS, "Stage 3: ");
+                       BUGLVL(D_INIT_REASONS) numprint = 0;
+                       goto out1;
                }
-               if (isa_readb(ptr) != TESTvalue) {
+               if (readb(base) != TESTvalue) {
                        BUGMSG2(D_INIT_REASONS, "(%02Xh != %02Xh)\n",
-                               isa_readb(ptr), TESTvalue);
+                               readb(base), TESTvalue);
                        BUGMSG2(D_INIT_REASONS, "S3: ");
                        BUGLVL(D_INIT_REASONS) numprint = 0;
-                       release_mem_region(*p, BUFFER_SIZE);
-                       *p-- = shmems[--numshmems];
-                       continue;
+                       goto out2;
                }
                /* By writing 0x42 to the TESTvalue location, we also make
                 * sure no "mirror" shmem areas show up - if they occur
                 * in another pass through this loop, they will be discarded
                 * because *cptr != TESTvalue.
                 */
-               isa_writeb(0x42, ptr);
-               if (isa_readb(ptr) != 0x42) {
+               writeb(0x42, base);
+               if (readb(base) != 0x42) {
                        BUGMSG2(D_INIT_REASONS, "(read only)\n");
                        BUGMSG2(D_INIT_REASONS, "S3: ");
-                       release_mem_region(*p, BUFFER_SIZE);
-                       *p-- = shmems[--numshmems];
-                       continue;
+                       goto out2;
                }
                BUGMSG2(D_INIT_REASONS, "\n");
                BUGMSG2(D_INIT_REASONS, "S3: ");
                BUGLVL(D_INIT_REASONS) numprint = 0;
+               iomem[index] = base;
+               continue;
+       out2:
+               iounmap(base);
+       out1:
+               release_mem_region(*p, MIRROR_SIZE);
+       out:
+               *p-- = shmems[--numshmems];
+               index--;
        }
        BUGMSG2(D_INIT, "\n");
 
@@ -252,6 +277,8 @@ static void __init com90xx_probe(void)
                BUGMSG2(D_NORMAL, "S3: No ARCnet cards found.\n");
                for (port = &ports[0]; port < ports + numports; port++)
                        release_region(*port, ARCNET_TOTAL_SIZE);
+               kfree(shmems);
+               kfree(iomem);
                return;
        }
        /* Stage 4: something of a dummy, to report the shmems that are
@@ -351,30 +378,32 @@ static void __init com90xx_probe(void)
                        mdelay(RESETtime);
                } else {
                        /* just one shmem and port, assume they match */
-                       isa_writeb(TESTvalue, shmems[0]);
+                       writeb(TESTvalue, iomem[0]);
                }
 #else
                inb(_RESET);
                mdelay(RESETtime);
 #endif
 
-               for (p = &shmems[0]; p < shmems + numshmems; p++) {
-                       u_long ptr = *p;
+               for (index = 0; index < numshmems; index++) {
+                       u_long ptr = shmems[index];
+                       void __iomem *base = iomem[index];
 
-                       if (isa_readb(ptr) == TESTvalue) {      /* found one */
+                       if (readb(base) == TESTvalue) { /* found one */
                                BUGMSG2(D_INIT, "%lXh)\n", *p);
                                openparen = 0;
 
                                /* register the card */
-                               if (com90xx_found(*port, airq, *p) == 0)
+                               if (com90xx_found(*port, airq, ptr, base) == 0)
                                        found = 1;
                                numprint = -1;
 
                                /* remove shmem from the list */
-                               *p = shmems[--numshmems];
+                               shmems[index] = shmems[--numshmems];
+                               iomem[index] = iomem[numshmems];
                                break;  /* go to the next I/O port */
                        } else {
-                               BUGMSG2(D_INIT_REASONS, "%Xh-", isa_readb(ptr));
+                               BUGMSG2(D_INIT_REASONS, "%Xh-", readb(base));
                        }
                }
 
@@ -391,17 +420,40 @@ static void __init com90xx_probe(void)
        BUGLVL(D_INIT_REASONS) printk("\n");
 
        /* Now put back TESTvalue on all leftover shmems. */
-       for (p = &shmems[0]; p < shmems + numshmems; p++) {
-               isa_writeb(TESTvalue, *p);
-               release_mem_region(*p, BUFFER_SIZE);
+       for (index = 0; index < numshmems; index++) {
+               writeb(TESTvalue, iomem[index]);
+               iounmap(iomem[index]);
+               release_mem_region(shmems[index], MIRROR_SIZE);
        }
+       kfree(shmems);
+       kfree(iomem);
 }
 
+static int check_mirror(unsigned long addr, size_t size)
+{
+       void __iomem *p;
+       int res = -1;
+
+       if (!request_mem_region(addr, size, "arcnet (90xx)"))
+               return -1;
+
+       p = ioremap(addr, size);
+       if (p) {
+               if (readb(p) == TESTvalue)
+                       res = 1;
+               else
+                       res = 0;
+               iounmap(p);
+       }
+
+       release_mem_region(addr, size);
+       return res;
+}
 
 /* Set up the struct net_device associated with this card.  Called after
  * probing succeeds.
  */
-static int __init com90xx_found(int ioaddr, int airq, u_long shmem)
+static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem *p)
 {
        struct net_device *dev = NULL;
        struct arcnet_local *lp;
@@ -412,7 +464,8 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem)
        dev = alloc_arcdev(device);
        if (!dev) {
                BUGMSG2(D_NORMAL, "com90xx: Can't allocate device!\n");
-               release_mem_region(shmem, BUFFER_SIZE);
+               iounmap(p);
+               release_mem_region(shmem, MIRROR_SIZE);
                return -ENOMEM;
        }
        lp = dev->priv;
@@ -423,24 +476,27 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem)
         * 2k (or there are no mirrors at all) but on some, it's 4k.
         */
        mirror_size = MIRROR_SIZE;
-       if (isa_readb(shmem) == TESTvalue
-           && isa_readb(shmem - mirror_size) != TESTvalue
-           && isa_readb(shmem - 2 * mirror_size) == TESTvalue)
-               mirror_size *= 2;
+       if (readb(p) == TESTvalue &&
+           check_mirror(shmem - MIRROR_SIZE, MIRROR_SIZE) == 0 &&
+           check_mirror(shmem - 2 * MIRROR_SIZE, MIRROR_SIZE) == 1)
+               mirror_size = 2 * MIRROR_SIZE;
 
-       first_mirror = last_mirror = shmem;
-       while (isa_readb(first_mirror) == TESTvalue)
+       first_mirror = shmem - mirror_size;
+       while (check_mirror(first_mirror, mirror_size) == 1)
                first_mirror -= mirror_size;
        first_mirror += mirror_size;
 
-       while (isa_readb(last_mirror) == TESTvalue)
+       last_mirror = shmem + mirror_size;
+       while (check_mirror(last_mirror, mirror_size) == 1)
                last_mirror += mirror_size;
        last_mirror -= mirror_size;
 
        dev->mem_start = first_mirror;
        dev->mem_end = last_mirror + MIRROR_SIZE - 1;
 
-       release_mem_region(shmem, BUFFER_SIZE);
+       iounmap(p);
+       release_mem_region(shmem, MIRROR_SIZE);
+
        if (!request_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1, "arcnet (90xx)"))
                goto err_free_dev;
 
index 6d79137..6d6c69f 100644 (file)
@@ -43,7 +43,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
                      int bufnum);
 
 
-struct ArcProto rfc1051_proto =
+static struct ArcProto rfc1051_proto =
 {
        .suffix         = 's',
        .mtu            = XMTU - RFC1051_HDR_SIZE,
index 6b6ae4b..bee3422 100644 (file)
@@ -43,7 +43,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
                      int bufnum);
 static int continue_tx(struct net_device *dev, int bufnum);
 
-struct ArcProto rfc1201_proto =
+static struct ArcProto rfc1201_proto =
 {
        .suffix         = 'a',
        .mtu            = 1500, /* could be more, but some receivers can't handle it... */
index 6a93b66..d52deb8 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
+#include <linux/jiffies.h>
 
 #include <asm/system.h>
 #include <asm/ecard.h>
@@ -355,7 +356,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
        dma_start = jiffies;
 
        while ((readb (addr + EN0_ISR) & ENISR_RDC) == 0)
-               if (jiffies - dma_start > 2*HZ/100) { /* 20ms */
+               if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */
                        printk(KERN_ERR "%s: timeout waiting for TX RDC\n",
                                dev->name);
                        etherh_reset (dev);
index a24200d..b787b65 100644 (file)
@@ -46,7 +46,7 @@ typedef enum {
 } board_t;
 
 /* indexed by board_t, above */
-static struct {
+static const struct {
        char *name;
 } board_info[] __devinitdata = {
        { "Broadcom NetXtreme II BCM5706 1000Base-T" },
@@ -3476,7 +3476,7 @@ bnx2_test_registers(struct bnx2 *bp)
 {
        int ret;
        int i;
-       static struct {
+       static const struct {
                u16   offset;
                u16   flags;
                u32   rw_mask;
@@ -3891,7 +3891,7 @@ reg_test_err:
 static int
 bnx2_do_mem_test(struct bnx2 *bp, u32 start, u32 size)
 {
-       static u32 test_pattern[] = { 0x00000000, 0xffffffff, 0x55555555,
+       static const u32 test_pattern[] = { 0x00000000, 0xffffffff, 0x55555555,
                0xaaaaaaaa , 0xaa55aa55, 0x55aa55aa };
        int i;
 
@@ -3916,7 +3916,7 @@ bnx2_test_memory(struct bnx2 *bp)
 {
        int ret = 0;
        int i;
-       static struct {
+       static const struct {
                u32   offset;
                u32   len;
        } mem_tbl[] = {
@@ -5122,7 +5122,7 @@ static struct {
 
 #define STATS_OFFSET32(offset_name) (offsetof(struct statistics_block, offset_name) / 4)
 
-static unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = {
+static const unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = {
     STATS_OFFSET32(stat_IfHCInOctets_hi),
     STATS_OFFSET32(stat_IfHCInBadOctets_hi),
     STATS_OFFSET32(stat_IfHCOutOctets_hi),
index 0c21bd8..8158974 100644 (file)
  * accompanying it.
  */
 
-static int bnx2_COM_b06FwReleaseMajor = 0x1;
-static int bnx2_COM_b06FwReleaseMinor = 0x0;
-static int bnx2_COM_b06FwReleaseFix = 0x0;
-static u32 bnx2_COM_b06FwStartAddr = 0x080008b4;
-static u32 bnx2_COM_b06FwTextAddr = 0x08000000;
-static int bnx2_COM_b06FwTextLen = 0x57bc;
-static u32 bnx2_COM_b06FwDataAddr = 0x08005840;
-static int bnx2_COM_b06FwDataLen = 0x0;
-static u32 bnx2_COM_b06FwRodataAddr = 0x080057c0;
-static int bnx2_COM_b06FwRodataLen = 0x58;
-static u32 bnx2_COM_b06FwBssAddr = 0x08005860;
-static int bnx2_COM_b06FwBssLen = 0x88;
-static u32 bnx2_COM_b06FwSbssAddr = 0x08005840;
-static int bnx2_COM_b06FwSbssLen = 0x1c;
+static const int bnx2_COM_b06FwReleaseMajor = 0x1;
+static const int bnx2_COM_b06FwReleaseMinor = 0x0;
+static const int bnx2_COM_b06FwReleaseFix = 0x0;
+static const u32 bnx2_COM_b06FwStartAddr = 0x080008b4;
+static const u32 bnx2_COM_b06FwTextAddr = 0x08000000;
+static const int bnx2_COM_b06FwTextLen = 0x57bc;
+static const u32 bnx2_COM_b06FwDataAddr = 0x08005840;
+static const int bnx2_COM_b06FwDataLen = 0x0;
+static const u32 bnx2_COM_b06FwRodataAddr = 0x080057c0;
+static const int bnx2_COM_b06FwRodataLen = 0x58;
+static const u32 bnx2_COM_b06FwBssAddr = 0x08005860;
+static const int bnx2_COM_b06FwBssLen = 0x88;
+static const u32 bnx2_COM_b06FwSbssAddr = 0x08005840;
+static const int bnx2_COM_b06FwSbssLen = 0x1c;
 static u32 bnx2_COM_b06FwText[(0x57bc/4) + 1] = {
        0x0a00022d, 0x00000000, 0x00000000, 0x0000000d, 0x636f6d20, 0x322e352e,
        0x38000000, 0x02050802, 0x00000000, 0x00000003, 0x00000014, 0x00000032,
@@ -2325,20 +2325,20 @@ static u32 bnx2_rv2p_proc2[] = {
        0x0000000c, 0x29520000, 0x00000018, 0x80000002, 0x0000000c, 0x29800000,
        0x00000018, 0x00570000 };
 
-static int bnx2_TPAT_b06FwReleaseMajor = 0x1;
-static int bnx2_TPAT_b06FwReleaseMinor = 0x0;
-static int bnx2_TPAT_b06FwReleaseFix = 0x0;
-static u32 bnx2_TPAT_b06FwStartAddr = 0x08000860;
-static u32 bnx2_TPAT_b06FwTextAddr = 0x08000800;
-static int bnx2_TPAT_b06FwTextLen = 0x122c;
-static u32 bnx2_TPAT_b06FwDataAddr = 0x08001a60;
-static int bnx2_TPAT_b06FwDataLen = 0x0;
-static u32 bnx2_TPAT_b06FwRodataAddr = 0x00000000;
-static int bnx2_TPAT_b06FwRodataLen = 0x0;
-static u32 bnx2_TPAT_b06FwBssAddr = 0x08001aa0;
-static int bnx2_TPAT_b06FwBssLen = 0x250;
-static u32 bnx2_TPAT_b06FwSbssAddr = 0x08001a60;
-static int bnx2_TPAT_b06FwSbssLen = 0x34;
+static const int bnx2_TPAT_b06FwReleaseMajor = 0x1;
+static const int bnx2_TPAT_b06FwReleaseMinor = 0x0;
+static const int bnx2_TPAT_b06FwReleaseFix = 0x0;
+static const u32 bnx2_TPAT_b06FwStartAddr = 0x08000860;
+static const u32 bnx2_TPAT_b06FwTextAddr = 0x08000800;
+static const int bnx2_TPAT_b06FwTextLen = 0x122c;
+static const u32 bnx2_TPAT_b06FwDataAddr = 0x08001a60;
+static const int bnx2_TPAT_b06FwDataLen = 0x0;
+static const u32 bnx2_TPAT_b06FwRodataAddr = 0x00000000;
+static const int bnx2_TPAT_b06FwRodataLen = 0x0;
+static const u32 bnx2_TPAT_b06FwBssAddr = 0x08001aa0;
+static const int bnx2_TPAT_b06FwBssLen = 0x250;
+static const u32 bnx2_TPAT_b06FwSbssAddr = 0x08001a60;
+static const int bnx2_TPAT_b06FwSbssLen = 0x34;
 static u32 bnx2_TPAT_b06FwText[(0x122c/4) + 1] = {
        0x0a000218, 0x00000000, 0x00000000, 0x0000000d, 0x74706174, 0x20322e35,
        0x2e313100, 0x02050b01, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -2540,20 +2540,20 @@ static u32 bnx2_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x0 };
 static u32 bnx2_TPAT_b06FwBss[(0x250/4) + 1] = { 0x0 };
 static u32 bnx2_TPAT_b06FwSbss[(0x34/4) + 1] = { 0x0 };
 
-static int bnx2_TXP_b06FwReleaseMajor = 0x1;
-static int bnx2_TXP_b06FwReleaseMinor = 0x0;
-static int bnx2_TXP_b06FwReleaseFix = 0x0;
-static u32 bnx2_TXP_b06FwStartAddr = 0x080034b0;
-static u32 bnx2_TXP_b06FwTextAddr = 0x08000000;
-static int bnx2_TXP_b06FwTextLen = 0x5748;
-static u32 bnx2_TXP_b06FwDataAddr = 0x08005760;
-static int bnx2_TXP_b06FwDataLen = 0x0;
-static u32 bnx2_TXP_b06FwRodataAddr = 0x00000000;
-static int bnx2_TXP_b06FwRodataLen = 0x0;
-static u32 bnx2_TXP_b06FwBssAddr = 0x080057a0;
-static int bnx2_TXP_b06FwBssLen = 0x1c4;
-static u32 bnx2_TXP_b06FwSbssAddr = 0x08005760;
-static int bnx2_TXP_b06FwSbssLen = 0x38;
+static const int bnx2_TXP_b06FwReleaseMajor = 0x1;
+static const int bnx2_TXP_b06FwReleaseMinor = 0x0;
+static const int bnx2_TXP_b06FwReleaseFix = 0x0;
+static const u32 bnx2_TXP_b06FwStartAddr = 0x080034b0;
+static const u32 bnx2_TXP_b06FwTextAddr = 0x08000000;
+static const int bnx2_TXP_b06FwTextLen = 0x5748;
+static const u32 bnx2_TXP_b06FwDataAddr = 0x08005760;
+static const int bnx2_TXP_b06FwDataLen = 0x0;
+static const u32 bnx2_TXP_b06FwRodataAddr = 0x00000000;
+static const int bnx2_TXP_b06FwRodataLen = 0x0;
+static const u32 bnx2_TXP_b06FwBssAddr = 0x080057a0;
+static const int bnx2_TXP_b06FwBssLen = 0x1c4;
+static const u32 bnx2_TXP_b06FwSbssAddr = 0x08005760;
+static const int bnx2_TXP_b06FwSbssLen = 0x38;
 static u32 bnx2_TXP_b06FwText[(0x5748/4) + 1] = {
        0x0a000d2c, 0x00000000, 0x00000000, 0x0000000d, 0x74787020, 0x322e352e,
        0x38000000, 0x02050800, 0x0000000a, 0x000003e8, 0x0000ea60, 0x00000000,
index f2a6318..e83bc82 100644 (file)
@@ -1261,7 +1261,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
        struct ethhdr *eth_data;
        struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
        struct slave *tx_slave = NULL;
-       static u32 ip_bcast = 0xffffffff;
+       static const u32 ip_bcast = 0xffffffff;
        int hash_size = 0;
        int do_tx_balance = 1;
        u32 hash_index = 0;
index bcf9f17..2d0ac16 100644 (file)
@@ -131,7 +131,7 @@ MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
 
 /*----------------------------- Global variables ----------------------------*/
 
-static const char *version =
+static const char * const version =
        DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n";
 
 LIST_HEAD(bond_dev_list);
@@ -1040,6 +1040,10 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
        if ((bond->params.mode == BOND_MODE_TLB) ||
            (bond->params.mode == BOND_MODE_ALB)) {
                bond_alb_handle_active_change(bond, new_active);
+               if (old_active)
+                       bond_set_slave_inactive_flags(old_active);
+               if (new_active)
+                       bond_set_slave_active_flags(new_active);
        } else {
                bond->curr_active_slave = new_active;
        }
@@ -1443,15 +1447,16 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
        switch (bond->params.mode) {
        case BOND_MODE_ACTIVEBACKUP:
-               /* if we're in active-backup mode, we need one and only one active
-                * interface. The backup interfaces will have their NOARP flag set
-                * because we need them to be completely deaf and not to respond to
-                * any ARP request on the network to avoid fooling a switch. Thus,
-                * since we guarantee that curr_active_slave always point to the last
-                * usable interface, we just have to verify this interface's flag.
+               /* if we're in active-backup mode, we need one and
+                * only one active interface. The backup interfaces
+                * will have their SLAVE_INACTIVE flag set because we
+                * need them to be drop all packets. Thus, since we
+                * guarantee that curr_active_slave always point to
+                * the last usable interface, we just have to verify
+                * this interface's flag.
                 */
                if (((!bond->curr_active_slave) ||
-                    (bond->curr_active_slave->dev->flags & IFF_NOARP)) &&
+                    (bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) &&
                    (new_slave->link != BOND_LINK_DOWN)) {
                        dprintk("This is the first active slave\n");
                        /* first slave or no active slave yet, and this link
@@ -1492,6 +1497,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
                         * is OK, so make this interface the active one
                         */
                        bond_change_active_slave(bond, new_slave);
+               } else {
+                       bond_set_slave_inactive_flags(new_slave);
                }
                break;
        default:
@@ -1724,13 +1731,8 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
        addr.sa_family = slave_dev->type;
        dev_set_mac_address(slave_dev, &addr);
 
-       /* restore the original state of the
-        * IFF_NOARP flag that might have been
-        * set by bond_set_slave_inactive_flags()
-        */
-       if ((slave->original_flags & IFF_NOARP) == 0) {
-               slave_dev->flags &= ~IFF_NOARP;
-       }
+       slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
+                                  IFF_SLAVE_INACTIVE);
 
        kfree(slave);
 
@@ -1816,12 +1818,8 @@ static int bond_release_all(struct net_device *bond_dev)
                addr.sa_family = slave_dev->type;
                dev_set_mac_address(slave_dev, &addr);
 
-               /* restore the original state of the IFF_NOARP flag that might have
-                * been set by bond_set_slave_inactive_flags()
-                */
-               if ((slave->original_flags & IFF_NOARP) == 0) {
-                       slave_dev->flags &= ~IFF_NOARP;
-               }
+               slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
+                                          IFF_SLAVE_INACTIVE);
 
                kfree(slave);
 
@@ -4061,14 +4059,17 @@ void bond_set_mode_ops(struct bonding *bond, int mode)
                bond_dev->hard_start_xmit = bond_xmit_broadcast;
                break;
        case BOND_MODE_8023AD:
+               bond_set_master_3ad_flags(bond);
                bond_dev->hard_start_xmit = bond_3ad_xmit_xor;
                if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34)
                        bond->xmit_hash_policy = bond_xmit_hash_policy_l34;
                else
                        bond->xmit_hash_policy = bond_xmit_hash_policy_l2;
                break;
-       case BOND_MODE_TLB:
        case BOND_MODE_ALB:
+               bond_set_master_alb_flags(bond);
+               /* FALLTHRU */
+       case BOND_MODE_TLB:
                bond_dev->hard_start_xmit = bond_alb_xmit;
                bond_dev->set_mac_address = bond_alb_set_mac_address;
                break;
index 041bcc5..5a9bd95 100644 (file)
@@ -424,6 +424,12 @@ static ssize_t bonding_store_mode(struct class_device *cd, const char *buf, size
                ret = -EINVAL;
                goto out;
        } else {
+               if (bond->params.mode == BOND_MODE_8023AD)
+                       bond_unset_master_3ad_flags(bond);
+
+               if (bond->params.mode == BOND_MODE_ALB)
+                       bond_unset_master_alb_flags(bond);
+
                bond->params.mode = new_value;
                bond_set_mode_ops(bond, bond->params.mode);
                printk(KERN_INFO DRV_NAME ": %s: setting mode to %s (%d).\n",
index 3dd78d0..ce9dc9b 100644 (file)
@@ -22,8 +22,8 @@
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#define DRV_VERSION    "3.0.1"
-#define DRV_RELDATE    "January 9, 2006"
+#define DRV_VERSION    "3.0.2"
+#define DRV_RELDATE    "February 21, 2006"
 #define DRV_NAME       "bonding"
 #define DRV_DESCRIPTION        "Ethernet Channel Bonding Driver"
 
@@ -230,14 +230,37 @@ static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
 
 static inline void bond_set_slave_inactive_flags(struct slave *slave)
 {
-       slave->state = BOND_STATE_BACKUP;
-       slave->dev->flags |= IFF_NOARP;
+       struct bonding *bond = slave->dev->master->priv;
+       if (bond->params.mode != BOND_MODE_TLB &&
+           bond->params.mode != BOND_MODE_ALB)
+               slave->state = BOND_STATE_BACKUP;
+       slave->dev->priv_flags |= IFF_SLAVE_INACTIVE;
 }
 
 static inline void bond_set_slave_active_flags(struct slave *slave)
 {
        slave->state = BOND_STATE_ACTIVE;
-       slave->dev->flags &= ~IFF_NOARP;
+       slave->dev->priv_flags &= ~IFF_SLAVE_INACTIVE;
+}
+
+static inline void bond_set_master_3ad_flags(struct bonding *bond)
+{
+       bond->dev->priv_flags |= IFF_MASTER_8023AD;
+}
+
+static inline void bond_unset_master_3ad_flags(struct bonding *bond)
+{
+       bond->dev->priv_flags &= ~IFF_MASTER_8023AD;
+}
+
+static inline void bond_set_master_alb_flags(struct bonding *bond)
+{
+       bond->dev->priv_flags |= IFF_MASTER_ALB;
+}
+
+static inline void bond_unset_master_alb_flags(struct bonding *bond)
+{
+       bond->dev->priv_flags &= ~IFF_MASTER_ALB;
 }
 
 struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
index e824aca..542e5e0 100644 (file)
@@ -87,15 +87,9 @@ static int tricn_write(adapter_t *adapter, int bundle_addr, int module_addr,
 static int tricn_init(adapter_t *adapter)
 {
        int     i               = 0;
-       int     sme             = 1;
        int     stat            = 0;
        int     timeout         = 0;
        int     is_ready        = 0;
-       int     dynamic_deskew  = 0;
-
-       if (dynamic_deskew)
-               sme = 0;
-
 
        /* 1 */
        timeout=1000;
@@ -113,11 +107,9 @@ static int tricn_init(adapter_t *adapter)
        }
 
        /* 2 */
-       if (sme) {
-               tricn_write(adapter, 0, 0, 0, TRICN_CNFG, 0x81);
-               tricn_write(adapter, 0, 1, 0, TRICN_CNFG, 0x81);
-               tricn_write(adapter, 0, 2, 0, TRICN_CNFG, 0x81);
-       }
+       tricn_write(adapter, 0, 0, 0, TRICN_CNFG, 0x81);
+       tricn_write(adapter, 0, 1, 0, TRICN_CNFG, 0x81);
+       tricn_write(adapter, 0, 2, 0, TRICN_CNFG, 0x81);
        for (i=1; i<= 8; i++) tricn_write(adapter, 0, 0, i, TRICN_CNFG, 0xf1);
        for (i=1; i<= 2; i++) tricn_write(adapter, 0, 1, i, TRICN_CNFG, 0xf1);
        for (i=1; i<= 3; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1);
index 2c5b849..30ff8ea 100644 (file)
@@ -1021,7 +1021,7 @@ static void restart_tx_queues(struct sge *sge)
                        if (test_and_clear_bit(nd->if_port,
                                               &sge->stopped_tx_queues) &&
                            netif_running(nd)) {
-                               sge->stats.cmdQ_restarted[3]++;
+                               sge->stats.cmdQ_restarted[2]++;
                                netif_wake_queue(nd);
                        }
                }
@@ -1350,7 +1350,7 @@ static int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
                if (unlikely(credits < count)) {
                        netif_stop_queue(dev);
                        set_bit(dev->if_port, &sge->stopped_tx_queues);
-                       sge->stats.cmdQ_full[3]++;
+                       sge->stats.cmdQ_full[2]++;
                        spin_unlock(&q->lock);
                        if (!netif_queue_stopped(dev))
                                CH_ERR("%s: Tx ring full while queue awake!\n",
@@ -1358,7 +1358,7 @@ static int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
                        return NETDEV_TX_BUSY;
                }
                if (unlikely(credits - count < q->stop_thres)) {
-                       sge->stats.cmdQ_full[3]++;
+                       sge->stats.cmdQ_full[2]++;
                        netif_stop_queue(dev);
                        set_bit(dev->if_port, &sge->stopped_tx_queues);
                }
index 1ebb5d1..12e4e96 100644 (file)
@@ -686,7 +686,7 @@ int t1_init_hw_modules(adapter_t *adapter)
  */
 static void __devinit get_pci_mode(adapter_t *adapter, struct chelsio_pci_params *p)
 {
-       static unsigned short speed_map[] = { 33, 66, 100, 133 };
+       static const unsigned short speed_map[] = { 33, 66, 100, 133 };
        u32 pci_mode;
 
        pci_read_config_dword(adapter->pdev, A_PCICFG_MODE, &pci_mode);
index 70b47e4..32d1316 100644 (file)
@@ -993,7 +993,7 @@ dgrs_download(struct net_device *dev0)
        int             is;
        unsigned long   i;
 
-       static int      iv2is[16] = {
+       static const int iv2is[16] = {
                                0, 0, 0, ES4H_IS_INT3,
                                0, ES4H_IS_INT5, 0, ES4H_IS_INT7,
                                0, 0, ES4H_IS_INT10, ES4H_IS_INT11,
index 1e49e1e..8c20d4c 100644 (file)
@@ -1,4 +1,4 @@
-static int dgrs_firmnum = 550;
+static const int dgrs_firmnum = 550;
 static char dgrs_firmver[] = "$Version$";
 static char dgrs_firmdate[] = "11/16/96 03:45:15";
 static unsigned char dgrs_code[] __initdata = {
@@ -9963,4 +9963,4 @@ static unsigned char dgrs_code[] __initdata = {
        109,46,99,0,114,99,0,0,48,120,0,0,
        0,0,0,0,0,0,0,0,0,0,0,0
        } ;
-static int dgrs_ncode = 119520 ;
+static const int dgrs_ncode = 119520 ;
index fb9dae3..1f36274 100644 (file)
@@ -90,8 +90,8 @@ module_param(tx_coalesce, int, 0); /* HW xmit count each TxDMAComplete */
 #define EnableInt() \
 writew(DEFAULT_INTR, ioaddr + IntEnable)
 
-static int max_intrloop = 50;
-static int multicast_filter_limit = 0x40;
+static const int max_intrloop = 50;
+static const int multicast_filter_limit = 0x40;
 
 static int rio_open (struct net_device *dev);
 static void rio_timer (unsigned long data);
index 24253c8..31ac001 100644 (file)
@@ -598,8 +598,8 @@ static void e100_enable_irq(struct nic *nic)
 
        spin_lock_irqsave(&nic->cmd_lock, flags);
        writeb(irq_mask_none, &nic->csr->scb.cmd_hi);
-       spin_unlock_irqrestore(&nic->cmd_lock, flags);
        e100_write_flush(nic);
+       spin_unlock_irqrestore(&nic->cmd_lock, flags);
 }
 
 static void e100_disable_irq(struct nic *nic)
@@ -608,8 +608,8 @@ static void e100_disable_irq(struct nic *nic)
 
        spin_lock_irqsave(&nic->cmd_lock, flags);
        writeb(irq_mask_all, &nic->csr->scb.cmd_hi);
-       spin_unlock_irqrestore(&nic->cmd_lock, flags);
        e100_write_flush(nic);
+       spin_unlock_irqrestore(&nic->cmd_lock, flags);
 }
 
 static void e100_hw_reset(struct nic *nic)
@@ -1582,8 +1582,8 @@ static void e100_watchdog(unsigned long data)
         * interrupt mask bit and the SW Interrupt generation bit */
        spin_lock_irq(&nic->cmd_lock);
        writeb(readb(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi);
-       spin_unlock_irq(&nic->cmd_lock);
        e100_write_flush(nic);
+       spin_unlock_irq(&nic->cmd_lock);
 
        e100_update_stats(nic);
        e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex);
@@ -2154,6 +2154,9 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
 
        msleep(10);
 
+       pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr,
+                       RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+
        if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd),
           skb->data, ETH_DATA_LEN))
                err = -EAGAIN;
@@ -2161,8 +2164,8 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
 err_loopback_none:
        mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0);
        nic->loopback = lb_none;
-       e100_hw_init(nic);
        e100_clean_cbs(nic);
+       e100_hw_reset(nic);
 err_clean_rx:
        e100_rx_clean_list(nic);
        return err;
index 99baf0e..281de41 100644 (file)
 struct e1000_adapter;
 
 #include "e1000_hw.h"
-#ifdef CONFIG_E1000_MQ
-#include <linux/cpu.h>
-#include <linux/smp.h>
-#endif
 
 #ifdef DBG
 #define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args)
@@ -169,12 +165,6 @@ struct e1000_buffer {
        uint16_t next_to_watch;
 };
 
-#ifdef CONFIG_E1000_MQ
-struct e1000_queue_stats {
-       uint64_t packets;
-       uint64_t bytes;
-};
-#endif
 
 struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; };
 struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; };
@@ -198,12 +188,7 @@ struct e1000_tx_ring {
        spinlock_t tx_lock;
        uint16_t tdh;
        uint16_t tdt;
-
        boolean_t last_tx_tso;
-
-#ifdef CONFIG_E1000_MQ
-       struct e1000_queue_stats tx_stats;
-#endif
 };
 
 struct e1000_rx_ring {
@@ -230,9 +215,6 @@ struct e1000_rx_ring {
 
        uint16_t rdh;
        uint16_t rdt;
-#ifdef CONFIG_E1000_MQ
-       struct e1000_queue_stats rx_stats;
-#endif
 };
 
 #define E1000_DESC_UNUSED(R) \
@@ -260,6 +242,7 @@ struct e1000_adapter {
        uint32_t rx_buffer_len;
        uint32_t part_num;
        uint32_t wol;
+       uint32_t ksp3_port_a;
        uint32_t smartspeed;
        uint32_t en_mng_pt;
        uint16_t link_speed;
@@ -269,8 +252,8 @@ struct e1000_adapter {
        spinlock_t tx_queue_lock;
 #endif
        atomic_t irq_sem;
-       struct work_struct tx_timeout_task;
        struct work_struct watchdog_task;
+       struct work_struct reset_task;
        uint8_t fc_autoneg;
 
        struct timer_list blink_timer;
@@ -278,9 +261,6 @@ struct e1000_adapter {
 
        /* TX */
        struct e1000_tx_ring *tx_ring;      /* One per active queue */
-#ifdef CONFIG_E1000_MQ
-       struct e1000_tx_ring **cpu_tx_ring; /* per-cpu */
-#endif
        unsigned long tx_queue_len;
        uint32_t txd_cmd;
        uint32_t tx_int_delay;
@@ -301,23 +281,18 @@ struct e1000_adapter {
        /* RX */
 #ifdef CONFIG_E1000_NAPI
        boolean_t (*clean_rx) (struct e1000_adapter *adapter,
-                                                  struct e1000_rx_ring *rx_ring,
-                                                  int *work_done, int work_to_do);
+                              struct e1000_rx_ring *rx_ring,
+                              int *work_done, int work_to_do);
 #else
        boolean_t (*clean_rx) (struct e1000_adapter *adapter,
-                                                  struct e1000_rx_ring *rx_ring);
+                              struct e1000_rx_ring *rx_ring);
 #endif
        void (*alloc_rx_buf) (struct e1000_adapter *adapter,
-                                                 struct e1000_rx_ring *rx_ring,
-                                                 int cleaned_count);
+                             struct e1000_rx_ring *rx_ring,
+                               int cleaned_count);
        struct e1000_rx_ring *rx_ring;      /* One per active queue */
 #ifdef CONFIG_E1000_NAPI
        struct net_device *polling_netdev;  /* One per active queue */
-#endif
-#ifdef CONFIG_E1000_MQ
-       struct net_device **cpu_netdev;     /* per-cpu */
-       struct call_async_data_struct rx_sched_call_data;
-       cpumask_t cpumask;
 #endif
        int num_tx_queues;
        int num_rx_queues;
@@ -353,10 +328,37 @@ struct e1000_adapter {
        struct e1000_rx_ring test_rx_ring;
 
 
-       u32 *config_space;
+       uint32_t *config_space;
        int msg_enable;
 #ifdef CONFIG_PCI_MSI
        boolean_t have_msi;
+#endif
+       /* to not mess up cache alignment, always add to the bottom */
+       boolean_t txb2b;
+#ifdef NETIF_F_TSO
+       boolean_t tso_force;
 #endif
 };
+
+
+/*  e1000_main.c  */
+extern char e1000_driver_name[];
+extern char e1000_driver_version[];
+int e1000_up(struct e1000_adapter *adapter);
+void e1000_down(struct e1000_adapter *adapter);
+void e1000_reset(struct e1000_adapter *adapter);
+int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
+int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+void e1000_update_stats(struct e1000_adapter *adapter);
+int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
+
+/*  e1000_ethtool.c  */
+void e1000_set_ethtool_ops(struct net_device *netdev);
+
+/*  e1000_param.c  */
+void e1000_check_options(struct e1000_adapter *adapter);
+
+
 #endif /* _E1000_H_ */
index 5cedc81..ecccca3 100644 (file)
 
 #include <asm/uaccess.h>
 
-extern char e1000_driver_name[];
-extern char e1000_driver_version[];
-
-extern int e1000_up(struct e1000_adapter *adapter);
-extern void e1000_down(struct e1000_adapter *adapter);
-extern void e1000_reset(struct e1000_adapter *adapter);
-extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
-extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
-extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_update_stats(struct e1000_adapter *adapter);
-
 struct e1000_stats {
        char stat_string[ETH_GSTRING_LEN];
        int sizeof_stat;
@@ -60,7 +47,6 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
        { "tx_bytes", E1000_STAT(net_stats.tx_bytes) },
        { "rx_errors", E1000_STAT(net_stats.rx_errors) },
        { "tx_errors", E1000_STAT(net_stats.tx_errors) },
-       { "rx_dropped", E1000_STAT(net_stats.rx_dropped) },
        { "tx_dropped", E1000_STAT(net_stats.tx_dropped) },
        { "multicast", E1000_STAT(net_stats.multicast) },
        { "collisions", E1000_STAT(net_stats.collisions) },
@@ -68,7 +54,6 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
        { "rx_over_errors", E1000_STAT(net_stats.rx_over_errors) },
        { "rx_crc_errors", E1000_STAT(net_stats.rx_crc_errors) },
        { "rx_frame_errors", E1000_STAT(net_stats.rx_frame_errors) },
-       { "rx_fifo_errors", E1000_STAT(net_stats.rx_fifo_errors) },
        { "rx_no_buffer_count", E1000_STAT(stats.rnbc) },
        { "rx_missed_errors", E1000_STAT(net_stats.rx_missed_errors) },
        { "tx_aborted_errors", E1000_STAT(net_stats.tx_aborted_errors) },
@@ -97,14 +82,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
        { "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) },
 };
 
-#ifdef CONFIG_E1000_MQ
-#define E1000_QUEUE_STATS_LEN \
-       (((struct e1000_adapter *)netdev->priv)->num_tx_queues + \
-        ((struct e1000_adapter *)netdev->priv)->num_rx_queues) \
-       * (sizeof(struct e1000_queue_stats) / sizeof(uint64_t))
-#else
 #define E1000_QUEUE_STATS_LEN 0
-#endif
 #define E1000_GLOBAL_STATS_LEN \
        sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
 #define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN + E1000_QUEUE_STATS_LEN)
@@ -346,6 +324,9 @@ e1000_set_tso(struct net_device *netdev, uint32_t data)
                netdev->features |= NETIF_F_TSO;
        else
                netdev->features &= ~NETIF_F_TSO;
+
+       DPRINTK(PROBE, INFO, "TSO is %s\n", data ? "Enabled" : "Disabled");
+       adapter->tso_force = TRUE;
        return 0;
 }
 #endif /* NETIF_F_TSO */
@@ -594,6 +575,7 @@ e1000_get_drvinfo(struct net_device *netdev,
        case e1000_82571:
        case e1000_82572:
        case e1000_82573:
+       case e1000_80003es2lan:
                sprintf(firmware_version, "%d.%d-%d",
                        (eeprom_data & 0xF000) >> 12,
                        (eeprom_data & 0x0FF0) >> 4,
@@ -642,6 +624,9 @@ e1000_set_ringparam(struct net_device *netdev,
        struct e1000_rx_ring *rxdr, *rx_old, *rx_new;
        int i, err, tx_ring_size, rx_ring_size;
 
+       if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+               return -EINVAL;
+
        tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_tx_queues;
        rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues;
 
@@ -669,9 +654,6 @@ e1000_set_ringparam(struct net_device *netdev,
        txdr = adapter->tx_ring;
        rxdr = adapter->rx_ring;
 
-       if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
-               return -EINVAL;
-
        rxdr->count = max(ring->rx_pending,(uint32_t)E1000_MIN_RXD);
        rxdr->count = min(rxdr->count,(uint32_t)(mac_type < e1000_82544 ?
                E1000_MAX_RXD : E1000_MAX_82544_RXD));
@@ -767,6 +749,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
        /* there are several bits on newer hardware that are r/w */
        case e1000_82571:
        case e1000_82572:
+       case e1000_80003es2lan:
                toggle = 0x7FFFF3FF;
                break;
        case e1000_82573:
@@ -1256,6 +1239,10 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
                e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x9140);
                /* autoneg off */
                e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8140);
+       } else if (adapter->hw.phy_type == e1000_phy_gg82563) {
+               e1000_write_phy_reg(&adapter->hw,
+                                   GG82563_PHY_KMRN_MODE_CTRL,
+                                   0x1CE);
        }
        /* force 1000, set loopback */
        e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x4140);
@@ -1325,6 +1312,7 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
        case e1000_82571:
        case e1000_82572:
        case e1000_82573:
+       case e1000_80003es2lan:
                return e1000_integrated_phy_loopback(adapter);
                break;
 
@@ -1405,6 +1393,11 @@ e1000_loopback_cleanup(struct e1000_adapter *adapter)
        case e1000_82546_rev_3:
        default:
                hw->autoneg = TRUE;
+               if (hw->phy_type == e1000_phy_gg82563) {
+                       e1000_write_phy_reg(hw,
+                                           GG82563_PHY_KMRN_MODE_CTRL,
+                                           0x180);
+               }
                e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
                if (phy_reg & MII_CR_LOOPBACK) {
                        phy_reg &= ~MII_CR_LOOPBACK;
@@ -1640,10 +1633,26 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
        case E1000_DEV_ID_82546EB_QUAD_COPPER:
        case E1000_DEV_ID_82545EM_FIBER:
        case E1000_DEV_ID_82545EM_COPPER:
+       case E1000_DEV_ID_82546GB_QUAD_COPPER:
                wol->supported = 0;
                wol->wolopts   = 0;
                return;
 
+       case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
+               /* device id 10B5 port-A supports wol */
+               if (!adapter->ksp3_port_a) {
+                       wol->supported = 0;
+                       return;
+               }
+               /* KSP3 does not suppport UCAST wake-ups for any interface */
+               wol->supported = WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
+
+               if (adapter->wol & E1000_WUFC_EX)
+                       DPRINTK(DRV, ERR, "Interface does not support "
+                       "directed (unicast) frame wake-up packets\n");
+               wol->wolopts = 0;
+               goto do_defaults;
+
        case E1000_DEV_ID_82546EB_FIBER:
        case E1000_DEV_ID_82546GB_FIBER:
        case E1000_DEV_ID_82571EB_FIBER:
@@ -1658,8 +1667,9 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
        default:
                wol->supported = WAKE_UCAST | WAKE_MCAST |
                                 WAKE_BCAST | WAKE_MAGIC;
-
                wol->wolopts = 0;
+
+do_defaults:
                if (adapter->wol & E1000_WUFC_EX)
                        wol->wolopts |= WAKE_UCAST;
                if (adapter->wol & E1000_WUFC_MC)
@@ -1684,10 +1694,22 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
        case E1000_DEV_ID_82543GC_COPPER:
        case E1000_DEV_ID_82544EI_FIBER:
        case E1000_DEV_ID_82546EB_QUAD_COPPER:
+       case E1000_DEV_ID_82546GB_QUAD_COPPER:
        case E1000_DEV_ID_82545EM_FIBER:
        case E1000_DEV_ID_82545EM_COPPER:
                return wol->wolopts ? -EOPNOTSUPP : 0;
 
+       case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
+               /* device id 10B5 port-A supports wol */
+               if (!adapter->ksp3_port_a)
+                       return wol->wolopts ? -EOPNOTSUPP : 0;
+
+               if (wol->wolopts & WAKE_UCAST) {
+                       DPRINTK(DRV, ERR, "Interface does not support "
+                       "directed (unicast) frame wake-up packets\n");
+                       return -EOPNOTSUPP;
+               }
+
        case E1000_DEV_ID_82546EB_FIBER:
        case E1000_DEV_ID_82546GB_FIBER:
        case E1000_DEV_ID_82571EB_FIBER:
@@ -1799,11 +1821,6 @@ e1000_get_ethtool_stats(struct net_device *netdev,
                struct ethtool_stats *stats, uint64_t *data)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
-#ifdef CONFIG_E1000_MQ
-       uint64_t *queue_stat;
-       int stat_count = sizeof(struct e1000_queue_stats) / sizeof(uint64_t);
-       int j, k;
-#endif
        int i;
 
        e1000_update_stats(adapter);
@@ -1812,29 +1829,12 @@ e1000_get_ethtool_stats(struct net_device *netdev,
                data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
                        sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
        }
-#ifdef CONFIG_E1000_MQ
-       for (j = 0; j < adapter->num_tx_queues; j++) {
-               queue_stat = (uint64_t *)&adapter->tx_ring[j].tx_stats;
-               for (k = 0; k < stat_count; k++)
-                       data[i + k] = queue_stat[k];
-               i += k;
-       }
-       for (j = 0; j < adapter->num_rx_queues; j++) {
-               queue_stat = (uint64_t *)&adapter->rx_ring[j].rx_stats;
-               for (k = 0; k < stat_count; k++)
-                       data[i + k] = queue_stat[k];
-               i += k;
-       }
-#endif
 /*     BUG_ON(i != E1000_STATS_LEN); */
 }
 
 static void
 e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
 {
-#ifdef CONFIG_E1000_MQ
-       struct e1000_adapter *adapter = netdev_priv(netdev);
-#endif
        uint8_t *p = data;
        int i;
 
@@ -1849,20 +1849,6 @@ e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
                               ETH_GSTRING_LEN);
                        p += ETH_GSTRING_LEN;
                }
-#ifdef CONFIG_E1000_MQ
-               for (i = 0; i < adapter->num_tx_queues; i++) {
-                       sprintf(p, "tx_queue_%u_packets", i);
-                       p += ETH_GSTRING_LEN;
-                       sprintf(p, "tx_queue_%u_bytes", i);
-                       p += ETH_GSTRING_LEN;
-               }
-               for (i = 0; i < adapter->num_rx_queues; i++) {
-                       sprintf(p, "rx_queue_%u_packets", i);
-                       p += ETH_GSTRING_LEN;
-                       sprintf(p, "rx_queue_%u_bytes", i);
-                       p += ETH_GSTRING_LEN;
-               }
-#endif
 /*             BUG_ON(p - data != E1000_STATS_LEN * ETH_GSTRING_LEN); */
                break;
        }
index beeec0f..523c2c9 100644 (file)
@@ -100,6 +100,8 @@ static void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset,
 
 #define E1000_WRITE_REG_IO(a, reg, val) \
            e1000_write_reg_io((a), E1000_##reg, val)
+static int32_t e1000_configure_kmrn_for_10_100(struct e1000_hw *hw);
+static int32_t e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
 
 /* IGP cable length table */
 static const
@@ -153,6 +155,11 @@ e1000_set_phy_type(struct e1000_hw *hw)
             hw->phy_type = e1000_phy_igp;
             break;
         }
+    case GG82563_E_PHY_ID:
+        if (hw->mac_type == e1000_80003es2lan) {
+            hw->phy_type = e1000_phy_gg82563;
+            break;
+        }
         /* Fall Through */
     default:
         /* Should never have loaded on this device */
@@ -353,12 +360,19 @@ e1000_set_mac_type(struct e1000_hw *hw)
     case E1000_DEV_ID_82573L:
         hw->mac_type = e1000_82573;
         break;
+    case E1000_DEV_ID_80003ES2LAN_COPPER_DPT:
+    case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
+        hw->mac_type = e1000_80003es2lan;
+        break;
     default:
         /* Should never have loaded on this device */
         return -E1000_ERR_MAC_TYPE;
     }
 
     switch(hw->mac_type) {
+    case e1000_80003es2lan:
+        hw->swfw_sync_present = TRUE;
+        /* fall through */
     case e1000_82571:
     case e1000_82572:
     case e1000_82573:
@@ -399,6 +413,7 @@ e1000_set_media_type(struct e1000_hw *hw)
     case E1000_DEV_ID_82546GB_SERDES:
     case E1000_DEV_ID_82571EB_SERDES:
     case E1000_DEV_ID_82572EI_SERDES:
+    case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
         hw->media_type = e1000_media_type_internal_serdes;
         break;
     default:
@@ -575,6 +590,7 @@ e1000_reset_hw(struct e1000_hw *hw)
             /* fall through */
         case e1000_82571:
         case e1000_82572:
+        case e1000_80003es2lan:
             ret_val = e1000_get_auto_rd_done(hw);
             if(ret_val)
                 /* We don't want to continue accessing MAC registers. */
@@ -641,6 +657,7 @@ e1000_init_hw(struct e1000_hw *hw)
     uint16_t cmd_mmrbc;
     uint16_t stat_mmrbc;
     uint32_t mta_size;
+    uint32_t reg_data;
     uint32_t ctrl_ext;
 
     DEBUGFUNC("e1000_init_hw");
@@ -739,6 +756,7 @@ e1000_init_hw(struct e1000_hw *hw)
         case e1000_82571:
         case e1000_82572:
         case e1000_82573:
+        case e1000_80003es2lan:
             ctrl |= E1000_TXDCTL_COUNT_DESC;
             break;
         }
@@ -752,12 +770,34 @@ e1000_init_hw(struct e1000_hw *hw)
     switch (hw->mac_type) {
     default:
         break;
+    case e1000_80003es2lan:
+        /* Enable retransmit on late collisions */
+        reg_data = E1000_READ_REG(hw, TCTL);
+        reg_data |= E1000_TCTL_RTLC;
+        E1000_WRITE_REG(hw, TCTL, reg_data);
+
+        /* Configure Gigabit Carry Extend Padding */
+        reg_data = E1000_READ_REG(hw, TCTL_EXT);
+        reg_data &= ~E1000_TCTL_EXT_GCEX_MASK;
+        reg_data |= DEFAULT_80003ES2LAN_TCTL_EXT_GCEX;
+        E1000_WRITE_REG(hw, TCTL_EXT, reg_data);
+
+        /* Configure Transmit Inter-Packet Gap */
+        reg_data = E1000_READ_REG(hw, TIPG);
+        reg_data &= ~E1000_TIPG_IPGT_MASK;
+        reg_data |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000;
+        E1000_WRITE_REG(hw, TIPG, reg_data);
+
+        reg_data = E1000_READ_REG_ARRAY(hw, FFLT, 0x0001);
+        reg_data &= ~0x00100000;
+        E1000_WRITE_REG_ARRAY(hw, FFLT, 0x0001, reg_data);
+        /* Fall through */
     case e1000_82571:
     case e1000_82572:
         ctrl = E1000_READ_REG(hw, TXDCTL1);
-        ctrl &= ~E1000_TXDCTL_WTHRESH;
-        ctrl |= E1000_TXDCTL_COUNT_DESC | E1000_TXDCTL_FULL_TX_DESC_WB;
-        ctrl |= (1 << 22);
+        ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
+        if(hw->mac_type >= e1000_82571)
+            ctrl |= E1000_TXDCTL_COUNT_DESC;
         E1000_WRITE_REG(hw, TXDCTL1, ctrl);
         break;
     }
@@ -906,7 +946,13 @@ e1000_setup_link(struct e1000_hw *hw)
      * signal detection.  So this should be done before e1000_setup_pcs_link()
      * or e1000_phy_setup() is called.
      */
-    if(hw->mac_type == e1000_82543) {
+    if (hw->mac_type == e1000_82543) {
+               ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
+                                                                       1, &eeprom_data);
+               if (ret_val) {
+                       DEBUGOUT("EEPROM Read Error\n");
+                       return -E1000_ERR_EEPROM;
+               }
         ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) <<
                     SWDPIO__EXT_SHIFT);
         E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
@@ -1308,6 +1354,154 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
     return E1000_SUCCESS;
 }
 
+/********************************************************************
+* Copper link setup for e1000_phy_gg82563 series.
+*
+* hw - Struct containing variables accessed by shared code
+*********************************************************************/
+static int32_t
+e1000_copper_link_ggp_setup(struct e1000_hw *hw)
+{
+    int32_t ret_val;
+    uint16_t phy_data;
+    uint32_t reg_data;
+
+    DEBUGFUNC("e1000_copper_link_ggp_setup");
+
+    if(!hw->phy_reset_disable) {
+        
+        /* Enable CRS on TX for half-duplex operation. */
+        ret_val = e1000_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
+                                     &phy_data);
+        if(ret_val)
+            return ret_val;
+
+        phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
+        /* Use 25MHz for both link down and 1000BASE-T for Tx clock */
+        phy_data |= GG82563_MSCR_TX_CLK_1000MBPS_25MHZ;
+
+        ret_val = e1000_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
+                                      phy_data);
+        if(ret_val)
+            return ret_val;
+
+        /* Options:
+         *   MDI/MDI-X = 0 (default)
+         *   0 - Auto for all speeds
+         *   1 - MDI mode
+         *   2 - MDI-X mode
+         *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
+         */
+        ret_val = e1000_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL, &phy_data);
+        if(ret_val)
+            return ret_val;
+
+        phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK;
+
+        switch (hw->mdix) {
+        case 1:
+            phy_data |= GG82563_PSCR_CROSSOVER_MODE_MDI;
+            break;
+        case 2:
+            phy_data |= GG82563_PSCR_CROSSOVER_MODE_MDIX;
+            break;
+        case 0:
+        default:
+            phy_data |= GG82563_PSCR_CROSSOVER_MODE_AUTO;
+            break;
+        }
+
+        /* Options:
+         *   disable_polarity_correction = 0 (default)
+         *       Automatic Correction for Reversed Cable Polarity
+         *   0 - Disabled
+         *   1 - Enabled
+         */
+        phy_data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
+        if(hw->disable_polarity_correction == 1)
+            phy_data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
+        ret_val = e1000_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data);
+
+        if(ret_val)
+            return ret_val;
+
+        /* SW Reset the PHY so all changes take effect */
+        ret_val = e1000_phy_reset(hw);
+        if (ret_val) {
+            DEBUGOUT("Error Resetting the PHY\n");
+            return ret_val;
+        }
+    } /* phy_reset_disable */
+
+    if (hw->mac_type == e1000_80003es2lan) {
+        /* Bypass RX and TX FIFO's */
+        ret_val = e1000_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL,
+                                       E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS |
+                                       E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS);
+        if (ret_val)
+            return ret_val;
+
+        ret_val = e1000_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, &phy_data);
+        if (ret_val)
+            return ret_val;
+
+        phy_data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG;
+        ret_val = e1000_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, phy_data);
+
+        if (ret_val)
+            return ret_val;
+
+        reg_data = E1000_READ_REG(hw, CTRL_EXT);
+        reg_data &= ~(E1000_CTRL_EXT_LINK_MODE_MASK);
+        E1000_WRITE_REG(hw, CTRL_EXT, reg_data);
+
+        ret_val = e1000_read_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
+                                          &phy_data);
+        if (ret_val)
+            return ret_val;
+
+        /* Do not init these registers when the HW is in IAMT mode, since the
+         * firmware will have already initialized them.  We only initialize
+         * them if the HW is not in IAMT mode.
+         */
+        if (e1000_check_mng_mode(hw) == FALSE) {
+            /* Enable Electrical Idle on the PHY */
+            phy_data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
+            ret_val = e1000_write_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
+                                          phy_data);
+            if (ret_val)
+                return ret_val;
+
+            ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                         &phy_data);
+            if (ret_val)
+                return ret_val;
+
+            /* Enable Pass False Carrier on the PHY */
+            phy_data |= GG82563_KMCR_PASS_FALSE_CARRIER;
+
+            ret_val = e1000_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                          phy_data);
+            if (ret_val)
+                return ret_val;
+        }
+
+        /* Workaround: Disable padding in Kumeran interface in the MAC
+         * and in the PHY to avoid CRC errors.
+         */
+        ret_val = e1000_read_phy_reg(hw, GG82563_PHY_INBAND_CTRL,
+                                     &phy_data);
+        if (ret_val)
+            return ret_val;
+        phy_data |= GG82563_ICR_DIS_PADDING;
+        ret_val = e1000_write_phy_reg(hw, GG82563_PHY_INBAND_CTRL,
+                                      phy_data);
+        if (ret_val)
+            return ret_val;
+    }
+
+    return E1000_SUCCESS;
+}
 
 /********************************************************************
 * Copper link setup for e1000_phy_m88 series.
@@ -1518,6 +1712,7 @@ e1000_setup_copper_link(struct e1000_hw *hw)
     int32_t ret_val;
     uint16_t i;
     uint16_t phy_data;
+    uint16_t reg_data;
 
     DEBUGFUNC("e1000_setup_copper_link");
 
@@ -1526,6 +1721,22 @@ e1000_setup_copper_link(struct e1000_hw *hw)
     if(ret_val)
         return ret_val;
 
+    switch (hw->mac_type) {
+    case e1000_80003es2lan:
+        ret_val = e1000_read_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL,
+                                      &reg_data);
+        if (ret_val)
+            return ret_val;
+        reg_data |= E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING;
+        ret_val = e1000_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL,
+                                       reg_data);
+        if (ret_val)
+            return ret_val;
+        break;
+    default:
+        break;
+    }
+
     if (hw->phy_type == e1000_phy_igp ||
         hw->phy_type == e1000_phy_igp_2) {
         ret_val = e1000_copper_link_igp_setup(hw);
@@ -1535,6 +1746,10 @@ e1000_setup_copper_link(struct e1000_hw *hw)
         ret_val = e1000_copper_link_mgp_setup(hw);
         if(ret_val)
             return ret_val;
+    } else if (hw->phy_type == e1000_phy_gg82563) {
+        ret_val = e1000_copper_link_ggp_setup(hw);
+        if(ret_val)
+            return ret_val;
     }
 
     if(hw->autoneg) {
@@ -1581,6 +1796,59 @@ e1000_setup_copper_link(struct e1000_hw *hw)
     return E1000_SUCCESS;
 }
 
+/******************************************************************************
+* Configure the MAC-to-PHY interface for 10/100Mbps
+*
+* hw - Struct containing variables accessed by shared code
+******************************************************************************/
+static int32_t
+e1000_configure_kmrn_for_10_100(struct e1000_hw *hw)
+{
+    int32_t ret_val = E1000_SUCCESS;
+    uint32_t tipg;
+    uint16_t reg_data;
+
+    DEBUGFUNC("e1000_configure_kmrn_for_10_100");
+
+    reg_data = E1000_KUMCTRLSTA_HD_CTRL_10_100_DEFAULT;
+    ret_val = e1000_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_HD_CTRL,
+                                   reg_data);
+    if (ret_val)
+        return ret_val;
+
+    /* Configure Transmit Inter-Packet Gap */
+    tipg = E1000_READ_REG(hw, TIPG);
+    tipg &= ~E1000_TIPG_IPGT_MASK;
+    tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_10_100;
+    E1000_WRITE_REG(hw, TIPG, tipg);
+
+    return ret_val;
+}
+
+static int32_t
+e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
+{
+    int32_t ret_val = E1000_SUCCESS;
+    uint16_t reg_data;
+    uint32_t tipg;
+
+    DEBUGFUNC("e1000_configure_kmrn_for_1000");
+
+    reg_data = E1000_KUMCTRLSTA_HD_CTRL_1000_DEFAULT;
+    ret_val = e1000_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_HD_CTRL,
+                                   reg_data);
+    if (ret_val)
+        return ret_val;
+
+    /* Configure Transmit Inter-Packet Gap */
+    tipg = E1000_READ_REG(hw, TIPG);
+    tipg &= ~E1000_TIPG_IPGT_MASK;
+    tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000;
+    E1000_WRITE_REG(hw, TIPG, tipg);
+
+    return ret_val;
+}
+
 /******************************************************************************
 * Configures PHY autoneg and flow control advertisement settings
 *
@@ -1802,7 +2070,8 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
     /* Write the configured values back to the Device Control Reg. */
     E1000_WRITE_REG(hw, CTRL, ctrl);
 
-    if (hw->phy_type == e1000_phy_m88) {
+    if ((hw->phy_type == e1000_phy_m88) ||
+        (hw->phy_type == e1000_phy_gg82563)) {
         ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
         if(ret_val)
             return ret_val;
@@ -1871,7 +2140,8 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
             msec_delay(100);
         }
         if((i == 0) &&
-           (hw->phy_type == e1000_phy_m88)) {
+           ((hw->phy_type == e1000_phy_m88) ||
+            (hw->phy_type == e1000_phy_gg82563))) {
             /* We didn't get link.  Reset the DSP and wait again for link. */
             ret_val = e1000_phy_reset_dsp(hw);
             if(ret_val) {
@@ -1930,6 +2200,27 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
             if(ret_val)
                 return ret_val;
         }
+    } else if (hw->phy_type == e1000_phy_gg82563) {
+        /* The TX_CLK of the Extended PHY Specific Control Register defaults
+         * to 2.5MHz on a reset.  We need to re-force it back to 25MHz, if
+         * we're not in a forced 10/duplex configuration. */
+        ret_val = e1000_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data);
+        if (ret_val)
+            return ret_val;
+
+        phy_data &= ~GG82563_MSCR_TX_CLK_MASK;
+        if ((hw->forced_speed_duplex == e1000_10_full) ||
+            (hw->forced_speed_duplex == e1000_10_half))
+            phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5MHZ;
+        else
+            phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25MHZ;
+
+        /* Also due to the reset, we need to enable CRS on Tx. */
+        phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
+
+        ret_val = e1000_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data);
+        if (ret_val)
+            return ret_val;
     }
     return E1000_SUCCESS;
 }
@@ -2592,6 +2883,16 @@ e1000_get_speed_and_duplex(struct e1000_hw *hw,
         }
     }
 
+    if ((hw->mac_type == e1000_80003es2lan) && 
+        (hw->media_type == e1000_media_type_copper)) {
+        if (*speed == SPEED_1000)
+            ret_val = e1000_configure_kmrn_for_1000(hw);
+        else
+            ret_val = e1000_configure_kmrn_for_10_100(hw);
+        if (ret_val)
+            return ret_val;
+    }
+
     return E1000_SUCCESS;
 }
 
@@ -2767,6 +3068,72 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw)
     return data;
 }
 
+int32_t
+e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
+{
+    uint32_t swfw_sync = 0;
+    uint32_t swmask = mask;
+    uint32_t fwmask = mask << 16;
+    int32_t timeout = 200;
+
+    DEBUGFUNC("e1000_swfw_sync_acquire");
+
+    if (!hw->swfw_sync_present)
+        return e1000_get_hw_eeprom_semaphore(hw);
+
+    while(timeout) {
+            if (e1000_get_hw_eeprom_semaphore(hw))
+                return -E1000_ERR_SWFW_SYNC;
+
+            swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC);
+            if (!(swfw_sync & (fwmask | swmask))) {
+                break;
+            }
+
+            /* firmware currently using resource (fwmask) */
+            /* or other software thread currently using resource (swmask) */
+            e1000_put_hw_eeprom_semaphore(hw);
+            msec_delay_irq(5);
+            timeout--;
+    }
+
+    if (!timeout) {
+        DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
+        return -E1000_ERR_SWFW_SYNC;
+    }
+
+    swfw_sync |= swmask;
+    E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync);
+
+    e1000_put_hw_eeprom_semaphore(hw);
+    return E1000_SUCCESS;
+}
+
+void
+e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask)
+{
+    uint32_t swfw_sync;
+    uint32_t swmask = mask;
+
+    DEBUGFUNC("e1000_swfw_sync_release");
+
+    if (!hw->swfw_sync_present) {
+        e1000_put_hw_eeprom_semaphore(hw);
+        return;
+    }
+
+    /* if (e1000_get_hw_eeprom_semaphore(hw))
+     *    return -E1000_ERR_SWFW_SYNC; */
+    while (e1000_get_hw_eeprom_semaphore(hw) != E1000_SUCCESS);
+        /* empty */
+
+    swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC);
+    swfw_sync &= ~swmask;
+    E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync);
+
+    e1000_put_hw_eeprom_semaphore(hw);
+}
+
 /*****************************************************************************
 * Reads the value from a PHY register, if the value is on a specific non zero
 * page, sets the page first.
@@ -2779,22 +3146,55 @@ e1000_read_phy_reg(struct e1000_hw *hw,
                    uint16_t *phy_data)
 {
     uint32_t ret_val;
+    uint16_t swfw;
 
     DEBUGFUNC("e1000_read_phy_reg");
 
+    if ((hw->mac_type == e1000_80003es2lan) &&
+        (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+        swfw = E1000_SWFW_PHY1_SM;
+    } else {
+        swfw = E1000_SWFW_PHY0_SM;
+    }
+    if (e1000_swfw_sync_acquire(hw, swfw))
+        return -E1000_ERR_SWFW_SYNC;
+
     if((hw->phy_type == e1000_phy_igp || 
         hw->phy_type == e1000_phy_igp_2) &&
        (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
         ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
                                          (uint16_t)reg_addr);
         if(ret_val) {
+            e1000_swfw_sync_release(hw, swfw);
             return ret_val;
         }
+    } else if (hw->phy_type == e1000_phy_gg82563) {
+        if (((reg_addr & MAX_PHY_REG_ADDRESS) > MAX_PHY_MULTI_PAGE_REG) ||
+            (hw->mac_type == e1000_80003es2lan)) {
+            /* Select Configuration Page */
+            if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
+                ret_val = e1000_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT,
+                          (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
+            } else {
+                /* Use Alternative Page Select register to access
+                 * registers 30 and 31
+                 */
+                ret_val = e1000_write_phy_reg_ex(hw,
+                                                 GG82563_PHY_PAGE_SELECT_ALT,
+                          (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
+            }
+
+            if (ret_val) {
+                e1000_swfw_sync_release(hw, swfw);
+                return ret_val;
+            }
+        }
     }
 
     ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
                                     phy_data);
 
+    e1000_swfw_sync_release(hw, swfw);
     return ret_val;
 }
 
@@ -2885,22 +3285,55 @@ e1000_write_phy_reg(struct e1000_hw *hw,
                     uint16_t phy_data)
 {
     uint32_t ret_val;
+    uint16_t swfw;
 
     DEBUGFUNC("e1000_write_phy_reg");
 
+    if ((hw->mac_type == e1000_80003es2lan) &&
+        (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+        swfw = E1000_SWFW_PHY1_SM;
+    } else {
+        swfw = E1000_SWFW_PHY0_SM;
+    }
+    if (e1000_swfw_sync_acquire(hw, swfw))
+        return -E1000_ERR_SWFW_SYNC;
+
     if((hw->phy_type == e1000_phy_igp || 
         hw->phy_type == e1000_phy_igp_2) &&
        (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
         ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
                                          (uint16_t)reg_addr);
         if(ret_val) {
+            e1000_swfw_sync_release(hw, swfw);
             return ret_val;
         }
+    } else if (hw->phy_type == e1000_phy_gg82563) {
+        if (((reg_addr & MAX_PHY_REG_ADDRESS) > MAX_PHY_MULTI_PAGE_REG) ||
+            (hw->mac_type == e1000_80003es2lan)) {
+            /* Select Configuration Page */
+            if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
+                ret_val = e1000_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT,
+                          (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
+            } else {
+                /* Use Alternative Page Select register to access
+                 * registers 30 and 31
+                 */
+                ret_val = e1000_write_phy_reg_ex(hw,
+                                                 GG82563_PHY_PAGE_SELECT_ALT,
+                          (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
+            }
+
+            if (ret_val) {
+                e1000_swfw_sync_release(hw, swfw);
+                return ret_val;
+            }
+        }
     }
 
     ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
                                      phy_data);
 
+    e1000_swfw_sync_release(hw, swfw);
     return ret_val;
 }
 
@@ -2967,6 +3400,65 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw,
     return E1000_SUCCESS;
 }
 
+int32_t
+e1000_read_kmrn_reg(struct e1000_hw *hw,
+                    uint32_t reg_addr,
+                    uint16_t *data)
+{
+    uint32_t reg_val;
+    uint16_t swfw;
+    DEBUGFUNC("e1000_read_kmrn_reg");
+
+    if ((hw->mac_type == e1000_80003es2lan) &&
+        (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+        swfw = E1000_SWFW_PHY1_SM;
+    } else {
+        swfw = E1000_SWFW_PHY0_SM;
+    }
+    if (e1000_swfw_sync_acquire(hw, swfw))
+        return -E1000_ERR_SWFW_SYNC;
+
+    /* Write register address */
+    reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) &
+              E1000_KUMCTRLSTA_OFFSET) |
+              E1000_KUMCTRLSTA_REN;
+    E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val);
+    udelay(2);
+
+    /* Read the data returned */
+    reg_val = E1000_READ_REG(hw, KUMCTRLSTA);
+    *data = (uint16_t)reg_val;
+
+    e1000_swfw_sync_release(hw, swfw);
+    return E1000_SUCCESS;
+}
+
+int32_t
+e1000_write_kmrn_reg(struct e1000_hw *hw,
+                     uint32_t reg_addr,
+                     uint16_t data)
+{
+    uint32_t reg_val;
+    uint16_t swfw;
+    DEBUGFUNC("e1000_write_kmrn_reg");
+
+    if ((hw->mac_type == e1000_80003es2lan) &&
+        (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+        swfw = E1000_SWFW_PHY1_SM;
+    } else {
+        swfw = E1000_SWFW_PHY0_SM;
+    }
+    if (e1000_swfw_sync_acquire(hw, swfw))
+        return -E1000_ERR_SWFW_SYNC;
+
+    reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) &
+              E1000_KUMCTRLSTA_OFFSET) | data;
+    E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val);
+    udelay(2);
+
+    e1000_swfw_sync_release(hw, swfw);
+    return E1000_SUCCESS;
+}
 
 /******************************************************************************
 * Returns the PHY to the power-on reset state
@@ -2979,6 +3471,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
     uint32_t ctrl, ctrl_ext;
     uint32_t led_ctrl;
     int32_t ret_val;
+    uint16_t swfw;
 
     DEBUGFUNC("e1000_phy_hw_reset");
 
@@ -2991,11 +3484,21 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
     DEBUGOUT("Resetting Phy...\n");
 
     if(hw->mac_type > e1000_82543) {
+        if ((hw->mac_type == e1000_80003es2lan) &&
+            (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+            swfw = E1000_SWFW_PHY1_SM;
+        } else {
+            swfw = E1000_SWFW_PHY0_SM;
+        }
+        if (e1000_swfw_sync_acquire(hw, swfw)) {
+            e1000_release_software_semaphore(hw);
+            return -E1000_ERR_SWFW_SYNC;
+        }
         /* Read the device control register and assert the E1000_CTRL_PHY_RST
          * bit. Then, take it out of reset.
          * For pre-e1000_82571 hardware, we delay for 10ms between the assert 
          * and deassert.  For e1000_82571 hardware and later, we instead delay
-         * for 10ms after the deassertion.
+         * for 50us between and 10ms after the deassertion.
          */
         ctrl = E1000_READ_REG(hw, CTRL);
         E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
@@ -3011,6 +3514,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
         
         if (hw->mac_type >= e1000_82571)
             msec_delay(10);
+        e1000_swfw_sync_release(hw, swfw);
     } else {
         /* Read the Extended Device Control Register, assert the PHY_RESET_DIR
          * bit to put the PHY into reset. Then, take it out of reset.
@@ -3037,6 +3541,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
 
     /* Wait for FW to finish PHY configuration. */
     ret_val = e1000_get_phy_cfg_done(hw);
+    e1000_release_software_semaphore(hw);
 
     return ret_val;
 }
@@ -3114,6 +3619,15 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
         return E1000_SUCCESS;
     }
 
+    /* ESB-2 PHY reads require e1000_phy_gg82563 to be set because of a work-
+     * around that forces PHY page 0 to be set or the reads fail.  The rest of
+     * the code in this routine uses e1000_read_phy_reg to read the PHY ID.
+     * So for ESB-2 we need to have this set so our reads won't fail.  If the
+     * attached PHY is not a e1000_phy_gg82563, the routines below will figure
+     * this out as well. */
+    if (hw->mac_type == e1000_80003es2lan)
+        hw->phy_type = e1000_phy_gg82563;
+
     /* Read the PHY ID Registers to identify which PHY is onboard. */
     ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high);
     if(ret_val)
@@ -3151,6 +3665,9 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
     case e1000_82573:
         if(hw->phy_id == M88E1111_I_PHY_ID) match = TRUE;
         break;
+    case e1000_80003es2lan:
+        if (hw->phy_id == GG82563_E_PHY_ID) match = TRUE;
+        break;
     default:
         DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
         return -E1000_ERR_CONFIG;
@@ -3177,8 +3694,10 @@ e1000_phy_reset_dsp(struct e1000_hw *hw)
     DEBUGFUNC("e1000_phy_reset_dsp");
 
     do {
-        ret_val = e1000_write_phy_reg(hw, 29, 0x001d);
-        if(ret_val) break;
+        if (hw->phy_type != e1000_phy_gg82563) {
+            ret_val = e1000_write_phy_reg(hw, 29, 0x001d);
+            if(ret_val) break;
+        }
         ret_val = e1000_write_phy_reg(hw, 30, 0x00c1);
         if(ret_val) break;
         ret_val = e1000_write_phy_reg(hw, 30, 0x0000);
@@ -3310,8 +3829,17 @@ e1000_phy_m88_get_info(struct e1000_hw *hw,
         /* Cable Length Estimation and Local/Remote Receiver Information
          * are only valid at 1000 Mbps.
          */
-        phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
-                                  M88E1000_PSSR_CABLE_LENGTH_SHIFT);
+        if (hw->phy_type != e1000_phy_gg82563) {
+            phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
+                                      M88E1000_PSSR_CABLE_LENGTH_SHIFT);
+        } else {
+            ret_val = e1000_read_phy_reg(hw, GG82563_PHY_DSP_DISTANCE,
+                                         &phy_data);
+            if (ret_val)
+                return ret_val;
+
+            phy_info->cable_length = phy_data & GG82563_DSPD_CABLE_LENGTH;
+        }
 
         ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
         if(ret_val)
@@ -3392,7 +3920,8 @@ e1000_validate_mdi_setting(struct e1000_hw *hw)
 
 /******************************************************************************
  * Sets up eeprom variables in the hw struct.  Must be called after mac_type
- * is configured.
+ * is configured.  Additionally, if this is ICH8, the flash controller GbE
+ * registers must be mapped, or this will crash.
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
@@ -3505,6 +4034,20 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
             E1000_WRITE_REG(hw, EECD, eecd);
         }
         break;
+    case e1000_80003es2lan:
+        eeprom->type = e1000_eeprom_spi;
+        eeprom->opcode_bits = 8;
+        eeprom->delay_usec = 1;
+        if (eecd & E1000_EECD_ADDR_BITS) {
+            eeprom->page_size = 32;
+            eeprom->address_bits = 16;
+        } else {
+            eeprom->page_size = 8;
+            eeprom->address_bits = 8;
+        }
+        eeprom->use_eerd = TRUE;
+        eeprom->use_eewr = FALSE;
+        break;
     default:
         break;
     }
@@ -3685,9 +4228,8 @@ e1000_acquire_eeprom(struct e1000_hw *hw)
 
     DEBUGFUNC("e1000_acquire_eeprom");
 
-    if(e1000_get_hw_eeprom_semaphore(hw))
-        return -E1000_ERR_EEPROM;
-
+    if (e1000_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM))
+        return -E1000_ERR_SWFW_SYNC;
     eecd = E1000_READ_REG(hw, EECD);
 
     if (hw->mac_type != e1000_82573) {
@@ -3706,7 +4248,7 @@ e1000_acquire_eeprom(struct e1000_hw *hw)
                 eecd &= ~E1000_EECD_REQ;
                 E1000_WRITE_REG(hw, EECD, eecd);
                 DEBUGOUT("Could not acquire EEPROM grant\n");
-                e1000_put_hw_eeprom_semaphore(hw);
+                e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
                 return -E1000_ERR_EEPROM;
             }
         }
@@ -3829,7 +4371,7 @@ e1000_release_eeprom(struct e1000_hw *hw)
         E1000_WRITE_REG(hw, EECD, eecd);
     }
 
-    e1000_put_hw_eeprom_semaphore(hw);
+    e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
 }
 
 /******************************************************************************
@@ -3908,6 +4450,8 @@ e1000_read_eeprom(struct e1000_hw *hw,
     if (e1000_is_onboard_nvm_eeprom(hw) == TRUE &&
     hw->eeprom.use_eerd == FALSE) {
         switch (hw->mac_type) {
+        case e1000_80003es2lan:
+            break;
         default:
             /* Prepare the EEPROM for reading  */
             if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
@@ -4025,6 +4569,9 @@ e1000_write_eeprom_eewr(struct e1000_hw *hw,
     uint32_t    i              = 0;
     int32_t     error          = 0;
 
+    if (e1000_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM))
+        return -E1000_ERR_SWFW_SYNC;
+
     for (i = 0; i < words; i++) {
         register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) | 
                          ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) | 
@@ -4044,6 +4591,7 @@ e1000_write_eeprom_eewr(struct e1000_hw *hw,
         }       
     }
     
+    e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
     return error;
 }
 
@@ -4085,6 +4633,8 @@ e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
 {
     uint32_t eecd = 0;
 
+    DEBUGFUNC("e1000_is_onboard_nvm_eeprom");
+
     if(hw->mac_type == e1000_82573) {
         eecd = E1000_READ_REG(hw, EECD);
 
@@ -4511,6 +5061,7 @@ e1000_read_mac_addr(struct e1000_hw * hw)
     case e1000_82546:
     case e1000_82546_rev_3:
     case e1000_82571:
+    case e1000_80003es2lan:
         if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
             hw->perm_mac_addr[5] ^= 0x01;
         break;
@@ -4749,8 +5300,37 @@ e1000_rar_set(struct e1000_hw *hw,
     rar_low = ((uint32_t) addr[0] |
                ((uint32_t) addr[1] << 8) |
                ((uint32_t) addr[2] << 16) | ((uint32_t) addr[3] << 24));
+    rar_high = ((uint32_t) addr[4] | ((uint32_t) addr[5] << 8));
 
-    rar_high = ((uint32_t) addr[4] | ((uint32_t) addr[5] << 8) | E1000_RAH_AV);
+    /* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx
+     * unit hang.
+     *
+     * Description:
+     * If there are any Rx frames queued up or otherwise present in the HW
+     * before RSS is enabled, and then we enable RSS, the HW Rx unit will
+     * hang.  To work around this issue, we have to disable receives and
+     * flush out all Rx frames before we enable RSS. To do so, we modify we
+     * redirect all Rx traffic to manageability and then reset the HW.
+     * This flushes away Rx frames, and (since the redirections to
+     * manageability persists across resets) keeps new ones from coming in
+     * while we work.  Then, we clear the Address Valid AV bit for all MAC
+     * addresses and undo the re-direction to manageability.
+     * Now, frames are coming in again, but the MAC won't accept them, so
+     * far so good.  We now proceed to initialize RSS (if necessary) and
+     * configure the Rx unit.  Last, we re-enable the AV bits and continue
+     * on our merry way.
+     */
+    switch (hw->mac_type) {
+    case e1000_82571:
+    case e1000_82572:
+    case e1000_80003es2lan:
+        if (hw->leave_av_bit_off == TRUE)
+            break;
+    default:
+        /* Indicate to hardware the Address is Valid. */
+        rar_high |= E1000_RAH_AV;
+        break;
+    }
 
     E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
     E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
@@ -5330,6 +5910,7 @@ e1000_get_bus_info(struct e1000_hw *hw)
         hw->bus_width = e1000_bus_width_pciex_1;
         break;
     case e1000_82571:
+    case e1000_80003es2lan:
         hw->bus_type = e1000_bus_type_pci_express;
         hw->bus_speed = e1000_bus_speed_2500;
         hw->bus_width = e1000_bus_width_pciex_4;
@@ -5475,6 +6056,34 @@ e1000_get_cable_length(struct e1000_hw *hw,
             return -E1000_ERR_PHY;
             break;
         }
+    } else if (hw->phy_type == e1000_phy_gg82563) {
+        ret_val = e1000_read_phy_reg(hw, GG82563_PHY_DSP_DISTANCE,
+                                     &phy_data);
+        if (ret_val)
+            return ret_val;
+        cable_length = phy_data & GG82563_DSPD_CABLE_LENGTH;
+
+        switch (cable_length) {
+        case e1000_gg_cable_length_60:
+            *min_length = 0;
+            *max_length = e1000_igp_cable_length_60;
+            break;
+        case e1000_gg_cable_length_60_115:
+            *min_length = e1000_igp_cable_length_60;
+            *max_length = e1000_igp_cable_length_115;
+            break;
+        case e1000_gg_cable_length_115_150:
+            *min_length = e1000_igp_cable_length_115;
+            *max_length = e1000_igp_cable_length_150;
+            break;
+        case e1000_gg_cable_length_150:
+            *min_length = e1000_igp_cable_length_150;
+            *max_length = e1000_igp_cable_length_180;
+            break;
+        default:
+            return -E1000_ERR_PHY;
+            break;
+        }
     } else if(hw->phy_type == e1000_phy_igp) { /* For IGP PHY */
         uint16_t agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
                                                          {IGP01E1000_PHY_AGC_A,
@@ -5584,7 +6193,8 @@ e1000_check_polarity(struct e1000_hw *hw,
 
     DEBUGFUNC("e1000_check_polarity");
 
-    if(hw->phy_type == e1000_phy_m88) {
+    if ((hw->phy_type == e1000_phy_m88) ||
+        (hw->phy_type == e1000_phy_gg82563)) {
         /* return the Polarity bit in the Status register. */
         ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
                                      &phy_data);
@@ -5653,7 +6263,8 @@ e1000_check_downshift(struct e1000_hw *hw)
             return ret_val;
 
         hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0;
-    } else if(hw->phy_type == e1000_phy_m88) {
+    } else if ((hw->phy_type == e1000_phy_m88) ||
+               (hw->phy_type == e1000_phy_gg82563)) {
         ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
                                      &phy_data);
         if(ret_val)
@@ -6686,6 +7297,7 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
     case e1000_82571:
     case e1000_82572:
     case e1000_82573:
+    case e1000_80003es2lan:
         while(timeout) {
             if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) break;
             else msec_delay(1);
@@ -6729,6 +7341,11 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
     default:
         msec_delay(10);
         break;
+    case e1000_80003es2lan:
+        /* Separate *_CFG_DONE_* bit for each port */
+        if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+            cfg_mask = E1000_EEPROM_CFG_DONE_PORT_1;
+        /* Fall Through */
     case e1000_82571:
     case e1000_82572:
         while (timeout) {
@@ -6746,12 +7363,6 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
         break;
     }
 
-    /* PHY configuration from NVM just starts after EECD_AUTO_RD sets to high.
-     * Need to wait for PHY configuration completion before accessing NVM
-     * and PHY. */
-    if (hw->mac_type == e1000_82573)
-        msec_delay(25);
-
     return E1000_SUCCESS;
 }
 
@@ -6777,6 +7388,11 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
     if(!hw->eeprom_semaphore_present)
         return E1000_SUCCESS;
 
+    if (hw->mac_type == e1000_80003es2lan) {
+        /* Get the SW semaphore. */
+        if (e1000_get_software_semaphore(hw) != E1000_SUCCESS)
+            return -E1000_ERR_EEPROM;
+    }
 
     /* Get the FW semaphore. */
     timeout = hw->eeprom.word_size + 1;
@@ -6822,10 +7438,75 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
         return;
 
     swsm = E1000_READ_REG(hw, SWSM);
+    if (hw->mac_type == e1000_80003es2lan) {
+        /* Release both semaphores. */
+        swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
+    } else
         swsm &= ~(E1000_SWSM_SWESMBI);
     E1000_WRITE_REG(hw, SWSM, swsm);
 }
 
+/***************************************************************************
+ *
+ * Obtaining software semaphore bit (SMBI) before resetting PHY.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - E1000_ERR_RESET if fail to obtain semaphore.
+ *            E1000_SUCCESS at any other case.
+ *
+ ***************************************************************************/
+int32_t
+e1000_get_software_semaphore(struct e1000_hw *hw)
+{
+    int32_t timeout = hw->eeprom.word_size + 1;
+    uint32_t swsm;
+
+    DEBUGFUNC("e1000_get_software_semaphore");
+
+    if (hw->mac_type != e1000_80003es2lan)
+        return E1000_SUCCESS;
+
+    while(timeout) {
+        swsm = E1000_READ_REG(hw, SWSM);
+        /* If SMBI bit cleared, it is now set and we hold the semaphore */
+        if(!(swsm & E1000_SWSM_SMBI))
+            break;
+        msec_delay_irq(1);
+        timeout--;
+    }
+
+    if(!timeout) {
+        DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
+        return -E1000_ERR_RESET;
+    }
+
+    return E1000_SUCCESS;
+}
+
+/***************************************************************************
+ *
+ * Release semaphore bit (SMBI).
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ ***************************************************************************/
+void
+e1000_release_software_semaphore(struct e1000_hw *hw)
+{
+    uint32_t swsm;
+
+    DEBUGFUNC("e1000_release_software_semaphore");
+
+    if (hw->mac_type != e1000_80003es2lan)
+        return;
+
+    swsm = E1000_READ_REG(hw, SWSM);
+    /* Release the SW semaphores.*/
+    swsm &= ~E1000_SWSM_SMBI;
+    E1000_WRITE_REG(hw, SWSM, swsm);
+}
+
 /******************************************************************************
  * Checks if PHY reset is blocked due to SOL/IDER session, for example.
  * Returning E1000_BLK_PHY_RESET isn't necessarily an error.  But it's up to
@@ -6862,6 +7543,7 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
     case e1000_82571:
     case e1000_82572:
     case e1000_82573:
+    case e1000_80003es2lan:
         fwsm = E1000_READ_REG(hw, FWSM);
         if((fwsm & E1000_FWSM_MODE_MASK) != 0)
             return TRUE;
index f1219dd..150e45e 100644 (file)
@@ -60,6 +60,7 @@ typedef enum {
     e1000_82571,
     e1000_82572,
     e1000_82573,
+    e1000_80003es2lan,
     e1000_num_macs
 } e1000_mac_type;
 
@@ -138,6 +139,13 @@ typedef enum {
     e1000_cable_length_undefined = 0xFF
 } e1000_cable_length;
 
+typedef enum {
+    e1000_gg_cable_length_60 = 0,
+    e1000_gg_cable_length_60_115 = 1,
+    e1000_gg_cable_length_115_150 = 2,
+    e1000_gg_cable_length_150 = 4
+} e1000_gg_cable_length;
+
 typedef enum {
     e1000_igp_cable_length_10  = 10,
     e1000_igp_cable_length_20  = 20,
@@ -208,6 +216,7 @@ typedef enum {
     e1000_phy_m88 = 0,
     e1000_phy_igp,
     e1000_phy_igp_2,
+    e1000_phy_gg82563,
     e1000_phy_undefined = 0xFF
 } e1000_phy_type;
 
@@ -281,6 +290,7 @@ typedef enum {
 #define E1000_ERR_MASTER_REQUESTS_PENDING 10
 #define E1000_ERR_HOST_INTERFACE_COMMAND 11
 #define E1000_BLK_PHY_RESET   12
+#define E1000_ERR_SWFW_SYNC 13
 
 /* Function prototypes */
 /* Initialization */
@@ -304,6 +314,8 @@ int32_t e1000_phy_hw_reset(struct e1000_hw *hw);
 int32_t e1000_phy_reset(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);
@@ -454,6 +466,8 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
 #define E1000_DEV_ID_82573E_IAMT         0x108C
 #define E1000_DEV_ID_82573L              0x109A
 #define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
+#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT     0x1096
+#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT     0x1098
 
 
 #define NODE_ADDRESS_SIZE 6
@@ -850,6 +864,7 @@ struct e1000_ffvt_entry {
 #define E1000_TXCW     0x00178  /* TX Configuration Word - RW */
 #define E1000_RXCW     0x00180  /* RX Configuration Word - RO */
 #define E1000_TCTL     0x00400  /* TX Control - RW */
+#define E1000_TCTL_EXT 0x00404  /* Extended TX Control - RW */
 #define E1000_TIPG     0x00410  /* TX Inter-packet gap -RW */
 #define E1000_TBT      0x00448  /* TX Burst Timer - RW */
 #define E1000_AIT      0x00458  /* Adaptive Interframe Spacing Throttle - RW */
@@ -996,6 +1011,11 @@ struct e1000_ffvt_entry {
 #define E1000_FFMT     0x09000  /* Flexible Filter Mask Table - RW Array */
 #define E1000_FFVT     0x09800  /* Flexible Filter Value Table - RW Array */
 
+#define E1000_KUMCTRLSTA 0x00034 /* MAC-PHY interface - RW */
+#define E1000_MDPHYA     0x0003C  /* PHY address - RW */
+#define E1000_MANC2H     0x05860  /* Managment Control To Host - RW */
+#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */
+
 #define E1000_GCR       0x05B00 /* PCI-Ex Control */
 #define E1000_GSCL_1    0x05B10 /* PCI-Ex Statistic Control #1 */
 #define E1000_GSCL_2    0x05B14 /* PCI-Ex Statistic Control #2 */
@@ -1065,6 +1085,7 @@ struct e1000_ffvt_entry {
 #define E1000_82542_RXCW     E1000_RXCW
 #define E1000_82542_MTA      0x00200
 #define E1000_82542_TCTL     E1000_TCTL
+#define E1000_82542_TCTL_EXT E1000_TCTL_EXT
 #define E1000_82542_TIPG     E1000_TIPG
 #define E1000_82542_TDBAL    0x00420
 #define E1000_82542_TDBAH    0x00424
@@ -1212,6 +1233,8 @@ struct e1000_ffvt_entry {
 #define E1000_82542_RSSRK       E1000_RSSRK
 #define E1000_82542_RSSIM       E1000_RSSIM
 #define E1000_82542_RSSIR       E1000_RSSIR
+#define E1000_82542_KUMCTRLSTA E1000_KUMCTRLSTA
+#define E1000_82542_SW_FW_SYNC E1000_SW_FW_SYNC
 
 /* Statistics counters collected by the MAC */
 struct e1000_hw_stats {
@@ -1303,6 +1326,7 @@ struct e1000_hw {
     e1000_ffe_config ffe_config_state;
     uint32_t asf_firmware_present;
     uint32_t eeprom_semaphore_present;
+    uint32_t swfw_sync_present;
     unsigned long io_base;
     uint32_t phy_id;
     uint32_t phy_revision;
@@ -1361,6 +1385,7 @@ struct e1000_hw {
     boolean_t ifs_params_forced;
     boolean_t in_ifs_mode;
     boolean_t mng_reg_access_disabled;
+    boolean_t leave_av_bit_off;
 };
 
 
@@ -1393,6 +1418,8 @@ struct e1000_hw {
 #define E1000_CTRL_FRCDPX   0x00001000  /* Force Duplex */
 #define E1000_CTRL_D_UD_EN  0x00002000  /* Dock/Undock enable */
 #define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */
+#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through PHYRST_N pin */
+#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external LINK_0 and LINK_1 pins */
 #define E1000_CTRL_SWDPIN0  0x00040000  /* SWDPIN 0 value */
 #define E1000_CTRL_SWDPIN1  0x00080000  /* SWDPIN 1 value */
 #define E1000_CTRL_SWDPIN2  0x00100000  /* SWDPIN 2 value */
@@ -1429,6 +1456,16 @@ struct e1000_hw {
 #define E1000_STATUS_BUS64      0x00001000      /* In 64 bit slot */
 #define E1000_STATUS_PCIX_MODE  0x00002000      /* PCI-X mode */
 #define E1000_STATUS_PCIX_SPEED 0x0000C000      /* PCI-X bus speed */
+#define E1000_STATUS_BMC_SKU_0  0x00100000 /* BMC USB redirect disabled */
+#define E1000_STATUS_BMC_SKU_1  0x00200000 /* BMC SRAM disabled */
+#define E1000_STATUS_BMC_SKU_2  0x00400000 /* BMC SDRAM disabled */
+#define E1000_STATUS_BMC_CRYPTO 0x00800000 /* BMC crypto disabled */
+#define E1000_STATUS_BMC_LITE   0x01000000 /* BMC external code execution disabled */
+#define E1000_STATUS_RGMII_ENABLE 0x02000000 /* RGMII disabled */
+#define E1000_STATUS_FUSE_8       0x04000000
+#define E1000_STATUS_FUSE_9       0x08000000
+#define E1000_STATUS_SERDES0_DIS  0x10000000 /* SERDES disabled on port 0 */
+#define E1000_STATUS_SERDES1_DIS  0x20000000 /* SERDES disabled on port 1 */
 
 /* Constants used to intrepret the masked PCI-X bus speed. */
 #define E1000_STATUS_PCIX_SPEED_66  0x00000000 /* PCI-X bus speed  50-66 MHz */
@@ -1506,6 +1543,8 @@ struct e1000_hw {
 #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
 #define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
 #define E1000_CTRL_EXT_LINK_MODE_TBI  0x00C00000
+#define E1000_CTRL_EXT_LINK_MODE_KMRN    0x00000000
+#define E1000_CTRL_EXT_LINK_MODE_SERDES  0x00C00000
 #define E1000_CTRL_EXT_WR_WMARK_MASK  0x03000000
 #define E1000_CTRL_EXT_WR_WMARK_256   0x00000000
 #define E1000_CTRL_EXT_WR_WMARK_320   0x01000000
@@ -1515,6 +1554,9 @@ struct e1000_hw {
 #define E1000_CTRL_EXT_DRV_LOAD       0x10000000  /* Driver loaded bit for FW */
 #define E1000_CTRL_EXT_IAME           0x08000000  /* Interrupt acknowledge Auto-mask */
 #define E1000_CTRL_EXT_INT_TIMER_CLR  0x20000000  /* Clear Interrupt timers after IMS clear */
+#define E1000_CRTL_EXT_PB_PAREN       0x01000000 /* packet buffer parity error detection enabled */
+#define E1000_CTRL_EXT_DF_PAREN       0x02000000 /* descriptor FIFO parity error detection enable */
+#define E1000_CTRL_EXT_GHOST_PAREN    0x40000000
 
 /* MDI Control */
 #define E1000_MDIC_DATA_MASK 0x0000FFFF
@@ -1528,6 +1570,32 @@ struct e1000_hw {
 #define E1000_MDIC_INT_EN    0x20000000
 #define E1000_MDIC_ERROR     0x40000000
 
+#define E1000_KUMCTRLSTA_MASK           0x0000FFFF
+#define E1000_KUMCTRLSTA_OFFSET         0x001F0000
+#define E1000_KUMCTRLSTA_OFFSET_SHIFT   16
+#define E1000_KUMCTRLSTA_REN            0x00200000
+
+#define E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL      0x00000000
+#define E1000_KUMCTRLSTA_OFFSET_CTRL           0x00000001
+#define E1000_KUMCTRLSTA_OFFSET_INB_CTRL       0x00000002
+#define E1000_KUMCTRLSTA_OFFSET_DIAG           0x00000003
+#define E1000_KUMCTRLSTA_OFFSET_TIMEOUTS       0x00000004
+#define E1000_KUMCTRLSTA_OFFSET_INB_PARAM      0x00000009
+#define E1000_KUMCTRLSTA_OFFSET_HD_CTRL        0x00000010
+#define E1000_KUMCTRLSTA_OFFSET_M2P_SERDES     0x0000001E
+#define E1000_KUMCTRLSTA_OFFSET_M2P_MODES      0x0000001F
+
+/* FIFO Control */
+#define E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS   0x00000008
+#define E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS   0x00000800
+
+/* In-Band Control */
+#define E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING  0x00000010
+
+/* Half-Duplex Control */
+#define E1000_KUMCTRLSTA_HD_CTRL_10_100_DEFAULT 0x00000004
+#define E1000_KUMCTRLSTA_HD_CTRL_1000_DEFAULT  0x00000000
+
 /* LED Control */
 #define E1000_LEDCTL_LED0_MODE_MASK       0x0000000F
 #define E1000_LEDCTL_LED0_MODE_SHIFT      0
@@ -1590,6 +1658,13 @@ struct e1000_hw {
 #define E1000_ICR_MNG           0x00040000 /* Manageability event */
 #define E1000_ICR_DOCK          0x00080000 /* Dock/Undock */
 #define E1000_ICR_INT_ASSERTED  0x80000000 /* If this bit asserted, the driver should claim the interrupt */
+#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* queue 0 Rx descriptor FIFO parity error */
+#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* queue 0 Tx descriptor FIFO parity error */
+#define E1000_ICR_HOST_ARB_PAR  0x00400000 /* host arb read buffer parity error */
+#define E1000_ICR_PB_PAR        0x00800000 /* packet buffer parity error */
+#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* queue 1 Rx descriptor FIFO parity error */
+#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* queue 1 Tx descriptor FIFO parity error */
+#define E1000_ICR_ALL_PARITY    0x03F00000 /* all parity error bits */
 
 /* Interrupt Cause Set */
 #define E1000_ICS_TXDW      E1000_ICR_TXDW      /* Transmit desc written back */
@@ -1610,6 +1685,12 @@ struct e1000_hw {
 #define E1000_ICS_ACK       E1000_ICR_ACK       /* Receive Ack frame */
 #define E1000_ICS_MNG       E1000_ICR_MNG       /* Manageability event */
 #define E1000_ICS_DOCK      E1000_ICR_DOCK      /* Dock/Undock */
+#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */
+#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */
+#define E1000_ICS_HOST_ARB_PAR  E1000_ICR_HOST_ARB_PAR  /* host arb read buffer parity error */
+#define E1000_ICS_PB_PAR        E1000_ICR_PB_PAR        /* packet buffer parity error */
+#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */
+#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */
 
 /* Interrupt Mask Set */
 #define E1000_IMS_TXDW      E1000_ICR_TXDW      /* Transmit desc written back */
@@ -1630,6 +1711,12 @@ struct e1000_hw {
 #define E1000_IMS_ACK       E1000_ICR_ACK       /* Receive Ack frame */
 #define E1000_IMS_MNG       E1000_ICR_MNG       /* Manageability event */
 #define E1000_IMS_DOCK      E1000_ICR_DOCK      /* Dock/Undock */
+#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */
+#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */
+#define E1000_IMS_HOST_ARB_PAR  E1000_ICR_HOST_ARB_PAR  /* host arb read buffer parity error */
+#define E1000_IMS_PB_PAR        E1000_ICR_PB_PAR        /* packet buffer parity error */
+#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */
+#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */
 
 /* Interrupt Mask Clear */
 #define E1000_IMC_TXDW      E1000_ICR_TXDW      /* Transmit desc written back */
@@ -1650,6 +1737,12 @@ struct e1000_hw {
 #define E1000_IMC_ACK       E1000_ICR_ACK       /* Receive Ack frame */
 #define E1000_IMC_MNG       E1000_ICR_MNG       /* Manageability event */
 #define E1000_IMC_DOCK      E1000_ICR_DOCK      /* Dock/Undock */
+#define E1000_IMC_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */
+#define E1000_IMC_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */
+#define E1000_IMC_HOST_ARB_PAR  E1000_ICR_HOST_ARB_PAR  /* host arb read buffer parity error */
+#define E1000_IMC_PB_PAR        E1000_ICR_PB_PAR        /* packet buffer parity error */
+#define E1000_IMC_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */
+#define E1000_IMC_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */
 
 /* Receive Control */
 #define E1000_RCTL_RST            0x00000001    /* Software reset */
@@ -1719,6 +1812,12 @@ struct e1000_hw {
 #define E1000_PSRCTL_BSIZE2_SHIFT  6            /* Shift _left_ 6 */
 #define E1000_PSRCTL_BSIZE3_SHIFT 14            /* Shift _left_ 14 */
 
+/* SW_W_SYNC definitions */
+#define E1000_SWFW_EEP_SM     0x0001
+#define E1000_SWFW_PHY0_SM    0x0002
+#define E1000_SWFW_PHY1_SM    0x0004
+#define E1000_SWFW_MAC_CSR_SM 0x0008
+
 /* Receive Descriptor */
 #define E1000_RDT_DELAY 0x0000ffff      /* Delay timer (1=1024us) */
 #define E1000_RDT_FPDB  0x80000000      /* Flush descriptor block */
@@ -1797,6 +1896,11 @@ struct e1000_hw {
 #define E1000_TCTL_RTLC   0x01000000    /* Re-transmit on late collision */
 #define E1000_TCTL_NRTU   0x02000000    /* No Re-transmit on underrun */
 #define E1000_TCTL_MULR   0x10000000    /* Multiple request support */
+/* Extended Transmit Control */
+#define E1000_TCTL_EXT_BST_MASK  0x000003FF /* Backoff Slot Time */
+#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */
+
+#define DEFAULT_80003ES2LAN_TCTL_EXT_GCEX   0x00010000
 
 /* Receive Checksum Control */
 #define E1000_RXCSUM_PCSS_MASK 0x000000FF   /* Packet Checksum Start */
@@ -1874,6 +1978,7 @@ struct e1000_hw {
 #define E1000_MANC_TCO_RESET     0x00010000 /* TCO Reset Occurred */
 #define E1000_MANC_RCV_TCO_EN    0x00020000 /* Receive TCO Packets Enabled */
 #define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */
+#define E1000_MANC_RCV_ALL       0x00080000 /* Receive All Enabled */
 #define E1000_MANC_BLK_PHY_RST_ON_IDE   0x00040000 /* Block phy resets */
 #define E1000_MANC_EN_MAC_ADDR_FILTER   0x00100000 /* Enable MAC address
                                                     * filtering */
@@ -1962,19 +2067,19 @@ struct e1000_host_command_info {
 /* PCI-Ex registers */
 
 /* PCI-Ex Control Register */
-#define E1000_GCR_RXD_NO_SNOOP                 0x00000001
-#define E1000_GCR_RXDSCW_NO_SNOOP              0x00000002
-#define E1000_GCR_RXDSCR_NO_SNOOP              0x00000004
-#define E1000_GCR_TXD_NO_SNOOP                 0x00000008
-#define E1000_GCR_TXDSCW_NO_SNOOP              0x00000010
-#define E1000_GCR_TXDSCR_NO_SNOOP              0x00000020
-
-#define PCI_EX_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP            | \
-                                                        E1000_GCR_RXDSCW_NO_SNOOP      | \
-                                                        E1000_GCR_RXDSCR_NO_SNOOP      | \
-                                                        E1000_GCR TXD_NO_SNOOP         | \
-                                                        E1000_GCR_TXDSCW_NO_SNOOP      | \
-                                                        E1000_GCR_TXDSCR_NO_SNOOP)
+#define E1000_GCR_RXD_NO_SNOOP          0x00000001
+#define E1000_GCR_RXDSCW_NO_SNOOP       0x00000002
+#define E1000_GCR_RXDSCR_NO_SNOOP       0x00000004
+#define E1000_GCR_TXD_NO_SNOOP          0x00000008
+#define E1000_GCR_TXDSCW_NO_SNOOP       0x00000010
+#define E1000_GCR_TXDSCR_NO_SNOOP       0x00000020
+
+#define PCI_EX_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP         | \
+                             E1000_GCR_RXDSCW_NO_SNOOP      | \
+                             E1000_GCR_RXDSCR_NO_SNOOP      | \
+                             E1000_GCR_TXD_NO_SNOOP         | \
+                             E1000_GCR_TXDSCW_NO_SNOOP      | \
+                             E1000_GCR_TXDSCR_NO_SNOOP)
 
 #define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
 /* Function Active and Power State to MNG */
@@ -2035,12 +2140,14 @@ struct e1000_host_command_info {
 #define EEPROM_INIT_CONTROL1_REG      0x000A
 #define EEPROM_INIT_CONTROL2_REG      0x000F
 #define EEPROM_INIT_CONTROL3_PORT_B   0x0014
+#define EEPROM_INIT_3GIO_3            0x001A
 #define EEPROM_INIT_CONTROL3_PORT_A   0x0024
 #define EEPROM_CFG                    0x0012
 #define EEPROM_FLASH_VERSION          0x0032
 #define EEPROM_CHECKSUM_REG           0x003F
 
 #define E1000_EEPROM_CFG_DONE         0x00040000   /* MNG config cycle done */
+#define E1000_EEPROM_CFG_DONE_PORT_1  0x00080000   /* ...for second port */
 
 /* Word definitions for ID LED Settings */
 #define ID_LED_RESERVED_0000 0x0000
@@ -2084,6 +2191,9 @@ struct e1000_host_command_info {
 #define EEPROM_WORD0F_ANE        0x0800
 #define EEPROM_WORD0F_SWPDIO_EXT 0x00F0
 
+/* Mask bits for fields in Word 0x1a of the EEPROM */
+#define EEPROM_WORD1A_ASPM_MASK  0x000C
+
 /* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */
 #define EEPROM_SUM 0xBABA
 
@@ -2126,8 +2236,11 @@ struct e1000_host_command_info {
 
 #define DEFAULT_82542_TIPG_IPGR2 10
 #define DEFAULT_82543_TIPG_IPGR2 6
+#define DEFAULT_80003ES2LAN_TIPG_IPGR2 7
 #define E1000_TIPG_IPGR2_SHIFT  20
 
+#define DEFAULT_80003ES2LAN_TIPG_IPGT_10_100 0x00000009
+#define DEFAULT_80003ES2LAN_TIPG_IPGT_1000   0x00000008
 #define E1000_TXDMAC_DPP 0x00000001
 
 /* Adaptive IFS defines */
@@ -2368,6 +2481,78 @@ struct e1000_host_command_info {
 
 #define IGP01E1000_ANALOG_REGS_PAGE  0x20C0
 
+/* Bits...
+ * 15-5: page
+ * 4-0: register offset
+ */
+#define GG82563_PAGE_SHIFT        5
+#define GG82563_REG(page, reg)    \
+        (((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS))
+#define GG82563_MIN_ALT_REG       30
+
+/* GG82563 Specific Registers */
+#define GG82563_PHY_SPEC_CTRL           \
+        GG82563_REG(0, 16) /* PHY Specific Control */
+#define GG82563_PHY_SPEC_STATUS         \
+        GG82563_REG(0, 17) /* PHY Specific Status */
+#define GG82563_PHY_INT_ENABLE          \
+        GG82563_REG(0, 18) /* Interrupt Enable */
+#define GG82563_PHY_SPEC_STATUS_2       \
+        GG82563_REG(0, 19) /* PHY Specific Status 2 */
+#define GG82563_PHY_RX_ERR_CNTR         \
+        GG82563_REG(0, 21) /* Receive Error Counter */
+#define GG82563_PHY_PAGE_SELECT         \
+        GG82563_REG(0, 22) /* Page Select */
+#define GG82563_PHY_SPEC_CTRL_2         \
+        GG82563_REG(0, 26) /* PHY Specific Control 2 */
+#define GG82563_PHY_PAGE_SELECT_ALT     \
+        GG82563_REG(0, 29) /* Alternate Page Select */
+#define GG82563_PHY_TEST_CLK_CTRL       \
+        GG82563_REG(0, 30) /* Test Clock Control (use reg. 29 to select) */
+
+#define GG82563_PHY_MAC_SPEC_CTRL       \
+        GG82563_REG(2, 21) /* MAC Specific Control Register */
+#define GG82563_PHY_MAC_SPEC_CTRL_2     \
+        GG82563_REG(2, 26) /* MAC Specific Control 2 */
+
+#define GG82563_PHY_DSP_DISTANCE    \
+        GG82563_REG(5, 26) /* DSP Distance */
+
+/* Page 193 - Port Control Registers */
+#define GG82563_PHY_KMRN_MODE_CTRL   \
+        GG82563_REG(193, 16) /* Kumeran Mode Control */
+#define GG82563_PHY_PORT_RESET          \
+        GG82563_REG(193, 17) /* Port Reset */
+#define GG82563_PHY_REVISION_ID         \
+        GG82563_REG(193, 18) /* Revision ID */
+#define GG82563_PHY_DEVICE_ID           \
+        GG82563_REG(193, 19) /* Device ID */
+#define GG82563_PHY_PWR_MGMT_CTRL       \
+        GG82563_REG(193, 20) /* Power Management Control */
+#define GG82563_PHY_RATE_ADAPT_CTRL     \
+        GG82563_REG(193, 25) /* Rate Adaptation Control */
+
+/* Page 194 - KMRN Registers */
+#define GG82563_PHY_KMRN_FIFO_CTRL_STAT \
+        GG82563_REG(194, 16) /* FIFO's Control/Status */
+#define GG82563_PHY_KMRN_CTRL           \
+        GG82563_REG(194, 17) /* Control */
+#define GG82563_PHY_INBAND_CTRL         \
+        GG82563_REG(194, 18) /* Inband Control */
+#define GG82563_PHY_KMRN_DIAGNOSTIC     \
+        GG82563_REG(194, 19) /* Diagnostic */
+#define GG82563_PHY_ACK_TIMEOUTS        \
+        GG82563_REG(194, 20) /* Acknowledge Timeouts */
+#define GG82563_PHY_ADV_ABILITY         \
+        GG82563_REG(194, 21) /* Advertised Ability */
+#define GG82563_PHY_LINK_PARTNER_ADV_ABILITY \
+        GG82563_REG(194, 23) /* Link Partner Advertised Ability */
+#define GG82563_PHY_ADV_NEXT_PAGE       \
+        GG82563_REG(194, 24) /* Advertised Next Page */
+#define GG82563_PHY_LINK_PARTNER_ADV_NEXT_PAGE \
+        GG82563_REG(194, 25) /* Link Partner Advertised Next page */
+#define GG82563_PHY_KMRN_MISC           \
+        GG82563_REG(194, 26) /* Misc. */
 
 /* PHY Control Register */
 #define MII_CR_SPEED_SELECT_MSB 0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
@@ -2681,6 +2866,113 @@ struct e1000_host_command_info {
 #define IGP01E1000_ANALOG_FUSE_FINE_1               0x0080
 #define IGP01E1000_ANALOG_FUSE_FINE_10              0x0500
 
+/* GG82563 PHY Specific Status Register (Page 0, Register 16 */
+#define GG82563_PSCR_DISABLE_JABBER             0x0001 /* 1=Disable Jabber */
+#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE  0x0002 /* 1=Polarity Reversal Disabled */
+#define GG82563_PSCR_POWER_DOWN                 0x0004 /* 1=Power Down */
+#define GG82563_PSCR_COPPER_TRANSMITER_DISABLE  0x0008 /* 1=Transmitter Disabled */
+#define GG82563_PSCR_CROSSOVER_MODE_MASK        0x0060
+#define GG82563_PSCR_CROSSOVER_MODE_MDI         0x0000 /* 00=Manual MDI configuration */
+#define GG82563_PSCR_CROSSOVER_MODE_MDIX        0x0020 /* 01=Manual MDIX configuration */
+#define GG82563_PSCR_CROSSOVER_MODE_AUTO        0x0060 /* 11=Automatic crossover */
+#define GG82563_PSCR_ENALBE_EXTENDED_DISTANCE   0x0080 /* 1=Enable Extended Distance */
+#define GG82563_PSCR_ENERGY_DETECT_MASK         0x0300
+#define GG82563_PSCR_ENERGY_DETECT_OFF          0x0000 /* 00,01=Off */
+#define GG82563_PSCR_ENERGY_DETECT_RX           0x0200 /* 10=Sense on Rx only (Energy Detect) */
+#define GG82563_PSCR_ENERGY_DETECT_RX_TM        0x0300 /* 11=Sense and Tx NLP */
+#define GG82563_PSCR_FORCE_LINK_GOOD            0x0400 /* 1=Force Link Good */
+#define GG82563_PSCR_DOWNSHIFT_ENABLE           0x0800 /* 1=Enable Downshift */
+#define GG82563_PSCR_DOWNSHIFT_COUNTER_MASK     0x7000
+#define GG82563_PSCR_DOWNSHIFT_COUNTER_SHIFT    12
+
+/* PHY Specific Status Register (Page 0, Register 17) */
+#define GG82563_PSSR_JABBER                0x0001 /* 1=Jabber */
+#define GG82563_PSSR_POLARITY              0x0002 /* 1=Polarity Reversed */
+#define GG82563_PSSR_LINK                  0x0008 /* 1=Link is Up */
+#define GG82563_PSSR_ENERGY_DETECT         0x0010 /* 1=Sleep, 0=Active */
+#define GG82563_PSSR_DOWNSHIFT             0x0020 /* 1=Downshift */
+#define GG82563_PSSR_CROSSOVER_STATUS      0x0040 /* 1=MDIX, 0=MDI */
+#define GG82563_PSSR_RX_PAUSE_ENABLED      0x0100 /* 1=Receive Pause Enabled */
+#define GG82563_PSSR_TX_PAUSE_ENABLED      0x0200 /* 1=Transmit Pause Enabled */
+#define GG82563_PSSR_LINK_UP               0x0400 /* 1=Link Up */
+#define GG82563_PSSR_SPEED_DUPLEX_RESOLVED 0x0800 /* 1=Resolved */
+#define GG82563_PSSR_PAGE_RECEIVED         0x1000 /* 1=Page Received */
+#define GG82563_PSSR_DUPLEX                0x2000 /* 1-Full-Duplex */
+#define GG82563_PSSR_SPEED_MASK            0xC000
+#define GG82563_PSSR_SPEED_10MBPS          0x0000 /* 00=10Mbps */
+#define GG82563_PSSR_SPEED_100MBPS         0x4000 /* 01=100Mbps */
+#define GG82563_PSSR_SPEED_1000MBPS        0x8000 /* 10=1000Mbps */
+
+/* PHY Specific Status Register 2 (Page 0, Register 19) */
+#define GG82563_PSSR2_JABBER                0x0001 /* 1=Jabber */
+#define GG82563_PSSR2_POLARITY_CHANGED      0x0002 /* 1=Polarity Changed */
+#define GG82563_PSSR2_ENERGY_DETECT_CHANGED 0x0010 /* 1=Energy Detect Changed */
+#define GG82563_PSSR2_DOWNSHIFT_INTERRUPT   0x0020 /* 1=Downshift Detected */
+#define GG82563_PSSR2_MDI_CROSSOVER_CHANGE  0x0040 /* 1=Crossover Changed */
+#define GG82563_PSSR2_FALSE_CARRIER         0x0100 /* 1=False Carrier */
+#define GG82563_PSSR2_SYMBOL_ERROR          0x0200 /* 1=Symbol Error */
+#define GG82563_PSSR2_LINK_STATUS_CHANGED   0x0400 /* 1=Link Status Changed */
+#define GG82563_PSSR2_AUTO_NEG_COMPLETED    0x0800 /* 1=Auto-Neg Completed */
+#define GG82563_PSSR2_PAGE_RECEIVED         0x1000 /* 1=Page Received */
+#define GG82563_PSSR2_DUPLEX_CHANGED        0x2000 /* 1=Duplex Changed */
+#define GG82563_PSSR2_SPEED_CHANGED         0x4000 /* 1=Speed Changed */
+#define GG82563_PSSR2_AUTO_NEG_ERROR        0x8000 /* 1=Auto-Neg Error */
+
+/* PHY Specific Control Register 2 (Page 0, Register 26) */
+#define GG82563_PSCR2_10BT_POLARITY_FORCE           0x0002 /* 1=Force Negative Polarity */
+#define GG82563_PSCR2_1000MB_TEST_SELECT_MASK       0x000C
+#define GG82563_PSCR2_1000MB_TEST_SELECT_NORMAL     0x0000 /* 00,01=Normal Operation */
+#define GG82563_PSCR2_1000MB_TEST_SELECT_112NS      0x0008 /* 10=Select 112ns Sequence */
+#define GG82563_PSCR2_1000MB_TEST_SELECT_16NS       0x000C /* 11=Select 16ns Sequence */
+#define GG82563_PSCR2_REVERSE_AUTO_NEG              0x2000 /* 1=Reverse Auto-Negotiation */
+#define GG82563_PSCR2_1000BT_DISABLE                0x4000 /* 1=Disable 1000BASE-T */
+#define GG82563_PSCR2_TRANSMITER_TYPE_MASK          0x8000
+#define GG82563_PSCR2_TRANSMITTER_TYPE_CLASS_B      0x0000 /* 0=Class B */
+#define GG82563_PSCR2_TRANSMITTER_TYPE_CLASS_A      0x8000 /* 1=Class A */
+
+/* MAC Specific Control Register (Page 2, Register 21) */
+/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */
+#define GG82563_MSCR_TX_CLK_MASK                    0x0007
+#define GG82563_MSCR_TX_CLK_10MBPS_2_5MHZ           0x0004
+#define GG82563_MSCR_TX_CLK_100MBPS_25MHZ           0x0005
+#define GG82563_MSCR_TX_CLK_1000MBPS_2_5MHZ         0x0006
+#define GG82563_MSCR_TX_CLK_1000MBPS_25MHZ          0x0007
+
+#define GG82563_MSCR_ASSERT_CRS_ON_TX               0x0010 /* 1=Assert */
+
+/* DSP Distance Register (Page 5, Register 26) */
+#define GG82563_DSPD_CABLE_LENGTH               0x0007 /* 0 = <50M;
+                                                             1 = 50-80M;
+                                                             2 = 80-110M;
+                                                             3 = 110-140M;
+                                                             4 = >140M */
+
+/* Kumeran Mode Control Register (Page 193, Register 16) */
+#define GG82563_KMCR_PHY_LEDS_EN                    0x0020 /* 1=PHY LEDs, 0=Kumeran Inband LEDs */
+#define GG82563_KMCR_FORCE_LINK_UP                  0x0040 /* 1=Force Link Up */
+#define GG82563_KMCR_SUPPRESS_SGMII_EPD_EXT         0x0080
+#define GG82563_KMCR_MDIO_BUS_SPEED_SELECT_MASK     0x0400
+#define GG82563_KMCR_MDIO_BUS_SPEED_SELECT          0x0400 /* 1=6.25MHz, 0=0.8MHz */
+#define GG82563_KMCR_PASS_FALSE_CARRIER             0x0800
+
+/* Power Management Control Register (Page 193, Register 20) */
+#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE         0x0001 /* 1=Enalbe SERDES Electrical Idle */
+#define GG82563_PMCR_DISABLE_PORT                   0x0002 /* 1=Disable Port */
+#define GG82563_PMCR_DISABLE_SERDES                 0x0004 /* 1=Disable SERDES */
+#define GG82563_PMCR_REVERSE_AUTO_NEG               0x0008 /* 1=Enable Reverse Auto-Negotiation */
+#define GG82563_PMCR_DISABLE_1000_NON_D0            0x0010 /* 1=Disable 1000Mbps Auto-Neg in non D0 */
+#define GG82563_PMCR_DISABLE_1000                   0x0020 /* 1=Disable 1000Mbps Auto-Neg Always */
+#define GG82563_PMCR_REVERSE_AUTO_NEG_D0A           0x0040 /* 1=Enable D0a Reverse Auto-Negotiation */
+#define GG82563_PMCR_FORCE_POWER_STATE              0x0080 /* 1=Force Power State */
+#define GG82563_PMCR_PROGRAMMED_POWER_STATE_MASK    0x0300
+#define GG82563_PMCR_PROGRAMMED_POWER_STATE_DR      0x0000 /* 00=Dr */
+#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D0U     0x0100 /* 01=D0u */
+#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D0A     0x0200 /* 10=D0a */
+#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D3      0x0300 /* 11=D3 */
+
+/* In-Band Control Register (Page 194, Register 18) */
+#define GG82563_ICR_DIS_PADDING                     0x0010 /* Disable Padding Use */
+
 
 /* Bit definitions for valid PHY IDs. */
 /* I = Integrated
@@ -2695,6 +2987,7 @@ struct e1000_host_command_info {
 #define M88E1011_I_REV_4   0x04
 #define M88E1111_I_PHY_ID  0x01410CC0
 #define L1LXT971A_PHY_ID   0x001378E0
+#define GG82563_E_PHY_ID   0x01410CA0
 
 /* Miscellaneous PHY bit definitions. */
 #define PHY_PREAMBLE        0xFFFFFFFF
index 4c4db96..f39de16 100644 (file)
 #include "e1000.h"
 
 /* Change Log
+ * 7.0.33      3-Feb-2006
+ *   o Added another fix for the pass false carrier bit
+ * 7.0.32      24-Jan-2006
+ *   o Need to rebuild with noew version number for the pass false carrier 
+ *     fix in e1000_hw.c
+ * 7.0.30      18-Jan-2006
+ *   o fixup for tso workaround to disable it for pci-x
+ *   o fix mem leak on 82542
+ *   o fixes for 10 Mb/s connections and incorrect stats
+ * 7.0.28      01/06/2006
+ *   o hardware workaround to only set "speed mode" bit for 1G link.
+ * 7.0.26      12/23/2005
+ *   o wake on lan support modified for device ID 10B5
+ *   o fix dhcp + vlan issue not making it to the iAMT firmware
+ * 7.0.24      12/9/2005
+ *   o New hardware support for the Gigabit NIC embedded in the south bridge
+ *   o Fixes to the recycling logic (skb->tail) from IBM LTC
  * 6.3.9       12/16/2005
  *   o incorporate fix for recycled skbs from IBM LTC
  * 6.3.7       11/18/2005
  *     rx_buffer_len
  * 6.3.1       9/19/05
  *   o Use adapter->tx_timeout_factor in Tx Hung Detect logic 
-       (e1000_clean_tx_irq)
*      (e1000_clean_tx_irq)
  *   o Support for 8086:10B5 device (Quad Port)
- * 6.2.14      9/15/05
- *   o In AMT enabled configurations, set/reset DRV_LOAD bit on interface 
- *     open/close 
- * 6.2.13       9/14/05
- *   o Invoke e1000_check_mng_mode only for 8257x controllers since it 
- *     accesses the FWSM that is not supported in other controllers
- * 6.2.12       9/9/05
- *   o Add support for device id E1000_DEV_ID_82546GB_QUAD_COPPER
- *   o set RCTL:SECRC only for controllers newer than 82543. 
- *   o When the n/w interface comes down reset DRV_LOAD bit to notify f/w.
- *     This code was moved from e1000_remove to e1000_close
- * 6.2.10       9/6/05
- *   o Fix error in updating RDT in el1000_alloc_rx_buffers[_ps] -- one off.
- *   o Enable fc by default on 82573 controllers (do not read eeprom)
- *   o Fix rx_errors statistic not to include missed_packet_count
- *   o Fix rx_dropped statistic not to include missed_packet_count 
-       (Padraig Brady)
- * 6.2.9        8/30/05
- *   o Remove call to update statistics from the controller ib e1000_get_stats
- * 6.2.8        8/30/05
- *   o Improved algorithm for rx buffer allocation/rdt update
- *   o Flow control watermarks relative to rx PBA size
- *   o Simplified 'Tx Hung' detect logic
- * 6.2.7       8/17/05
- *   o Report rx buffer allocation failures and tx timeout counts in stats
- * 6.2.6       8/16/05
- *   o Implement workaround for controller erratum -- linear non-tso packet
- *     following a TSO gets written back prematurely
- * 6.2.5       8/15/05
- *   o Set netdev->tx_queue_len based on link speed/duplex settings.
- *   o Fix net_stats.rx_fifo_errors <p@draigBrady.com>
- *   o Do not power off PHY if SoL/IDER session is active
- * 6.2.4       8/10/05
- *   o Fix loopback test setup/cleanup for 82571/3 controllers
- *   o Fix parsing of outgoing packets (e1000_transfer_dhcp_info) to treat
- *     all packets as raw
- *   o Prevent operations that will cause the PHY to be reset if SoL/IDER
- *     sessions are active and log a message
- * 6.2.2       7/21/05
- *   o used fixed size descriptors for all MTU sizes, reduces memory load
- * 6.1.2       4/13/05
- *   o Fixed ethtool diagnostics
- *   o Enabled flow control to take default eeprom settings
- *   o Added stats_lock around e1000_read_phy_reg commands to avoid concurrent
- *     calls, one from mii_ioctl and other from within update_stats while 
- *     processing MIIREG ioctl.
  */
 
 char e1000_driver_name[] = "e1000";
@@ -103,7 +74,7 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-#define DRV_VERSION "6.3.9-k4"DRIVERNAPI
+#define DRV_VERSION "7.0.33-k2"DRIVERNAPI
 char e1000_driver_version[] = DRV_VERSION;
 static char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
 
@@ -157,32 +128,26 @@ static struct pci_device_id e1000_pci_tbl[] = {
        INTEL_E1000_ETHERNET_DEVICE(0x108A),
        INTEL_E1000_ETHERNET_DEVICE(0x108B),
        INTEL_E1000_ETHERNET_DEVICE(0x108C),
+       INTEL_E1000_ETHERNET_DEVICE(0x1096),
+       INTEL_E1000_ETHERNET_DEVICE(0x1098),
        INTEL_E1000_ETHERNET_DEVICE(0x1099),
        INTEL_E1000_ETHERNET_DEVICE(0x109A),
        INTEL_E1000_ETHERNET_DEVICE(0x10B5),
+       INTEL_E1000_ETHERNET_DEVICE(0x10B9),
        /* required last entry */
        {0,}
 };
 
 MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
 
-int e1000_up(struct e1000_adapter *adapter);
-void e1000_down(struct e1000_adapter *adapter);
-void e1000_reset(struct e1000_adapter *adapter);
-int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
-int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
-int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
-void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
-void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
 static int e1000_setup_tx_resources(struct e1000_adapter *adapter,
-                                   struct e1000_tx_ring *txdr);
+                                    struct e1000_tx_ring *txdr);
 static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
-                                   struct e1000_rx_ring *rxdr);
+                                    struct e1000_rx_ring *rxdr);
 static void e1000_free_tx_resources(struct e1000_adapter *adapter,
-                                   struct e1000_tx_ring *tx_ring);
+                                    struct e1000_tx_ring *tx_ring);
 static void e1000_free_rx_resources(struct e1000_adapter *adapter,
-                                   struct e1000_rx_ring *rx_ring);
-void e1000_update_stats(struct e1000_adapter *adapter);
+                                    struct e1000_rx_ring *rx_ring);
 
 /* Local Function Prototypes */
 
@@ -191,9 +156,6 @@ static void e1000_exit_module(void);
 static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
 static void __devexit e1000_remove(struct pci_dev *pdev);
 static int e1000_alloc_queues(struct e1000_adapter *adapter);
-#ifdef CONFIG_E1000_MQ
-static void e1000_setup_queue_mapping(struct e1000_adapter *adapter);
-#endif
 static int e1000_sw_init(struct e1000_adapter *adapter);
 static int e1000_open(struct net_device *netdev);
 static int e1000_close(struct net_device *netdev);
@@ -241,11 +203,10 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
 static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
 static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
                           int cmd);
-void e1000_set_ethtool_ops(struct net_device *netdev);
 static void e1000_enter_82542_rst(struct e1000_adapter *adapter);
 static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
 static void e1000_tx_timeout(struct net_device *dev);
-static void e1000_tx_timeout_task(struct net_device *dev);
+static void e1000_reset_task(struct net_device *dev);
 static void e1000_smartspeed(struct e1000_adapter *adapter);
 static inline int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
                                              struct sk_buff *skb);
@@ -265,14 +226,6 @@ static int e1000_resume(struct pci_dev *pdev);
 static void e1000_netpoll (struct net_device *netdev);
 #endif
 
-#ifdef CONFIG_E1000_MQ
-/* for multiple Rx queues */
-void e1000_rx_schedule(void *data);
-#endif
-
-/* Exported from other modules */
-
-extern void e1000_check_options(struct e1000_adapter *adapter);
 
 static struct pci_driver e1000_driver = {
        .name     = e1000_driver_name,
@@ -380,7 +333,8 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter)
                                        (vid != old_vid) &&
                                        !adapter->vlgrp->vlan_devices[old_vid])
                                e1000_vlan_rx_kill_vid(netdev, old_vid);
-               }
+               } else
+                       adapter->mng_vlan_id = vid;
        }
 }
 
@@ -502,10 +456,6 @@ e1000_up(struct e1000_adapter *adapter)
                return err;
        }
 
-#ifdef CONFIG_E1000_MQ
-       e1000_setup_queue_mapping(adapter);
-#endif
-
        adapter->tx_queue_len = netdev->tx_queue_len;
 
        mod_timer(&adapter->watchdog_timer, jiffies);
@@ -526,9 +476,7 @@ e1000_down(struct e1000_adapter *adapter)
                                     e1000_check_mng_mode(&adapter->hw);
 
        e1000_irq_disable(adapter);
-#ifdef CONFIG_E1000_MQ
-       while (atomic_read(&adapter->rx_sched_call_data.count) != 0);
-#endif
+
        free_irq(adapter->pdev->irq, netdev);
 #ifdef CONFIG_PCI_MSI
        if (adapter->hw.mac_type > e1000_82547_rev_2 &&
@@ -587,6 +535,7 @@ e1000_reset(struct e1000_adapter *adapter)
                break;
        case e1000_82571:
        case e1000_82572:
+       case e1000_80003es2lan:
                pba = E1000_PBA_38K;
                break;
        case e1000_82573:
@@ -619,7 +568,10 @@ e1000_reset(struct e1000_adapter *adapter)
 
        adapter->hw.fc_high_water = fc_high_water_mark;
        adapter->hw.fc_low_water = fc_high_water_mark - 8;
-       adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME;
+       if (adapter->hw.mac_type == e1000_80003es2lan)
+               adapter->hw.fc_pause_time = 0xFFFF;
+       else
+               adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME;
        adapter->hw.fc_send_xon = 1;
        adapter->hw.fc = adapter->hw.original_fc;
 
@@ -663,6 +615,7 @@ e1000_probe(struct pci_dev *pdev,
        unsigned long mmio_start, mmio_len;
 
        static int cards_found = 0;
+       static int e1000_ksp3_port_a = 0; /* global ksp3 port a indication */
        int i, err, pci_using_dac;
        uint16_t eeprom_data;
        uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
@@ -755,6 +708,15 @@ e1000_probe(struct pci_dev *pdev,
        if ((err = e1000_check_phy_reset_block(&adapter->hw)))
                DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
 
+       /* if ksp3, indicate if it's port a being setup */
+       if (pdev->device == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 && 
+                       e1000_ksp3_port_a == 0) 
+               adapter->ksp3_port_a = 1;
+       e1000_ksp3_port_a++;
+       /* Reset for multiple KP3 adapters */
+       if (e1000_ksp3_port_a == 4)
+               e1000_ksp3_port_a = 0;
+
        if (adapter->hw.mac_type >= e1000_82543) {
                netdev->features = NETIF_F_SG |
                                   NETIF_F_HW_CSUM |
@@ -826,8 +788,8 @@ e1000_probe(struct pci_dev *pdev,
        adapter->phy_info_timer.function = &e1000_update_phy_info;
        adapter->phy_info_timer.data = (unsigned long) adapter;
 
-       INIT_WORK(&adapter->tx_timeout_task,
-               (void (*)(void *))e1000_tx_timeout_task, netdev);
+       INIT_WORK(&adapter->reset_task,
+               (void (*)(void *))e1000_reset_task, netdev);
 
        /* we're going to reset, so assume we have no link for now */
 
@@ -854,6 +816,7 @@ e1000_probe(struct pci_dev *pdev,
        case e1000_82546:
        case e1000_82546_rev_3:
        case e1000_82571:
+       case e1000_80003es2lan:
                if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1){
                        e1000_read_eeprom(&adapter->hw,
                                EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
@@ -972,10 +935,6 @@ e1000_remove(struct pci_dev *pdev)
        iounmap(adapter->hw.hw_addr);
        pci_release_regions(pdev);
 
-#ifdef CONFIG_E1000_MQ
-       free_percpu(adapter->cpu_netdev);
-       free_percpu(adapter->cpu_tx_ring);
-#endif
        free_netdev(netdev);
 
        pci_disable_device(pdev);
@@ -1056,40 +1015,8 @@ e1000_sw_init(struct e1000_adapter *adapter)
                hw->master_slave = E1000_MASTER_SLAVE;
        }
 
-#ifdef CONFIG_E1000_MQ
-       /* Number of supported queues */
-       switch (hw->mac_type) {
-       case e1000_82571:
-       case e1000_82572:
-               /* These controllers support 2 tx queues, but with a single
-                * qdisc implementation, multiple tx queues aren't quite as
-                * interesting.  If we can find a logical way of mapping
-                * flows to a queue, then perhaps we can up the num_tx_queue
-                * count back to its default.  Until then, we run the risk of
-                * terrible performance due to SACK overload. */
-               adapter->num_tx_queues = 1;
-               adapter->num_rx_queues = 2;
-               break;
-       default:
-               adapter->num_tx_queues = 1;
-               adapter->num_rx_queues = 1;
-               break;
-       }
-       adapter->num_rx_queues = min(adapter->num_rx_queues, num_online_cpus());
-       adapter->num_tx_queues = min(adapter->num_tx_queues, num_online_cpus());
-       DPRINTK(DRV, INFO, "Multiqueue Enabled: Rx Queue count = %u %s\n",
-               adapter->num_rx_queues,
-               ((adapter->num_rx_queues == 1)
-                ? ((num_online_cpus() > 1)
-                       ? "(due to unsupported feature in current adapter)"
-                       : "(due to unsupported system configuration)")
-                : ""));
-       DPRINTK(DRV, INFO, "Multiqueue Enabled: Tx Queue count = %u\n",
-               adapter->num_tx_queues);
-#else
        adapter->num_tx_queues = 1;
        adapter->num_rx_queues = 1;
-#endif
 
        if (e1000_alloc_queues(adapter)) {
                DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n");
@@ -1152,51 +1079,9 @@ e1000_alloc_queues(struct e1000_adapter *adapter)
        memset(adapter->polling_netdev, 0, size);
 #endif
 
-#ifdef CONFIG_E1000_MQ
-       adapter->rx_sched_call_data.func = e1000_rx_schedule;
-       adapter->rx_sched_call_data.info = adapter->netdev;
-
-       adapter->cpu_netdev = alloc_percpu(struct net_device *);
-       adapter->cpu_tx_ring = alloc_percpu(struct e1000_tx_ring *);
-#endif
-
        return E1000_SUCCESS;
 }
 
-#ifdef CONFIG_E1000_MQ
-static void __devinit
-e1000_setup_queue_mapping(struct e1000_adapter *adapter)
-{
-       int i, cpu;
-
-       adapter->rx_sched_call_data.func = e1000_rx_schedule;
-       adapter->rx_sched_call_data.info = adapter->netdev;
-       cpus_clear(adapter->rx_sched_call_data.cpumask);
-
-       adapter->cpu_netdev = alloc_percpu(struct net_device *);
-       adapter->cpu_tx_ring = alloc_percpu(struct e1000_tx_ring *);
-
-       lock_cpu_hotplug();
-       i = 0;
-       for_each_online_cpu(cpu) {
-               *per_cpu_ptr(adapter->cpu_tx_ring, cpu) = &adapter->tx_ring[i % adapter->num_tx_queues];
-               /* This is incomplete because we'd like to assign separate
-                * physical cpus to these netdev polling structures and
-                * avoid saturating a subset of cpus.
-                */
-               if (i < adapter->num_rx_queues) {
-                       *per_cpu_ptr(adapter->cpu_netdev, cpu) = &adapter->polling_netdev[i];
-                       adapter->rx_ring[i].cpu = cpu;
-                       cpu_set(cpu, adapter->cpumask);
-               } else
-                       *per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL;
-
-               i++;
-       }
-       unlock_cpu_hotplug();
-}
-#endif
-
 /**
  * e1000_open - Called when a network interface is made active
  * @netdev: network interface device structure
@@ -1435,18 +1320,6 @@ e1000_configure_tx(struct e1000_adapter *adapter)
        /* Setup the HW Tx Head and Tail descriptor pointers */
 
        switch (adapter->num_tx_queues) {
-       case 2:
-               tdba = adapter->tx_ring[1].dma;
-               tdlen = adapter->tx_ring[1].count *
-                       sizeof(struct e1000_tx_desc);
-               E1000_WRITE_REG(hw, TDBAL1, (tdba & 0x00000000ffffffffULL));
-               E1000_WRITE_REG(hw, TDBAH1, (tdba >> 32));
-               E1000_WRITE_REG(hw, TDLEN1, tdlen);
-               E1000_WRITE_REG(hw, TDH1, 0);
-               E1000_WRITE_REG(hw, TDT1, 0);
-               adapter->tx_ring[1].tdh = E1000_TDH1;
-               adapter->tx_ring[1].tdt = E1000_TDT1;
-               /* Fall Through */
        case 1:
        default:
                tdba = adapter->tx_ring[0].dma;
@@ -1477,6 +1350,10 @@ e1000_configure_tx(struct e1000_adapter *adapter)
                ipgr1 = DEFAULT_82542_TIPG_IPGR1;
                ipgr2 = DEFAULT_82542_TIPG_IPGR2;
                break;
+       case e1000_80003es2lan:
+               ipgr1 = DEFAULT_82543_TIPG_IPGR1;
+               ipgr2 = DEFAULT_80003ES2LAN_TIPG_IPGR2;
+               break;
        default:
                ipgr1 = DEFAULT_82543_TIPG_IPGR1;
                ipgr2 = DEFAULT_82543_TIPG_IPGR2;
@@ -1497,10 +1374,13 @@ e1000_configure_tx(struct e1000_adapter *adapter)
        tctl = E1000_READ_REG(hw, TCTL);
 
        tctl &= ~E1000_TCTL_CT;
-       tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | E1000_TCTL_RTLC |
+       tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
                (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
 
-       E1000_WRITE_REG(hw, TCTL, tctl);
+#ifdef DISABLE_MULR
+       /* disable Multiple Reads for debugging */
+       tctl &= ~E1000_TCTL_MULR;
+#endif
 
        if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572) {
                tarc = E1000_READ_REG(hw, TARC0);
@@ -1513,6 +1393,15 @@ e1000_configure_tx(struct e1000_adapter *adapter)
                else
                        tarc |= (1 << 28);
                E1000_WRITE_REG(hw, TARC1, tarc);
+       } else if (hw->mac_type == e1000_80003es2lan) {
+               tarc = E1000_READ_REG(hw, TARC0);
+               tarc |= 1;
+               if (hw->media_type == e1000_media_type_internal_serdes)
+                       tarc |= (1 << 20);
+               E1000_WRITE_REG(hw, TARC0, tarc);
+               tarc = E1000_READ_REG(hw, TARC1);
+               tarc |= 1;
+               E1000_WRITE_REG(hw, TARC1, tarc);
        }
 
        e1000_config_collision_dist(hw);
@@ -1531,6 +1420,9 @@ e1000_configure_tx(struct e1000_adapter *adapter)
        if (hw->mac_type == e1000_82544 &&
            hw->bus_type == e1000_bus_type_pcix)
                adapter->pcix_82544 = 1;
+
+       E1000_WRITE_REG(hw, TCTL, tctl);
+
 }
 
 /**
@@ -1790,12 +1682,9 @@ e1000_configure_rx(struct e1000_adapter *adapter)
        uint64_t rdba;
        struct e1000_hw *hw = &adapter->hw;
        uint32_t rdlen, rctl, rxcsum, ctrl_ext;
-#ifdef CONFIG_E1000_MQ
-       uint32_t reta, mrqc;
-       int i;
-#endif
 
        if (adapter->rx_ps_pages) {
+               /* this is a 32 byte descriptor */
                rdlen = adapter->rx_ring[0].count *
                        sizeof(union e1000_rx_desc_packet_split);
                adapter->clean_rx = e1000_clean_rx_irq_ps;
@@ -1837,18 +1726,6 @@ e1000_configure_rx(struct e1000_adapter *adapter)
        /* Setup the HW Rx Head and Tail Descriptor Pointers and
         * the Base and Length of the Rx Descriptor Ring */
        switch (adapter->num_rx_queues) {
-#ifdef CONFIG_E1000_MQ
-       case 2:
-               rdba = adapter->rx_ring[1].dma;
-               E1000_WRITE_REG(hw, RDBAL1, (rdba & 0x00000000ffffffffULL));
-               E1000_WRITE_REG(hw, RDBAH1, (rdba >> 32));
-               E1000_WRITE_REG(hw, RDLEN1, rdlen);
-               E1000_WRITE_REG(hw, RDH1, 0);
-               E1000_WRITE_REG(hw, RDT1, 0);
-               adapter->rx_ring[1].rdh = E1000_RDH1;
-               adapter->rx_ring[1].rdt = E1000_RDT1;
-               /* Fall Through */
-#endif
        case 1:
        default:
                rdba = adapter->rx_ring[0].dma;
@@ -1862,46 +1739,6 @@ e1000_configure_rx(struct e1000_adapter *adapter)
                break;
        }
 
-#ifdef CONFIG_E1000_MQ
-       if (adapter->num_rx_queues > 1) {
-               uint32_t random[10];
-
-               get_random_bytes(&random[0], 40);
-
-               if (hw->mac_type <= e1000_82572) {
-                       E1000_WRITE_REG(hw, RSSIR, 0);
-                       E1000_WRITE_REG(hw, RSSIM, 0);
-               }
-
-               switch (adapter->num_rx_queues) {
-               case 2:
-               default:
-                       reta = 0x00800080;
-                       mrqc = E1000_MRQC_ENABLE_RSS_2Q;
-                       break;
-               }
-
-               /* Fill out redirection table */
-               for (i = 0; i < 32; i++)
-                       E1000_WRITE_REG_ARRAY(hw, RETA, i, reta);
-               /* Fill out hash function seeds */
-               for (i = 0; i < 10; i++)
-                       E1000_WRITE_REG_ARRAY(hw, RSSRK, i, random[i]);
-
-               mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 |
-                        E1000_MRQC_RSS_FIELD_IPV4_TCP);
-               E1000_WRITE_REG(hw, MRQC, mrqc);
-       }
-
-       /* Multiqueue and packet checksumming are mutually exclusive. */
-       if (hw->mac_type >= e1000_82571) {
-               rxcsum = E1000_READ_REG(hw, RXCSUM);
-               rxcsum |= E1000_RXCSUM_PCSD;
-               E1000_WRITE_REG(hw, RXCSUM, rxcsum);
-       }
-
-#else
-
        /* Enable 82543 Receive Checksum Offload for TCP and UDP */
        if (hw->mac_type >= e1000_82543) {
                rxcsum = E1000_READ_REG(hw, RXCSUM);
@@ -1920,7 +1757,6 @@ e1000_configure_rx(struct e1000_adapter *adapter)
                }
                E1000_WRITE_REG(hw, RXCSUM, rxcsum);
        }
-#endif /* CONFIG_E1000_MQ */
 
        if (hw->mac_type == e1000_82573)
                E1000_WRITE_REG(hw, ERT, 0x0100);
@@ -2392,7 +2228,7 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
        struct e1000_tx_ring *txdr = adapter->tx_ring;
-       uint32_t link;
+       uint32_t link, tctl;
 
        e1000_check_for_link(&adapter->hw);
        if (adapter->hw.mac_type == e1000_82573) {
@@ -2418,20 +2254,61 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
                               adapter->link_duplex == FULL_DUPLEX ?
                               "Full Duplex" : "Half Duplex");
 
-                       /* tweak tx_queue_len according to speed/duplex */
+                       /* tweak tx_queue_len according to speed/duplex
+                        * and adjust the timeout factor */
                        netdev->tx_queue_len = adapter->tx_queue_len;
                        adapter->tx_timeout_factor = 1;
-                       if (adapter->link_duplex == HALF_DUPLEX) {
+                       adapter->txb2b = 1;
+                       switch (adapter->link_speed) {
+                       case SPEED_10:
+                               adapter->txb2b = 0;
+                               netdev->tx_queue_len = 10;
+                               adapter->tx_timeout_factor = 8;
+                               break;
+                       case SPEED_100:
+                               adapter->txb2b = 0;
+                               netdev->tx_queue_len = 100;
+                               /* maybe add some timeout factor ? */
+                               break;
+                       }
+
+                       if ((adapter->hw.mac_type == e1000_82571 || 
+                            adapter->hw.mac_type == e1000_82572) &&
+                           adapter->txb2b == 0) {
+#define SPEED_MODE_BIT (1 << 21)
+                               uint32_t tarc0;
+                               tarc0 = E1000_READ_REG(&adapter->hw, TARC0);
+                               tarc0 &= ~SPEED_MODE_BIT;
+                               E1000_WRITE_REG(&adapter->hw, TARC0, tarc0);
+                       }
+                               
+#ifdef NETIF_F_TSO
+                       /* disable TSO for pcie and 10/100 speeds, to avoid
+                        * some hardware issues */
+                       if (!adapter->tso_force &&
+                           adapter->hw.bus_type == e1000_bus_type_pci_express){
                                switch (adapter->link_speed) {
                                case SPEED_10:
-                                       netdev->tx_queue_len = 10;
-                                       adapter->tx_timeout_factor = 8;
-                                       break;
                                case SPEED_100:
-                                       netdev->tx_queue_len = 100;
+                                       DPRINTK(PROBE,INFO,
+                                       "10/100 speed: disabling TSO\n");
+                                       netdev->features &= ~NETIF_F_TSO;
+                                       break;
+                               case SPEED_1000:
+                                       netdev->features |= NETIF_F_TSO;
+                                       break;
+                               default:
+                                       /* oops */
                                        break;
                                }
                        }
+#endif
+
+                       /* enable transmits in the hardware, need to do this
+                        * after setting TARC0 */
+                       tctl = E1000_READ_REG(&adapter->hw, TCTL);
+                       tctl |= E1000_TCTL_EN;
+                       E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
 
                        netif_carrier_on(netdev);
                        netif_wake_queue(netdev);
@@ -2446,6 +2323,16 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
                        netif_carrier_off(netdev);
                        netif_stop_queue(netdev);
                        mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ);
+
+                       /* 80003ES2LAN workaround--
+                        * For packet buffer work-around on link down event;
+                        * disable receives in the ISR and
+                        * reset device here in the watchdog
+                        */
+                       if (adapter->hw.mac_type == e1000_80003es2lan) {
+                               /* reset device */
+                               schedule_work(&adapter->reset_task);
+                       }
                }
 
                e1000_smartspeed(adapter);
@@ -2465,16 +2352,14 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
 
        e1000_update_adaptive(&adapter->hw);
 
-#ifdef CONFIG_E1000_MQ
-       txdr = *per_cpu_ptr(adapter->cpu_tx_ring, smp_processor_id());
-#endif
        if (!netif_carrier_ok(netdev)) {
                if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
                        /* We've lost link, so the controller stops DMA,
                         * but we've got queued Tx work that's never going
                         * to get done, so reset controller to flush Tx.
                         * (Do the reset outside of interrupt context). */
-                       schedule_work(&adapter->tx_timeout_task);
+                       adapter->tx_timeout_count++;
+                       schedule_work(&adapter->reset_task);
                }
        }
 
@@ -2649,9 +2534,9 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
                /* Workaround for Controller erratum --
                 * descriptor for non-tso packet in a linear SKB that follows a
                 * tso gets written back prematurely before the data is fully
-                * DMAd to the controller */
+                * DMA'd to the controller */
                if (!skb->data_len && tx_ring->last_tx_tso &&
-                               !skb_shinfo(skb)->tso_size) {
+                   !skb_shinfo(skb)->tso_size) {
                        tx_ring->last_tx_tso = 0;
                        size -= 4;
                }
@@ -2840,7 +2725,7 @@ e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
                          E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) )
                        return 0;
        }
-       if ((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) {
+       if (skb->len > MINIMUM_DHCP_PACKET_SIZE) {
                struct ethhdr *eth = (struct ethhdr *) skb->data;
                if ((htons(ETH_P_IP) == eth->h_proto)) {
                        const struct iphdr *ip =
@@ -2881,11 +2766,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        unsigned int f;
        len -= skb->data_len;
 
-#ifdef CONFIG_E1000_MQ
-       tx_ring = *per_cpu_ptr(adapter->cpu_tx_ring, smp_processor_id());
-#else
        tx_ring = adapter->tx_ring;
-#endif
 
        if (unlikely(skb->len <= 0)) {
                dev_kfree_skb_any(skb);
@@ -2905,21 +2786,29 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                max_per_txd = min(mss << 2, max_per_txd);
                max_txd_pwr = fls(max_per_txd) - 1;
 
-       /* TSO Workaround for 82571/2 Controllers -- if skb->data
+       /* TSO Workaround for 82571/2/3 Controllers -- if skb->data
         * points to just header, pull a few bytes of payload from
         * frags into skb->data */
                hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
-               if (skb->data_len && (hdr_len == (skb->len - skb->data_len)) &&
-                       (adapter->hw.mac_type == e1000_82571 ||
-                       adapter->hw.mac_type == e1000_82572)) {
-                       unsigned int pull_size;
-                       pull_size = min((unsigned int)4, skb->data_len);
-                       if (!__pskb_pull_tail(skb, pull_size)) {
-                               printk(KERN_ERR "__pskb_pull_tail failed.\n");
-                               dev_kfree_skb_any(skb);
-                               return NETDEV_TX_OK;
+               if (skb->data_len && (hdr_len == (skb->len - skb->data_len))) {
+                       switch (adapter->hw.mac_type) {
+                               unsigned int pull_size;
+                       case e1000_82571:
+                       case e1000_82572:
+                       case e1000_82573:
+                               pull_size = min((unsigned int)4, skb->data_len);
+                               if (!__pskb_pull_tail(skb, pull_size)) {
+                                       printk(KERN_ERR 
+                                               "__pskb_pull_tail failed.\n");
+                                       dev_kfree_skb_any(skb);
+                                       return NETDEV_TX_OK;
+                               }
+                               len = skb->len - skb->data_len;
+                               break;
+                       default:
+                               /* do nothing */
+                               break;
                        }
-                       len = skb->len - skb->data_len;
                }
        }
 
@@ -2935,7 +2824,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 #ifdef NETIF_F_TSO
        /* Controller Erratum workaround */
        if (!skb->data_len && tx_ring->last_tx_tso &&
-               !skb_shinfo(skb)->tso_size)
+           !skb_shinfo(skb)->tso_size)
                count++;
 #endif
 
@@ -2958,7 +2847,9 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        if (adapter->pcix_82544)
                count += nr_frags;
 
-       if (adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) )
+
+       if (adapter->hw.tx_pkt_filtering &&
+           (adapter->hw.mac_type == e1000_82573))
                e1000_transfer_dhcp_info(adapter, skb);
 
        local_irq_save(flags);
@@ -3036,15 +2927,15 @@ e1000_tx_timeout(struct net_device *netdev)
        struct e1000_adapter *adapter = netdev_priv(netdev);
 
        /* Do the reset outside of interrupt context */
-       schedule_work(&adapter->tx_timeout_task);
+       adapter->tx_timeout_count++;
+       schedule_work(&adapter->reset_task);
 }
 
 static void
-e1000_tx_timeout_task(struct net_device *netdev)
+e1000_reset_task(struct net_device *netdev)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
 
-       adapter->tx_timeout_count++;
        e1000_down(adapter);
        e1000_up(adapter);
 }
@@ -3079,6 +2970,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
+       uint16_t eeprom_data = 0;
 
        if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
            (max_frame > MAX_JUMBO_FRAME_SIZE)) {
@@ -3090,14 +2982,28 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
        switch (adapter->hw.mac_type) {
        case e1000_82542_rev2_0:
        case e1000_82542_rev2_1:
-       case e1000_82573:
                if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
                        DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n");
                        return -EINVAL;
                }
                break;
+       case e1000_82573:
+               /* only enable jumbo frames if ASPM is disabled completely
+                * this means both bits must be zero in 0x1A bits 3:2 */
+               e1000_read_eeprom(&adapter->hw, EEPROM_INIT_3GIO_3, 1,
+                                 &eeprom_data);
+               if (eeprom_data & EEPROM_WORD1A_ASPM_MASK) {
+                       if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
+                               DPRINTK(PROBE, ERR,
+                                       "Jumbo Frames not supported.\n");
+                               return -EINVAL;
+                       }
+                       break;
+               }
+               /* fall through to get support */
        case e1000_82571:
        case e1000_82572:
+       case e1000_80003es2lan:
 #define MAX_STD_JUMBO_FRAME_SIZE 9234
                if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
                        DPRINTK(PROBE, ERR, "MTU > 9216 not supported.\n");
@@ -3251,11 +3157,15 @@ e1000_update_stats(struct e1000_adapter *adapter)
 
        /* Rx Errors */
 
+       /* RLEC on some newer hardware can be incorrect so build
+       * our own version based on RUC and ROC */
        adapter->net_stats.rx_errors = adapter->stats.rxerrc +
                adapter->stats.crcerrs + adapter->stats.algnerrc +
-               adapter->stats.rlec + adapter->stats.cexterr;
+               adapter->stats.ruc + adapter->stats.roc +
+               adapter->stats.cexterr;
        adapter->net_stats.rx_dropped = 0;
-       adapter->net_stats.rx_length_errors = adapter->stats.rlec;
+       adapter->net_stats.rx_length_errors = adapter->stats.ruc +
+                                             adapter->stats.roc;
        adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
        adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc;
        adapter->net_stats.rx_missed_errors = adapter->stats.mpc;
@@ -3288,29 +3198,6 @@ e1000_update_stats(struct e1000_adapter *adapter)
        spin_unlock_irqrestore(&adapter->stats_lock, flags);
 }
 
-#ifdef CONFIG_E1000_MQ
-void
-e1000_rx_schedule(void *data)
-{
-       struct net_device *poll_dev, *netdev = data;
-       struct e1000_adapter *adapter = netdev->priv;
-       int this_cpu = get_cpu();
-
-       poll_dev = *per_cpu_ptr(adapter->cpu_netdev, this_cpu);
-       if (poll_dev == NULL) {
-               put_cpu();
-               return;
-       }
-
-       if (likely(netif_rx_schedule_prep(poll_dev)))
-               __netif_rx_schedule(poll_dev);
-       else
-               e1000_irq_enable(adapter);
-
-       put_cpu();
-}
-#endif
-
 /**
  * e1000_intr - Interrupt Handler
  * @irq: interrupt number
@@ -3324,7 +3211,7 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
        struct net_device *netdev = data;
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
-       uint32_t icr = E1000_READ_REG(hw, ICR);
+       uint32_t rctl, icr = E1000_READ_REG(hw, ICR);
 #ifndef CONFIG_E1000_NAPI
        int i;
 #else
@@ -3346,6 +3233,17 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
 
        if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
                hw->get_link_status = 1;
+               /* 80003ES2LAN workaround--
+                * For packet buffer work-around on link down event;
+                * disable receives here in the ISR and
+                * reset adapter in watchdog
+                */
+               if (netif_carrier_ok(netdev) &&
+                   (adapter->hw.mac_type == e1000_80003es2lan)) {
+                       /* disable receives */
+                       rctl = E1000_READ_REG(hw, RCTL);
+                       E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
+               }
                mod_timer(&adapter->watchdog_timer, jiffies);
        }
 
@@ -3355,26 +3253,11 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
                E1000_WRITE_REG(hw, IMC, ~0);
                E1000_WRITE_FLUSH(hw);
        }
-#ifdef CONFIG_E1000_MQ
-       if (atomic_read(&adapter->rx_sched_call_data.count) == 0) {
-               /* We must setup the cpumask once count == 0 since
-                * each cpu bit is cleared when the work is done. */
-               adapter->rx_sched_call_data.cpumask = adapter->cpumask;
-               atomic_add(adapter->num_rx_queues - 1, &adapter->irq_sem);
-               atomic_set(&adapter->rx_sched_call_data.count,
-                          adapter->num_rx_queues);
-               smp_call_async_mask(&adapter->rx_sched_call_data);
-       } else {
-               printk("call_data.count == %u\n", atomic_read(&adapter->rx_sched_call_data.count));
-       }
-#else /* if !CONFIG_E1000_MQ */
        if (likely(netif_rx_schedule_prep(&adapter->polling_netdev[0])))
                __netif_rx_schedule(&adapter->polling_netdev[0]);
        else
                e1000_irq_enable(adapter);
-#endif /* CONFIG_E1000_MQ */
-
-#else /* if !CONFIG_E1000_NAPI */
+#else
        /* Writing IMC and IMS is needed for 82547.
         * Due to Hub Link bus being occupied, an interrupt
         * de-assertion message is not able to be sent.
@@ -3398,7 +3281,7 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
        if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
                e1000_irq_enable(adapter);
 
-#endif /* CONFIG_E1000_NAPI */
+#endif
 
        return IRQ_HANDLED;
 }
@@ -3474,6 +3357,9 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
        struct e1000_tx_desc *tx_desc, *eop_desc;
        struct e1000_buffer *buffer_info;
        unsigned int i, eop;
+#ifdef CONFIG_E1000_NAPI
+       unsigned int count = 0;
+#endif
        boolean_t cleaned = FALSE;
 
        i = tx_ring->next_to_clean;
@@ -3486,21 +3372,20 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
                        buffer_info = &tx_ring->buffer_info[i];
                        cleaned = (i == eop);
 
-#ifdef CONFIG_E1000_MQ
-                       tx_ring->tx_stats.bytes += buffer_info->length;
-#endif
                        e1000_unmap_and_free_tx_resource(adapter, buffer_info);
                        memset(tx_desc, 0, sizeof(struct e1000_tx_desc));
 
                        if (unlikely(++i == tx_ring->count)) i = 0;
                }
 
-#ifdef CONFIG_E1000_MQ
-               tx_ring->tx_stats.packets++;
-#endif
 
                eop = tx_ring->buffer_info[i].next_to_watch;
                eop_desc = E1000_TX_DESC(*tx_ring, eop);
+#ifdef CONFIG_E1000_NAPI
+#define E1000_TX_WEIGHT 64
+               /* weight of a sort for tx, to avoid endless transmit cleanup */
+               if (count++ == E1000_TX_WEIGHT) break;
+#endif
        }
 
        tx_ring->next_to_clean = i;
@@ -3519,7 +3404,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
                adapter->detect_tx_hung = FALSE;
                if (tx_ring->buffer_info[eop].dma &&
                    time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
-                              adapter->tx_timeout_factor * HZ)
+                              (adapter->tx_timeout_factor * HZ))
                    && !(E1000_READ_REG(&adapter->hw, STATUS) &
                         E1000_STATUS_TXOFF)) {
 
@@ -3644,10 +3529,15 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
                skb = buffer_info->skb;
                buffer_info->skb = NULL;
 
+               prefetch(skb->data - NET_IP_ALIGN);
+
                if (++i == rx_ring->count) i = 0;
                next_rxd = E1000_RX_DESC(*rx_ring, i);
+               prefetch(next_rxd);
+
                next_buffer = &rx_ring->buffer_info[i];
                next_skb = next_buffer->skb;
+               prefetch(next_skb->data - NET_IP_ALIGN);
 
                cleaned = TRUE;
                cleaned_count++;
@@ -3710,7 +3600,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
                e1000_rx_checksum(adapter,
                                  (uint32_t)(status) |
                                  ((uint32_t)(rx_desc->errors) << 24),
-                                 rx_desc->csum, skb);
+                                 le16_to_cpu(rx_desc->csum), skb);
 
                skb->protocol = eth_type_trans(skb, netdev);
 #ifdef CONFIG_E1000_NAPI
@@ -3733,10 +3623,6 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
                }
 #endif /* CONFIG_E1000_NAPI */
                netdev->last_rx = jiffies;
-#ifdef CONFIG_E1000_MQ
-               rx_ring->rx_stats.packets++;
-               rx_ring->rx_stats.bytes += length;
-#endif
 
 next_desc:
                rx_desc->status = 0;
@@ -3747,6 +3633,7 @@ next_desc:
                        cleaned_count = 0;
                }
 
+               /* use prefetched values */
                rx_desc = next_rxd;
                buffer_info = next_buffer;
        }
@@ -3789,9 +3676,9 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
        i = rx_ring->next_to_clean;
        rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
        staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
-       buffer_info = &rx_ring->buffer_info[i];
 
        while (staterr & E1000_RXD_STAT_DD) {
+               buffer_info = &rx_ring->buffer_info[i];
                ps_page = &rx_ring->ps_page[i];
                ps_page_dma = &rx_ring->ps_page_dma[i];
 #ifdef CONFIG_E1000_NAPI
@@ -3801,10 +3688,16 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
 #endif
                skb = buffer_info->skb;
 
+               /* in the packet split case this is header only */
+               prefetch(skb->data - NET_IP_ALIGN);
+
                if (++i == rx_ring->count) i = 0;
                next_rxd = E1000_RX_DESC_PS(*rx_ring, i);
+               prefetch(next_rxd);
+
                next_buffer = &rx_ring->buffer_info[i];
                next_skb = next_buffer->skb;
+               prefetch(next_skb->data - NET_IP_ALIGN);
 
                cleaned = TRUE;
                cleaned_count++;
@@ -3836,29 +3729,55 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
                /* Good Receive */
                skb_put(skb, length);
 
+               {
+               /* this looks ugly, but it seems compiler issues make it
+                  more efficient than reusing j */
+               int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]);
+
+               /* page alloc/put takes too long and effects small packet
+                * throughput, so unsplit small packets and save the alloc/put*/
+               if (l1 && ((length + l1) < E1000_CB_LENGTH)) {
+                       u8 *vaddr;
+                       /* there is no documentation about how to call 
+                        * kmap_atomic, so we can't hold the mapping
+                        * very long */
+                       pci_dma_sync_single_for_cpu(pdev,
+                               ps_page_dma->ps_page_dma[0],
+                               PAGE_SIZE,
+                               PCI_DMA_FROMDEVICE);
+                       vaddr = kmap_atomic(ps_page->ps_page[0],
+                                           KM_SKB_DATA_SOFTIRQ);
+                       memcpy(skb->tail, vaddr, l1);
+                       kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ);
+                       pci_dma_sync_single_for_device(pdev,
+                               ps_page_dma->ps_page_dma[0],
+                               PAGE_SIZE, PCI_DMA_FROMDEVICE);
+                       skb_put(skb, l1);
+                       length += l1;
+                       goto copydone;
+               } /* if */
+               }
+               
                for (j = 0; j < adapter->rx_ps_pages; j++) {
-                       if (!(length = le16_to_cpu(rx_desc->wb.upper.length[j])))
+                       if (!(length= le16_to_cpu(rx_desc->wb.upper.length[j])))
                                break;
-
                        pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j],
                                        PAGE_SIZE, PCI_DMA_FROMDEVICE);
                        ps_page_dma->ps_page_dma[j] = 0;
-                       skb_shinfo(skb)->frags[j].page =
-                               ps_page->ps_page[j];
+                       skb_fill_page_desc(skb, j, ps_page->ps_page[j], 0,
+                                          length);
                        ps_page->ps_page[j] = NULL;
-                       skb_shinfo(skb)->frags[j].page_offset = 0;
-                       skb_shinfo(skb)->frags[j].size = length;
-                       skb_shinfo(skb)->nr_frags++;
                        skb->len += length;
                        skb->data_len += length;
                }
 
+copydone:
                e1000_rx_checksum(adapter, staterr,
-                                 rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);
+                                 le16_to_cpu(rx_desc->wb.lower.hi_dword.csum_ip.csum), skb);
                skb->protocol = eth_type_trans(skb, netdev);
 
                if (likely(rx_desc->wb.upper.header_status &
-                         E1000_RXDPS_HDRSTAT_HDRSP))
+                          cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP)))
                        adapter->rx_hdr_split++;
 #ifdef CONFIG_E1000_NAPI
                if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
@@ -3878,13 +3797,9 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
                }
 #endif /* CONFIG_E1000_NAPI */
                netdev->last_rx = jiffies;
-#ifdef CONFIG_E1000_MQ
-               rx_ring->rx_stats.packets++;
-               rx_ring->rx_stats.bytes += length;
-#endif
 
 next_desc:
-               rx_desc->wb.middle.status_error &= ~0xFF;
+               rx_desc->wb.middle.status_error &= cpu_to_le32(~0xFF);
                buffer_info->skb = NULL;
 
                /* return some buffers to hardware, one at a time is too slow */
@@ -3893,6 +3808,7 @@ next_desc:
                        cleaned_count = 0;
                }
 
+               /* use prefetched values */
                rx_desc = next_rxd;
                buffer_info = next_buffer;
 
@@ -3936,7 +3852,6 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
                        goto map_skb;
                }
 
-
                if (unlikely(!skb)) {
                        /* Better luck next round */
                        adapter->alloc_rx_buff_failed++;
@@ -4242,7 +4157,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
                        spin_unlock_irqrestore(&adapter->stats_lock, flags);
                        return -EIO;
                }
-               if (adapter->hw.phy_type == e1000_phy_m88) {
+               if (adapter->hw.phy_type == e1000_media_type_copper) {
                        switch (data->reg_num) {
                        case PHY_CTRL:
                                if (mii_reg & MII_CR_POWER_DOWN)
@@ -4258,8 +4173,8 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
                                        else
                                                spddplx = SPEED_10;
                                        spddplx += (mii_reg & 0x100)
-                                                  ? FULL_DUPLEX :
-                                                  HALF_DUPLEX;
+                                                  ? DUPLEX_FULL :
+                                                  DUPLEX_HALF;
                                        retval = e1000_set_spd_dplx(adapter,
                                                                    spddplx);
                                        if (retval) {
@@ -4489,8 +4404,8 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
 }
 
 #ifdef CONFIG_PM
-/* these functions save and restore 16 or 64 dwords (64-256 bytes) of config
- * space versus the 64 bytes that pci_[save|restore]_state handle
+/* Save/restore 16 or 64 dwords of PCI config space depending on which
+ * bus we're on (PCI(X) vs. PCI-E)
  */
 #define PCIE_CONFIG_SPACE_LEN 256
 #define PCI_CONFIG_SPACE_LEN 64
@@ -4500,6 +4415,7 @@ e1000_pci_save_state(struct e1000_adapter *adapter)
        struct pci_dev *dev = adapter->pdev;
        int size;
        int i;
+
        if (adapter->hw.mac_type >= e1000_82571)
                size = PCIE_CONFIG_SPACE_LEN;
        else
@@ -4523,8 +4439,10 @@ e1000_pci_restore_state(struct e1000_adapter *adapter)
        struct pci_dev *dev = adapter->pdev;
        int size;
        int i;
+
        if (adapter->config_space == NULL)
                return;
+
        if (adapter->hw.mac_type >= e1000_82571)
                size = PCIE_CONFIG_SPACE_LEN;
        else
@@ -4552,8 +4470,8 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
                e1000_down(adapter);
 
 #ifdef CONFIG_PM
-       /* implement our own version of pci_save_state(pdev) because pci 
-        * express adapters have larger 256 byte config spaces */
+       /* Implement our own version of pci_save_state(pdev) because pci-
+        * express adapters have 256-byte config spaces. */
        retval = e1000_pci_save_state(adapter);
        if (retval)
                return retval;
@@ -4610,7 +4528,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
                retval = pci_enable_wake(pdev, PCI_D3hot, 0);
                if (retval)
                        DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
-               retval = pci_enable_wake(pdev, PCI_D3cold, 0); /* 4 == D3 cold */
+               retval = pci_enable_wake(pdev, PCI_D3cold, 0);
                if (retval)
                        DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
        }
@@ -4626,7 +4544,8 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
                                DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
                        retval = pci_enable_wake(pdev, PCI_D3cold, 1);
                        if (retval)
-                               DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
+                               DPRINTK(PROBE, ERR,
+                                       "Error enabling D3 cold wake\n");
                }
        }
 
index 3768d83..e0a4d37 100644 (file)
@@ -268,7 +268,7 @@ e1000_validate_option(int *value, struct e1000_option *opt,
                BUG();
        }
 
-       DPRINTK(PROBE, INFO, "Invalid %s specified (%i) %s\n",
+       DPRINTK(PROBE, INFO, "Invalid %s value specified (%i) %s\n",
               opt->name, *value, opt->err);
        *value = opt->def;
        return -1;
index 8c62ced..467fc86 100644 (file)
@@ -27,7 +27,7 @@
                rx_align support: enables rx DMA without causing unaligned accesses.
 */
 
-static const char *version =
+static const char * const version =
 "eepro100.c:v1.09j-t 9/29/99 Donald Becker http://www.scyld.com/network/eepro100.html\n"
 "eepro100.c: $Revision: 1.36 $ 2000/11/17 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n";
 
@@ -469,7 +469,7 @@ static const char i82558_config_cmd[CONFIG_DATA_SIZE] = {
        0x31, 0x05, };
 
 /* PHY media interface chips. */
-static const char *phys[] = {
+static const char * const phys[] = {
        "None", "i82553-A/B", "i82553-C", "i82503",
        "DP83840", "80c240", "80c24", "i82555",
        "unknown-8", "unknown-9", "DP83840A", "unknown-11",
index f119ec4..2f7b868 100644 (file)
@@ -225,7 +225,7 @@ struct epic_chip_info {
 
 
 /* indexed by chip_t */
-static struct epic_chip_info pci_id_tbl[] = {
+static const struct epic_chip_info pci_id_tbl[] = {
        { "SMSC EPIC/100 83c170",
         EPIC_IOTYPE, EPIC_TOTAL_SIZE, TYPE2_INTR | NO_MII | MII_PWRDWN },
        { "SMSC EPIC/100 83c170",
@@ -291,7 +291,7 @@ enum CommandBits {
                         RxDone | RxStarted | RxEarlyWarn | RxOverflow | RxFull)
 #define EpicNormalEvent        (0x0000ffff & ~EpicNapiEvent)
 
-static u16 media2miictl[16] = {
+static const u16 media2miictl[16] = {
        0, 0x0C00, 0x0C00, 0x2000,  0x0100, 0x2100, 0, 0,
        0, 0, 0, 0,  0, 0, 0, 0 };
 
index f32a6b3..b67545b 100644 (file)
@@ -161,6 +161,7 @@ static char *version =
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/bitops.h>
+#include <linux/jiffies.h>
 
 #include <asm/system.h>                  
 #include <asm/io.h>              
@@ -754,7 +755,7 @@ static void eth16i_set_port(int ioaddr, int porttype)
 
 static int eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l)
 {
-       int starttime;
+       unsigned long starttime;
 
        outb(0xff, ioaddr + TX_STATUS_REG);
 
@@ -765,7 +766,7 @@ static int eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l)
        outb(TX_START | 1, ioaddr + TRANSMIT_START_REG); 
 
        while( (inb(ioaddr + TX_STATUS_REG) & 0x80) == 0) {
-               if( (jiffies - starttime) > TX_TIMEOUT) {
+               if( time_after(jiffies, starttime + TX_TIMEOUT)) {
                        return -1;
                }
        }
@@ -775,18 +776,18 @@ static int eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l)
 
 static int eth16i_receive_probe_packet(int ioaddr)
 {
-       int starttime;
+       unsigned long starttime;
 
        starttime = jiffies;
 
        while((inb(ioaddr + TX_STATUS_REG) & 0x20) == 0) {
-               if( (jiffies - starttime) > TX_TIMEOUT) {
+               if( time_after(jiffies, starttime + TX_TIMEOUT)) {
 
                        if(eth16i_debug > 1)
                                printk(KERN_DEBUG "Timeout occurred waiting transmit packet received\n");
                        starttime = jiffies;
                        while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) {
-                               if( (jiffies - starttime) > TX_TIMEOUT) {
+                               if( time_after(jiffies, starttime + TX_TIMEOUT)) {
                                        if(eth16i_debug > 1)
                                                printk(KERN_DEBUG "Timeout occurred waiting receive packet\n");
                                        return -1;
index 55dbe9a..a844926 100644 (file)
@@ -160,7 +160,7 @@ struct chip_info {
        int flags;
 };
 
-static struct chip_info skel_netdrv_tbl[] = {
+static const struct chip_info skel_netdrv_tbl[] = {
        {"100/10M Ethernet PCI Adapter", 136, HAS_MII_XCVR},
        {"100/10M Ethernet PCI Adapter", 136, HAS_CHIP_XCVR},
        {"1000/100/10M Ethernet PCI Adapter", 136, HAS_MII_XCVR},
index 3682ec6..e7fc28b 100644 (file)
  *     0.47: 26 Oct 2005: Add phyaddr 0 in phy scan.
  *     0.48: 24 Dec 2005: Disable TSO, bugfix for pci_map_single
  *     0.49: 10 Dec 2005: Fix tso for large buffers.
+ *     0.50: 20 Jan 2006: Add 8021pq tagging support.
+ *     0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings.
+ *     0.52: 20 Jan 2006: Add MSI/MSIX support.
  *
  * 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.49"
+#define FORCEDETH_VERSION              "0.52"
 #define DRV_NAME                       "forcedeth"
 
 #include <linux/module.h>
 #define DEV_HAS_LARGEDESC      0x0004  /* device supports jumbo frames and needs packet format 2 */
 #define DEV_HAS_HIGH_DMA        0x0008  /* device supports 64bit dma */
 #define DEV_HAS_CHECKSUM        0x0010  /* device supports tx and rx checksum offloads */
+#define DEV_HAS_VLAN            0x0020  /* device supports vlan tagging and striping */
+#define DEV_HAS_MSI             0x0040  /* device supports MSI */
+#define DEV_HAS_MSI_X           0x0080  /* device supports MSI-X */
 
 enum {
        NvRegIrqStatus = 0x000,
@@ -166,14 +172,17 @@ enum {
 #define NVREG_IRQ_TX_OK                        0x0010
 #define NVREG_IRQ_TIMER                        0x0020
 #define NVREG_IRQ_LINK                 0x0040
-#define NVREG_IRQ_TX_ERROR             0x0080
-#define NVREG_IRQ_TX1                  0x0100
+#define NVREG_IRQ_RX_FORCED            0x0080
+#define NVREG_IRQ_TX_FORCED            0x0100
 #define NVREG_IRQMASK_THROUGHPUT       0x00df
 #define NVREG_IRQMASK_CPU              0x0040
+#define NVREG_IRQ_TX_ALL               (NVREG_IRQ_TX_ERR|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_FORCED)
+#define NVREG_IRQ_RX_ALL               (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_RX_FORCED)
+#define NVREG_IRQ_OTHER                        (NVREG_IRQ_TIMER|NVREG_IRQ_LINK)
 
 #define NVREG_IRQ_UNKNOWN      (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR| \
-                                       NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX_ERROR| \
-                                       NVREG_IRQ_TX1))
+                                       NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_RX_FORCED| \
+                                       NVREG_IRQ_TX_FORCED))
 
        NvRegUnknownSetupReg6 = 0x008,
 #define NVREG_UNKSETUP6_VAL            3
@@ -185,6 +194,10 @@ enum {
        NvRegPollingInterval = 0x00c,
 #define NVREG_POLL_DEFAULT_THROUGHPUT  970
 #define NVREG_POLL_DEFAULT_CPU 13
+       NvRegMSIMap0 = 0x020,
+       NvRegMSIMap1 = 0x024,
+       NvRegMSIIrqMask = 0x030,
+#define NVREG_MSI_VECTOR_0_ENABLED 0x01
        NvRegMisc1 = 0x080,
 #define NVREG_MISC1_HD         0x02
 #define NVREG_MISC1_FORCE      0x3b0f3c
@@ -254,6 +267,10 @@ enum {
 #define NVREG_TXRXCTL_DESC_1   0
 #define NVREG_TXRXCTL_DESC_2   0x02100
 #define NVREG_TXRXCTL_DESC_3   0x02200
+#define NVREG_TXRXCTL_VLANSTRIP 0x00040
+#define NVREG_TXRXCTL_VLANINS  0x00080
+       NvRegTxRingPhysAddrHigh = 0x148,
+       NvRegRxRingPhysAddrHigh = 0x14C,
        NvRegMIIStatus = 0x180,
 #define NVREG_MIISTAT_ERROR            0x0001
 #define NVREG_MIISTAT_LINKCHANGE       0x0008
@@ -303,6 +320,11 @@ enum {
 #define NVREG_POWERSTATE_D1            0x0001
 #define NVREG_POWERSTATE_D2            0x0002
 #define NVREG_POWERSTATE_D3            0x0003
+       NvRegVlanControl = 0x300,
+#define NVREG_VLANCONTROL_ENABLE       0x2000
+       NvRegMSIXMap0 = 0x3e0,
+       NvRegMSIXMap1 = 0x3e4,
+       NvRegMSIXIrqStatus = 0x3f0,
 };
 
 /* Big endian: should work, but is untested */
@@ -314,7 +336,7 @@ struct ring_desc {
 struct ring_desc_ex {
        u32 PacketBufferHigh;
        u32 PacketBufferLow;
-       u32 Reserved;
+       u32 TxVlan;
        u32 FlagLen;
 };
 
@@ -355,6 +377,8 @@ typedef union _ring_type {
 #define NV_TX2_CHECKSUM_L3     (1<<27)
 #define NV_TX2_CHECKSUM_L4     (1<<26)
 
+#define NV_TX3_VLAN_TAG_PRESENT (1<<18)
+
 #define NV_RX_DESCRIPTORVALID  (1<<16)
 #define NV_RX_MISSEDFRAME      (1<<17)
 #define NV_RX_SUBSTRACT1       (1<<18)
@@ -385,6 +409,9 @@ typedef union _ring_type {
 #define NV_RX2_ERROR           (1<<30)
 #define NV_RX2_AVAIL           (1<<31)
 
+#define NV_RX3_VLAN_TAG_PRESENT (1<<16)
+#define NV_RX3_VLAN_TAG_MASK   (0x0000FFFF)
+
 /* Miscelaneous hardware related defines: */
 #define NV_PCI_REGSZ           0x270
 
@@ -475,6 +502,18 @@ typedef union _ring_type {
 #define LPA_1000FULL   0x0800
 #define LPA_1000HALF   0x0400
 
+/* MSI/MSI-X defines */
+#define NV_MSI_X_MAX_VECTORS  8
+#define NV_MSI_X_VECTORS_MASK 0x000f
+#define NV_MSI_CAPABLE        0x0010
+#define NV_MSI_X_CAPABLE      0x0020
+#define NV_MSI_ENABLED        0x0040
+#define NV_MSI_X_ENABLED      0x0080
+
+#define NV_MSI_X_VECTOR_ALL   0x0
+#define NV_MSI_X_VECTOR_RX    0x0
+#define NV_MSI_X_VECTOR_TX    0x1
+#define NV_MSI_X_VECTOR_OTHER 0x2
 
 /*
  * SMP locking:
@@ -511,6 +550,7 @@ struct fe_priv {
        u32 irqmask;
        u32 desc_ver;
        u32 txrxctl_bits;
+       u32 vlanctl_bits;
 
        void __iomem *base;
 
@@ -525,6 +565,7 @@ struct fe_priv {
        unsigned int pkt_limit;
        struct timer_list oom_kick;
        struct timer_list nic_poll;
+       u32 nic_poll_irq;
 
        /* media detection workaround.
         * Locking: Within irq hander or disable_irq+spin_lock(&np->lock);
@@ -540,6 +581,13 @@ struct fe_priv {
        dma_addr_t tx_dma[TX_RING];
        unsigned int tx_dma_len[TX_RING];
        u32 tx_flags;
+
+       /* vlan fields */
+       struct vlan_group *vlangrp;
+
+       /* msi/msi-x fields */
+       u32 msi_flags;
+       struct msix_entry msi_x_entry[NV_MSI_X_MAX_VECTORS];
 };
 
 /*
@@ -567,6 +615,16 @@ static int optimization_mode = NV_OPTIMIZATION_MODE_THROUGHPUT;
  */
 static int poll_interval = -1;
 
+/*
+ * Disable MSI interrupts
+ */
+static int disable_msi = 0;
+
+/*
+ * Disable MSIX interrupts
+ */
+static int disable_msix = 0;
+
 static inline struct fe_priv *get_nvpriv(struct net_device *dev)
 {
        return netdev_priv(dev);
@@ -612,6 +670,33 @@ static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target,
        return 0;
 }
 
+#define NV_SETUP_RX_RING 0x01
+#define NV_SETUP_TX_RING 0x02
+
+static void setup_hw_rings(struct net_device *dev, int rxtx_flags)
+{
+       struct fe_priv *np = get_nvpriv(dev);
+       u8 __iomem *base = get_hwbase(dev);
+
+       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+               if (rxtx_flags & NV_SETUP_RX_RING) {
+                       writel((u32) cpu_to_le64(np->ring_addr), base + NvRegRxRingPhysAddr);
+               }
+               if (rxtx_flags & NV_SETUP_TX_RING) {
+                       writel((u32) cpu_to_le64(np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+               }
+       } else {
+               if (rxtx_flags & NV_SETUP_RX_RING) {
+                       writel((u32) cpu_to_le64(np->ring_addr), base + NvRegRxRingPhysAddr);
+                       writel((u32) (cpu_to_le64(np->ring_addr) >> 32), base + NvRegRxRingPhysAddrHigh);
+               }
+               if (rxtx_flags & NV_SETUP_TX_RING) {
+                       writel((u32) cpu_to_le64(np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
+                       writel((u32) (cpu_to_le64(np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)) >> 32), base + NvRegTxRingPhysAddrHigh);
+               }
+       }
+}
+
 #define MII_READ       (-1)
 /* mii_rw: read/write a register on the PHY.
  *
@@ -903,14 +988,27 @@ static void nv_do_rx_refill(unsigned long data)
        struct net_device *dev = (struct net_device *) data;
        struct fe_priv *np = netdev_priv(dev);
 
-       disable_irq(dev->irq);
+
+       if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
+           ((np->msi_flags & NV_MSI_X_ENABLED) && 
+            ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
+               disable_irq(dev->irq);
+       } else {
+               disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+       }
        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);
        }
-       enable_irq(dev->irq);
+       if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
+           ((np->msi_flags & NV_MSI_X_ENABLED) && 
+            ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
+               enable_irq(dev->irq);
+       } else {
+               enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+       }
 }
 
 static void nv_init_rx(struct net_device *dev) 
@@ -965,7 +1063,7 @@ static int nv_release_txskb(struct net_device *dev, unsigned int skbnr)
        }
 
        if (np->tx_skbuff[skbnr]) {
-               dev_kfree_skb_irq(np->tx_skbuff[skbnr]);
+               dev_kfree_skb_any(np->tx_skbuff[skbnr]);
                np->tx_skbuff[skbnr] = NULL;
                return 1;
        } else {
@@ -1031,6 +1129,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
        u32 bcnt;
        u32 size = skb->len-skb->data_len;
        u32 entries = (size >> NV_TX2_TSO_MAX_SHIFT) + ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
+       u32 tx_flags_vlan = 0;
 
        /* add fragments to entries count */
        for (i = 0; i < fragments; i++) {
@@ -1111,10 +1210,16 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
 #endif
        tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0);
 
+       /* vlan tag */
+       if (np->vlangrp && vlan_tx_tag_present(skb)) {
+               tx_flags_vlan = NV_TX3_VLAN_TAG_PRESENT | vlan_tx_tag_get(skb);
+       }
+
        /* 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);
        } 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);
        }       
 
@@ -1209,9 +1314,14 @@ static void nv_tx_timeout(struct net_device *dev)
 {
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
+       u32 status;
+
+       if (np->msi_flags & NV_MSI_X_ENABLED)
+               status = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK;
+       else
+               status = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK;
 
-       printk(KERN_INFO "%s: Got tx_timeout. irq: %08x\n", dev->name,
-                       readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK);
+       printk(KERN_INFO "%s: Got tx_timeout. irq: %08x\n", dev->name, status);
 
        {
                int i;
@@ -1273,10 +1383,7 @@ static void nv_tx_timeout(struct net_device *dev)
                printk(KERN_DEBUG "%s: tx_timeout: dead entries!\n", dev->name);
                nv_drain_tx(dev);
                np->next_tx = np->nic_tx = 0;
-               if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-                       writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
-               else
-                       writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
+               setup_hw_rings(dev, NV_SETUP_TX_RING);
                netif_wake_queue(dev);
        }
 
@@ -1342,6 +1449,8 @@ static void nv_rx_process(struct net_device *dev)
 {
        struct fe_priv *np = netdev_priv(dev);
        u32 Flags;
+       u32 vlanflags = 0;
+
 
        for (;;) {
                struct sk_buff *skb;
@@ -1357,6 +1466,7 @@ static void nv_rx_process(struct net_device *dev)
                } else {
                        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);
                }
 
                dprintk(KERN_DEBUG "%s: nv_rx_process: looking at packet %d, Flags 0x%x.\n",
@@ -1474,7 +1584,11 @@ 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);
-               netif_rx(skb);
+               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);
+               }
                dev->last_rx = jiffies;
                np->stats.rx_packets++;
                np->stats.rx_bytes += len;
@@ -1523,7 +1637,15 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
                 * guessed, there is probably a simpler approach.
                 * Changing the MTU is a rare event, it shouldn't matter.
                 */
-               disable_irq(dev->irq);
+               if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
+                   ((np->msi_flags & NV_MSI_X_ENABLED) && 
+                    ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
+                       disable_irq(dev->irq);
+               } else {
+                       disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+                       disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
+                       disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
+               }
                spin_lock_bh(&dev->xmit_lock);
                spin_lock(&np->lock);
                /* stop engines */
@@ -1544,11 +1666,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
                }
                /* reinit nic view of the rx queue */
                writel(np->rx_buf_sz, base + NvRegOffloadConfig);
-               writel((u32) np->ring_addr, base + NvRegRxRingPhysAddr);
-               if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-                       writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
-               else
-                       writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
+               setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
                writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
                        base + NvRegRingSizes);
                pci_push(base);
@@ -1560,7 +1678,15 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
                nv_start_tx(dev);
                spin_unlock(&np->lock);
                spin_unlock_bh(&dev->xmit_lock);
-               enable_irq(dev->irq);
+               if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
+                   ((np->msi_flags & NV_MSI_X_ENABLED) && 
+                    ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
+                       enable_irq(dev->irq);
+               } else {
+                       enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+                       enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
+                       enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
+               }
        }
        return 0;
 }
@@ -1866,8 +1992,13 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
        dprintk(KERN_DEBUG "%s: nv_nic_irq\n", dev->name);
 
        for (i=0; ; i++) {
-               events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK;
-               writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
+               if (!(np->msi_flags & NV_MSI_X_ENABLED)) {
+                       events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK;
+                       writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
+               } else {
+                       events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK;
+                       writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus);
+               }
                pci_push(base);
                dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events);
                if (!(events & np->irqmask))
@@ -1907,11 +2038,16 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
                if (i > max_interrupt_work) {
                        spin_lock(&np->lock);
                        /* disable interrupts on the nic */
-                       writel(0, base + NvRegIrqMask);
+                       if (!(np->msi_flags & NV_MSI_X_ENABLED))
+                               writel(0, base + NvRegIrqMask);
+                       else
+                               writel(np->irqmask, base + NvRegIrqMask);
                        pci_push(base);
 
-                       if (!np->in_shutdown)
+                       if (!np->in_shutdown) {
+                               np->nic_poll_irq = np->irqmask;
                                mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
+                       }
                        printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i);
                        spin_unlock(&np->lock);
                        break;
@@ -1923,22 +2059,212 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
        return IRQ_RETVAL(i);
 }
 
+static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *) data;
+       struct fe_priv *np = netdev_priv(dev);
+       u8 __iomem *base = get_hwbase(dev);
+       u32 events;
+       int i;
+
+       dprintk(KERN_DEBUG "%s: nv_nic_irq_tx\n", dev->name);
+
+       for (i=0; ; i++) {
+               events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_TX_ALL;
+               writel(NVREG_IRQ_TX_ALL, base + NvRegMSIXIrqStatus);
+               pci_push(base);
+               dprintk(KERN_DEBUG "%s: tx irq: %08x\n", dev->name, events);
+               if (!(events & np->irqmask))
+                       break;
+
+               spin_lock(&np->lock);
+               nv_tx_done(dev);
+               spin_unlock(&np->lock);
+               
+               if (events & (NVREG_IRQ_TX_ERR)) {
+                       dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
+                                               dev->name, events);
+               }
+               if (i > max_interrupt_work) {
+                       spin_lock(&np->lock);
+                       /* disable interrupts on the nic */
+                       writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask);
+                       pci_push(base);
+
+                       if (!np->in_shutdown) {
+                               np->nic_poll_irq |= NVREG_IRQ_TX_ALL;
+                               mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
+                       }
+                       printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i);
+                       spin_unlock(&np->lock);
+                       break;
+               }
+
+       }
+       dprintk(KERN_DEBUG "%s: nv_nic_irq_tx completed\n", dev->name);
+
+       return IRQ_RETVAL(i);
+}
+
+static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *) data;
+       struct fe_priv *np = netdev_priv(dev);
+       u8 __iomem *base = get_hwbase(dev);
+       u32 events;
+       int i;
+
+       dprintk(KERN_DEBUG "%s: nv_nic_irq_rx\n", dev->name);
+
+       for (i=0; ; i++) {
+               events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_RX_ALL;
+               writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus);
+               pci_push(base);
+               dprintk(KERN_DEBUG "%s: rx irq: %08x\n", dev->name, events);
+               if (!(events & np->irqmask))
+                       break;
+               
+               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 (i > max_interrupt_work) {
+                       spin_lock(&np->lock);
+                       /* disable interrupts on the nic */
+                       writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
+                       pci_push(base);
+
+                       if (!np->in_shutdown) {
+                               np->nic_poll_irq |= NVREG_IRQ_RX_ALL;
+                               mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
+                       }
+                       printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i);
+                       spin_unlock(&np->lock);
+                       break;
+               }
+
+       }
+       dprintk(KERN_DEBUG "%s: nv_nic_irq_rx completed\n", dev->name);
+
+       return IRQ_RETVAL(i);
+}
+
+static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *) data;
+       struct fe_priv *np = netdev_priv(dev);
+       u8 __iomem *base = get_hwbase(dev);
+       u32 events;
+       int i;
+
+       dprintk(KERN_DEBUG "%s: nv_nic_irq_other\n", dev->name);
+
+       for (i=0; ; i++) {
+               events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_OTHER;
+               writel(NVREG_IRQ_OTHER, base + NvRegMSIXIrqStatus);
+               pci_push(base);
+               dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events);
+               if (!(events & np->irqmask))
+                       break;
+               
+               if (events & NVREG_IRQ_LINK) {
+                       spin_lock(&np->lock);
+                       nv_link_irq(dev);
+                       spin_unlock(&np->lock);
+               }
+               if (np->need_linktimer && time_after(jiffies, np->link_timeout)) {
+                       spin_lock(&np->lock);
+                       nv_linkchange(dev);
+                       spin_unlock(&np->lock);
+                       np->link_timeout = jiffies + LINK_TIMEOUT;
+               }
+               if (events & (NVREG_IRQ_UNKNOWN)) {
+                       printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n",
+                                               dev->name, events);
+               }
+               if (i > max_interrupt_work) {
+                       spin_lock(&np->lock);
+                       /* disable interrupts on the nic */
+                       writel(NVREG_IRQ_OTHER, base + NvRegIrqMask);
+                       pci_push(base);
+
+                       if (!np->in_shutdown) {
+                               np->nic_poll_irq |= NVREG_IRQ_OTHER;
+                               mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
+                       }
+                       printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i);
+                       spin_unlock(&np->lock);
+                       break;
+               }
+
+       }
+       dprintk(KERN_DEBUG "%s: nv_nic_irq_other completed\n", dev->name);
+
+       return IRQ_RETVAL(i);
+}
+
 static void nv_do_nic_poll(unsigned long data)
 {
        struct net_device *dev = (struct net_device *) data;
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
+       u32 mask = 0;
 
-       disable_irq(dev->irq);
-       /* FIXME: Do we need synchronize_irq(dev->irq) here? */
        /*
+        * First disable irq(s) and then
         * reenable interrupts on the nic, we have to do this before calling
         * nv_nic_irq because that may decide to do otherwise
         */
-       writel(np->irqmask, base + NvRegIrqMask);
+
+       if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
+           ((np->msi_flags & NV_MSI_X_ENABLED) && 
+            ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
+               disable_irq(dev->irq);
+               mask = np->irqmask;
+       } else {
+               if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
+                       disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+                       mask |= NVREG_IRQ_RX_ALL;
+               }
+               if (np->nic_poll_irq & NVREG_IRQ_TX_ALL) {
+                       disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
+                       mask |= NVREG_IRQ_TX_ALL;
+               }
+               if (np->nic_poll_irq & NVREG_IRQ_OTHER) {
+                       disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
+                       mask |= NVREG_IRQ_OTHER;
+               }
+       }
+       np->nic_poll_irq = 0;
+
+       /* FIXME: Do we need synchronize_irq(dev->irq) here? */
+       
+       writel(mask, base + NvRegIrqMask);
        pci_push(base);
-       nv_nic_irq((int) 0, (void *) data, (struct pt_regs *) NULL);
-       enable_irq(dev->irq);
+
+       if (!(np->msi_flags & NV_MSI_X_ENABLED) || 
+           ((np->msi_flags & NV_MSI_X_ENABLED) && 
+            ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
+               nv_nic_irq((int) 0, (void *) data, (struct pt_regs *) NULL);
+               enable_irq(dev->irq);
+       } else {
+               if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
+                       nv_nic_irq_rx((int) 0, (void *) data, (struct pt_regs *) NULL);
+                       enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+               }
+               if (np->nic_poll_irq & NVREG_IRQ_TX_ALL) {
+                       nv_nic_irq_tx((int) 0, (void *) data, (struct pt_regs *) NULL);
+                       enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
+               }
+               if (np->nic_poll_irq & NVREG_IRQ_OTHER) {
+                       nv_nic_irq_other((int) 0, (void *) data, (struct pt_regs *) NULL);
+                       enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
+               }
+       }
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2217,11 +2543,66 @@ static struct ethtool_ops ops = {
        .get_perm_addr = ethtool_op_get_perm_addr,
 };
 
+static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
+{
+       struct fe_priv *np = get_nvpriv(dev);
+
+       spin_lock_irq(&np->lock);
+
+       /* save vlan group */
+       np->vlangrp = grp;
+
+       if (grp) {
+               /* enable vlan on MAC */
+               np->txrxctl_bits |= NVREG_TXRXCTL_VLANSTRIP | NVREG_TXRXCTL_VLANINS;
+       } else {
+               /* disable vlan on MAC */
+               np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANSTRIP;
+               np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANINS;
+       }
+
+       writel(np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
+
+       spin_unlock_irq(&np->lock);
+};
+
+static void nv_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+{
+       /* nothing to do */
+};
+
+static void set_msix_vector_map(struct net_device *dev, u32 vector, u32 irqmask)
+{
+       u8 __iomem *base = get_hwbase(dev);
+       int i;
+       u32 msixmap = 0;
+
+       /* Each interrupt bit can be mapped to a MSIX vector (4 bits).
+        * MSIXMap0 represents the first 8 interrupts and MSIXMap1 represents
+        * the remaining 8 interrupts.
+        */
+       for (i = 0; i < 8; i++) {
+               if ((irqmask >> i) & 0x1) {
+                       msixmap |= vector << (i << 2);
+               }
+       }
+       writel(readl(base + NvRegMSIXMap0) | msixmap, base + NvRegMSIXMap0);
+
+       msixmap = 0;
+       for (i = 0; i < 8; i++) {
+               if ((irqmask >> (i + 8)) & 0x1) {
+                       msixmap |= vector << (i << 2);
+               }
+       }
+       writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1);
+}
+
 static int nv_open(struct net_device *dev)
 {
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
-       int ret, oom, i;
+       int ret = 1;
+       int oom, i;
 
        dprintk(KERN_DEBUG "nv_open: begin\n");
 
@@ -2253,11 +2634,7 @@ static int nv_open(struct net_device *dev)
        nv_copy_mac_to_hw(dev);
 
        /* 4) give hw rings */
-       writel((u32) np->ring_addr, base + NvRegRxRingPhysAddr);
-       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-               writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
-       else
-               writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
+       setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
        writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
                base + NvRegRingSizes);
 
@@ -2265,6 +2642,7 @@ static int nv_open(struct net_device *dev)
        writel(np->linkspeed, base + NvRegLinkSpeed);
        writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);
        writel(np->txrxctl_bits, base + NvRegTxRxControl);
+       writel(np->vlanctl_bits, base + NvRegVlanControl);
        pci_push(base);
        writel(NVREG_TXRXCTL_BIT1|np->txrxctl_bits, base + NvRegTxRxControl);
        reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31,
@@ -2315,9 +2693,77 @@ static int nv_open(struct net_device *dev)
        writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
        pci_push(base);
 
-       ret = request_irq(dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev);
-       if (ret)
-               goto out_drain;
+       if (np->msi_flags & NV_MSI_X_CAPABLE) {
+               for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
+                       np->msi_x_entry[i].entry = i;
+               }
+               if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) {
+                       np->msi_flags |= NV_MSI_X_ENABLED;
+                       if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) {
+                               /* Request irq for rx handling */
+                               if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) {
+                                       printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret);
+                                       pci_disable_msix(np->pci_dev);
+                                       np->msi_flags &= ~NV_MSI_X_ENABLED;
+                                       goto out_drain;
+                               }
+                               /* Request irq for tx handling */
+                               if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) {
+                                       printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret);
+                                       pci_disable_msix(np->pci_dev);
+                                       np->msi_flags &= ~NV_MSI_X_ENABLED;
+                                       goto out_drain;
+                               }
+                               /* Request irq for link and timer handling */
+                               if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) {
+                                       printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret);
+                                       pci_disable_msix(np->pci_dev);
+                                       np->msi_flags &= ~NV_MSI_X_ENABLED;
+                                       goto out_drain;
+                               }
+
+                               /* map interrupts to their respective vector */
+                               writel(0, base + NvRegMSIXMap0);
+                               writel(0, base + NvRegMSIXMap1);
+                               set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL);
+                               set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL);
+                               set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER);
+                       } else {
+                               /* Request irq for all interrupts */
+                               if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
+                                       printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
+                                       pci_disable_msix(np->pci_dev);
+                                       np->msi_flags &= ~NV_MSI_X_ENABLED;
+                                       goto out_drain;
+                               }
+
+                               /* map interrupts to vector 0 */
+                               writel(0, base + NvRegMSIXMap0);
+                               writel(0, base + NvRegMSIXMap1);
+                       }
+               }
+       }
+       if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) {
+               if ((ret = pci_enable_msi(np->pci_dev)) == 0) {
+                       np->msi_flags |= NV_MSI_ENABLED;
+                       if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
+                               printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
+                               pci_disable_msi(np->pci_dev);
+                               np->msi_flags &= ~NV_MSI_ENABLED;
+                               goto out_drain;
+                       }
+
+                       /* map interrupts to vector 0 */
+                       writel(0, base + NvRegMSIMap0);
+                       writel(0, base + NvRegMSIMap1);
+                       /* enable msi vector 0 */
+                       writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask);
+               }
+       }
+       if (ret != 0) {
+               if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0)
+                       goto out_drain;
+       }
 
        /* ask for interrupts */
        writel(np->irqmask, base + NvRegIrqMask);
@@ -2364,6 +2810,7 @@ static int nv_close(struct net_device *dev)
 {
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base;
+       int i;
 
        spin_lock_irq(&np->lock);
        np->in_shutdown = 1;
@@ -2381,13 +2828,31 @@ static int nv_close(struct net_device *dev)
 
        /* disable interrupts on the nic or we will lock up */
        base = get_hwbase(dev);
-       writel(0, base + NvRegIrqMask);
+       if (np->msi_flags & NV_MSI_X_ENABLED) {
+               writel(np->irqmask, base + NvRegIrqMask);
+       } else {
+               if (np->msi_flags & NV_MSI_ENABLED)
+                       writel(0, base + NvRegMSIIrqMask);
+               writel(0, base + NvRegIrqMask);
+       }
        pci_push(base);
        dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name);
 
        spin_unlock_irq(&np->lock);
 
-       free_irq(dev->irq, dev);
+       if (np->msi_flags & NV_MSI_X_ENABLED) {
+               for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
+                       free_irq(np->msi_x_entry[i].vector, dev);
+               }
+               pci_disable_msix(np->pci_dev);
+               np->msi_flags &= ~NV_MSI_X_ENABLED;
+       } else {
+               free_irq(np->pci_dev->irq, dev);
+               if (np->msi_flags & NV_MSI_ENABLED) {
+                       pci_disable_msi(np->pci_dev);
+                       np->msi_flags &= ~NV_MSI_ENABLED;
+               }
+       }
 
        drain_ring(dev);
 
@@ -2471,7 +2936,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                        printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
                                        pci_name(pci_dev));
                } else {
-                       dev->features |= NETIF_F_HIGHDMA;
+                       if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
+                               printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n",
+                                       pci_name(pci_dev));
+                               goto out_relreg;
+                       } else {
+                               dev->features |= NETIF_F_HIGHDMA;
+                               printk(KERN_INFO "forcedeth: using HIGHDMA\n");
+                       }
                }
                np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
        } else if (id->driver_data & DEV_HAS_LARGEDESC) {
@@ -2496,6 +2968,22 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
 #endif
        }
 
+       np->vlanctl_bits = 0;
+       if (id->driver_data & DEV_HAS_VLAN) {
+               np->vlanctl_bits = NVREG_VLANCONTROL_ENABLE;
+               dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX;
+               dev->vlan_rx_register = nv_vlan_rx_register;
+               dev->vlan_rx_kill_vid = nv_vlan_rx_kill_vid;
+       }
+
+       np->msi_flags = 0;
+       if ((id->driver_data & DEV_HAS_MSI) && !disable_msi) {
+               np->msi_flags |= NV_MSI_CAPABLE;
+       }
+       if ((id->driver_data & DEV_HAS_MSI_X) && !disable_msix) {
+               np->msi_flags |= NV_MSI_X_CAPABLE;
+       }
+
        err = -ENOMEM;
        np->base = ioremap(addr, NV_PCI_REGSZ);
        if (!np->base)
@@ -2578,10 +3066,15 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
        } else {
                np->tx_flags = NV_TX2_VALID;
        }
-       if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT)
+       if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) {
                np->irqmask = NVREG_IRQMASK_THROUGHPUT;
-       else
+               if (np->msi_flags & NV_MSI_X_CAPABLE) /* set number of vectors */
+                       np->msi_flags |= 0x0003;
+       } else {
                np->irqmask = NVREG_IRQMASK_CPU;
+               if (np->msi_flags & NV_MSI_X_CAPABLE) /* set number of vectors */
+                       np->msi_flags |= 0x0001;
+       }
 
        if (id->driver_data & DEV_NEED_TIMERIRQ)
                np->irqmask |= NVREG_IRQ_TIMER;
@@ -2737,11 +3230,11 @@ static struct pci_device_id pci_tbl[] = {
        },
        {       /* MCP55 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X,
        },
        {       /* MCP55 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X,
        },
        {0,},
 };
@@ -2771,6 +3264,10 @@ module_param(optimization_mode, int, 0);
 MODULE_PARM_DESC(optimization_mode, "In throughput mode (0), every tx & rx packet will generate an interrupt. In CPU mode (1), interrupts are controlled by a timer.");
 module_param(poll_interval, int, 0);
 MODULE_PARM_DESC(poll_interval, "Interval determines how frequent timer interrupt is generated by [(time_in_micro_secs * 100) / (2^10)]. Min is 0 and Max is 65535.");
+module_param(disable_msi, int, 0);
+MODULE_PARM_DESC(disable_msi, "Disable MSI interrupts by setting to 1.");
+module_param(disable_msix, int, 0);
+MODULE_PARM_DESC(disable_msix, "Disable MSIX interrupts by setting to 1.");
 
 MODULE_AUTHOR("Manfred Spraul <manfred@colorfullife.com>");
 MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver");
index bc9a3bf..0ea4cb4 100644 (file)
@@ -427,7 +427,7 @@ that case.
 static void hamachi_timer(unsigned long data);
 
 enum capability_flags {CanHaveMII=1, };
-static struct chip_info {
+static const struct chip_info {
        u16     vendor_id, device_id, device_id_mask, pad;
        const char *name;
        void (*media_timer)(unsigned long data);
index e4188d0..9220de9 100644 (file)
@@ -905,7 +905,7 @@ static int epp_open(struct net_device *dev)
        /* autoprobe baud rate */
        tstart = jiffies;
        i = 0;
-       while ((signed)(jiffies-tstart-HZ/3) < 0) {
+       while (time_before(jiffies, tstart + HZ/3)) {
                if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1)
                        goto epptimeout;
                if ((stat & (EPP_NRAEF|EPP_NRHF)) == EPP_NRHF) {
index 55c7ed6..247c8ca 100644 (file)
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
+#include <linux/jiffies.h>
 
 #include <asm/io.h>
 
@@ -1499,7 +1500,7 @@ static int hp100_start_xmit_bm(struct sk_buff *skb, struct net_device *dev)
                printk("hp100: %s: start_xmit_bm: No TX PDL available.\n", dev->name);
 #endif
                /* not waited long enough since last tx? */
-               if (jiffies - dev->trans_start < HZ)
+               if (time_before(jiffies, dev->trans_start + HZ))
                        return -EAGAIN;
 
                if (hp100_check_lan(dev))
@@ -1652,7 +1653,7 @@ static int hp100_start_xmit(struct sk_buff *skb, struct net_device *dev)
                printk("hp100: %s: start_xmit: tx free mem = 0x%x\n", dev->name, i);
 #endif
                /* not waited long enough since last failed tx try? */
-               if (jiffies - dev->trans_start < HZ) {
+               if (time_before(jiffies, dev->trans_start + HZ)) {
 #ifdef HP100_DEBUG
                        printk("hp100: %s: trans_start timing problem\n",
                               dev->name);
@@ -1718,17 +1719,10 @@ static int hp100_start_xmit(struct sk_buff *skb, struct net_device *dev)
        hp100_outw(i, FRAGMENT_LEN);    /* and first/only fragment length    */
 
        if (lp->mode == 2) {    /* memory mapped */
-               if (lp->mem_ptr_virt) { /* high pci memory was remapped */
-                       /* Note: The J2585B needs alignment to 32bits here!  */
-                       memcpy_toio(lp->mem_ptr_virt, skb->data, (skb->len + 3) & ~3);
-                       if (!ok_flag)
-                               memset_io(lp->mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb->len);
-               } else {
-                       /* Note: The J2585B needs alignment to 32bits here!  */
-                       isa_memcpy_toio(lp->mem_ptr_phys, skb->data, (skb->len + 3) & ~3);
-                       if (!ok_flag)
-                               isa_memset_io(lp->mem_ptr_phys, 0, HP100_MIN_PACKET_SIZE - skb->len);
-               }
+               /* Note: The J2585B needs alignment to 32bits here!  */
+               memcpy_toio(lp->mem_ptr_virt, skb->data, (skb->len + 3) & ~3);
+               if (!ok_flag)
+                       memset_io(lp->mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb->len);
        } else {                /* programmed i/o */
                outsl(ioaddr + HP100_REG_DATA32, skb->data,
                      (skb->len + 3) >> 2);
@@ -1798,10 +1792,7 @@ static void hp100_rx(struct net_device *dev)
                /* First we get the header, which contains information about the */
                /* actual length of the received packet. */
                if (lp->mode == 2) {    /* memory mapped mode */
-                       if (lp->mem_ptr_virt)   /* if memory was remapped */
-                               header = readl(lp->mem_ptr_virt);
-                       else
-                               header = isa_readl(lp->mem_ptr_phys);
+                       header = readl(lp->mem_ptr_virt);
                } else          /* programmed i/o */
                        header = hp100_inl(DATA32);
 
@@ -1833,13 +1824,9 @@ static void hp100_rx(struct net_device *dev)
                        ptr = skb->data;
 
                        /* Now transfer the data from the card into that area */
-                       if (lp->mode == 2) {
-                               if (lp->mem_ptr_virt)
-                                       memcpy_fromio(ptr, lp->mem_ptr_virt,pkt_len);
-                               /* Note alignment to 32bit transfers */
-                               else
-                                       isa_memcpy_fromio(ptr, lp->mem_ptr_phys, pkt_len);
-                       } else  /* io mapped */
+                       if (lp->mode == 2)
+                               memcpy_fromio(ptr, lp->mem_ptr_virt,pkt_len);
+                       else    /* io mapped */
                                insl(ioaddr + HP100_REG_DATA32, ptr, pkt_len >> 2);
 
                        skb->protocol = eth_type_trans(skb, dev);
index 591c586..7e49522 100644 (file)
@@ -204,7 +204,7 @@ static inline int emac_phy_gpcs(int phy_mode)
 
 static inline void emac_tx_enable(struct ocp_enet_private *dev)
 {
-       struct emac_regs *p = dev->emacp;
+       struct emac_regs __iomem *p = dev->emacp;
        unsigned long flags;
        u32 r;
 
@@ -220,7 +220,7 @@ static inline void emac_tx_enable(struct ocp_enet_private *dev)
 
 static void emac_tx_disable(struct ocp_enet_private *dev)
 {
-       struct emac_regs *p = dev->emacp;
+       struct emac_regs __iomem *p = dev->emacp;
        unsigned long flags;
        u32 r;
 
@@ -244,7 +244,7 @@ static void emac_tx_disable(struct ocp_enet_private *dev)
 
 static void emac_rx_enable(struct ocp_enet_private *dev)
 {
-       struct emac_regs *p = dev->emacp;
+       struct emac_regs __iomem *p = dev->emacp;
        unsigned long flags;
        u32 r;
 
@@ -275,7 +275,7 @@ static void emac_rx_enable(struct ocp_enet_private *dev)
 
 static void emac_rx_disable(struct ocp_enet_private *dev)
 {
-       struct emac_regs *p = dev->emacp;
+       struct emac_regs __iomem *p = dev->emacp;
        unsigned long flags;
        u32 r;
 
@@ -299,7 +299,7 @@ static void emac_rx_disable(struct ocp_enet_private *dev)
 
 static inline void emac_rx_disable_async(struct ocp_enet_private *dev)
 {
-       struct emac_regs *p = dev->emacp;
+       struct emac_regs __iomem *p = dev->emacp;
        unsigned long flags;
        u32 r;
 
@@ -315,7 +315,7 @@ static inline void emac_rx_disable_async(struct ocp_enet_private *dev)
 
 static int emac_reset(struct ocp_enet_private *dev)
 {
-       struct emac_regs *p = dev->emacp;
+       struct emac_regs __iomem *p = dev->emacp;
        unsigned long flags;
        int n = 20;
 
@@ -348,7 +348,7 @@ static int emac_reset(struct ocp_enet_private *dev)
 
 static void emac_hash_mc(struct ocp_enet_private *dev)
 {
-       struct emac_regs *p = dev->emacp;
+       struct emac_regs __iomem *p = dev->emacp;
        u16 gaht[4] = { 0 };
        struct dev_mc_list *dmi;
 
@@ -393,7 +393,7 @@ static inline int emac_opb_mhz(void)
 /* BHs disabled */
 static int emac_configure(struct ocp_enet_private *dev)
 {
-       struct emac_regs *p = dev->emacp;
+       struct emac_regs __iomem *p = dev->emacp;
        struct net_device *ndev = dev->ndev;
        int gige;
        u32 r;
@@ -555,7 +555,7 @@ static void emac_full_tx_reset(struct net_device *ndev)
 
 static int __emac_mdio_read(struct ocp_enet_private *dev, u8 id, u8 reg)
 {
-       struct emac_regs *p = dev->emacp;
+       struct emac_regs __iomem *p = dev->emacp;
        u32 r;
        int n;
 
@@ -604,7 +604,7 @@ static int __emac_mdio_read(struct ocp_enet_private *dev, u8 id, u8 reg)
 static void __emac_mdio_write(struct ocp_enet_private *dev, u8 id, u8 reg,
                              u16 val)
 {
-       struct emac_regs *p = dev->emacp;
+       struct emac_regs __iomem *p = dev->emacp;
        int n;
 
        DBG2("%d: mdio_write(%02x,%02x,%04x)" NL, dev->def->index, id, reg,
@@ -666,7 +666,7 @@ static void emac_mdio_write(struct net_device *ndev, int id, int reg, int val)
 static void emac_set_multicast_list(struct net_device *ndev)
 {
        struct ocp_enet_private *dev = ndev->priv;
-       struct emac_regs *p = dev->emacp;
+       struct emac_regs __iomem *p = dev->emacp;
        u32 rmr = emac_iff2rmr(ndev);
 
        DBG("%d: multicast %08x" NL, dev->def->index, rmr);
@@ -825,7 +825,7 @@ static void emac_clean_rx_ring(struct ocp_enet_private *dev)
 }
 
 static inline int emac_alloc_rx_skb(struct ocp_enet_private *dev, int slot,
-                                   int flags)
+                                   gfp_t flags)
 {
        struct sk_buff *skb = alloc_skb(dev->rx_skb_size, flags);
        if (unlikely(!skb))
@@ -1047,7 +1047,7 @@ static inline u16 emac_tx_csum(struct ocp_enet_private *dev,
 
 static inline int emac_xmit_finish(struct ocp_enet_private *dev, int len)
 {
-       struct emac_regs *p = dev->emacp;
+       struct emac_regs __iomem *p = dev->emacp;
        struct net_device *ndev = dev->ndev;
 
        /* Send the packet out */
@@ -1519,7 +1519,7 @@ static void emac_rxde(void *param)
 static irqreturn_t emac_irq(int irq, void *dev_instance, struct pt_regs *regs)
 {
        struct ocp_enet_private *dev = dev_instance;
-       struct emac_regs *p = dev->emacp;
+       struct emac_regs __iomem *p = dev->emacp;
        struct ibm_emac_error_stats *st = &dev->estats;
 
        u32 isr = in_be32(&p->isr);
@@ -1619,17 +1619,17 @@ static void emac_remove(struct ocp_device *ocpdev)
 
        DBG("%d: remove" NL, dev->def->index);
 
-       ocp_set_drvdata(ocpdev, 0);
+       ocp_set_drvdata(ocpdev, NULL);
        unregister_netdev(dev->ndev);
 
        tah_fini(dev->tah_dev);
        rgmii_fini(dev->rgmii_dev, dev->rgmii_input);
        zmii_fini(dev->zmii_dev, dev->zmii_input);
 
-       emac_dbg_register(dev->def->index, 0);
+       emac_dbg_register(dev->def->index, NULL);
 
        mal_unregister_commac(dev->mal, &dev->commac);
-       iounmap((void *)dev->emacp);
+       iounmap(dev->emacp);
        kfree(dev->ndev);
 }
 
@@ -2048,9 +2048,7 @@ static int __init emac_probe(struct ocp_device *ocpdev)
                goto out4;
 
        /* Map EMAC regs */
-       dev->emacp =
-           (struct emac_regs *)ioremap(dev->def->paddr,
-                                       sizeof(struct emac_regs));
+       dev->emacp = ioremap(dev->def->paddr, sizeof(struct emac_regs));
        if (!dev->emacp) {
                printk(KERN_ERR "emac%d: could not ioremap device registers!\n",
                       dev->def->index);
@@ -2210,7 +2208,7 @@ static int __init emac_probe(struct ocp_device *ocpdev)
 
        return 0;
       out6:
-       iounmap((void *)dev->emacp);
+       iounmap(dev->emacp);
       out5:
        tah_fini(dev->tah_dev);
       out4:
index 911abba..f61273b 100644 (file)
@@ -155,7 +155,7 @@ struct ibm_emac_error_stats {
 
 struct ocp_enet_private {
        struct net_device               *ndev;          /* 0 */
-       struct emac_regs                *emacp;
+       struct emac_regs                __iomem *emacp;
        
        struct mal_descriptor           *tx_desc;
        int                             tx_cnt;
index 75d3b86..c7e1ecf 100644 (file)
@@ -58,7 +58,7 @@ static void emac_desc_dump(int idx, struct ocp_enet_private *p)
 
 static void emac_mac_dump(int idx, struct ocp_enet_private *dev)
 {
-       struct emac_regs *p = dev->emacp;
+       struct emac_regs __iomem *p = dev->emacp;
 
        printk("** EMAC%d registers **\n"
               "MR0 = 0x%08x MR1 = 0x%08x TMR0 = 0x%08x TMR1 = 0x%08x\n"
index a1ffb8a..7f03d53 100644 (file)
@@ -31,7 +31,7 @@ struct rgmii_regs {
 
 /* RGMII device */
 struct ibm_ocp_rgmii {
-       struct rgmii_regs *base;
+       struct rgmii_regs __iomem *base;
        int users;              /* number of EMACs using this RGMII bridge */
 };
 
index 35c1185..e129e0a 100644 (file)
@@ -80,7 +80,7 @@ static inline u32 zmii_mode_mask(int mode, int input)
 static int __init zmii_init(struct ocp_device *ocpdev, int input, int *mode)
 {
        struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev);
-       struct zmii_regs *p;
+       struct zmii_regs __iomem *p;
 
        ZMII_DBG("%d: init(%d, %d)" NL, ocpdev->def->index, input, *mode);
 
@@ -94,8 +94,7 @@ static int __init zmii_init(struct ocp_device *ocpdev, int input, int *mode)
                }
                dev->mode = PHY_MODE_NA;
 
-               p = (struct zmii_regs *)ioremap(ocpdev->def->paddr,
-                                               sizeof(struct zmii_regs));
+               p = ioremap(ocpdev->def->paddr, sizeof(struct zmii_regs));
                if (!p) {
                        printk(KERN_ERR
                               "zmii%d: could not ioremap device registers!\n",
@@ -231,7 +230,7 @@ void __exit __zmii_fini(struct ocp_device *ocpdev, int input)
        if (!--dev->users) {
                /* Free everything if this is the last user */
                ocp_set_drvdata(ocpdev, NULL);
-               iounmap((void *)dev->base);
+               iounmap(dev->base);
                kfree(dev);
        }
 }
index 0bb2606..92c8544 100644 (file)
@@ -32,7 +32,7 @@ struct zmii_regs {
 
 /* ZMII device */
 struct ibm_ocp_zmii {
-       struct zmii_regs *base;
+       struct zmii_regs __iomem *base;
        int mode;               /* subset of PHY_MODE_XXXX */
        int users;              /* number of EMACs using this ZMII bridge */
        u32 fer_save;           /* FER value left by firmware */
index 7a08134..c81fe1c 100644 (file)
@@ -283,7 +283,7 @@ config USB_IRDA
          Say Y here if you want to build support for the USB IrDA FIR Dongle
          device driver.  To compile it as a module, choose M here: the module
          will be called irda-usb.  IrDA-USB support the various IrDA USB
-         dongles available and most of their pecularities.  Those dongles
+         dongles available and most of their peculiarities.  Those dongles
          plug in the USB port of your computer, are plug and play, and
          support SIR and FIR (4Mbps) speeds.  On the other hand, those
          dongles tend to be less efficient than a FIR chipset.
@@ -360,7 +360,7 @@ config ALI_FIR
        help
          Say Y here if you want to build support for the ALi M5123 FIR
          Controller.  The ALi M5123 FIR Controller is embedded in ALi M1543C,
-         M1535, M1535D, M1535+, M1535D Sourth Bridge.  This driver supports
+         M1535, M1535D, M1535+, M1535D South Bridge.  This driver supports
          SIR, MIR and FIR (4Mbps) speeds.
 
          To compile it as a module, choose M here: the module will be called
index 02d5c68..f6f3daf 100644 (file)
@@ -622,7 +622,7 @@ static int __init mac_sonic_init_module(void)
        return 0;
 
 out_unregister:
-       driver_unregister(&mac_sonic_driver);
+       platform_driver_unregister(&mac_sonic_driver);
 
        return -ENOMEM;
 }
index c0998ef..9f26613 100644 (file)
@@ -10,7 +10,7 @@
  *
  * Copyright (C) 2003 Ralf Baechle <ralf@linux-mips.org>
  *
- * Copyright (C) 2004-2005 MontaVista Software, Inc.
+ * Copyright (C) 2004-2006 MontaVista Software, Inc.
  *                        Dale Farnsworth <dale@farnsworth.org>
  *
  * Copyright (C) 2004 Steven J. Hill <sjhill1@rockwellcollins.com>
@@ -37,8 +37,6 @@
 #include <linux/tcp.h>
 #include <linux/udp.h>
 #include <linux/etherdevice.h>
-#include <linux/in.h>
-#include <linux/ip.h>
 
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <asm/delay.h>
 #include "mv643xx_eth.h"
 
-/*
- * The first part is the high level driver of the gigE ethernet ports.
- */
-
-/* Constants */
-#define VLAN_HLEN              4
-#define FCS_LEN                        4
-#define DMA_ALIGN              8       /* hw requires 8-byte alignment */
-#define HW_IP_ALIGN            2       /* hw aligns IP header */
-#define WRAP                   HW_IP_ALIGN + ETH_HLEN + VLAN_HLEN + FCS_LEN
-#define RX_SKB_SIZE            ((dev->mtu + WRAP + 7) & ~0x7)
-
-#define INT_UNMASK_ALL                 0x0007ffff
-#define INT_UNMASK_ALL_EXT             0x0011ffff
-#define INT_MASK_ALL                   0x00000000
-#define INT_MASK_ALL_EXT               0x00000000
-#define INT_CAUSE_CHECK_BITS           INT_CAUSE_UNMASK_ALL
-#define INT_CAUSE_CHECK_BITS_EXT       INT_CAUSE_UNMASK_ALL_EXT
-
-#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
-#define MAX_DESCS_PER_SKB      (MAX_SKB_FRAGS + 1)
-#else
-#define MAX_DESCS_PER_SKB      1
-#endif
-
-#define PHY_WAIT_ITERATIONS    1000    /* 1000 iterations * 10uS = 10mS max */
-#define PHY_WAIT_MICRO_SECONDS 10
-
 /* Static function declarations */
-static int eth_port_link_is_up(unsigned int eth_port_num);
 static void eth_port_uc_addr_get(struct net_device *dev,
                                                unsigned char *MacAddr);
 static void eth_port_set_multicast_list(struct net_device *);
+static void mv643xx_eth_port_enable_tx(unsigned int port_num,
+                                               unsigned int queues);
+static void mv643xx_eth_port_enable_rx(unsigned int port_num,
+                                               unsigned int queues);
+static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num);
+static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num);
 static int mv643xx_eth_open(struct net_device *);
 static int mv643xx_eth_stop(struct net_device *);
 static int mv643xx_eth_change_mtu(struct net_device *, int);
@@ -93,8 +68,12 @@ static void eth_port_init_mac_tables(unsigned int eth_port_num);
 #ifdef MV643XX_NAPI
 static int mv643xx_poll(struct net_device *dev, int *budget);
 #endif
+static int ethernet_phy_get(unsigned int eth_port_num);
 static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr);
 static int ethernet_phy_detect(unsigned int eth_port_num);
+static int mv643xx_mdio_read(struct net_device *dev, int phy_id, int location);
+static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, int val);
+static int mv643xx_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 static struct ethtool_ops mv643xx_ethtool_ops;
 
 static char mv643xx_driver_name[] = "mv643xx_eth";
@@ -153,67 +132,53 @@ static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
 }
 
 /*
- * mv643xx_eth_rx_task
+ * mv643xx_eth_rx_refill_descs
  *
  * Fills / refills RX queue on a certain gigabit ethernet port
  *
  * Input :     pointer to ethernet interface network device structure
  * Output :    N/A
  */
-static void mv643xx_eth_rx_task(void *data)
+static void mv643xx_eth_rx_refill_descs(struct net_device *dev)
 {
-       struct net_device *dev = (struct net_device *)data;
        struct mv643xx_private *mp = netdev_priv(dev);
        struct pkt_info pkt_info;
        struct sk_buff *skb;
        int unaligned;
 
-       if (test_and_set_bit(0, &mp->rx_task_busy))
-               panic("%s: Error in test_set_bit / clear_bit", dev->name);
-
-       while (mp->rx_ring_skbs < (mp->rx_ring_size - 5)) {
-               skb = dev_alloc_skb(RX_SKB_SIZE + DMA_ALIGN);
+       while (mp->rx_desc_count < mp->rx_ring_size) {
+               skb = dev_alloc_skb(ETH_RX_SKB_SIZE + ETH_DMA_ALIGN);
                if (!skb)
                        break;
-               mp->rx_ring_skbs++;
-               unaligned = (u32)skb->data & (DMA_ALIGN - 1);
+               mp->rx_desc_count++;
+               unaligned = (u32)skb->data & (ETH_DMA_ALIGN - 1);
                if (unaligned)
-                       skb_reserve(skb, DMA_ALIGN - unaligned);
+                       skb_reserve(skb, ETH_DMA_ALIGN - unaligned);
                pkt_info.cmd_sts = ETH_RX_ENABLE_INTERRUPT;
-               pkt_info.byte_cnt = RX_SKB_SIZE;
-               pkt_info.buf_ptr = dma_map_single(NULL, skb->data, RX_SKB_SIZE,
-                                                       DMA_FROM_DEVICE);
+               pkt_info.byte_cnt = ETH_RX_SKB_SIZE;
+               pkt_info.buf_ptr = dma_map_single(NULL, skb->data,
+                                       ETH_RX_SKB_SIZE, DMA_FROM_DEVICE);
                pkt_info.return_info = skb;
                if (eth_rx_return_buff(mp, &pkt_info) != ETH_OK) {
                        printk(KERN_ERR
                                "%s: Error allocating RX Ring\n", dev->name);
                        break;
                }
-               skb_reserve(skb, HW_IP_ALIGN);
+               skb_reserve(skb, ETH_HW_IP_ALIGN);
        }
-       clear_bit(0, &mp->rx_task_busy);
        /*
         * If RX ring is empty of SKB, set a timer to try allocating
-        * again in a later time .
+        * again at a later time.
         */
-       if ((mp->rx_ring_skbs == 0) && (mp->rx_timer_flag == 0)) {
+       if (mp->rx_desc_count == 0) {
                printk(KERN_INFO "%s: Rx ring is empty\n", dev->name);
-               /* After 100mSec */
-               mp->timeout.expires = jiffies + (HZ / 10);
+               mp->timeout.expires = jiffies + (HZ / 10);      /* 100 mSec */
                add_timer(&mp->timeout);
-               mp->rx_timer_flag = 1;
-       }
-#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
-       else {
-               /* Return interrupts */
-               mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(mp->port_num),
-                                                       INT_UNMASK_ALL);
        }
-#endif
 }
 
 /*
- * mv643xx_eth_rx_task_timer_wrapper
+ * mv643xx_eth_rx_refill_descs_timer_wrapper
  *
  * Timer routine to wake up RX queue filling task. This function is
  * used only in case the RX queue is empty, and all alloc_skb has
@@ -222,13 +187,9 @@ static void mv643xx_eth_rx_task(void *data)
  * Input :     pointer to ethernet interface network device structure
  * Output :    N/A
  */
-static void mv643xx_eth_rx_task_timer_wrapper(unsigned long data)
+static inline void mv643xx_eth_rx_refill_descs_timer_wrapper(unsigned long data)
 {
-       struct net_device *dev = (struct net_device *)data;
-       struct mv643xx_private *mp = netdev_priv(dev);
-
-       mp->rx_timer_flag = 0;
-       mv643xx_eth_rx_task((void *)data);
+       mv643xx_eth_rx_refill_descs((struct net_device *)data);
 }
 
 /*
@@ -245,8 +206,7 @@ static void mv643xx_eth_update_mac_address(struct net_device *dev)
        unsigned int port_num = mp->port_num;
 
        eth_port_init_mac_tables(port_num);
-       memcpy(mp->port_mac_addr, dev->dev_addr, 6);
-       eth_port_uc_addr_set(port_num, mp->port_mac_addr);
+       eth_port_uc_addr_set(port_num, dev->dev_addr);
 }
 
 /*
@@ -260,13 +220,14 @@ static void mv643xx_eth_update_mac_address(struct net_device *dev)
 static void mv643xx_eth_set_rx_mode(struct net_device *dev)
 {
        struct mv643xx_private *mp = netdev_priv(dev);
+       u32 config_reg;
 
+       config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num));
        if (dev->flags & IFF_PROMISC)
-               mp->port_config |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
+               config_reg |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
        else
-               mp->port_config &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
-
-       mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), mp->port_config);
+               config_reg &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
+       mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), config_reg);
 
        eth_port_set_multicast_list(dev);
 }
@@ -322,53 +283,82 @@ static void mv643xx_eth_tx_timeout_task(struct net_device *dev)
 
        netif_device_detach(dev);
        eth_port_reset(mp->port_num);
-       eth_port_start(mp);
+       eth_port_start(dev);
        netif_device_attach(dev);
 }
 
-/*
- * mv643xx_eth_free_tx_queue
- *
- * Input :     dev - a pointer to the required interface
+/**
+ * mv643xx_eth_free_tx_descs - Free the tx desc data for completed descriptors
  *
- * Output :    0 if was able to release skb , nonzero otherwise
+ * If force is non-zero, frees uncompleted descriptors as well
  */
-static int mv643xx_eth_free_tx_queue(struct net_device *dev,
-                                       unsigned int eth_int_cause_ext)
+int mv643xx_eth_free_tx_descs(struct net_device *dev, int force)
 {
        struct mv643xx_private *mp = netdev_priv(dev);
-       struct net_device_stats *stats = &mp->stats;
-       struct pkt_info pkt_info;
-       int released = 1;
+       struct eth_tx_desc *desc;
+       u32 cmd_sts;
+       struct sk_buff *skb;
+       unsigned long flags;
+       int tx_index;
+       dma_addr_t addr;
+       int count;
+       int released = 0;
+
+       while (mp->tx_desc_count > 0) {
+               spin_lock_irqsave(&mp->lock, flags);
+               tx_index = mp->tx_used_desc_q;
+               desc = &mp->p_tx_desc_area[tx_index];
+               cmd_sts = desc->cmd_sts;
+
+               if (!force && (cmd_sts & ETH_BUFFER_OWNED_BY_DMA)) {
+                       spin_unlock_irqrestore(&mp->lock, flags);
+                       return released;
+               }
 
-       if (!(eth_int_cause_ext & (BIT0 | BIT8)))
-               return released;
+               mp->tx_used_desc_q = (tx_index + 1) % mp->tx_ring_size;
+               mp->tx_desc_count--;
 
-       /* Check only queue 0 */
-       while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) {
-               if (pkt_info.cmd_sts & BIT0) {
+               addr = desc->buf_ptr;
+               count = desc->byte_cnt;
+               skb = mp->tx_skb[tx_index];
+               if (skb)
+                       mp->tx_skb[tx_index] = NULL;
+
+               spin_unlock_irqrestore(&mp->lock, flags);
+
+               if (cmd_sts & ETH_ERROR_SUMMARY) {
                        printk("%s: Error in TX\n", dev->name);
-                       stats->tx_errors++;
+                       mp->stats.tx_errors++;
                }
 
-               if (pkt_info.cmd_sts & ETH_TX_FIRST_DESC)
-                       dma_unmap_single(NULL, pkt_info.buf_ptr,
-                                       pkt_info.byte_cnt,
-                                       DMA_TO_DEVICE);
+               if (cmd_sts & ETH_TX_FIRST_DESC)
+                       dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE);
                else
-                       dma_unmap_page(NULL, pkt_info.buf_ptr,
-                                       pkt_info.byte_cnt,
-                                       DMA_TO_DEVICE);
+                       dma_unmap_page(NULL, addr, count, DMA_TO_DEVICE);
 
-               if (pkt_info.return_info) {
-                       dev_kfree_skb_irq(pkt_info.return_info);
-                       released = 0;
-               }
+               if (skb)
+                       dev_kfree_skb_irq(skb);
+
+               released = 1;
        }
 
        return released;
 }
 
+static void mv643xx_eth_free_completed_tx_descs(struct net_device *dev)
+{
+       struct mv643xx_private *mp = netdev_priv(dev);
+
+       if (mv643xx_eth_free_tx_descs(dev, 0) &&
+           mp->tx_ring_size - mp->tx_desc_count >= MAX_DESCS_PER_SKB)
+               netif_wake_queue(dev);
+}
+
+static void mv643xx_eth_free_all_tx_descs(struct net_device *dev)
+{
+       mv643xx_eth_free_tx_descs(dev, 1);
+}
+
 /*
  * mv643xx_eth_receive
  *
@@ -380,11 +370,7 @@ static int mv643xx_eth_free_tx_queue(struct net_device *dev,
  *
  * Output :    number of served packets
  */
-#ifdef MV643XX_NAPI
 static int mv643xx_eth_receive_queue(struct net_device *dev, int budget)
-#else
-static int mv643xx_eth_receive_queue(struct net_device *dev)
-#endif
 {
        struct mv643xx_private *mp = netdev_priv(dev);
        struct net_device_stats *stats = &mp->stats;
@@ -392,15 +378,14 @@ static int mv643xx_eth_receive_queue(struct net_device *dev)
        struct sk_buff *skb;
        struct pkt_info pkt_info;
 
-#ifdef MV643XX_NAPI
        while (budget-- > 0 && eth_port_receive(mp, &pkt_info) == ETH_OK) {
-#else
-       while (eth_port_receive(mp, &pkt_info) == ETH_OK) {
-#endif
-               mp->rx_ring_skbs--;
+               mp->rx_desc_count--;
                received_packets++;
 
-               /* Update statistics. Note byte count includes 4 byte CRC count */
+               /*
+                * Update statistics.
+                * Note byte count includes 4 byte CRC count
+                */
                stats->rx_packets++;
                stats->rx_bytes += pkt_info.byte_cnt;
                skb = pkt_info.return_info;
@@ -448,10 +433,61 @@ static int mv643xx_eth_receive_queue(struct net_device *dev)
                }
                dev->last_rx = jiffies;
        }
+       mv643xx_eth_rx_refill_descs(dev);       /* Fill RX ring with skb's */
 
        return received_packets;
 }
 
+/* Set the mv643xx port configuration register for the speed/duplex mode. */
+static void mv643xx_eth_update_pscr(struct net_device *dev,
+                                   struct ethtool_cmd *ecmd)
+{
+       struct mv643xx_private *mp = netdev_priv(dev);
+       int port_num = mp->port_num;
+       u32 o_pscr, n_pscr;
+       unsigned int queues;
+
+       o_pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num));
+       n_pscr = o_pscr;
+
+       /* clear speed, duplex and rx buffer size fields */
+       n_pscr &= ~(MV643XX_ETH_SET_MII_SPEED_TO_100  |
+                  MV643XX_ETH_SET_GMII_SPEED_TO_1000 |
+                  MV643XX_ETH_SET_FULL_DUPLEX_MODE   |
+                  MV643XX_ETH_MAX_RX_PACKET_MASK);
+
+       if (ecmd->duplex == DUPLEX_FULL)
+               n_pscr |= MV643XX_ETH_SET_FULL_DUPLEX_MODE;
+
+       if (ecmd->speed == SPEED_1000)
+               n_pscr |= MV643XX_ETH_SET_GMII_SPEED_TO_1000 |
+                         MV643XX_ETH_MAX_RX_PACKET_9700BYTE;
+       else {
+               if (ecmd->speed == SPEED_100)
+                       n_pscr |= MV643XX_ETH_SET_MII_SPEED_TO_100;
+               n_pscr |= MV643XX_ETH_MAX_RX_PACKET_1522BYTE;
+       }
+
+       if (n_pscr != o_pscr) {
+               if ((o_pscr & MV643XX_ETH_SERIAL_PORT_ENABLE) == 0)
+                       mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
+                                                               n_pscr);
+               else {
+                       queues = mv643xx_eth_port_disable_tx(port_num);
+
+                       o_pscr &= ~MV643XX_ETH_SERIAL_PORT_ENABLE;
+                       mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
+                                                               o_pscr);
+                       mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
+                                                               n_pscr);
+                       mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
+                                                               n_pscr);
+                       if (queues)
+                               mv643xx_eth_port_enable_tx(port_num, queues);
+               }
+       }
+}
+
 /*
  * mv643xx_eth_int_handler
  *
@@ -473,78 +509,52 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
 
        /* Read interrupt cause registers */
        eth_int_cause = mv_read(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num)) &
-                                               INT_UNMASK_ALL;
-
-       if (eth_int_cause & BIT1)
+                                               ETH_INT_UNMASK_ALL;
+       if (eth_int_cause & ETH_INT_CAUSE_EXT) {
                eth_int_cause_ext = mv_read(
                        MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
-                                               INT_UNMASK_ALL_EXT;
+                                               ETH_INT_UNMASK_ALL_EXT;
+               mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num),
+                                                       ~eth_int_cause_ext);
+       }
 
-#ifdef MV643XX_NAPI
-       if (!(eth_int_cause & 0x0007fffd)) {
-               /* Dont ack the Rx interrupt */
-#endif
-               /*
-                * Clear specific ethernet port intrerrupt registers by
-                * acknowleding relevant bits.
-                */
-               mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num),
-                                                       ~eth_int_cause);
-               if (eth_int_cause_ext != 0x0)
-                       mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG
-                                       (port_num), ~eth_int_cause_ext);
-
-               /* UDP change : We may need this */
-               if ((eth_int_cause_ext & 0x0000ffff) &&
-                   (mv643xx_eth_free_tx_queue(dev, eth_int_cause_ext) == 0) &&
-                   (mp->tx_ring_size > mp->tx_ring_skbs + MAX_DESCS_PER_SKB))
-                       netif_wake_queue(dev);
-#ifdef MV643XX_NAPI
-       } else {
-               if (netif_rx_schedule_prep(dev)) {
-                       /* Mask all the interrupts */
-                       mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
-                                                               INT_MASK_ALL);
-                       /* wait for previous write to complete */
-                       mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
-                       __netif_rx_schedule(dev);
+       /* PHY status changed */
+       if (eth_int_cause_ext & ETH_INT_CAUSE_PHY) {
+               struct ethtool_cmd cmd;
+
+               if (mii_link_ok(&mp->mii)) {
+                       mii_ethtool_gset(&mp->mii, &cmd);
+                       mv643xx_eth_update_pscr(dev, &cmd);
+                       mv643xx_eth_port_enable_tx(port_num,
+                                                  ETH_TX_QUEUES_ENABLED);
+                       if (!netif_carrier_ok(dev)) {
+                               netif_carrier_on(dev);
+                               if (mp->tx_ring_size - mp->tx_desc_count >=
+                                                       MAX_DESCS_PER_SKB)
+                                       netif_wake_queue(dev);
+                       }
+               } else if (netif_carrier_ok(dev)) {
+                       netif_stop_queue(dev);
+                       netif_carrier_off(dev);
                }
-#else
-               if (eth_int_cause & (BIT2 | BIT11))
-                       mv643xx_eth_receive_queue(dev, 0);
+       }
 
-               /*
-                * After forwarded received packets to upper layer, add a task
-                * in an interrupts enabled context that refills the RX ring
-                * with skb's.
-                */
-#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
-               /* Mask all interrupts on ethernet port */
+#ifdef MV643XX_NAPI
+       if (eth_int_cause & ETH_INT_CAUSE_RX) {
+               /* schedule the NAPI poll routine to maintain port */
                mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
-                                                       INT_MASK_ALL);
-               /* wait for previous write to take effect */
+                                                       ETH_INT_MASK_ALL);
+               /* wait for previous write to complete */
                mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
 
-               queue_task(&mp->rx_task, &tq_immediate);
-               mark_bh(IMMEDIATE_BH);
+               netif_rx_schedule(dev);
+       }
 #else
-               mp->rx_task.func(dev);
+       if (eth_int_cause & ETH_INT_CAUSE_RX)
+               mv643xx_eth_receive_queue(dev, INT_MAX);
+       if (eth_int_cause_ext & ETH_INT_CAUSE_TX)
+               mv643xx_eth_free_completed_tx_descs(dev);
 #endif
-#endif
-       }
-       /* PHY status changed */
-       if (eth_int_cause_ext & (BIT16 | BIT20)) {
-               if (eth_port_link_is_up(port_num)) {
-                       netif_carrier_on(dev);
-                       netif_wake_queue(dev);
-                       /* Start TX queue */
-                       mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG
-                                                               (port_num), 1);
-               } else {
-                       netif_carrier_off(dev);
-                       netif_stop_queue(dev);
-               }
-       }
 
        /*
         * If no real interrupt occured, exit.
@@ -670,9 +680,6 @@ static void ether_init_rx_desc_ring(struct mv643xx_private *mp)
        mp->rx_used_desc_q = 0;
 
        mp->rx_desc_area_size = rx_desc_num * sizeof(struct eth_rx_desc);
-
-       /* Add the queue to the list of RX queues of this port */
-       mp->port_rx_queue_command |= 1;
 }
 
 /*
@@ -712,14 +719,36 @@ static void ether_init_tx_desc_ring(struct mv643xx_private *mp)
 
        mp->tx_curr_desc_q = 0;
        mp->tx_used_desc_q = 0;
-#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
-       mp->tx_first_desc_q = 0;
-#endif
 
        mp->tx_desc_area_size = tx_desc_num * sizeof(struct eth_tx_desc);
+}
 
-       /* Add the queue to the list of Tx queues of this port */
-       mp->port_tx_queue_command |= 1;
+static int mv643xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct mv643xx_private *mp = netdev_priv(dev);
+       int err;
+
+       spin_lock_irq(&mp->lock);
+       err = mii_ethtool_sset(&mp->mii, cmd);
+       spin_unlock_irq(&mp->lock);
+
+       return err;
+}
+
+static int mv643xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct mv643xx_private *mp = netdev_priv(dev);
+       int err;
+
+       spin_lock_irq(&mp->lock);
+       err = mii_ethtool_gset(&mp->mii, cmd);
+       spin_unlock_irq(&mp->lock);
+
+       /* The PHY may support 1000baseT_Half, but the mv643xx does not */
+       cmd->supported &= ~SUPPORTED_1000baseT_Half;
+       cmd->advertising &= ~ADVERTISED_1000baseT_Half;
+
+       return err;
 }
 
 /*
@@ -750,23 +779,12 @@ static int mv643xx_eth_open(struct net_device *dev)
                return -EAGAIN;
        }
 
-       /* Stop RX Queues */
-       mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
-
-       /* Set the MAC Address */
-       memcpy(mp->port_mac_addr, dev->dev_addr, 6);
-
        eth_port_init(mp);
 
-       INIT_WORK(&mp->rx_task, (void (*)(void *))mv643xx_eth_rx_task, dev);
-
        memset(&mp->timeout, 0, sizeof(struct timer_list));
-       mp->timeout.function = mv643xx_eth_rx_task_timer_wrapper;
+       mp->timeout.function = mv643xx_eth_rx_refill_descs_timer_wrapper;
        mp->timeout.data = (unsigned long)dev;
 
-       mp->rx_task_busy = 0;
-       mp->rx_timer_flag = 0;
-
        /* Allocate RX and TX skb rings */
        mp->rx_skb = kmalloc(sizeof(*mp->rx_skb) * mp->rx_ring_size,
                                                                GFP_KERNEL);
@@ -784,7 +802,7 @@ static int mv643xx_eth_open(struct net_device *dev)
        }
 
        /* Allocate TX ring */
-       mp->tx_ring_skbs = 0;
+       mp->tx_desc_count = 0;
        size = mp->tx_ring_size * sizeof(struct eth_tx_desc);
        mp->tx_desc_area_size = size;
 
@@ -809,7 +827,7 @@ static int mv643xx_eth_open(struct net_device *dev)
        ether_init_tx_desc_ring(mp);
 
        /* Allocate RX ring */
-       mp->rx_ring_skbs = 0;
+       mp->rx_desc_count = 0;
        size = mp->rx_ring_size * sizeof(struct eth_rx_desc);
        mp->rx_desc_area_size = size;
 
@@ -839,9 +857,13 @@ static int mv643xx_eth_open(struct net_device *dev)
 
        ether_init_rx_desc_ring(mp);
 
-       mv643xx_eth_rx_task(dev);       /* Fill RX ring with skb's */
+       mv643xx_eth_rx_refill_descs(dev);       /* Fill RX ring with skb's */
+
+       /* Clear any pending ethernet port interrupts */
+       mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+       mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
 
-       eth_port_start(mp);
+       eth_port_start(dev);
 
        /* Interrupt Coalescing */
 
@@ -853,16 +875,13 @@ static int mv643xx_eth_open(struct net_device *dev)
        mp->tx_int_coal =
                eth_port_set_tx_coal(port_num, 133000000, MV643XX_TX_COAL);
 
-       /* Clear any pending ethernet port interrupts */
-       mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
-       mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
-
        /* Unmask phy and link status changes interrupts */
        mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
-                                               INT_UNMASK_ALL_EXT);
+                                               ETH_INT_UNMASK_ALL_EXT);
 
        /* Unmask RX buffer and TX end interrupt */
-       mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_UNMASK_ALL);
+       mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
+
        return 0;
 
 out_free_tx_skb:
@@ -878,25 +897,14 @@ out_free_irq:
 static void mv643xx_eth_free_tx_rings(struct net_device *dev)
 {
        struct mv643xx_private *mp = netdev_priv(dev);
-       unsigned int port_num = mp->port_num;
-       unsigned int curr;
-       struct sk_buff *skb;
 
        /* Stop Tx Queues */
-       mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
-
-       /* Free outstanding skb's on TX rings */
-       for (curr = 0; mp->tx_ring_skbs && curr < mp->tx_ring_size; curr++) {
-               skb = mp->tx_skb[curr];
-               if (skb) {
-                       mp->tx_ring_skbs -= skb_shinfo(skb)->nr_frags;
-                       dev_kfree_skb(skb);
-                       mp->tx_ring_skbs--;
-               }
-       }
-       if (mp->tx_ring_skbs)
-               printk("%s: Error on Tx descriptor free - could not free %d"
-                               " descriptors\n", dev->name, mp->tx_ring_skbs);
+       mv643xx_eth_port_disable_tx(mp->port_num);
+
+       /* Free outstanding skb's on TX ring */
+       mv643xx_eth_free_all_tx_descs(dev);
+
+       BUG_ON(mp->tx_used_desc_q != mp->tx_curr_desc_q);
 
        /* Free TX ring */
        if (mp->tx_sram_size)
@@ -913,21 +921,21 @@ static void mv643xx_eth_free_rx_rings(struct net_device *dev)
        int curr;
 
        /* Stop RX Queues */
-       mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
+       mv643xx_eth_port_disable_rx(port_num);
 
        /* Free preallocated skb's on RX rings */
-       for (curr = 0; mp->rx_ring_skbs && curr < mp->rx_ring_size; curr++) {
+       for (curr = 0; mp->rx_desc_count && curr < mp->rx_ring_size; curr++) {
                if (mp->rx_skb[curr]) {
                        dev_kfree_skb(mp->rx_skb[curr]);
-                       mp->rx_ring_skbs--;
+                       mp->rx_desc_count--;
                }
        }
 
-       if (mp->rx_ring_skbs)
+       if (mp->rx_desc_count)
                printk(KERN_ERR
                        "%s: Error in freeing Rx Ring. %d skb's still"
                        " stuck in RX Ring - ignoring them\n", dev->name,
-                       mp->rx_ring_skbs);
+                       mp->rx_desc_count);
        /* Free RX ring */
        if (mp->rx_sram_size)
                iounmap(mp->p_rx_desc_area);
@@ -952,7 +960,7 @@ static int mv643xx_eth_stop(struct net_device *dev)
        unsigned int port_num = mp->port_num;
 
        /* Mask all interrupts on ethernet port */
-       mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_MASK_ALL);
+       mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
        /* wait for previous write to complete */
        mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
 
@@ -977,30 +985,6 @@ static int mv643xx_eth_stop(struct net_device *dev)
 }
 
 #ifdef MV643XX_NAPI
-static void mv643xx_tx(struct net_device *dev)
-{
-       struct mv643xx_private *mp = netdev_priv(dev);
-       struct pkt_info pkt_info;
-
-       while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) {
-               if (pkt_info.cmd_sts & ETH_TX_FIRST_DESC)
-                       dma_unmap_single(NULL, pkt_info.buf_ptr,
-                                       pkt_info.byte_cnt,
-                                       DMA_TO_DEVICE);
-               else
-                       dma_unmap_page(NULL, pkt_info.buf_ptr,
-                                       pkt_info.byte_cnt,
-                                       DMA_TO_DEVICE);
-
-               if (pkt_info.return_info)
-                       dev_kfree_skb_irq(pkt_info.return_info);
-       }
-
-       if (netif_queue_stopped(dev) &&
-                       mp->tx_ring_size > mp->tx_ring_skbs + MAX_DESCS_PER_SKB)
-               netif_wake_queue(dev);
-}
-
 /*
  * mv643xx_poll
  *
@@ -1014,7 +998,7 @@ static int mv643xx_poll(struct net_device *dev, int *budget)
 
 #ifdef MV643XX_TX_FAST_REFILL
        if (++mp->tx_clean_threshold > 5) {
-               mv643xx_tx(dev);
+               mv643xx_eth_free_completed_tx_descs(dev);
                mp->tx_clean_threshold = 0;
        }
 #endif
@@ -1025,7 +1009,6 @@ static int mv643xx_poll(struct net_device *dev, int *budget)
                if (orig_budget > dev->quota)
                        orig_budget = dev->quota;
                work_done = mv643xx_eth_receive_queue(dev, orig_budget);
-               mp->rx_task.func(dev);
                *budget -= work_done;
                dev->quota -= work_done;
                if (work_done >= orig_budget)
@@ -1037,14 +1020,17 @@ static int mv643xx_poll(struct net_device *dev, int *budget)
                mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
                mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
                mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
-                                               INT_UNMASK_ALL);
+                                               ETH_INT_UNMASK_ALL);
        }
 
        return done ? 0 : 1;
 }
 #endif
 
-/* Hardware can't handle unaligned fragments smaller than 9 bytes.
+/**
+ * has_tiny_unaligned_frags - check if skb has any small, unaligned fragments
+ *
+ * Hardware can't handle unaligned fragments smaller than 9 bytes.
  * This helper function detects that case.
  */
 
@@ -1061,223 +1047,166 @@ static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb)
        return 0;
 }
 
+/**
+ * eth_alloc_tx_desc_index - return the index of the next available tx desc
+ */
+static int eth_alloc_tx_desc_index(struct mv643xx_private *mp)
+{
+       int tx_desc_curr;
 
-/*
- * mv643xx_eth_start_xmit
- *
- * This function is queues a packet in the Tx descriptor for
- * required port.
- *
- * Input :     skb - a pointer to socket buffer
- *             dev - a pointer to the required port
+       BUG_ON(mp->tx_desc_count >= mp->tx_ring_size);
+
+       tx_desc_curr = mp->tx_curr_desc_q;
+       mp->tx_curr_desc_q = (tx_desc_curr + 1) % mp->tx_ring_size;
+
+       BUG_ON(mp->tx_curr_desc_q == mp->tx_used_desc_q);
+
+       return tx_desc_curr;
+}
+
+/**
+ * eth_tx_fill_frag_descs - fill tx hw descriptors for an skb's fragments.
  *
- * Output :    zero upon success
+ * Ensure the data for each fragment to be transmitted is mapped properly,
+ * then fill in descriptors in the tx hw queue.
  */
-static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static void eth_tx_fill_frag_descs(struct mv643xx_private *mp,
+                                  struct sk_buff *skb)
 {
-       struct mv643xx_private *mp = netdev_priv(dev);
-       struct net_device_stats *stats = &mp->stats;
-       ETH_FUNC_RET_STATUS status;
-       unsigned long flags;
-       struct pkt_info pkt_info;
+       int frag;
+       int tx_index;
+       struct eth_tx_desc *desc;
 
-       if (netif_queue_stopped(dev)) {
-               printk(KERN_ERR
-                       "%s: Tried sending packet when interface is stopped\n",
-                       dev->name);
-               return 1;
+       for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
+               skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
+
+               tx_index = eth_alloc_tx_desc_index(mp);
+               desc = &mp->p_tx_desc_area[tx_index];
+
+               desc->cmd_sts = ETH_BUFFER_OWNED_BY_DMA;
+               /* Last Frag enables interrupt and frees the skb */
+               if (frag == (skb_shinfo(skb)->nr_frags - 1)) {
+                       desc->cmd_sts |= ETH_ZERO_PADDING |
+                                        ETH_TX_LAST_DESC |
+                                        ETH_TX_ENABLE_INTERRUPT;
+                       mp->tx_skb[tx_index] = skb;
+               } else
+                       mp->tx_skb[tx_index] = 0;
+
+               desc = &mp->p_tx_desc_area[tx_index];
+               desc->l4i_chk = 0;
+               desc->byte_cnt = this_frag->size;
+               desc->buf_ptr = dma_map_page(NULL, this_frag->page,
+                                               this_frag->page_offset,
+                                               this_frag->size,
+                                               DMA_TO_DEVICE);
        }
+}
 
-       /* This is a hard error, log it. */
-       if ((mp->tx_ring_size - mp->tx_ring_skbs) <=
-                                       (skb_shinfo(skb)->nr_frags + 1)) {
-               netif_stop_queue(dev);
-               printk(KERN_ERR
-                       "%s: Bug in mv643xx_eth - Trying to transmit when"
-                       " queue full !\n", dev->name);
-               return 1;
-       }
+/**
+ * eth_tx_submit_descs_for_skb - submit data from an skb to the tx hw
+ *
+ * Ensure the data for an skb to be transmitted is mapped properly,
+ * then fill in descriptors in the tx hw queue and start the hardware.
+ */
+static void eth_tx_submit_descs_for_skb(struct mv643xx_private *mp,
+                                       struct sk_buff *skb)
+{
+       int tx_index;
+       struct eth_tx_desc *desc;
+       u32 cmd_sts;
+       int length;
+       int nr_frags = skb_shinfo(skb)->nr_frags;
 
-       /* Paranoid check - this shouldn't happen */
-       if (skb == NULL) {
-               stats->tx_dropped++;
-               printk(KERN_ERR "mv64320_eth paranoid check failed\n");
-               return 1;
-       }
+       cmd_sts = ETH_TX_FIRST_DESC | ETH_GEN_CRC | ETH_BUFFER_OWNED_BY_DMA;
 
-#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
-       if (has_tiny_unaligned_frags(skb)) {
-               if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
-                       stats->tx_dropped++;
-                       printk(KERN_DEBUG "%s: failed to linearize tiny "
-                                       "unaligned fragment\n", dev->name);
-                       return 1;
-               }
-       }
+       tx_index = eth_alloc_tx_desc_index(mp);
+       desc = &mp->p_tx_desc_area[tx_index];
 
-       spin_lock_irqsave(&mp->lock, flags);
+       if (nr_frags) {
+               eth_tx_fill_frag_descs(mp, skb);
 
-       if (!skb_shinfo(skb)->nr_frags) {
-               if (skb->ip_summed != CHECKSUM_HW) {
-                       /* Errata BTS #50, IHL must be 5 if no HW checksum */
-                       pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
-                                          ETH_TX_FIRST_DESC |
-                                          ETH_TX_LAST_DESC |
-                                          5 << ETH_TX_IHL_SHIFT;
-                       pkt_info.l4i_chk = 0;
-               } else {
-                       pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
-                                          ETH_TX_FIRST_DESC |
-                                          ETH_TX_LAST_DESC |
-                                          ETH_GEN_TCP_UDP_CHECKSUM |
-                                          ETH_GEN_IP_V_4_CHECKSUM |
-                                          skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
-                       /* CPU already calculated pseudo header checksum. */
-                       if ((skb->protocol == ETH_P_IP) &&
-                           (skb->nh.iph->protocol == IPPROTO_UDP) ) {
-                               pkt_info.cmd_sts |= ETH_UDP_FRAME;
-                               pkt_info.l4i_chk = skb->h.uh->check;
-                       } else if ((skb->protocol == ETH_P_IP) &&
-                                  (skb->nh.iph->protocol == IPPROTO_TCP))
-                               pkt_info.l4i_chk = skb->h.th->check;
-                       else {
-                               printk(KERN_ERR
-                                       "%s: chksum proto != IPv4 TCP or UDP\n",
-                                       dev->name);
-                               spin_unlock_irqrestore(&mp->lock, flags);
-                               return 1;
-                       }
-               }
-               pkt_info.byte_cnt = skb->len;
-               pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,
-                                                       DMA_TO_DEVICE);
-               pkt_info.return_info = skb;
-               status = eth_port_send(mp, &pkt_info);
-               if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
-                       printk(KERN_ERR "%s: Error on transmitting packet\n",
-                                                               dev->name);
-               stats->tx_bytes += pkt_info.byte_cnt;
+               length = skb_headlen(skb);
+               mp->tx_skb[tx_index] = 0;
        } else {
-               unsigned int frag;
+               cmd_sts |= ETH_ZERO_PADDING |
+                          ETH_TX_LAST_DESC |
+                          ETH_TX_ENABLE_INTERRUPT;
+               length = skb->len;
+               mp->tx_skb[tx_index] = skb;
+       }
 
-               /* first frag which is skb header */
-               pkt_info.byte_cnt = skb_headlen(skb);
-               pkt_info.buf_ptr = dma_map_single(NULL, skb->data,
-                                                       skb_headlen(skb),
-                                                       DMA_TO_DEVICE);
-               pkt_info.l4i_chk = 0;
-               pkt_info.return_info = 0;
-
-               if (skb->ip_summed != CHECKSUM_HW)
-                       /* Errata BTS #50, IHL must be 5 if no HW checksum */
-                       pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
-                                          5 << ETH_TX_IHL_SHIFT;
-               else {
-                       pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
-                                          ETH_GEN_TCP_UDP_CHECKSUM |
-                                          ETH_GEN_IP_V_4_CHECKSUM |
-                                          skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
-                       /* CPU already calculated pseudo header checksum. */
-                       if ((skb->protocol == ETH_P_IP) &&
-                           (skb->nh.iph->protocol == IPPROTO_UDP)) {
-                               pkt_info.cmd_sts |= ETH_UDP_FRAME;
-                               pkt_info.l4i_chk = skb->h.uh->check;
-                       } else if ((skb->protocol == ETH_P_IP) &&
-                                  (skb->nh.iph->protocol == IPPROTO_TCP))
-                               pkt_info.l4i_chk = skb->h.th->check;
-                       else {
-                               printk(KERN_ERR
-                                       "%s: chksum proto != IPv4 TCP or UDP\n",
-                                       dev->name);
-                               spin_unlock_irqrestore(&mp->lock, flags);
-                               return 1;
-                       }
-               }
+       desc->byte_cnt = length;
+       desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE);
 
-               status = eth_port_send(mp, &pkt_info);
-               if (status != ETH_OK) {
-                       if ((status == ETH_ERROR))
-                               printk(KERN_ERR
-                                       "%s: Error on transmitting packet\n",
-                                       dev->name);
-                       if (status == ETH_QUEUE_FULL)
-                               printk("Error on Queue Full \n");
-                       if (status == ETH_QUEUE_LAST_RESOURCE)
-                               printk("Tx resource error \n");
+       if (skb->ip_summed == CHECKSUM_HW) {
+               BUG_ON(skb->protocol != ETH_P_IP);
+
+               cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM |
+                          ETH_GEN_IP_V_4_CHECKSUM  |
+                          skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
+
+               switch (skb->nh.iph->protocol) {
+               case IPPROTO_UDP:
+                       cmd_sts |= ETH_UDP_FRAME;
+                       desc->l4i_chk = skb->h.uh->check;
+                       break;
+               case IPPROTO_TCP:
+                       desc->l4i_chk = skb->h.th->check;
+                       break;
+               default:
+                       BUG();
                }
-               stats->tx_bytes += pkt_info.byte_cnt;
-
-               /* Check for the remaining frags */
-               for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
-                       skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
-                       pkt_info.l4i_chk = 0x0000;
-                       pkt_info.cmd_sts = 0x00000000;
-
-                       /* Last Frag enables interrupt and frees the skb */
-                       if (frag == (skb_shinfo(skb)->nr_frags - 1)) {
-                               pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT |
-                                                       ETH_TX_LAST_DESC;
-                               pkt_info.return_info = skb;
-                       } else {
-                               pkt_info.return_info = 0;
-                       }
-                       pkt_info.l4i_chk = 0;
-                       pkt_info.byte_cnt = this_frag->size;
+       } else {
+               /* Errata BTS #50, IHL must be 5 if no HW checksum */
+               cmd_sts |= 5 << ETH_TX_IHL_SHIFT;
+               desc->l4i_chk = 0;
+       }
+
+       /* ensure all other descriptors are written before first cmd_sts */
+       wmb();
+       desc->cmd_sts = cmd_sts;
 
-                       pkt_info.buf_ptr = dma_map_page(NULL, this_frag->page,
-                                                       this_frag->page_offset,
-                                                       this_frag->size,
-                                                       DMA_TO_DEVICE);
+       /* ensure all descriptors are written before poking hardware */
+       wmb();
+       mv643xx_eth_port_enable_tx(mp->port_num, ETH_TX_QUEUES_ENABLED);
 
-                       status = eth_port_send(mp, &pkt_info);
+       mp->tx_desc_count += nr_frags + 1;
+}
 
-                       if (status != ETH_OK) {
-                               if ((status == ETH_ERROR))
-                                       printk(KERN_ERR "%s: Error on "
-                                                       "transmitting packet\n",
-                                                       dev->name);
+/**
+ * mv643xx_eth_start_xmit - queue an skb to the hardware for transmission
+ *
+ */
+static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct mv643xx_private *mp = netdev_priv(dev);
+       struct net_device_stats *stats = &mp->stats;
+       unsigned long flags;
 
-                               if (status == ETH_QUEUE_LAST_RESOURCE)
-                                       printk("Tx resource error \n");
+       BUG_ON(netif_queue_stopped(dev));
+       BUG_ON(skb == NULL);
+       BUG_ON(mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB);
 
-                               if (status == ETH_QUEUE_FULL)
-                                       printk("Queue is full \n");
-                       }
-                       stats->tx_bytes += pkt_info.byte_cnt;
+       if (has_tiny_unaligned_frags(skb)) {
+               if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
+                       stats->tx_dropped++;
+                       printk(KERN_DEBUG "%s: failed to linearize tiny "
+                                       "unaligned fragment\n", dev->name);
+                       return 1;
                }
        }
-#else
-       spin_lock_irqsave(&mp->lock, flags);
 
-       pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT | ETH_TX_FIRST_DESC |
-                                                       ETH_TX_LAST_DESC;
-       pkt_info.l4i_chk = 0;
-       pkt_info.byte_cnt = skb->len;
-       pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,
-                                                               DMA_TO_DEVICE);
-       pkt_info.return_info = skb;
-       status = eth_port_send(mp, &pkt_info);
-       if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
-               printk(KERN_ERR "%s: Error on transmitting packet\n",
-                                                               dev->name);
-       stats->tx_bytes += pkt_info.byte_cnt;
-#endif
-
-       /* Check if TX queue can handle another skb. If not, then
-        * signal higher layers to stop requesting TX
-        */
-       if (mp->tx_ring_size <= (mp->tx_ring_skbs + MAX_DESCS_PER_SKB))
-               /*
-                * Stop getting skb's from upper layers.
-                * Getting skb's from upper layers will be enabled again after
-                * packets are released.
-                */
-               netif_stop_queue(dev);
+       spin_lock_irqsave(&mp->lock, flags);
 
-       /* Update statistics and start of transmittion time */
+       eth_tx_submit_descs_for_skb(mp, skb);
+       stats->tx_bytes = skb->len;
        stats->tx_packets++;
        dev->trans_start = jiffies;
 
+       if (mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB)
+               netif_stop_queue(dev);
+
        spin_unlock_irqrestore(&mp->lock, flags);
 
        return 0;               /* success */
@@ -1306,16 +1235,45 @@ static void mv643xx_netpoll(struct net_device *netdev)
        struct mv643xx_private *mp = netdev_priv(netdev);
        int port_num = mp->port_num;
 
-       mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_MASK_ALL);
+       mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
        /* wait for previous write to complete */
        mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
 
        mv643xx_eth_int_handler(netdev->irq, netdev, NULL);
 
-       mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_UNMASK_ALL);
+       mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
 }
 #endif
 
+static void mv643xx_init_ethtool_cmd(struct net_device *dev, int phy_address,
+                                    int speed, int duplex,
+                                    struct ethtool_cmd *cmd)
+{
+       struct mv643xx_private *mp = netdev_priv(dev);
+
+       memset(cmd, 0, sizeof(*cmd));
+
+       cmd->port = PORT_MII;
+       cmd->transceiver = XCVR_INTERNAL;
+       cmd->phy_address = phy_address;
+
+       if (speed == 0) {
+               cmd->autoneg = AUTONEG_ENABLE;
+               /* mii lib checks, but doesn't use speed on AUTONEG_ENABLE */
+               cmd->speed = SPEED_100;
+               cmd->advertising = ADVERTISED_10baseT_Half  |
+                                  ADVERTISED_10baseT_Full  |
+                                  ADVERTISED_100baseT_Half |
+                                  ADVERTISED_100baseT_Full;
+               if (mp->mii.supports_gmii)
+                       cmd->advertising |= ADVERTISED_1000baseT_Full;
+       } else {
+               cmd->autoneg = AUTONEG_DISABLE;
+               cmd->speed = speed;
+               cmd->duplex = duplex;
+       }
+}
+
 /*/
  * mv643xx_eth_probe
  *
@@ -1336,6 +1294,9 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
        u8 *p;
        struct resource *res;
        int err;
+       struct ethtool_cmd cmd;
+       int duplex = DUPLEX_HALF;
+       int speed = 0;                  /* default to auto-negotiation */
 
        dev = alloc_etherdev(sizeof(struct mv643xx_private));
        if (!dev)
@@ -1373,6 +1334,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
        dev->tx_queue_len = mp->tx_ring_size;
        dev->base_addr = 0;
        dev->change_mtu = mv643xx_eth_change_mtu;
+       dev->do_ioctl = mv643xx_eth_do_ioctl;
        SET_ETHTOOL_OPS(dev, &mv643xx_ethtool_ops);
 
 #ifdef MV643XX_CHECKSUM_OFFLOAD_TX
@@ -1393,33 +1355,17 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
 
        /* set default config values */
        eth_port_uc_addr_get(dev, dev->dev_addr);
-       mp->port_config = MV643XX_ETH_PORT_CONFIG_DEFAULT_VALUE;
-       mp->port_config_extend = MV643XX_ETH_PORT_CONFIG_EXTEND_DEFAULT_VALUE;
-       mp->port_sdma_config = MV643XX_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE;
-       mp->port_serial_control = MV643XX_ETH_PORT_SERIAL_CONTROL_DEFAULT_VALUE;
        mp->rx_ring_size = MV643XX_ETH_PORT_DEFAULT_RECEIVE_QUEUE_SIZE;
        mp->tx_ring_size = MV643XX_ETH_PORT_DEFAULT_TRANSMIT_QUEUE_SIZE;
 
        pd = pdev->dev.platform_data;
        if (pd) {
-               if (pd->mac_addr != NULL)
+               if (pd->mac_addr)
                        memcpy(dev->dev_addr, pd->mac_addr, 6);
 
                if (pd->phy_addr || pd->force_phy_addr)
                        ethernet_phy_set(port_num, pd->phy_addr);
 
-               if (pd->port_config || pd->force_port_config)
-                       mp->port_config = pd->port_config;
-
-               if (pd->port_config_extend || pd->force_port_config_extend)
-                       mp->port_config_extend = pd->port_config_extend;
-
-               if (pd->port_sdma_config || pd->force_port_sdma_config)
-                       mp->port_sdma_config = pd->port_sdma_config;
-
-               if (pd->port_serial_control || pd->force_port_serial_control)
-                       mp->port_serial_control = pd->port_serial_control;
-
                if (pd->rx_queue_size)
                        mp->rx_ring_size = pd->rx_queue_size;
 
@@ -1435,16 +1381,33 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
                        mp->rx_sram_size = pd->rx_sram_size;
                        mp->rx_sram_addr = pd->rx_sram_addr;
                }
+
+               duplex = pd->duplex;
+               speed = pd->speed;
        }
 
+       /* Hook up MII support for ethtool */
+       mp->mii.dev = dev;
+       mp->mii.mdio_read = mv643xx_mdio_read;
+       mp->mii.mdio_write = mv643xx_mdio_write;
+       mp->mii.phy_id = ethernet_phy_get(port_num);
+       mp->mii.phy_id_mask = 0x3f;
+       mp->mii.reg_num_mask = 0x1f;
+
        err = ethernet_phy_detect(port_num);
        if (err) {
                pr_debug("MV643xx ethernet port %d: "
                                        "No PHY detected at addr %d\n",
                                        port_num, ethernet_phy_get(port_num));
-               return err;
+               goto out;
        }
 
+       ethernet_phy_reset(port_num);
+       mp->mii.supports_gmii = mii_check_gmii_support(&mp->mii);
+       mv643xx_init_ethtool_cmd(dev, mp->mii.phy_id, speed, duplex, &cmd);
+       mv643xx_eth_update_pscr(dev, &cmd);
+       mv643xx_set_settings(dev, &cmd);
+
        err = register_netdev(dev);
        if (err)
                goto out;
@@ -1689,26 +1652,9 @@ MODULE_DESCRIPTION("Ethernet driver for Marvell MV643XX");
  *             to the Rx descriptor ring to enable the reuse of this source.
  *             Return Rx resource is done using the eth_rx_return_buff API.
  *
- *             Transmit operation:
- *             The eth_port_send API supports Scatter-Gather which enables to
- *             send a packet spanned over multiple buffers. This means that
- *             for each packet info structure given by the user and put into
- *             the Tx descriptors ring, will be transmitted only if the 'LAST'
- *             bit will be set in the packet info command status field. This
- *             API also consider restriction regarding buffer alignments and
- *             sizes.
- *             The user must return a Tx resource after ensuring the buffer
- *             has been transmitted to enable the Tx ring indexes to update.
- *
- *             BOARD LAYOUT
- *             This device is on-board.  No jumper diagram is necessary.
- *
- *             EXTERNAL INTERFACE
- *
  *     Prior to calling the initialization routine eth_port_init() the user
  *     must set the following fields under mv643xx_private struct:
  *     port_num                User Ethernet port number.
- *     port_mac_addr[6]        User defined port MAC address.
  *     port_config             User port configuration value.
  *     port_config_extend      User port config extend value.
  *     port_sdma_config        User port SDMA config value.
@@ -1725,20 +1671,12 @@ MODULE_DESCRIPTION("Ethernet driver for Marvell MV643XX");
  *             return_info     Tx/Rx user resource return information.
  */
 
-/* defines */
-/* SDMA command macros */
-#define ETH_ENABLE_TX_QUEUE(eth_port) \
-       mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port), 1)
-
-/* locals */
-
 /* PHY routines */
 static int ethernet_phy_get(unsigned int eth_port_num);
 static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr);
 
 /* Ethernet Port routines */
-static int eth_port_uc_addr(unsigned int eth_port_num, unsigned char uc_nibble,
-                                                               int option);
+static void eth_port_set_filter_table_entry(int table, unsigned char entry);
 
 /*
  * eth_port_init - Initialize the Ethernet port driver
@@ -1766,17 +1704,11 @@ static int eth_port_uc_addr(unsigned int eth_port_num, unsigned char uc_nibble,
  */
 static void eth_port_init(struct mv643xx_private *mp)
 {
-       mp->port_rx_queue_command = 0;
-       mp->port_tx_queue_command = 0;
-
        mp->rx_resource_err = 0;
-       mp->tx_resource_err = 0;
 
        eth_port_reset(mp->port_num);
 
        eth_port_init_mac_tables(mp->port_num);
-
-       ethernet_phy_reset(mp->port_num);
 }
 
 /*
@@ -1798,7 +1730,7 @@ static void eth_port_init(struct mv643xx_private *mp)
  *     and ether_init_rx_desc_ring for Rx queues).
  *
  * INPUT:
- *     struct mv643xx_private *mp      Ethernet port control struct
+ *     dev - a pointer to the required interface
  *
  * OUTPUT:
  *     Ethernet port is ready to receive and transmit.
@@ -1806,10 +1738,13 @@ static void eth_port_init(struct mv643xx_private *mp)
  * RETURN:
  *     None.
  */
-static void eth_port_start(struct mv643xx_private *mp)
+static void eth_port_start(struct net_device *dev)
 {
+       struct mv643xx_private *mp = netdev_priv(dev);
        unsigned int port_num = mp->port_num;
        int tx_curr_desc, rx_curr_desc;
+       u32 pscr;
+       struct ethtool_cmd ethtool_cmd;
 
        /* Assignment of Tx CTRP of given queue */
        tx_curr_desc = mp->tx_curr_desc_q;
@@ -1822,37 +1757,45 @@ static void eth_port_start(struct mv643xx_private *mp)
                (u32)((struct eth_rx_desc *)mp->rx_desc_dma + rx_curr_desc));
 
        /* Add the assigned Ethernet address to the port's address table */
-       eth_port_uc_addr_set(port_num, mp->port_mac_addr);
+       eth_port_uc_addr_set(port_num, dev->dev_addr);
 
        /* Assign port configuration and command. */
-       mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num), mp->port_config);
+       mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num),
+                         MV643XX_ETH_PORT_CONFIG_DEFAULT_VALUE);
 
        mv_write(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port_num),
-                                               mp->port_config_extend);
+                         MV643XX_ETH_PORT_CONFIG_EXTEND_DEFAULT_VALUE);
 
+       pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num));
 
-       /* Increase the Rx side buffer size if supporting GigE */
-       if (mp->port_serial_control & MV643XX_ETH_SET_GMII_SPEED_TO_1000)
-               mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
-                       (mp->port_serial_control & 0xfff1ffff) | (0x5 << 17));
-       else
-               mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
-                                               mp->port_serial_control);
+       pscr &= ~(MV643XX_ETH_SERIAL_PORT_ENABLE | MV643XX_ETH_FORCE_LINK_PASS);
+       mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr);
+
+       pscr |= MV643XX_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL |
+               MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII    |
+               MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX     |
+               MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL         |
+               MV643XX_ETH_SERIAL_PORT_CONTROL_RESERVED;
 
-       mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
-               mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)) |
-                                               MV643XX_ETH_SERIAL_PORT_ENABLE);
+       mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr);
+
+       pscr |= MV643XX_ETH_SERIAL_PORT_ENABLE;
+       mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr);
 
        /* Assign port SDMA configuration */
        mv_write(MV643XX_ETH_SDMA_CONFIG_REG(port_num),
-                                                       mp->port_sdma_config);
+                         MV643XX_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE);
 
        /* Enable port Rx. */
-       mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
-                                               mp->port_rx_queue_command);
+       mv643xx_eth_port_enable_rx(port_num, ETH_RX_QUEUES_ENABLED);
 
        /* Disable port bandwidth limits by clearing MTU register */
        mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0);
+
+       /* save phy settings across reset */
+       mv643xx_get_settings(dev, &ethtool_cmd);
+       ethernet_phy_reset(mp->port_num);
+       mv643xx_set_settings(dev, &ethtool_cmd);
 }
 
 /*
@@ -1866,8 +1809,9 @@ static void eth_port_start(struct mv643xx_private *mp)
  *     char *          p_addr          Address to be set
  *
  * OUTPUT:
- *     Set MAC address low and high registers. also calls eth_port_uc_addr()
- *     To set the unicast table with the proper information.
+ *     Set MAC address low and high registers. also calls
+ *     eth_port_set_filter_table_entry() to set the unicast
+ *     table with the proper information.
  *
  * RETURN:
  *     N/A.
@@ -1878,6 +1822,7 @@ static void eth_port_uc_addr_set(unsigned int eth_port_num,
 {
        unsigned int mac_h;
        unsigned int mac_l;
+       int table;
 
        mac_l = (p_addr[4] << 8) | (p_addr[5]);
        mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) | (p_addr[2] << 8) |
@@ -1887,9 +1832,8 @@ static void eth_port_uc_addr_set(unsigned int eth_port_num,
        mv_write(MV643XX_ETH_MAC_ADDR_HIGH(eth_port_num), mac_h);
 
        /* Accept frames of this address */
-       eth_port_uc_addr(eth_port_num, p_addr[5], ACCEPT_MAC_ADDR);
-
-       return;
+       table = MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE(eth_port_num);
+       eth_port_set_filter_table_entry(table, p_addr[5] & 0x0f);
 }
 
 /*
@@ -1927,72 +1871,6 @@ static void eth_port_uc_addr_get(struct net_device *dev, unsigned char *p_addr)
        p_addr[5] = mac_l & 0xff;
 }
 
-/*
- * eth_port_uc_addr - This function Set the port unicast address table
- *
- * DESCRIPTION:
- *     This function locates the proper entry in the Unicast table for the
- *     specified MAC nibble and sets its properties according to function
- *     parameters.
- *
- * INPUT:
- *     unsigned int    eth_port_num    Port number.
- *     unsigned char   uc_nibble       Unicast MAC Address last nibble.
- *     int             option          0 = Add, 1 = remove address.
- *
- * OUTPUT:
- *     This function add/removes MAC addresses from the port unicast address
- *     table.
- *
- * RETURN:
- *     true is output succeeded.
- *     false if option parameter is invalid.
- *
- */
-static int eth_port_uc_addr(unsigned int eth_port_num, unsigned char uc_nibble,
-                                                               int option)
-{
-       unsigned int unicast_reg;
-       unsigned int tbl_offset;
-       unsigned int reg_offset;
-
-       /* Locate the Unicast table entry */
-       uc_nibble = (0xf & uc_nibble);
-       tbl_offset = (uc_nibble / 4) * 4;       /* Register offset from unicast table base */
-       reg_offset = uc_nibble % 4;     /* Entry offset within the above register */
-
-       switch (option) {
-       case REJECT_MAC_ADDR:
-               /* Clear accepts frame bit at given unicast DA table entry */
-               unicast_reg = mv_read((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
-                                               (eth_port_num) + tbl_offset));
-
-               unicast_reg &= (0x0E << (8 * reg_offset));
-
-               mv_write((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
-                               (eth_port_num) + tbl_offset), unicast_reg);
-               break;
-
-       case ACCEPT_MAC_ADDR:
-               /* Set accepts frame bit at unicast DA filter table entry */
-               unicast_reg =
-                       mv_read((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
-                                               (eth_port_num) + tbl_offset));
-
-               unicast_reg |= (0x01 << (8 * reg_offset));
-
-               mv_write((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
-                               (eth_port_num) + tbl_offset), unicast_reg);
-
-               break;
-
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
 /*
  * The entries in each table are indexed by a hash of a packet's MAC
  * address.  One bit in each entry determines whether the packet is
@@ -2205,8 +2083,8 @@ static void eth_port_init_mac_tables(unsigned int eth_port_num)
 
        /* Clear DA filter unicast table (Ex_dFUT) */
        for (table_index = 0; table_index <= 0xC; table_index += 4)
-               mv_write((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
-                                       (eth_port_num) + table_index), 0);
+               mv_write(MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
+                                       (eth_port_num) + table_index, 0);
 
        for (table_index = 0; table_index <= 0xFC; table_index += 4) {
                /* Clear DA filter special multicast table (Ex_dFSMT) */
@@ -2389,6 +2267,73 @@ static void ethernet_phy_reset(unsigned int eth_port_num)
        eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data);
        phy_reg_data |= 0x8000; /* Set bit 15 to reset the PHY */
        eth_port_write_smi_reg(eth_port_num, 0, phy_reg_data);
+
+       /* wait for PHY to come out of reset */
+       do {
+               udelay(1);
+               eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data);
+       } while (phy_reg_data & 0x8000);
+}
+
+static void mv643xx_eth_port_enable_tx(unsigned int port_num,
+                                       unsigned int queues)
+{
+       mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), queues);
+}
+
+static void mv643xx_eth_port_enable_rx(unsigned int port_num,
+                                       unsigned int queues)
+{
+       mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), queues);
+}
+
+static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num)
+{
+       u32 queues;
+
+       /* Stop Tx port activity. Check port Tx activity. */
+       queues = mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num))
+                                                       & 0xFF;
+       if (queues) {
+               /* Issue stop command for active queues only */
+               mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num),
+                                                       (queues << 8));
+
+               /* Wait for all Tx activity to terminate. */
+               /* Check port cause register that all Tx queues are stopped */
+               while (mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num))
+                                                       & 0xFF)
+                       udelay(PHY_WAIT_MICRO_SECONDS);
+
+               /* Wait for Tx FIFO to empty */
+               while (mv_read(MV643XX_ETH_PORT_STATUS_REG(port_num)) &
+                                                       ETH_PORT_TX_FIFO_EMPTY)
+                       udelay(PHY_WAIT_MICRO_SECONDS);
+       }
+
+       return queues;
+}
+
+static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num)
+{
+       u32 queues;
+
+       /* Stop Rx port activity. Check port Rx activity. */
+       queues = mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num))
+                                                       & 0xFF;
+       if (queues) {
+               /* Issue stop command for active queues only */
+               mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
+                                                       (queues << 8));
+
+               /* Wait for all Rx activity to terminate. */
+               /* Check port cause register that all Rx queues are stopped */
+               while (mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num))
+                                                       & 0xFF)
+                       udelay(PHY_WAIT_MICRO_SECONDS);
+       }
+
+       return queues;
 }
 
 /*
@@ -2413,70 +2358,21 @@ static void eth_port_reset(unsigned int port_num)
 {
        unsigned int reg_data;
 
-       /* Stop Tx port activity. Check port Tx activity. */
-       reg_data = mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num));
-
-       if (reg_data & 0xFF) {
-               /* Issue stop command for active channels only */
-               mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num),
-                                                       (reg_data << 8));
-
-               /* Wait for all Tx activity to terminate. */
-               /* Check port cause register that all Tx queues are stopped */
-               while (mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num))
-                                                                       & 0xFF)
-                       udelay(10);
-       }
-
-       /* Stop Rx port activity. Check port Rx activity. */
-       reg_data = mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num));
-
-       if (reg_data & 0xFF) {
-               /* Issue stop command for active channels only */
-               mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
-                                                       (reg_data << 8));
-
-               /* Wait for all Rx activity to terminate. */
-               /* Check port cause register that all Rx queues are stopped */
-               while (mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num))
-                                                                       & 0xFF)
-                       udelay(10);
-       }
+       mv643xx_eth_port_disable_tx(port_num);
+       mv643xx_eth_port_disable_rx(port_num);
 
        /* Clear all MIB counters */
        eth_clear_mib_counters(port_num);
 
        /* Reset the Enable bit in the Configuration Register */
        reg_data = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num));
-       reg_data &= ~MV643XX_ETH_SERIAL_PORT_ENABLE;
+       reg_data &= ~(MV643XX_ETH_SERIAL_PORT_ENABLE            |
+                       MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL      |
+                       MV643XX_ETH_FORCE_LINK_PASS);
        mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg_data);
 }
 
 
-static int eth_port_autoneg_supported(unsigned int eth_port_num)
-{
-       unsigned int phy_reg_data0;
-
-       eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data0);
-
-       return phy_reg_data0 & 0x1000;
-}
-
-static int eth_port_link_is_up(unsigned int eth_port_num)
-{
-       unsigned int phy_reg_data1;
-
-       eth_port_read_smi_reg(eth_port_num, 1, &phy_reg_data1);
-
-       if (eth_port_autoneg_supported(eth_port_num)) {
-               if (phy_reg_data1 & 0x20)       /* auto-neg complete */
-                       return 1;
-       } else if (phy_reg_data1 & 0x4)         /* link up */
-               return 1;
-
-       return 0;
-}
-
 /*
  * eth_port_read_smi_reg - Read PHY registers
  *
@@ -2582,250 +2478,21 @@ out:
 }
 
 /*
- * eth_port_send - Send an Ethernet packet
- *
- * DESCRIPTION:
- *     This routine send a given packet described by p_pktinfo parameter. It
- *     supports transmitting of a packet spaned over multiple buffers. The
- *     routine updates 'curr' and 'first' indexes according to the packet
- *     segment passed to the routine. In case the packet segment is first,
- *     the 'first' index is update. In any case, the 'curr' index is updated.
- *     If the routine get into Tx resource error it assigns 'curr' index as
- *     'first'. This way the function can abort Tx process of multiple
- *     descriptors per packet.
- *
- * INPUT:
- *     struct mv643xx_private  *mp             Ethernet Port Control srtuct.
- *     struct pkt_info         *p_pkt_info     User packet buffer.
- *
- * OUTPUT:
- *     Tx ring 'curr' and 'first' indexes are updated.
- *
- * RETURN:
- *     ETH_QUEUE_FULL in case of Tx resource error.
- *     ETH_ERROR in case the routine can not access Tx desc ring.
- *     ETH_QUEUE_LAST_RESOURCE if the routine uses the last Tx resource.
- *     ETH_OK otherwise.
- *
- */
-#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
-/*
- * Modified to include the first descriptor pointer in case of SG
+ * Wrappers for MII support library.
  */
-static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
-                                        struct pkt_info *p_pkt_info)
-{
-       int tx_desc_curr, tx_desc_used, tx_first_desc, tx_next_desc;
-       struct eth_tx_desc *current_descriptor;
-       struct eth_tx_desc *first_descriptor;
-       u32 command;
-
-       /* Do not process Tx ring in case of Tx ring resource error */
-       if (mp->tx_resource_err)
-               return ETH_QUEUE_FULL;
-
-       /*
-        * The hardware requires that each buffer that is <= 8 bytes
-        * in length must be aligned on an 8 byte boundary.
-        */
-       if (p_pkt_info->byte_cnt <= 8 && p_pkt_info->buf_ptr & 0x7) {
-               printk(KERN_ERR
-                       "mv643xx_eth port %d: packet size <= 8 problem\n",
-                       mp->port_num);
-               return ETH_ERROR;
-       }
-
-       mp->tx_ring_skbs++;
-       BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
-
-       /* Get the Tx Desc ring indexes */
-       tx_desc_curr = mp->tx_curr_desc_q;
-       tx_desc_used = mp->tx_used_desc_q;
-
-       current_descriptor = &mp->p_tx_desc_area[tx_desc_curr];
-
-       tx_next_desc = (tx_desc_curr + 1) % mp->tx_ring_size;
-
-       current_descriptor->buf_ptr = p_pkt_info->buf_ptr;
-       current_descriptor->byte_cnt = p_pkt_info->byte_cnt;
-       current_descriptor->l4i_chk = p_pkt_info->l4i_chk;
-       mp->tx_skb[tx_desc_curr] = p_pkt_info->return_info;
-
-       command = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC |
-                                                       ETH_BUFFER_OWNED_BY_DMA;
-       if (command & ETH_TX_FIRST_DESC) {
-               tx_first_desc = tx_desc_curr;
-               mp->tx_first_desc_q = tx_first_desc;
-               first_descriptor = current_descriptor;
-               mp->tx_first_command = command;
-       } else {
-               tx_first_desc = mp->tx_first_desc_q;
-               first_descriptor = &mp->p_tx_desc_area[tx_first_desc];
-               BUG_ON(first_descriptor == NULL);
-               current_descriptor->cmd_sts = command;
-       }
-
-       if (command & ETH_TX_LAST_DESC) {
-               wmb();
-               first_descriptor->cmd_sts = mp->tx_first_command;
-
-               wmb();
-               ETH_ENABLE_TX_QUEUE(mp->port_num);
-
-               /*
-                * Finish Tx packet. Update first desc in case of Tx resource
-                * error */
-               tx_first_desc = tx_next_desc;
-               mp->tx_first_desc_q = tx_first_desc;
-       }
-
-       /* Check for ring index overlap in the Tx desc ring */
-       if (tx_next_desc == tx_desc_used) {
-               mp->tx_resource_err = 1;
-               mp->tx_curr_desc_q = tx_first_desc;
-
-               return ETH_QUEUE_LAST_RESOURCE;
-       }
-
-       mp->tx_curr_desc_q = tx_next_desc;
-
-       return ETH_OK;
-}
-#else
-static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
-                                        struct pkt_info *p_pkt_info)
+static int mv643xx_mdio_read(struct net_device *dev, int phy_id, int location)
 {
-       int tx_desc_curr;
-       int tx_desc_used;
-       struct eth_tx_desc *current_descriptor;
-       unsigned int command_status;
-
-       /* Do not process Tx ring in case of Tx ring resource error */
-       if (mp->tx_resource_err)
-               return ETH_QUEUE_FULL;
-
-       mp->tx_ring_skbs++;
-       BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
-
-       /* Get the Tx Desc ring indexes */
-       tx_desc_curr = mp->tx_curr_desc_q;
-       tx_desc_used = mp->tx_used_desc_q;
-       current_descriptor = &mp->p_tx_desc_area[tx_desc_curr];
-
-       command_status = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC;
-       current_descriptor->buf_ptr = p_pkt_info->buf_ptr;
-       current_descriptor->byte_cnt = p_pkt_info->byte_cnt;
-       mp->tx_skb[tx_desc_curr] = p_pkt_info->return_info;
-
-       /* Set last desc with DMA ownership and interrupt enable. */
-       wmb();
-       current_descriptor->cmd_sts = command_status |
-                       ETH_BUFFER_OWNED_BY_DMA | ETH_TX_ENABLE_INTERRUPT;
-
-       wmb();
-       ETH_ENABLE_TX_QUEUE(mp->port_num);
-
-       /* Finish Tx packet. Update first desc in case of Tx resource error */
-       tx_desc_curr = (tx_desc_curr + 1) % mp->tx_ring_size;
-
-       /* Update the current descriptor */
-       mp->tx_curr_desc_q = tx_desc_curr;
-
-       /* Check for ring index overlap in the Tx desc ring */
-       if (tx_desc_curr == tx_desc_used) {
-               mp->tx_resource_err = 1;
-               return ETH_QUEUE_LAST_RESOURCE;
-       }
+       int val;
+       struct mv643xx_private *mp = netdev_priv(dev);
 
-       return ETH_OK;
+       eth_port_read_smi_reg(mp->port_num, location, &val);
+       return val;
 }
-#endif
 
-/*
- * eth_tx_return_desc - Free all used Tx descriptors
- *
- * DESCRIPTION:
- *     This routine returns the transmitted packet information to the caller.
- *     It uses the 'first' index to support Tx desc return in case a transmit
- *     of a packet spanned over multiple buffer still in process.
- *     In case the Tx queue was in "resource error" condition, where there are
- *     no available Tx resources, the function resets the resource error flag.
- *
- * INPUT:
- *     struct mv643xx_private  *mp             Ethernet Port Control srtuct.
- *     struct pkt_info         *p_pkt_info     User packet buffer.
- *
- * OUTPUT:
- *     Tx ring 'first' and 'used' indexes are updated.
- *
- * RETURN:
- *     ETH_OK on success
- *     ETH_ERROR otherwise.
- *
- */
-static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
-                                               struct pkt_info *p_pkt_info)
+static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, int val)
 {
-       int tx_desc_used;
-       int tx_busy_desc;
-       struct eth_tx_desc *p_tx_desc_used;
-       unsigned int command_status;
-       unsigned long flags;
-       int err = ETH_OK;
-
-       spin_lock_irqsave(&mp->lock, flags);
-
-#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
-       tx_busy_desc = mp->tx_first_desc_q;
-#else
-       tx_busy_desc = mp->tx_curr_desc_q;
-#endif
-
-       /* Get the Tx Desc ring indexes */
-       tx_desc_used = mp->tx_used_desc_q;
-
-       p_tx_desc_used = &mp->p_tx_desc_area[tx_desc_used];
-
-       /* Sanity check */
-       if (p_tx_desc_used == NULL) {
-               err = ETH_ERROR;
-               goto out;
-       }
-
-       /* Stop release. About to overlap the current available Tx descriptor */
-       if (tx_desc_used == tx_busy_desc && !mp->tx_resource_err) {
-               err = ETH_ERROR;
-               goto out;
-       }
-
-       command_status = p_tx_desc_used->cmd_sts;
-
-       /* Still transmitting... */
-       if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) {
-               err = ETH_ERROR;
-               goto out;
-       }
-
-       /* Pass the packet information to the caller */
-       p_pkt_info->cmd_sts = command_status;
-       p_pkt_info->return_info = mp->tx_skb[tx_desc_used];
-       p_pkt_info->buf_ptr = p_tx_desc_used->buf_ptr;
-       p_pkt_info->byte_cnt = p_tx_desc_used->byte_cnt;
-       mp->tx_skb[tx_desc_used] = NULL;
-
-       /* Update the next descriptor to release. */
-       mp->tx_used_desc_q = (tx_desc_used + 1) % mp->tx_ring_size;
-
-       /* Any Tx return cancels the Tx resource error status */
-       mp->tx_resource_err = 0;
-
-       BUG_ON(mp->tx_ring_skbs == 0);
-       mp->tx_ring_skbs--;
-
-out:
-       spin_unlock_irqrestore(&mp->lock, flags);
-
-       return err;
+       struct mv643xx_private *mp = netdev_priv(dev);
+       eth_port_write_smi_reg(mp->port_num, location, val);
 }
 
 /*
@@ -3017,111 +2684,6 @@ static const struct mv643xx_stats mv643xx_gstrings_stats[] = {
 #define MV643XX_STATS_LEN      \
        sizeof(mv643xx_gstrings_stats) / sizeof(struct mv643xx_stats)
 
-static int
-mv643xx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
-{
-       struct mv643xx_private *mp = netdev->priv;
-       int port_num = mp->port_num;
-       int autoneg = eth_port_autoneg_supported(port_num);
-       int mode_10_bit;
-       int auto_duplex;
-       int half_duplex = 0;
-       int full_duplex = 0;
-       int auto_speed;
-       int speed_10 = 0;
-       int speed_100 = 0;
-       int speed_1000 = 0;
-
-       u32 pcs = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num));
-       u32 psr = mv_read(MV643XX_ETH_PORT_STATUS_REG(port_num));
-
-       mode_10_bit = psr & MV643XX_ETH_PORT_STATUS_MODE_10_BIT;
-
-       if (mode_10_bit) {
-               ecmd->supported = SUPPORTED_10baseT_Half;
-       } else {
-               ecmd->supported = (SUPPORTED_10baseT_Half               |
-                                  SUPPORTED_10baseT_Full               |
-                                  SUPPORTED_100baseT_Half              |
-                                  SUPPORTED_100baseT_Full              |
-                                  SUPPORTED_1000baseT_Full             |
-                                  (autoneg ? SUPPORTED_Autoneg : 0)    |
-                                  SUPPORTED_TP);
-
-               auto_duplex = !(pcs & MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX);
-               auto_speed = !(pcs & MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII);
-
-               ecmd->advertising = ADVERTISED_TP;
-
-               if (autoneg) {
-                       ecmd->advertising |= ADVERTISED_Autoneg;
-
-                       if (auto_duplex) {
-                               half_duplex = 1;
-                               full_duplex = 1;
-                       } else {
-                               if (pcs & MV643XX_ETH_SET_FULL_DUPLEX_MODE)
-                                       full_duplex = 1;
-                               else
-                                       half_duplex = 1;
-                       }
-
-                       if (auto_speed) {
-                               speed_10 = 1;
-                               speed_100 = 1;
-                               speed_1000 = 1;
-                       } else {
-                               if (pcs & MV643XX_ETH_SET_GMII_SPEED_TO_1000)
-                                       speed_1000 = 1;
-                               else if (pcs & MV643XX_ETH_SET_MII_SPEED_TO_100)
-                                       speed_100 = 1;
-                               else
-                                       speed_10 = 1;
-                       }
-
-                       if (speed_10 & half_duplex)
-                               ecmd->advertising |= ADVERTISED_10baseT_Half;
-                       if (speed_10 & full_duplex)
-                               ecmd->advertising |= ADVERTISED_10baseT_Full;
-                       if (speed_100 & half_duplex)
-                               ecmd->advertising |= ADVERTISED_100baseT_Half;
-                       if (speed_100 & full_duplex)
-                               ecmd->advertising |= ADVERTISED_100baseT_Full;
-                       if (speed_1000)
-                               ecmd->advertising |= ADVERTISED_1000baseT_Full;
-               }
-       }
-
-       ecmd->port = PORT_TP;
-       ecmd->phy_address = ethernet_phy_get(port_num);
-
-       ecmd->transceiver = XCVR_EXTERNAL;
-
-       if (netif_carrier_ok(netdev)) {
-               if (mode_10_bit)
-                       ecmd->speed = SPEED_10;
-               else {
-                       if (psr & MV643XX_ETH_PORT_STATUS_GMII_1000)
-                               ecmd->speed = SPEED_1000;
-                       else if (psr & MV643XX_ETH_PORT_STATUS_MII_100)
-                               ecmd->speed = SPEED_100;
-                       else
-                               ecmd->speed = SPEED_10;
-               }
-
-               if (psr & MV643XX_ETH_PORT_STATUS_FULL_DUPLEX)
-                       ecmd->duplex = DUPLEX_FULL;
-               else
-                       ecmd->duplex = DUPLEX_HALF;
-       } else {
-               ecmd->speed = -1;
-               ecmd->duplex = -1;
-       }
-
-       ecmd->autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
-       return 0;
-}
-
 static void mv643xx_get_drvinfo(struct net_device *netdev,
                                struct ethtool_drvinfo *drvinfo)
 {
@@ -3168,15 +2730,41 @@ static void mv643xx_get_strings(struct net_device *netdev, uint32_t stringset,
        }
 }
 
+static u32 mv643xx_eth_get_link(struct net_device *dev)
+{
+       struct mv643xx_private *mp = netdev_priv(dev);
+
+       return mii_link_ok(&mp->mii);
+}
+
+static int mv643xx_eth_nway_restart(struct net_device *dev)
+{
+       struct mv643xx_private *mp = netdev_priv(dev);
+
+       return mii_nway_restart(&mp->mii);
+}
+
+static int mv643xx_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+       struct mv643xx_private *mp = netdev_priv(dev);
+
+       return generic_mii_ioctl(&mp->mii, if_mii(ifr), cmd, NULL);
+}
+
 static struct ethtool_ops mv643xx_ethtool_ops = {
        .get_settings           = mv643xx_get_settings,
+       .set_settings           = mv643xx_set_settings,
        .get_drvinfo            = mv643xx_get_drvinfo,
-       .get_link               = ethtool_op_get_link,
+       .get_link               = mv643xx_eth_get_link,
        .get_sg                 = ethtool_op_get_sg,
        .set_sg                 = ethtool_op_set_sg,
        .get_strings            = mv643xx_get_strings,
        .get_stats_count        = mv643xx_get_stats_count,
        .get_ethtool_stats      = mv643xx_get_ethtool_stats,
+       .get_strings            = mv643xx_get_strings,
+       .get_stats_count        = mv643xx_get_stats_count,
+       .get_ethtool_stats      = mv643xx_get_ethtool_stats,
+       .nway_reset             = mv643xx_eth_nway_restart,
 };
 
 /************* End ethtool support *************************/
index f769f9b..7754d19 100644 (file)
@@ -5,53 +5,16 @@
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
+#include <linux/mii.h>
 
 #include <linux/mv643xx.h>
 
-#define        BIT0    0x00000001
-#define        BIT1    0x00000002
-#define        BIT2    0x00000004
-#define        BIT3    0x00000008
-#define        BIT4    0x00000010
-#define        BIT5    0x00000020
-#define        BIT6    0x00000040
-#define        BIT7    0x00000080
-#define        BIT8    0x00000100
-#define        BIT9    0x00000200
-#define        BIT10   0x00000400
-#define        BIT11   0x00000800
-#define        BIT12   0x00001000
-#define        BIT13   0x00002000
-#define        BIT14   0x00004000
-#define        BIT15   0x00008000
-#define        BIT16   0x00010000
-#define        BIT17   0x00020000
-#define        BIT18   0x00040000
-#define        BIT19   0x00080000
-#define        BIT20   0x00100000
-#define        BIT21   0x00200000
-#define        BIT22   0x00400000
-#define        BIT23   0x00800000
-#define        BIT24   0x01000000
-#define        BIT25   0x02000000
-#define        BIT26   0x04000000
-#define        BIT27   0x08000000
-#define        BIT28   0x10000000
-#define        BIT29   0x20000000
-#define        BIT30   0x40000000
-#define        BIT31   0x80000000
-
-/*
- *  The first part is the high level driver of the gigE ethernet ports.
- */
-
 /* Checksum offload for Tx works for most packets, but
  * fails if previous packet sent did not use hw csum
  */
 #define        MV643XX_CHECKSUM_OFFLOAD_TX
 #define        MV643XX_NAPI
 #define        MV643XX_TX_FAST_REFILL
-#undef MV643XX_RX_QUEUE_FILL_ON_TASK   /* Does not work, yet */
 #undef MV643XX_COAL
 
 /*
 #define MV643XX_RX_COAL 100
 #endif
 
-/*
- * The second part is the low level driver of the gigE ethernet ports.
- */
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+#define MAX_DESCS_PER_SKB      (MAX_SKB_FRAGS + 1)
+#else
+#define MAX_DESCS_PER_SKB      1
+#endif
 
-/*
- * Header File for : MV-643xx network interface header
- *
- * DESCRIPTION:
- *     This header file contains macros typedefs and function declaration for
- *     the Marvell Gig Bit Ethernet Controller.
- *
- * DEPENDENCIES:
- *     None.
- *
- */
+#define ETH_VLAN_HLEN          4
+#define ETH_FCS_LEN            4
+#define ETH_DMA_ALIGN          8       /* hw requires 8-byte alignment */
+#define ETH_HW_IP_ALIGN                2       /* hw aligns IP header */
+#define ETH_WRAPPER_LEN                (ETH_HW_IP_ALIGN + ETH_HLEN + \
+                               ETH_VLAN_HLEN + ETH_FCS_LEN)
+#define ETH_RX_SKB_SIZE                ((dev->mtu + ETH_WRAPPER_LEN + 7) & ~0x7)
+
+#define ETH_RX_QUEUES_ENABLED  (1 << 0)        /* use only Q0 for receive */
+#define ETH_TX_QUEUES_ENABLED  (1 << 0)        /* use only Q0 for transmit */
+
+#define ETH_INT_CAUSE_RX_DONE  (ETH_RX_QUEUES_ENABLED << 2)
+#define ETH_INT_CAUSE_RX_ERROR (ETH_RX_QUEUES_ENABLED << 9)
+#define ETH_INT_CAUSE_RX       (ETH_INT_CAUSE_RX_DONE | ETH_INT_CAUSE_RX_ERROR)
+#define ETH_INT_CAUSE_EXT      0x00000002
+#define ETH_INT_UNMASK_ALL     (ETH_INT_CAUSE_RX | ETH_INT_CAUSE_EXT)
 
-/* MAC accepet/reject macros */
-#define ACCEPT_MAC_ADDR                                0
-#define REJECT_MAC_ADDR                                1
+#define ETH_INT_CAUSE_TX_DONE  (ETH_TX_QUEUES_ENABLED << 0)
+#define ETH_INT_CAUSE_TX_ERROR (ETH_TX_QUEUES_ENABLED << 8)
+#define ETH_INT_CAUSE_TX       (ETH_INT_CAUSE_TX_DONE | ETH_INT_CAUSE_TX_ERROR)
+#define ETH_INT_CAUSE_PHY      0x00010000
+#define ETH_INT_UNMASK_ALL_EXT (ETH_INT_CAUSE_TX | ETH_INT_CAUSE_PHY)
+
+#define ETH_INT_MASK_ALL       0x00000000
+#define ETH_INT_MASK_ALL_EXT   0x00000000
+
+#define PHY_WAIT_ITERATIONS    1000    /* 1000 iterations * 10uS = 10mS max */
+#define PHY_WAIT_MICRO_SECONDS 10
 
 /* Buffer offset from buffer pointer */
 #define RX_BUF_OFFSET                          0x2
 #define ETH_MIB_LATE_COLLISION                 0x7c
 
 /* Port serial status reg (PSR) */
-#define ETH_INTERFACE_GMII_MII                 0
-#define ETH_INTERFACE_PCM                      BIT0
-#define ETH_LINK_IS_DOWN                       0
-#define ETH_LINK_IS_UP                         BIT1
-#define ETH_PORT_AT_HALF_DUPLEX                        0
-#define ETH_PORT_AT_FULL_DUPLEX                        BIT2
-#define ETH_RX_FLOW_CTRL_DISABLED              0
-#define ETH_RX_FLOW_CTRL_ENBALED               BIT3
-#define ETH_GMII_SPEED_100_10                  0
-#define ETH_GMII_SPEED_1000                    BIT4
-#define ETH_MII_SPEED_10                       0
-#define ETH_MII_SPEED_100                      BIT5
-#define ETH_NO_TX                              0
-#define ETH_TX_IN_PROGRESS                     BIT7
-#define ETH_BYPASS_NO_ACTIVE                   0
-#define ETH_BYPASS_ACTIVE                      BIT8
-#define ETH_PORT_NOT_AT_PARTITION_STATE                0
-#define ETH_PORT_AT_PARTITION_STATE            BIT9
-#define ETH_PORT_TX_FIFO_NOT_EMPTY             0
-#define ETH_PORT_TX_FIFO_EMPTY                 BIT10
-
-#define ETH_DEFAULT_RX_BPDU_QUEUE_3            (BIT23 | BIT22)
-#define ETH_DEFAULT_RX_BPDU_QUEUE_4            BIT24
-#define ETH_DEFAULT_RX_BPDU_QUEUE_5            (BIT24 | BIT22)
-#define ETH_DEFAULT_RX_BPDU_QUEUE_6            (BIT24 | BIT23)
-#define ETH_DEFAULT_RX_BPDU_QUEUE_7            (BIT24 | BIT23 | BIT22)
+#define ETH_INTERFACE_PCM                      0x00000001
+#define ETH_LINK_IS_UP                         0x00000002
+#define ETH_PORT_AT_FULL_DUPLEX                        0x00000004
+#define ETH_RX_FLOW_CTRL_ENABLED               0x00000008
+#define ETH_GMII_SPEED_1000                    0x00000010
+#define ETH_MII_SPEED_100                      0x00000020
+#define ETH_TX_IN_PROGRESS                     0x00000080
+#define ETH_BYPASS_ACTIVE                      0x00000100
+#define ETH_PORT_AT_PARTITION_STATE            0x00000200
+#define ETH_PORT_TX_FIFO_EMPTY                 0x00000400
 
 /* SMI reg */
-#define ETH_SMI_BUSY           BIT28   /* 0 - Write, 1 - Read          */
-#define ETH_SMI_READ_VALID     BIT27   /* 0 - Write, 1 - Read          */
-#define ETH_SMI_OPCODE_WRITE   0       /* Completion of Read operation */
-#define ETH_SMI_OPCODE_READ    BIT26   /* Operation is in progress     */
+#define ETH_SMI_BUSY           0x10000000      /* 0 - Write, 1 - Read  */
+#define ETH_SMI_READ_VALID     0x08000000      /* 0 - Write, 1 - Read  */
+#define ETH_SMI_OPCODE_WRITE   0               /* Completion of Read   */
+#define ETH_SMI_OPCODE_READ    0x04000000      /* Operation is in progress */
+
+/* Interrupt Cause Register Bit Definitions */
 
 /* SDMA command status fields macros */
 
 /* Tx & Rx descriptors status */
-#define ETH_ERROR_SUMMARY                      (BIT0)
+#define ETH_ERROR_SUMMARY                      0x00000001
 
 /* Tx & Rx descriptors command */
-#define ETH_BUFFER_OWNED_BY_DMA                        (BIT31)
+#define ETH_BUFFER_OWNED_BY_DMA                        0x80000000
 
 /* Tx descriptors status */
-#define ETH_LC_ERROR                           (0    )
-#define ETH_UR_ERROR                           (BIT1 )
-#define ETH_RL_ERROR                           (BIT2 )
-#define ETH_LLC_SNAP_FORMAT                    (BIT9 )
+#define ETH_LC_ERROR                           0
+#define ETH_UR_ERROR                           0x00000002
+#define ETH_RL_ERROR                           0x00000004
+#define ETH_LLC_SNAP_FORMAT                    0x00000200
 
 /* Rx descriptors status */
-#define ETH_CRC_ERROR                          (0    )
-#define ETH_OVERRUN_ERROR                      (BIT1 )
-#define ETH_MAX_FRAME_LENGTH_ERROR             (BIT2 )
-#define ETH_RESOURCE_ERROR                     ((BIT2 | BIT1))
-#define ETH_VLAN_TAGGED                                (BIT19)
-#define ETH_BPDU_FRAME                         (BIT20)
-#define ETH_TCP_FRAME_OVER_IP_V_4              (0    )
-#define ETH_UDP_FRAME_OVER_IP_V_4              (BIT21)
-#define ETH_OTHER_FRAME_TYPE                   (BIT22)
-#define ETH_LAYER_2_IS_ETH_V_2                 (BIT23)
-#define ETH_FRAME_TYPE_IP_V_4                  (BIT24)
-#define ETH_FRAME_HEADER_OK                    (BIT25)
-#define ETH_RX_LAST_DESC                       (BIT26)
-#define ETH_RX_FIRST_DESC                      (BIT27)
-#define ETH_UNKNOWN_DESTINATION_ADDR           (BIT28)
-#define ETH_RX_ENABLE_INTERRUPT                        (BIT29)
-#define ETH_LAYER_4_CHECKSUM_OK                        (BIT30)
+#define ETH_OVERRUN_ERROR                      0x00000002
+#define ETH_MAX_FRAME_LENGTH_ERROR             0x00000004
+#define ETH_RESOURCE_ERROR                     0x00000006
+#define ETH_VLAN_TAGGED                                0x00080000
+#define ETH_BPDU_FRAME                         0x00100000
+#define ETH_UDP_FRAME_OVER_IP_V_4              0x00200000
+#define ETH_OTHER_FRAME_TYPE                   0x00400000
+#define ETH_LAYER_2_IS_ETH_V_2                 0x00800000
+#define ETH_FRAME_TYPE_IP_V_4                  0x01000000
+#define ETH_FRAME_HEADER_OK                    0x02000000
+#define ETH_RX_LAST_DESC                       0x04000000
+#define ETH_RX_FIRST_DESC                      0x08000000
+#define ETH_UNKNOWN_DESTINATION_ADDR           0x10000000
+#define ETH_RX_ENABLE_INTERRUPT                        0x20000000
+#define ETH_LAYER_4_CHECKSUM_OK                        0x40000000
 
 /* Rx descriptors byte count */
-#define ETH_FRAME_FRAGMENTED                   (BIT2)
+#define ETH_FRAME_FRAGMENTED                   0x00000004
 
 /* Tx descriptors command */
-#define ETH_LAYER_4_CHECKSUM_FIRST_DESC                (BIT10)
-#define ETH_FRAME_SET_TO_VLAN                  (BIT15)
-#define ETH_TCP_FRAME                          (0    )
-#define ETH_UDP_FRAME                          (BIT16)
-#define ETH_GEN_TCP_UDP_CHECKSUM               (BIT17)
-#define ETH_GEN_IP_V_4_CHECKSUM                        (BIT18)
-#define ETH_ZERO_PADDING                       (BIT19)
-#define ETH_TX_LAST_DESC                       (BIT20)
-#define ETH_TX_FIRST_DESC                      (BIT21)
-#define ETH_GEN_CRC                            (BIT22)
-#define ETH_TX_ENABLE_INTERRUPT                        (BIT23)
-#define ETH_AUTO_MODE                          (BIT30)
+#define ETH_LAYER_4_CHECKSUM_FIRST_DESC                0x00000400
+#define ETH_FRAME_SET_TO_VLAN                  0x00008000
+#define ETH_UDP_FRAME                          0x00010000
+#define ETH_GEN_TCP_UDP_CHECKSUM               0x00020000
+#define ETH_GEN_IP_V_4_CHECKSUM                        0x00040000
+#define ETH_ZERO_PADDING                       0x00080000
+#define ETH_TX_LAST_DESC                       0x00100000
+#define ETH_TX_FIRST_DESC                      0x00200000
+#define ETH_GEN_CRC                            0x00400000
+#define ETH_TX_ENABLE_INTERRUPT                        0x00800000
+#define ETH_AUTO_MODE                          0x40000000
 
 #define ETH_TX_IHL_SHIFT                       11
 
@@ -324,13 +285,6 @@ struct mv643xx_mib_counters {
 
 struct mv643xx_private {
        int port_num;                   /* User Ethernet port number    */
-       u8 port_mac_addr[6];            /* User defined port MAC address.*/
-       u32 port_config;                /* User port configuration value*/
-       u32 port_config_extend;         /* User port config extend value*/
-       u32 port_sdma_config;           /* User port SDMA config value  */
-       u32 port_serial_control;        /* User port serial control value */
-       u32 port_tx_queue_command;      /* Port active Tx queues summary*/
-       u32 port_rx_queue_command;      /* Port active Rx queues summary*/
 
        u32 rx_sram_addr;               /* Base address of rx sram area */
        u32 rx_sram_size;               /* Size of rx sram area         */
@@ -338,7 +292,6 @@ struct mv643xx_private {
        u32 tx_sram_size;               /* Size of tx sram area         */
 
        int rx_resource_err;            /* Rx ring resource error flag */
-       int tx_resource_err;            /* Tx ring resource error flag */
 
        /* Tx/Rx rings managment indexes fields. For driver use */
 
@@ -347,10 +300,6 @@ struct mv643xx_private {
 
        /* Next available and first returning Tx resource */
        int tx_curr_desc_q, tx_used_desc_q;
-#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
-       int tx_first_desc_q;
-       u32 tx_first_command;
-#endif
 
 #ifdef MV643XX_TX_FAST_REFILL
        u32 tx_clean_threshold;
@@ -358,54 +307,43 @@ struct mv643xx_private {
 
        struct eth_rx_desc *p_rx_desc_area;
        dma_addr_t rx_desc_dma;
-       unsigned int rx_desc_area_size;
+       int rx_desc_area_size;
        struct sk_buff **rx_skb;
 
        struct eth_tx_desc *p_tx_desc_area;
        dma_addr_t tx_desc_dma;
-       unsigned int tx_desc_area_size;
+       int tx_desc_area_size;
        struct sk_buff **tx_skb;
 
        struct work_struct tx_timeout_task;
 
-       /*
-        * Former struct mv643xx_eth_priv members start here
-        */
        struct net_device_stats stats;
        struct mv643xx_mib_counters mib_counters;
        spinlock_t lock;
        /* Size of Tx Ring per queue */
-       unsigned int tx_ring_size;
-       /* Ammont of SKBs outstanding on Tx queue */
-       unsigned int tx_ring_skbs;
+       int tx_ring_size;
+       /* Number of tx descriptors in use */
+       int tx_desc_count;
        /* Size of Rx Ring per queue */
-       unsigned int rx_ring_size;
-       /* Ammount of SKBs allocated to Rx Ring per queue */
-       unsigned int rx_ring_skbs;
-
-       /*
-        * rx_task used to fill RX ring out of bottom half context
-        */
-       struct work_struct rx_task;
+       int rx_ring_size;
+       /* Number of rx descriptors in use */
+       int rx_desc_count;
 
        /*
         * Used in case RX Ring is empty, which can be caused when
         * system does not have resources (skb's)
         */
        struct timer_list timeout;
-       long rx_task_busy __attribute__ ((aligned(SMP_CACHE_BYTES)));
-       unsigned rx_timer_flag;
 
        u32 rx_int_coal;
        u32 tx_int_coal;
+       struct mii_if_info mii;
 };
 
-/* ethernet.h API list */
-
 /* Port operation control routines */
 static void eth_port_init(struct mv643xx_private *mp);
 static void eth_port_reset(unsigned int eth_port_num);
-static void eth_port_start(struct mv643xx_private *mp);
+static void eth_port_start(struct net_device *dev);
 
 /* Port MAC address routines */
 static void eth_port_uc_addr_set(unsigned int eth_port_num,
@@ -423,10 +361,6 @@ static void eth_port_read_smi_reg(unsigned int eth_port_num,
 static void eth_clear_mib_counters(unsigned int eth_port_num);
 
 /* Port data flow control routines */
-static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
-                                        struct pkt_info *p_pkt_info);
-static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
-                                             struct pkt_info *p_pkt_info);
 static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
                                            struct pkt_info *p_pkt_info);
 static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
index 9d6d254..8d49998 100644 (file)
@@ -3,6 +3,7 @@
        Written/copyright 1999-2001 by Donald Becker.
        Portions copyright (c) 2001,2002 Sun Microsystems (thockin@sun.com)
        Portions copyright 2001,2002 Manfred Spraul (manfred@colorfullife.com)
+       Portions copyright 2004 Harald Welte <laforge@gnumonks.org>
 
        This software may be used and distributed according to the terms of
        the GNU General Public License (GPL), incorporated herein by reference.
 
        TODO:
        * big endian support with CFG:BEM instead of cpu_to_le32
-       * support for an external PHY
-       * NAPI
 */
 
 #include <linux/config.h>
 #include <linux/mii.h>
 #include <linux/crc32.h>
 #include <linux/bitops.h>
+#include <linux/prefetch.h>
 #include <asm/processor.h>     /* Processor type for cache alignment. */
 #include <asm/io.h>
 #include <asm/irq.h>
                                 NETIF_MSG_TX_ERR)
 static int debug = -1;
 
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 20;
 static int mtu;
 
 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
    This chip uses a 512 element hash table based on the Ethernet CRC.  */
-static int multicast_filter_limit = 100;
+static const int multicast_filter_limit = 100;
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
    Setting to > 1518 effectively disables this feature. */
@@ -251,14 +249,11 @@ MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("National Semiconductor DP8381x series PCI Ethernet driver");
 MODULE_LICENSE("GPL");
 
-module_param(max_interrupt_work, int, 0);
 module_param(mtu, int, 0);
 module_param(debug, int, 0);
 module_param(rx_copybreak, int, 0);
 module_param_array(options, int, NULL, 0);
 module_param_array(full_duplex, int, NULL, 0);
-MODULE_PARM_DESC(max_interrupt_work, 
-       "DP8381x maximum events handled per interrupt");
 MODULE_PARM_DESC(mtu, "DP8381x MTU (all boards)");
 MODULE_PARM_DESC(debug, "DP8381x default debug level");
 MODULE_PARM_DESC(rx_copybreak, 
@@ -374,7 +369,7 @@ enum pcistuff {
 
  
 /* array of board data directly indexed by pci_tbl[x].driver_data */
-static struct {
+static const struct {
        const char *name;
        unsigned long flags;
 } natsemi_pci_info[] __devinitdata = {
@@ -691,6 +686,8 @@ struct netdev_private {
        /* Based on MTU+slack. */
        unsigned int rx_buf_sz;
        int oom;
+       /* Interrupt status */
+       u32 intr_status;
        /* Do not touch the nic registers */
        int hands_off;
        /* external phy that is used: only valid if dev->if_port != PORT_TP */
@@ -748,7 +745,8 @@ static void init_registers(struct net_device *dev);
 static int start_tx(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
 static void netdev_error(struct net_device *dev, int intr_status);
-static void netdev_rx(struct net_device *dev);
+static int natsemi_poll(struct net_device *dev, int *budget);
+static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do);
 static void netdev_tx_done(struct net_device *dev);
 static int natsemi_change_mtu(struct net_device *dev, int new_mtu);
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -776,6 +774,18 @@ static inline void __iomem *ns_ioaddr(struct net_device *dev)
        return (void __iomem *) dev->base_addr;
 }
 
+static inline void natsemi_irq_enable(struct net_device *dev)
+{
+       writel(1, ns_ioaddr(dev) + IntrEnable);
+       readl(ns_ioaddr(dev) + IntrEnable);
+}
+
+static inline void natsemi_irq_disable(struct net_device *dev)
+{
+       writel(0, ns_ioaddr(dev) + IntrEnable);
+       readl(ns_ioaddr(dev) + IntrEnable);
+}
+
 static void move_int_phy(struct net_device *dev, int addr)
 {
        struct netdev_private *np = netdev_priv(dev);
@@ -879,6 +889,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
        spin_lock_init(&np->lock);
        np->msg_enable = (debug >= 0) ? (1<<debug)-1 : NATSEMI_DEF_MSG;
        np->hands_off = 0;
+       np->intr_status = 0;
 
        /* Initial port:
         * - If the nic was configured to use an external phy and if find_mii
@@ -932,6 +943,9 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
        dev->do_ioctl = &netdev_ioctl;
        dev->tx_timeout = &tx_timeout;
        dev->watchdog_timeo = TX_TIMEOUT;
+       dev->poll = natsemi_poll;
+       dev->weight = 64;
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
        dev->poll_controller = &natsemi_poll_controller;
 #endif
@@ -1484,6 +1498,31 @@ static void natsemi_reset(struct net_device *dev)
        writel(rfcr, ioaddr + RxFilterAddr);
 }
 
+static void reset_rx(struct net_device *dev)
+{
+       int i;
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = ns_ioaddr(dev);
+
+       np->intr_status &= ~RxResetDone;
+
+       writel(RxReset, ioaddr + ChipCmd);
+
+       for (i=0;i<NATSEMI_HW_TIMEOUT;i++) {
+               np->intr_status |= readl(ioaddr + IntrStatus);
+               if (np->intr_status & RxResetDone)
+                       break;
+               udelay(15);
+       }
+       if (i==NATSEMI_HW_TIMEOUT) {
+               printk(KERN_WARNING "%s: RX reset did not complete in %d usec.\n",
+                      dev->name, i*15);
+       } else if (netif_msg_hw(np)) {
+               printk(KERN_WARNING "%s: RX reset took %d usec.\n",
+                      dev->name, i*15);
+       }
+}
+
 static void natsemi_reload_eeprom(struct net_device *dev)
 {
        struct netdev_private *np = netdev_priv(dev);
@@ -2158,68 +2197,92 @@ static void netdev_tx_done(struct net_device *dev)
        }
 }
 
-/* The interrupt handler does all of the Rx thread work and cleans up
  after the Tx thread. */
+/* The interrupt handler doesn't actually handle interrupts itself, it
* schedules a NAPI poll if there is anything to do. */
 static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
 {
        struct net_device *dev = dev_instance;
        struct netdev_private *np = netdev_priv(dev);
        void __iomem * ioaddr = ns_ioaddr(dev);
-       int boguscnt = max_interrupt_work;
-       unsigned int handled = 0;
 
        if (np->hands_off)
                return IRQ_NONE;
-       do {
-               /* Reading automatically acknowledges all int sources. */
-               u32 intr_status = readl(ioaddr + IntrStatus);
+       
+       /* Reading automatically acknowledges. */
+       np->intr_status = readl(ioaddr + IntrStatus);
 
-               if (netif_msg_intr(np))
-                       printk(KERN_DEBUG
-                               "%s: Interrupt, status %#08x, mask %#08x.\n",
-                               dev->name, intr_status,
-                               readl(ioaddr + IntrMask));
+       if (netif_msg_intr(np))
+               printk(KERN_DEBUG
+                      "%s: Interrupt, status %#08x, mask %#08x.\n",
+                      dev->name, np->intr_status,
+                      readl(ioaddr + IntrMask));
 
-               if (intr_status == 0)
-                       break;
-               handled = 1;
+       if (!np->intr_status) 
+               return IRQ_NONE;
 
-               if (intr_status &
-                  (IntrRxDone | IntrRxIntr | RxStatusFIFOOver |
-                   IntrRxErr | IntrRxOverrun)) {
-                       netdev_rx(dev);
-               }
+       prefetch(&np->rx_skbuff[np->cur_rx % RX_RING_SIZE]);
 
-               if (intr_status &
-                  (IntrTxDone | IntrTxIntr | IntrTxIdle | IntrTxErr)) {
+       if (netif_rx_schedule_prep(dev)) {
+               /* Disable interrupts and register for poll */
+               natsemi_irq_disable(dev);
+               __netif_rx_schedule(dev);
+       }
+       return IRQ_HANDLED;
+}
+
+/* This is the NAPI poll routine.  As well as the standard RX handling
+ * it also handles all other interrupts that the chip might raise.
+ */
+static int natsemi_poll(struct net_device *dev, int *budget)
+{
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem * ioaddr = ns_ioaddr(dev);
+
+       int work_to_do = min(*budget, dev->quota);
+       int work_done = 0;
+
+       do {
+               if (np->intr_status &
+                   (IntrTxDone | IntrTxIntr | IntrTxIdle | IntrTxErr)) {
                        spin_lock(&np->lock);
                        netdev_tx_done(dev);
                        spin_unlock(&np->lock);
                }
 
                /* Abnormal error summary/uncommon events handlers. */
-               if (intr_status & IntrAbnormalSummary)
-                       netdev_error(dev, intr_status);
-
-               if (--boguscnt < 0) {
-                       if (netif_msg_intr(np))
-                               printk(KERN_WARNING
-                                       "%s: Too much work at interrupt, "
-                                       "status=%#08x.\n",
-                                       dev->name, intr_status);
-                       break;
+               if (np->intr_status & IntrAbnormalSummary)
+                       netdev_error(dev, np->intr_status);
+               
+               if (np->intr_status &
+                   (IntrRxDone | IntrRxIntr | RxStatusFIFOOver |
+                    IntrRxErr | IntrRxOverrun)) {
+                       netdev_rx(dev, &work_done, work_to_do);
                }
-       } while (1);
+               
+               *budget -= work_done;
+               dev->quota -= work_done;
 
-       if (netif_msg_intr(np))
-               printk(KERN_DEBUG "%s: exiting interrupt.\n", dev->name);
+               if (work_done >= work_to_do)
+                       return 1;
+
+               np->intr_status = readl(ioaddr + IntrStatus);
+       } while (np->intr_status);
+
+       netif_rx_complete(dev);
 
-       return IRQ_RETVAL(handled);
+       /* Reenable interrupts providing nothing is trying to shut
+        * the chip down. */
+       spin_lock(&np->lock);
+       if (!np->hands_off && netif_running(dev))
+               natsemi_irq_enable(dev);
+       spin_unlock(&np->lock);
+
+       return 0;
 }
 
 /* This routine is logically part of the interrupt handler, but separated
    for clarity and better register allocation. */
-static void netdev_rx(struct net_device *dev)
+static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do)
 {
        struct netdev_private *np = netdev_priv(dev);
        int entry = np->cur_rx % RX_RING_SIZE;
@@ -2237,6 +2300,12 @@ static void netdev_rx(struct net_device *dev)
                                entry, desc_status);
                if (--boguscnt < 0)
                        break;
+
+               if (*work_done >= work_to_do)
+                       break;
+
+               (*work_done)++;
+
                pkt_len = (desc_status & DescSizeMask) - 4;
                if ((desc_status&(DescMore|DescPktOK|DescRxLong)) != DescPktOK){
                        if (desc_status & DescMore) {
@@ -2248,6 +2317,23 @@ static void netdev_rx(struct net_device *dev)
                                                "status %#08x.\n", dev->name,
                                                np->cur_rx, desc_status);
                                np->stats.rx_length_errors++;
+
+                               /* The RX state machine has probably
+                                * locked up beneath us.  Follow the
+                                * reset procedure documented in
+                                * AN-1287. */
+
+                               spin_lock_irq(&np->lock);
+                               reset_rx(dev);
+                               reinit_rx(dev);
+                               writel(np->ring_dma, ioaddr + RxRingPtr);
+                               check_link(dev);
+                               spin_unlock_irq(&np->lock);
+
+                               /* We'll enable RX on exit from this
+                                * function. */
+                               break;
+
                        } else {
                                /* There was an error. */
                                np->stats.rx_errors++;
@@ -2293,7 +2379,7 @@ static void netdev_rx(struct net_device *dev)
                                np->rx_skbuff[entry] = NULL;
                        }
                        skb->protocol = eth_type_trans(skb, dev);
-                       netif_rx(skb);
+                       netif_receive_skb(skb);
                        dev->last_rx = jiffies;
                        np->stats.rx_packets++;
                        np->stats.rx_bytes += pkt_len;
@@ -3074,9 +3160,7 @@ static int netdev_close(struct net_device *dev)
        del_timer_sync(&np->timer);
        disable_irq(dev->irq);
        spin_lock_irq(&np->lock);
-       /* Disable interrupts, and flush posted writes */
-       writel(0, ioaddr + IntrEnable);
-       readl(ioaddr + IntrEnable);
+       natsemi_irq_disable(dev);
        np->hands_off = 1;
        spin_unlock_irq(&np->lock);
        enable_irq(dev->irq);
@@ -3158,6 +3242,9 @@ static void __devexit natsemi_remove1 (struct pci_dev *pdev)
  *     * netdev_timer: timer stopped by natsemi_suspend.
  *     * intr_handler: doesn't acquire the spinlock. suspend calls
  *             disable_irq() to enforce synchronization.
+ *      * natsemi_poll: checks before reenabling interrupts.  suspend
+ *              sets hands_off, disables interrupts and then waits with
+ *              netif_poll_disable().
  *
  * Interrupts must be disabled, otherwise hands_off can cause irq storms.
  */
@@ -3183,6 +3270,8 @@ static int natsemi_suspend (struct pci_dev *pdev, pm_message_t state)
                spin_unlock_irq(&np->lock);
                enable_irq(dev->irq);
 
+               netif_poll_disable(dev);
+
                /* Update the error counts. */
                __get_stats(dev);
 
@@ -3235,6 +3324,7 @@ static int natsemi_resume (struct pci_dev *pdev)
                mod_timer(&np->timer, jiffies + 1*HZ);
        }
        netif_device_attach(dev);
+       netif_poll_enable(dev);
 out:
        rtnl_unlock();
        return 0;
index 8f40368..aaebd28 100644 (file)
@@ -27,6 +27,7 @@ static const char version1[] =
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/jiffies.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -365,7 +366,7 @@ static void ne_reset_8390(struct net_device *dev)
 
        /* This check _should_not_ be necessary, omit eventually. */
        while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
-               if (jiffies - reset_start_time > 2*HZ/100) {
+               if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
                        printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
                        break;
                }
@@ -580,7 +581,7 @@ retry:
 #endif
 
        while ((inb_p(NE_BASE + EN0_ISR) & ENISR_RDC) == 0)
-               if (jiffies - dma_start > 2*HZ/100) {           /* 20ms */
+               if (time_after(jiffies, dma_start + 2*HZ/100)) {                /* 20ms */
                        printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
                        ne_reset_8390(dev);
                        NS8390_init(dev,1);
index 94f782d..08b218c 100644 (file)
@@ -50,6 +50,7 @@ static const char version2[] =
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/jiffies.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -341,7 +342,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
                outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
 
                while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
-               if (jiffies - reset_start_time > 2*HZ/100) {
+               if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
                        if (bad_card) {
                                printk(" (warning: no reset ack)");
                                break;
@@ -580,7 +581,7 @@ static void ne_reset_8390(struct net_device *dev)
 
        /* This check _should_not_ be necessary, omit eventually. */
        while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
-               if (jiffies - reset_start_time > 2*HZ/100) {
+               if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
                        printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
                        break;
                }
@@ -787,7 +788,7 @@ retry:
 #endif
 
        while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
-               if (jiffies - dma_start > 2*HZ/100) {           /* 20ms */
+               if (time_after(jiffies, dma_start + 2*HZ/100)) {                /* 20ms */
                        printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
                        ne_reset_8390(dev);
                        NS8390_init(dev,1);
index e6df375..2aa7b77 100644 (file)
@@ -75,6 +75,7 @@ static const char *version = "ne2.c:v0.91 Nov 16 1998 Wim Dumon <wimpie@kotnet.o
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/bitops.h>
+#include <linux/jiffies.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -395,7 +396,7 @@ static int __init ne2_probe1(struct net_device *dev, int slot)
                outb(inb(base_addr + NE_RESET), base_addr + NE_RESET);
 
                while ((inb_p(base_addr + EN0_ISR) & ENISR_RESET) == 0)
-                       if (jiffies - reset_start_time > 2*HZ/100) {
+                       if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
                                printk(" not found (no reset ack).\n");
                                retval = -ENODEV;
                                goto out;
@@ -548,7 +549,7 @@ static void ne_reset_8390(struct net_device *dev)
 
        /* This check _should_not_ be necessary, omit eventually. */
        while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
-               if (jiffies - reset_start_time > 2*HZ/100) {
+               if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
                        printk("%s: ne_reset_8390() did not complete.\n", 
                                        dev->name);
                        break;
@@ -749,7 +750,7 @@ retry:
 #endif
 
        while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
-               if (jiffies - dma_start > 2*HZ/100) {           /* 20ms */
+               if (time_after(jiffies, dma_start + 2*HZ/100)) {                /* 20ms */
                        printk("%s: timeout waiting for Tx RDC.\n", dev->name);
                        ne_reset_8390(dev);
                        NS8390_init(dev,1);
index d11821d..e3ebb58 100644 (file)
@@ -117,7 +117,7 @@ enum ne2k_pci_chipsets {
 };
 
 
-static struct {
+static const struct {
        char *name;
        int flags;
 } pci_clone_list[] __devinitdata = {
index b0c3b6a..0fede50 100644 (file)
 #include <linux/timer.h>
 #include <linux/if_vlan.h>
 #include <linux/rtnetlink.h>
+#include <linux/jiffies.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -651,7 +652,7 @@ static void FASTCALL(phy_intr(struct net_device *ndev));
 static void fastcall phy_intr(struct net_device *ndev)
 {
        struct ns83820 *dev = PRIV(ndev);
-       static char *speeds[] = { "10", "100", "1000", "1000(?)", "1000F" };
+       static const char *speeds[] = { "10", "100", "1000", "1000(?)", "1000F" };
        u32 cfg, new_cfg;
        u32 tbisr, tanar, tanlpar;
        int speed, fullduplex, newlinkstate;
@@ -1607,7 +1608,7 @@ static void ns83820_run_bist(struct net_device *ndev, const char *name, u32 enab
 {
        struct ns83820 *dev = PRIV(ndev);
        int timed_out = 0;
-       long start;
+       unsigned long start;
        u32 status;
        int loops = 0;
 
@@ -1625,7 +1626,7 @@ static void ns83820_run_bist(struct net_device *ndev, const char *name, u32 enab
                        break;
                if (status & fail)
                        break;
-               if ((jiffies - start) >= HZ) {
+               if (time_after_eq(jiffies, start + HZ)) {
                        timed_out = 1;
                        break;
                }
index 62167a2..d0f686d 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/jiffies.h>
 
 #include <asm/board.h>
 #include <asm/io.h>
@@ -606,7 +607,7 @@ retry:
 #endif
 
        while ((ei_ibp(base + EN0_ISR) & ENISR_RDC) == 0) {
-               if (jiffies - start > OAKNET_WAIT) {
+               if (time_after(jiffies, start + OAKNET_WAIT)) {
                        printk("%s: timeout waiting for Tx RDC.\n", dev->name);
                        oaknet_reset_8390(dev);
                        NS8390_init(dev, TRUE);
index 48774ef..ce90bec 100644 (file)
@@ -341,7 +341,7 @@ static void tc574_detach(struct pcmcia_device *p_dev)
 #define CS_CHECK(fn, ret) \
   do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
+static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
 
 static void tc574_config(dev_link_t *link)
 {
index 1c3c9c6..3dba508 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/if_arp.h>
 #include <linux/ioport.h>
 #include <linux/bitops.h>
+#include <linux/jiffies.h>
 
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
@@ -115,7 +116,7 @@ struct el3_private {
     spinlock_t         lock;
 };
 
-static char *if_names[] = { "auto", "10baseT", "10base2", "AUI" };
+static const char *if_names[] = { "auto", "10baseT", "10base2", "AUI" };
 
 /*====================================================================*/
 
@@ -796,7 +797,7 @@ static void media_check(unsigned long arg)
     media = inw(ioaddr+WN4_MEDIA) & 0xc810;
 
     /* Ignore collisions unless we've had no irq's recently */
-    if (jiffies - lp->last_irq < HZ) {
+    if (time_before(jiffies, lp->last_irq + HZ)) {
        media &= ~0x0010;
     } else {
        /* Try harder to detect carrier errors */
index 28fe2fb..b7ac14b 100644 (file)
@@ -309,7 +309,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 static int mfc_try_io_port(dev_link_t *link)
 {
     int i, ret;
-    static kio_addr_t serial_base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+    static const kio_addr_t serial_base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
 
     for (i = 0; i < 5; i++) {
        link->io.BasePort2 = serial_base[i];
index 4a23225..787176c 100644 (file)
@@ -388,7 +388,7 @@ static char *version =
 DRV_NAME " " DRV_VERSION " (Roger C. Pao)";
 #endif
 
-static char *if_names[]={
+static const char *if_names[]={
     "Auto", "10baseT", "BNC",
 };
 
index d85b758..b46e5f7 100644 (file)
@@ -66,7 +66,7 @@
 
 #define PCNET_RDC_TIMEOUT (2*HZ/100)   /* Max wait in jiffies for Tx RDC */
 
-static char *if_names[] = { "auto", "10baseT", "10base2"};
+static const char *if_names[] = { "auto", "10baseT", "10base2"};
 
 #ifdef PCMCIA_DEBUG
 static int pc_debug = PCMCIA_DEBUG;
@@ -1727,6 +1727,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
        PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V2)", 0x0733cc81, 0x3a3b28e9),
        PCMCIA_DEVICE_PROD_ID12("Linksys", "HomeLink Phoneline + 10/100 Network PC Card (PCM100H1)", 0x733cc81, 0x7a3e5c3a),
        PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TX", 0x88fcdeda, 0x6d772737),
+       PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TE", 0x88fcdeda, 0x0e714bee),
        PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN20T", 0x88fcdeda, 0x81090922),
        PCMCIA_DEVICE_PROD_ID12("LONGSHINE", "PCMCIA Ethernet Card", 0xf866b0b0, 0x6f6652e0),
        PCMCIA_DEVICE_PROD_ID12("MACNICA", "ME1-JEIDA", 0x20841b68, 0xaf8a3578),
index 0122415..8839c4f 100644 (file)
@@ -59,7 +59,7 @@
 
 /*====================================================================*/
 
-static char *if_names[] = { "auto", "10baseT", "10base2"};
+static const char *if_names[] = { "auto", "10baseT", "10base2"};
 
 /* Module parameters */
 
@@ -777,7 +777,7 @@ free_cfg_mem:
 static int osi_config(dev_link_t *link)
 {
     struct net_device *dev = link->priv;
-    static kio_addr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
+    static const kio_addr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
     int i, j;
 
     link->conf.Attributes |= CONF_ENABLE_SPKR;
index 593d8ad..eed4968 100644 (file)
@@ -208,7 +208,7 @@ enum xirc_cmd {         /* Commands */
 #define XIRCREG45_REV   15 /* Revision Register (rd) */
 #define XIRCREG50_IA   8   /* Individual Address (8-13) */
 
-static char *if_names[] = { "Auto", "10BaseT", "10Base2", "AUI", "100BaseT" };
+static const char *if_names[] = { "Auto", "10BaseT", "10Base2", "AUI", "100BaseT" };
 
 /****************
  * All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
index 8f6cf8c..7e90057 100644 (file)
@@ -26,7 +26,7 @@
 #define DRV_RELDATE    "01.Nov.2005"
 #define PFX            DRV_NAME ": "
 
-static const char *version =
+static const char * const version =
 DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n";
 
 #include <linux/module.h>
@@ -109,7 +109,7 @@ static int rx_copybreak = 200;
  * table to translate option values from tulip
  * to internal options
  */
-static unsigned char options_mapping[] = {
+static const unsigned char options_mapping[] = {
     PCNET32_PORT_ASEL,                    /*  0 Auto-select      */
     PCNET32_PORT_AUI,                     /*  1 BNC/AUI          */
     PCNET32_PORT_AUI,                     /*  2 AUI/BNC          */
@@ -733,7 +733,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
     int rc;                            /* return code */
     int size;                          /* size of packets */
     unsigned char *packet;             /* source packet data */
-    static int data_len = 60;          /* length of source packets */
+    static const int data_len = 60;            /* length of source packets */
     unsigned long flags;
     unsigned long ticks;
 
index 1474b7c..33cec2d 100644 (file)
@@ -132,7 +132,7 @@ struct phy_setting {
 };
 
 /* A mapping of all SUPPORTED settings to speed/duplex */
-static struct phy_setting settings[] = {
+static const struct phy_setting settings[] = {
        {
                .speed = 10000,
                .duplex = DUPLEX_FULL,
index 87ee327..d4449d6 100644 (file)
@@ -123,7 +123,7 @@ static const char version[] = "NET3 PLIP version 2.4-parport gniibe@mri.co.jp\n"
 #ifndef NET_DEBUG
 #define NET_DEBUG 1
 #endif
-static unsigned int net_debug = NET_DEBUG;
+static const unsigned int net_debug = NET_DEBUG;
 
 #define ENABLE(irq)  if (irq != -1) enable_irq(irq)
 #define DISABLE(irq) if (irq != -1) disable_irq(irq)
@@ -351,7 +351,7 @@ static int plip_bh_timeout_error(struct net_device *dev, struct net_local *nl,
 typedef int (*plip_func)(struct net_device *dev, struct net_local *nl,
                         struct plip_local *snd, struct plip_local *rcv);
 
-static plip_func connection_state_table[] =
+static const plip_func connection_state_table[] =
 {
        plip_none,
        plip_receive_packet,
index aa6540b..23659fd 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/ppp_channel.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
+#include <linux/jiffies.h>
 #include <asm/uaccess.h>
 #include <asm/string.h>
 
@@ -570,7 +571,7 @@ ppp_async_encode(struct asyncppp *ap)
                 * character if necessary.
                 */
                if (islcp || flag_time == 0
-                   || jiffies - ap->last_xmit >= flag_time)
+                   || time_after_eq(jiffies, ap->last_xmit + flag_time))
                        *buf++ = PPP_FLAG;
                ap->last_xmit = jiffies;
                fcs = PPP_INITFCS;
index 33cb825..33255fe 100644 (file)
@@ -108,7 +108,7 @@ static void
 ppp_print_hex (register __u8 * out, const __u8 * in, int count)
 {
        register __u8 next_ch;
-       static char hex[] = "0123456789ABCDEF";
+       static const char hex[] = "0123456789ABCDEF";
 
        while (count-- > 0) {
                next_ch = *in++;
index 8cc0d0b..0ad3310 100644 (file)
@@ -113,11 +113,11 @@ static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
 static int num_media = 0;
 
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 20;
+static const int max_interrupt_work = 20;
 
 /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
    The RTL chips use a 64 element hash table based on the Ethernet CRC. */
-static int multicast_filter_limit = 32;
+static const int multicast_filter_limit = 32;
 
 /* MAC address length */
 #define MAC_ADDR_LEN   6
index b7f00d6..79208f4 100644 (file)
 #include <linux/ethtool.h>
 #include <linux/workqueue.h>
 #include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <net/tcp.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
+#include <asm/div64.h>
 
 /* local include */
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "Version 2.0.9.4"
+#define DRV_VERSION "2.0.11.2"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
 static char s2io_driver_version[] = DRV_VERSION;
 
-int rxd_size[4] = {32,48,48,64};
-int rxd_count[4] = {127,85,85,63};
+static int rxd_size[4] = {32,48,48,64};
+static int rxd_count[4] = {127,85,85,63};
 
 static inline int RXD_IS_UP2DT(RxD_t *rxdp)
 {
@@ -168,6 +172,11 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
        {"\n DRIVER STATISTICS"},
        {"single_bit_ecc_errs"},
        {"double_bit_ecc_errs"},
+       ("lro_aggregated_pkts"),
+       ("lro_flush_both_count"),
+       ("lro_out_of_sequence_pkts"),
+       ("lro_flush_due_to_max_pkts"),
+       ("lro_avg_aggr_pkts"),
 };
 
 #define S2IO_STAT_LEN sizeof(ethtool_stats_keys)/ ETH_GSTRING_LEN
@@ -214,7 +223,7 @@ static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
 #define SWITCH_SIGN    0xA5A5A5A5A5A5A5A5ULL
 #define        END_SIGN        0x0
 
-static u64 herc_act_dtx_cfg[] = {
+static const u64 herc_act_dtx_cfg[] = {
        /* Set address */
        0x8000051536750000ULL, 0x80000515367500E0ULL,
        /* Write data */
@@ -235,7 +244,7 @@ static u64 herc_act_dtx_cfg[] = {
        END_SIGN
 };
 
-static u64 xena_mdio_cfg[] = {
+static const u64 xena_mdio_cfg[] = {
        /* Reset PMA PLL */
        0xC001010000000000ULL, 0xC0010100000000E0ULL,
        0xC0010100008000E4ULL,
@@ -245,7 +254,7 @@ static u64 xena_mdio_cfg[] = {
        END_SIGN
 };
 
-static u64 xena_dtx_cfg[] = {
+static const u64 xena_dtx_cfg[] = {
        0x8000051500000000ULL, 0x80000515000000E0ULL,
        0x80000515D93500E4ULL, 0x8001051500000000ULL,
        0x80010515000000E0ULL, 0x80010515001E00E4ULL,
@@ -273,7 +282,7 @@ static u64 xena_dtx_cfg[] = {
  * Constants for Fixing the MacAddress problem seen mostly on
  * Alpha machines.
  */
-static u64 fix_mac[] = {
+static const u64 fix_mac[] = {
        0x0060000000000000ULL, 0x0060600000000000ULL,
        0x0040600000000000ULL, 0x0000600000000000ULL,
        0x0020600000000000ULL, 0x0060600000000000ULL,
@@ -317,6 +326,12 @@ static unsigned int indicate_max_pkts;
 static unsigned int rxsync_frequency = 3;
 /* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */
 static unsigned int intr_type = 0;
+/* Large receive offload feature */
+static unsigned int lro = 0;
+/* Max pkts to be aggregated by LRO at one time. If not specified,
+ * aggregation happens until we hit max IP pkt size(64K)
+ */
+static unsigned int lro_max_pkts = 0xFFFF;
 
 /*
  * S2IO device table.
@@ -1476,6 +1491,19 @@ static int init_nic(struct s2io_nic *nic)
        writel((u32) (val64 >> 32), (add + 4));
        val64 = readq(&bar0->mac_cfg);
 
+       /* Enable FCS stripping by adapter */
+       add = &bar0->mac_cfg;
+       val64 = readq(&bar0->mac_cfg);
+       val64 |= MAC_CFG_RMAC_STRIP_FCS;
+       if (nic->device_type == XFRAME_II_DEVICE)
+               writeq(val64, &bar0->mac_cfg);
+       else {
+               writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
+               writel((u32) (val64), add);
+               writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
+               writel((u32) (val64 >> 32), (add + 4));
+       }
+
        /*
         * Set the time value to be inserted in the pause frame
         * generated by xena.
@@ -2127,7 +2155,7 @@ static void stop_nic(struct s2io_nic *nic)
        }
 }
 
-int fill_rxd_3buf(nic_t *nic, RxD_t *rxdp, struct sk_buff *skb)
+static int fill_rxd_3buf(nic_t *nic, RxD_t *rxdp, struct sk_buff *skb)
 {
        struct net_device *dev = nic->dev;
        struct sk_buff *frag_list;
@@ -2569,6 +2597,8 @@ static void rx_intr_handler(ring_info_t *ring_data)
 #ifndef CONFIG_S2IO_NAPI
        int pkt_cnt = 0;
 #endif
+       int i;
+
        spin_lock(&nic->rx_lock);
        if (atomic_read(&nic->card_state) == CARD_DOWN) {
                DBG_PRINT(INTR_DBG, "%s: %s going down for reset\n",
@@ -2661,6 +2691,18 @@ static void rx_intr_handler(ring_info_t *ring_data)
                        break;
 #endif
        }
+       if (nic->lro) {
+               /* Clear all LRO sessions before exiting */
+               for (i=0; i<MAX_LRO_SESSIONS; i++) {
+                       lro_t *lro = &nic->lro0_n[i];
+                       if (lro->in_use) {
+                               update_L3L4_header(nic, lro);
+                               queue_rx_frame(lro->parent);
+                               clear_lro_session(lro);
+                       }
+               }
+       }
+
        spin_unlock(&nic->rx_lock);
 }
 
@@ -2852,7 +2894,7 @@ static int wait_for_cmd_complete(nic_t * sp)
  *  void.
  */
 
-void s2io_reset(nic_t * sp)
+static void s2io_reset(nic_t * sp)
 {
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
        u64 val64;
@@ -2940,7 +2982,7 @@ void s2io_reset(nic_t * sp)
  *  SUCCESS on success and FAILURE on failure.
  */
 
-int s2io_set_swapper(nic_t * sp)
+static int s2io_set_swapper(nic_t * sp)
 {
        struct net_device *dev = sp->dev;
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
@@ -3089,7 +3131,7 @@ static int wait_for_msix_trans(nic_t *nic, int i)
        return ret;
 }
 
-void restore_xmsi_data(nic_t *nic)
+static void restore_xmsi_data(nic_t *nic)
 {
        XENA_dev_config_t __iomem *bar0 = nic->bar0;
        u64 val64;
@@ -3180,7 +3222,7 @@ int s2io_enable_msi(nic_t *nic)
        return 0;
 }
 
-int s2io_enable_msi_x(nic_t *nic)
+static int s2io_enable_msi_x(nic_t *nic)
 {
        XENA_dev_config_t __iomem *bar0 = nic->bar0;
        u64 tx_mat, rx_mat;
@@ -3668,23 +3710,32 @@ s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs)
         * else schedule a tasklet to reallocate the buffers.
         */
        for (i = 0; i < config->rx_ring_num; i++) {
-               int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
-               int level = rx_buffer_level(sp, rxb_size, i);
-
-               if ((level == PANIC) && (!TASKLET_IN_USE)) {
-                       DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", dev->name);
-                       DBG_PRINT(INTR_DBG, "PANIC levels\n");
-                       if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) {
-                               DBG_PRINT(ERR_DBG, "%s:Out of memory",
-                                         dev->name);
-                               DBG_PRINT(ERR_DBG, " in ISR!!\n");
+               if (!sp->lro) {
+                       int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
+                       int level = rx_buffer_level(sp, rxb_size, i);
+
+                       if ((level == PANIC) && (!TASKLET_IN_USE)) {
+                               DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", 
+                                                       dev->name);
+                               DBG_PRINT(INTR_DBG, "PANIC levels\n");
+                               if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) {
+                                       DBG_PRINT(ERR_DBG, "%s:Out of memory",
+                                                 dev->name);
+                                       DBG_PRINT(ERR_DBG, " in ISR!!\n");
+                                       clear_bit(0, (&sp->tasklet_status));
+                                       atomic_dec(&sp->isr_cnt);
+                                       return IRQ_HANDLED;
+                               }
                                clear_bit(0, (&sp->tasklet_status));
-                               atomic_dec(&sp->isr_cnt);
-                               return IRQ_HANDLED;
+                       } else if (level == LOW) {
+                               tasklet_schedule(&sp->task);
                        }
-                       clear_bit(0, (&sp->tasklet_status));
-               } else if (level == LOW) {
-                       tasklet_schedule(&sp->task);
+               }
+               else if (fill_rx_buffers(sp, i) == -ENOMEM) {
+                               DBG_PRINT(ERR_DBG, "%s:Out of memory",
+                                                       dev->name);
+                               DBG_PRINT(ERR_DBG, " in Rx Intr!!\n");
+                               break;
                }
        }
 
@@ -3697,29 +3748,37 @@ s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs)
 {
        ring_info_t *ring = (ring_info_t *)dev_id;
        nic_t *sp = ring->nic;
+       struct net_device *dev = (struct net_device *) dev_id;
        int rxb_size, level, rng_n;
 
        atomic_inc(&sp->isr_cnt);
        rx_intr_handler(ring);
 
        rng_n = ring->ring_no;
-       rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
-       level = rx_buffer_level(sp, rxb_size, rng_n);
-
-       if ((level == PANIC) && (!TASKLET_IN_USE)) {
-               int ret;
-               DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__);
-               DBG_PRINT(INTR_DBG, "PANIC levels\n");
-               if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) {
-                       DBG_PRINT(ERR_DBG, "Out of memory in %s",
-                                 __FUNCTION__);
+       if (!sp->lro) {
+               rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
+               level = rx_buffer_level(sp, rxb_size, rng_n);
+
+               if ((level == PANIC) && (!TASKLET_IN_USE)) {
+                       int ret;
+                       DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__);
+                       DBG_PRINT(INTR_DBG, "PANIC levels\n");
+                       if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) {
+                               DBG_PRINT(ERR_DBG, "Out of memory in %s",
+                                         __FUNCTION__);
+                               clear_bit(0, (&sp->tasklet_status));
+                               return IRQ_HANDLED;
+                       }
                        clear_bit(0, (&sp->tasklet_status));
-                       return IRQ_HANDLED;
+               } else if (level == LOW) {
+                       tasklet_schedule(&sp->task);
                }
-               clear_bit(0, (&sp->tasklet_status));
-       } else if (level == LOW) {
-               tasklet_schedule(&sp->task);
        }
+       else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) {
+                       DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name);
+                       DBG_PRINT(ERR_DBG, " in Rx Intr!!\n");
+       }
+
        atomic_dec(&sp->isr_cnt);
 
        return IRQ_HANDLED;
@@ -3875,24 +3934,33 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
         */
 #ifndef CONFIG_S2IO_NAPI
        for (i = 0; i < config->rx_ring_num; i++) {
-               int ret;
-               int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
-               int level = rx_buffer_level(sp, rxb_size, i);
-
-               if ((level == PANIC) && (!TASKLET_IN_USE)) {
-                       DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", dev->name);
-                       DBG_PRINT(INTR_DBG, "PANIC levels\n");
-                       if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) {
-                               DBG_PRINT(ERR_DBG, "%s:Out of memory",
-                                         dev->name);
-                               DBG_PRINT(ERR_DBG, " in ISR!!\n");
+               if (!sp->lro) {
+                       int ret;
+                       int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
+                       int level = rx_buffer_level(sp, rxb_size, i);
+
+                       if ((level == PANIC) && (!TASKLET_IN_USE)) {
+                               DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", 
+                                                       dev->name);
+                               DBG_PRINT(INTR_DBG, "PANIC levels\n");
+                               if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) {
+                                       DBG_PRINT(ERR_DBG, "%s:Out of memory",
+                                                 dev->name);
+                                       DBG_PRINT(ERR_DBG, " in ISR!!\n");
+                                       clear_bit(0, (&sp->tasklet_status));
+                                       atomic_dec(&sp->isr_cnt);
+                                       return IRQ_HANDLED;
+                               }
                                clear_bit(0, (&sp->tasklet_status));
-                               atomic_dec(&sp->isr_cnt);
-                               return IRQ_HANDLED;
+                       } else if (level == LOW) {
+                               tasklet_schedule(&sp->task);
                        }
-                       clear_bit(0, (&sp->tasklet_status));
-               } else if (level == LOW) {
-                       tasklet_schedule(&sp->task);
+               }
+               else if (fill_rx_buffers(sp, i) == -ENOMEM) {
+                               DBG_PRINT(ERR_DBG, "%s:Out of memory",
+                                                       dev->name);
+                               DBG_PRINT(ERR_DBG, " in Rx intr!!\n");
+                               break;
                }
        }
 #endif
@@ -4129,7 +4197,7 @@ static void s2io_set_multicast(struct net_device *dev)
  *  as defined in errno.h file on failure.
  */
 
-int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
+static int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
 {
        nic_t *sp = dev->priv;
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
@@ -5044,6 +5112,7 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
        int i = 0;
        nic_t *sp = dev->priv;
        StatInfo_t *stat_info = sp->mac_control.stats_info;
+       u64 tmp;
 
        s2io_updt_stats(sp);
        tmp_stats[i++] =
@@ -5135,6 +5204,16 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
        tmp_stats[i++] = 0;
        tmp_stats[i++] = stat_info->sw_stat.single_ecc_errs;
        tmp_stats[i++] = stat_info->sw_stat.double_ecc_errs;
+       tmp_stats[i++] = stat_info->sw_stat.clubbed_frms_cnt;
+       tmp_stats[i++] = stat_info->sw_stat.sending_both;
+       tmp_stats[i++] = stat_info->sw_stat.outof_sequence_pkts;
+       tmp_stats[i++] = stat_info->sw_stat.flush_max_pkts;
+       tmp = 0;
+       if (stat_info->sw_stat.num_aggregations) {
+               tmp = stat_info->sw_stat.sum_avg_pkts_aggregated;
+               do_div(tmp, stat_info->sw_stat.num_aggregations);
+       }
+       tmp_stats[i++] = tmp;
 }
 
 static int s2io_ethtool_get_regs_len(struct net_device *dev)
@@ -5516,6 +5595,14 @@ static int s2io_card_up(nic_t * sp)
        /* Setting its receive mode */
        s2io_set_multicast(dev);
 
+       if (sp->lro) {
+               /* Initialize max aggregatable pkts based on MTU */
+               sp->lro_max_aggr_per_sess = ((1<<16) - 1) / dev->mtu;
+               /* Check if we can use(if specified) user provided value */
+               if (lro_max_pkts < sp->lro_max_aggr_per_sess)
+                       sp->lro_max_aggr_per_sess = lro_max_pkts;
+       }
+
        /* Enable tasklet for the device */
        tasklet_init(&sp->task, s2io_tasklet, (unsigned long) dev);
 
@@ -5608,6 +5695,7 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
                ((unsigned long) rxdp->Host_Control);
        int ring_no = ring_data->ring_no;
        u16 l3_csum, l4_csum;
+       lro_t *lro;
 
        skb->dev = dev;
        if (rxdp->Control_1 & RXD_T_CODE) {
@@ -5656,7 +5744,8 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
                        skb_put(skb, buf2_len);
        }
 
-       if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) &&
+       if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && ((!sp->lro) ||
+           (sp->lro && (!(rxdp->Control_1 & RXD_FRAME_IP_FRAG)))) &&
            (sp->rx_csum)) {
                l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1);
                l4_csum = RXD_GET_L4_CKSUM(rxdp->Control_1);
@@ -5667,6 +5756,54 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
                         * a flag in the RxD.
                         */
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
+                       if (sp->lro) {
+                               u32 tcp_len;
+                               u8 *tcp;
+                               int ret = 0;
+
+                               ret = s2io_club_tcp_session(skb->data, &tcp,
+                                               &tcp_len, &lro, rxdp, sp);
+                               switch (ret) {
+                                       case 3: /* Begin anew */
+                                               lro->parent = skb;
+                                               goto aggregate;
+                                       case 1: /* Aggregate */
+                                       {
+                                               lro_append_pkt(sp, lro,
+                                                       skb, tcp_len);
+                                               goto aggregate;
+                                       }
+                                       case 4: /* Flush session */
+                                       {
+                                               lro_append_pkt(sp, lro,
+                                                       skb, tcp_len);
+                                               queue_rx_frame(lro->parent);
+                                               clear_lro_session(lro);
+                                               sp->mac_control.stats_info->
+                                                   sw_stat.flush_max_pkts++;
+                                               goto aggregate;
+                                       }
+                                       case 2: /* Flush both */
+                                               lro->parent->data_len =
+                                                       lro->frags_len;
+                                               sp->mac_control.stats_info->
+                                                    sw_stat.sending_both++;
+                                               queue_rx_frame(lro->parent);
+                                               clear_lro_session(lro);
+                                               goto send_up;
+                                       case 0: /* sessions exceeded */
+                                       case 5: /*
+                                                * First pkt in session not
+                                                * L3/L4 aggregatable
+                                                */
+                                               break;
+                                       default:
+                                               DBG_PRINT(ERR_DBG,
+                                                       "%s: Samadhana!!\n",
+                                                        __FUNCTION__);
+                                               BUG();
+                               }
+                       }
                } else {
                        /*
                         * Packet with erroneous checksum, let the
@@ -5678,25 +5815,31 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
                skb->ip_summed = CHECKSUM_NONE;
        }
 
-       skb->protocol = eth_type_trans(skb, dev);
+       if (!sp->lro) {
+               skb->protocol = eth_type_trans(skb, dev);
 #ifdef CONFIG_S2IO_NAPI
-       if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) {
-               /* Queueing the vlan frame to the upper layer */
-               vlan_hwaccel_receive_skb(skb, sp->vlgrp,
-                       RXD_GET_VLAN_TAG(rxdp->Control_2));
-       } else {
-               netif_receive_skb(skb);
-       }
+               if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) {
+                       /* Queueing the vlan frame to the upper layer */
+                       vlan_hwaccel_receive_skb(skb, sp->vlgrp,
+                               RXD_GET_VLAN_TAG(rxdp->Control_2));
+               } else {
+                       netif_receive_skb(skb);
+               }
 #else
-       if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) {
-               /* Queueing the vlan frame to the upper layer */
-               vlan_hwaccel_rx(skb, sp->vlgrp,
-                       RXD_GET_VLAN_TAG(rxdp->Control_2));
-       } else {
-               netif_rx(skb);
-       }
+               if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) {
+                       /* Queueing the vlan frame to the upper layer */
+                       vlan_hwaccel_rx(skb, sp->vlgrp,
+                               RXD_GET_VLAN_TAG(rxdp->Control_2));
+               } else {
+                       netif_rx(skb);
+               }
 #endif
+       } else {
+send_up:
+               queue_rx_frame(skb);
+       }               
        dev->last_rx = jiffies;
+aggregate:
        atomic_dec(&sp->rx_bufs_left[ring_no]);
        return SUCCESS;
 }
@@ -5714,7 +5857,7 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
  *  void.
  */
 
-void s2io_link(nic_t * sp, int link)
+static void s2io_link(nic_t * sp, int link)
 {
        struct net_device *dev = (struct net_device *) sp->dev;
 
@@ -5739,7 +5882,7 @@ void s2io_link(nic_t * sp, int link)
  *  returns the revision ID of the device.
  */
 
-int get_xena_rev_id(struct pci_dev *pdev)
+static int get_xena_rev_id(struct pci_dev *pdev)
 {
        u8 id = 0;
        int ret;
@@ -5808,6 +5951,8 @@ module_param(indicate_max_pkts, int, 0);
 #endif
 module_param(rxsync_frequency, int, 0);
 module_param(intr_type, int, 0);
+module_param(lro, int, 0);
+module_param(lro_max_pkts, int, 0);
 
 /**
  *  s2io_init_nic - Initialization of the adapter .
@@ -5939,6 +6084,7 @@ Defaulting to INTA\n");
        else
                sp->device_type = XFRAME_I_DEVICE;
 
+       sp->lro = lro;
                
        /* Initialize some PCI/PCI-X fields of the NIC. */
        s2io_init_pci(sp);
@@ -6242,6 +6388,10 @@ Defaulting to INTA\n");
                DBG_PRINT(ERR_DBG, "%s: 3-Buffer mode support has been "
                          "enabled\n",dev->name);
 
+       if (sp->lro)
+               DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
+                       dev->name);
+
        /* Initialize device name */
        strcpy(sp->name, dev->name);
        if (sp->device_type & XFRAME_II_DEVICE)
@@ -6344,7 +6494,7 @@ int __init s2io_starter(void)
  * Description: This function is the cleanup routine for the driver. It unregist * ers the driver.
  */
 
-void s2io_closer(void)
+static void s2io_closer(void)
 {
        pci_unregister_driver(&s2io_driver);
        DBG_PRINT(INIT_DBG, "cleanup done\n");
@@ -6352,3 +6502,318 @@ void s2io_closer(void)
 
 module_init(s2io_starter);
 module_exit(s2io_closer);
+
+static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip, 
+               struct tcphdr **tcp, RxD_t *rxdp)
+{
+       int ip_off;
+       u8 l2_type = (u8)((rxdp->Control_1 >> 37) & 0x7), ip_len;
+
+       if (!(rxdp->Control_1 & RXD_FRAME_PROTO_TCP)) {
+               DBG_PRINT(INIT_DBG,"%s: Non-TCP frames not supported for LRO\n",
+                         __FUNCTION__);
+               return -1;
+       }
+
+       /* TODO:
+        * By default the VLAN field in the MAC is stripped by the card, if this
+        * feature is turned off in rx_pa_cfg register, then the ip_off field
+        * has to be shifted by a further 2 bytes
+        */
+       switch (l2_type) {
+               case 0: /* DIX type */
+               case 4: /* DIX type with VLAN */
+                       ip_off = HEADER_ETHERNET_II_802_3_SIZE;
+                       break;
+               /* LLC, SNAP etc are considered non-mergeable */
+               default:
+                       return -1;
+       }
+
+       *ip = (struct iphdr *)((u8 *)buffer + ip_off);
+       ip_len = (u8)((*ip)->ihl);
+       ip_len <<= 2;
+       *tcp = (struct tcphdr *)((unsigned long)*ip + ip_len);
+
+       return 0;
+}
+
+static int check_for_socket_match(lro_t *lro, struct iphdr *ip,
+                                 struct tcphdr *tcp)
+{
+       DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
+       if ((lro->iph->saddr != ip->saddr) || (lro->iph->daddr != ip->daddr) ||
+          (lro->tcph->source != tcp->source) || (lro->tcph->dest != tcp->dest))
+               return -1;
+       return 0;
+}
+
+static inline int get_l4_pyld_length(struct iphdr *ip, struct tcphdr *tcp)
+{
+       return(ntohs(ip->tot_len) - (ip->ihl << 2) - (tcp->doff << 2));
+}
+
+static void initiate_new_session(lro_t *lro, u8 *l2h,
+                    struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len)
+{
+       DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
+       lro->l2h = l2h;
+       lro->iph = ip;
+       lro->tcph = tcp;
+       lro->tcp_next_seq = tcp_pyld_len + ntohl(tcp->seq);
+       lro->tcp_ack = ntohl(tcp->ack_seq);
+       lro->sg_num = 1;
+       lro->total_len = ntohs(ip->tot_len);
+       lro->frags_len = 0;
+       /* 
+        * check if we saw TCP timestamp. Other consistency checks have
+        * already been done.
+        */
+       if (tcp->doff == 8) {
+               u32 *ptr;
+               ptr = (u32 *)(tcp+1);
+               lro->saw_ts = 1;
+               lro->cur_tsval = *(ptr+1);
+               lro->cur_tsecr = *(ptr+2);
+       }
+       lro->in_use = 1;
+}
+
+static void update_L3L4_header(nic_t *sp, lro_t *lro)
+{
+       struct iphdr *ip = lro->iph;
+       struct tcphdr *tcp = lro->tcph;
+       u16 nchk;
+       StatInfo_t *statinfo = sp->mac_control.stats_info;
+       DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
+
+       /* Update L3 header */
+       ip->tot_len = htons(lro->total_len);
+       ip->check = 0;
+       nchk = ip_fast_csum((u8 *)lro->iph, ip->ihl);
+       ip->check = nchk;
+
+       /* Update L4 header */
+       tcp->ack_seq = lro->tcp_ack;
+       tcp->window = lro->window;
+
+       /* Update tsecr field if this session has timestamps enabled */
+       if (lro->saw_ts) {
+               u32 *ptr = (u32 *)(tcp + 1);
+               *(ptr+2) = lro->cur_tsecr;
+       }
+
+       /* Update counters required for calculation of
+        * average no. of packets aggregated.
+        */
+       statinfo->sw_stat.sum_avg_pkts_aggregated += lro->sg_num;
+       statinfo->sw_stat.num_aggregations++;
+}
+
+static void aggregate_new_rx(lro_t *lro, struct iphdr *ip,
+               struct tcphdr *tcp, u32 l4_pyld)
+{
+       DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
+       lro->total_len += l4_pyld;
+       lro->frags_len += l4_pyld;
+       lro->tcp_next_seq += l4_pyld;
+       lro->sg_num++;
+
+       /* Update ack seq no. and window ad(from this pkt) in LRO object */
+       lro->tcp_ack = tcp->ack_seq;
+       lro->window = tcp->window;
+       
+       if (lro->saw_ts) {
+               u32 *ptr;
+               /* Update tsecr and tsval from this packet */
+               ptr = (u32 *) (tcp + 1);
+               lro->cur_tsval = *(ptr + 1); 
+               lro->cur_tsecr = *(ptr + 2);
+       }
+}
+
+static int verify_l3_l4_lro_capable(lro_t *l_lro, struct iphdr *ip,
+                                   struct tcphdr *tcp, u32 tcp_pyld_len)
+{
+       u8 *ptr;
+
+       DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
+
+       if (!tcp_pyld_len) {
+               /* Runt frame or a pure ack */
+               return -1;
+       }
+
+       if (ip->ihl != 5) /* IP has options */
+               return -1;
+
+       if (tcp->urg || tcp->psh || tcp->rst || tcp->syn || tcp->fin ||
+                                                               !tcp->ack) {
+               /*
+                * Currently recognize only the ack control word and
+                * any other control field being set would result in
+                * flushing the LRO session
+                */
+               return -1;
+       }
+
+       /* 
+        * Allow only one TCP timestamp option. Don't aggregate if
+        * any other options are detected.
+        */
+       if (tcp->doff != 5 && tcp->doff != 8)
+               return -1;
+
+       if (tcp->doff == 8) {
+               ptr = (u8 *)(tcp + 1);  
+               while (*ptr == TCPOPT_NOP)
+                       ptr++;
+               if (*ptr != TCPOPT_TIMESTAMP || *(ptr+1) != TCPOLEN_TIMESTAMP)
+                       return -1;
+
+               /* Ensure timestamp value increases monotonically */
+               if (l_lro)
+                       if (l_lro->cur_tsval > *((u32 *)(ptr+2)))
+                               return -1;
+
+               /* timestamp echo reply should be non-zero */
+               if (*((u32 *)(ptr+6)) == 0) 
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int
+s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, lro_t **lro,
+                     RxD_t *rxdp, nic_t *sp)
+{
+       struct iphdr *ip;
+       struct tcphdr *tcph;
+       int ret = 0, i;
+
+       if (!(ret = check_L2_lro_capable(buffer, &ip, (struct tcphdr **)tcp,
+                                        rxdp))) {
+               DBG_PRINT(INFO_DBG,"IP Saddr: %x Daddr: %x\n",
+                         ip->saddr, ip->daddr);
+       } else {
+               return ret;
+       }
+
+       tcph = (struct tcphdr *)*tcp;
+       *tcp_len = get_l4_pyld_length(ip, tcph);
+       for (i=0; i<MAX_LRO_SESSIONS; i++) {
+               lro_t *l_lro = &sp->lro0_n[i];
+               if (l_lro->in_use) {
+                       if (check_for_socket_match(l_lro, ip, tcph))
+                               continue;
+                       /* Sock pair matched */
+                       *lro = l_lro;
+
+                       if ((*lro)->tcp_next_seq != ntohl(tcph->seq)) {
+                               DBG_PRINT(INFO_DBG, "%s:Out of order. expected "
+                                         "0x%x, actual 0x%x\n", __FUNCTION__,
+                                         (*lro)->tcp_next_seq,
+                                         ntohl(tcph->seq));
+
+                               sp->mac_control.stats_info->
+                                  sw_stat.outof_sequence_pkts++;
+                               ret = 2;
+                               break;
+                       }
+
+                       if (!verify_l3_l4_lro_capable(l_lro, ip, tcph,*tcp_len))
+                               ret = 1; /* Aggregate */
+                       else
+                               ret = 2; /* Flush both */
+                       break;
+               }
+       }
+
+       if (ret == 0) {
+               /* Before searching for available LRO objects,
+                * check if the pkt is L3/L4 aggregatable. If not
+                * don't create new LRO session. Just send this
+                * packet up.
+                */
+               if (verify_l3_l4_lro_capable(NULL, ip, tcph, *tcp_len)) {
+                       return 5;
+               }
+
+               for (i=0; i<MAX_LRO_SESSIONS; i++) {
+                       lro_t *l_lro = &sp->lro0_n[i];
+                       if (!(l_lro->in_use)) {
+                               *lro = l_lro;
+                               ret = 3; /* Begin anew */
+                               break;
+                       }
+               }
+       }
+
+       if (ret == 0) { /* sessions exceeded */
+               DBG_PRINT(INFO_DBG,"%s:All LRO sessions already in use\n",
+                         __FUNCTION__);
+               *lro = NULL;
+               return ret;
+       }
+
+       switch (ret) {
+               case 3:
+                       initiate_new_session(*lro, buffer, ip, tcph, *tcp_len);
+                       break;
+               case 2:
+                       update_L3L4_header(sp, *lro);
+                       break;
+               case 1:
+                       aggregate_new_rx(*lro, ip, tcph, *tcp_len);
+                       if ((*lro)->sg_num == sp->lro_max_aggr_per_sess) {
+                               update_L3L4_header(sp, *lro);
+                               ret = 4; /* Flush the LRO */
+                       }
+                       break;
+               default:
+                       DBG_PRINT(ERR_DBG,"%s:Dont know, can't say!!\n",
+                               __FUNCTION__);
+                       break;
+       }
+
+       return ret;
+}
+
+static void clear_lro_session(lro_t *lro)
+{
+       static u16 lro_struct_size = sizeof(lro_t);
+
+       memset(lro, 0, lro_struct_size);
+}
+
+static void queue_rx_frame(struct sk_buff *skb)
+{
+       struct net_device *dev = skb->dev;
+
+       skb->protocol = eth_type_trans(skb, dev);
+#ifdef CONFIG_S2IO_NAPI
+       netif_receive_skb(skb);
+#else
+       netif_rx(skb);
+#endif
+}
+
+static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb,
+                          u32 tcp_len)
+{
+       struct sk_buff *tmp, *first = lro->parent;
+
+       first->len += tcp_len;
+       first->data_len = lro->frags_len;
+       skb_pull(skb, (skb->len - tcp_len));
+       if ((tmp = skb_shinfo(first)->frag_list)) {
+               while (tmp->next)
+                       tmp = tmp->next;
+               tmp->next = skb;
+       }
+       else
+               skb_shinfo(first)->frag_list = skb;
+       sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++;
+       return;
+}
index 852a6a8..0a0b5b2 100644 (file)
@@ -64,7 +64,7 @@ typedef enum xena_max_outstanding_splits {
 #define        INTR_DBG        4
 
 /* Global variable that defines the present debug level of the driver. */
-int debug_level = ERR_DBG;     /* Default level. */
+static int debug_level = ERR_DBG;
 
 /* DEBUG message print. */
 #define DBG_PRINT(dbg_level, args...)  if(!(debug_level<dbg_level)) printk(args)
@@ -78,6 +78,13 @@ int debug_level = ERR_DBG;   /* Default level. */
 typedef struct {
        unsigned long long single_ecc_errs;
        unsigned long long double_ecc_errs;
+       /* LRO statistics */
+       unsigned long long clubbed_frms_cnt;
+       unsigned long long sending_both;
+       unsigned long long outof_sequence_pkts;
+       unsigned long long flush_max_pkts;
+       unsigned long long sum_avg_pkts_aggregated;
+       unsigned long long num_aggregations;
 } swStat_t;
 
 /* The statistics block of Xena */
@@ -268,7 +275,7 @@ typedef struct stat_block {
 #define MAX_RX_RINGS 8
 
 /* FIFO mappings for all possible number of fifos configured */
-int fifo_map[][MAX_TX_FIFOS] = {
+static int fifo_map[][MAX_TX_FIFOS] = {
        {0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 1, 1, 1, 1},
        {0, 0, 0, 1, 1, 1, 2, 2},
@@ -680,6 +687,24 @@ struct msix_info_st {
        u64 data;
 };
 
+/* Data structure to represent a LRO session */
+typedef struct lro {
+       struct sk_buff  *parent;
+       u8              *l2h;
+       struct iphdr    *iph;
+       struct tcphdr   *tcph;
+       u32             tcp_next_seq;
+       u32             tcp_ack;
+       int             total_len;
+       int             frags_len;
+       int             sg_num;
+       int             in_use;
+       u16             window;
+       u32             cur_tsval;
+       u32             cur_tsecr;
+       u8              saw_ts;
+}lro_t;
+
 /* Structure representing one instance of the NIC */
 struct s2io_nic {
        int rxd_mode;
@@ -784,6 +809,13 @@ struct s2io_nic {
 #define XFRAME_II_DEVICE       2
        u8 device_type;
 
+#define MAX_LRO_SESSIONS       32
+       lro_t lro0_n[MAX_LRO_SESSIONS];
+       unsigned long   clubbed_frms_cnt;
+       unsigned long   sending_both;
+       u8              lro;
+       u16             lro_max_aggr_per_sess;
+
 #define INTA   0
 #define MSI    1
 #define MSI_X  2
@@ -911,18 +943,16 @@ static void tx_intr_handler(fifo_info_t *fifo_data);
 static void alarm_intr_handler(struct s2io_nic *sp);
 
 static int s2io_starter(void);
-void s2io_closer(void);
 static void s2io_tx_watchdog(struct net_device *dev);
 static void s2io_tasklet(unsigned long dev_addr);
 static void s2io_set_multicast(struct net_device *dev);
 static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp);
-void s2io_link(nic_t * sp, int link);
-void s2io_reset(nic_t * sp);
+static void s2io_link(nic_t * sp, int link);
 #if defined(CONFIG_S2IO_NAPI)
 static int s2io_poll(struct net_device *dev, int *budget);
 #endif
 static void s2io_init_pci(nic_t * sp);
-int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
+static int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
 static void s2io_alarm_handle(unsigned long data);
 static int s2io_enable_msi(nic_t *nic);
 static irqreturn_t s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs);
@@ -930,14 +960,19 @@ static irqreturn_t
 s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs);
 static irqreturn_t
 s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs);
-int s2io_enable_msi_x(nic_t *nic);
 static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs);
 static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag);
 static struct ethtool_ops netdev_ethtool_ops;
 static void s2io_set_link(unsigned long data);
-int s2io_set_swapper(nic_t * sp);
+static int s2io_set_swapper(nic_t * sp);
 static void s2io_card_down(nic_t *nic);
 static int s2io_card_up(nic_t *nic);
-int get_xena_rev_id(struct pci_dev *pdev);
-void restore_xmsi_data(nic_t *nic);
+static int get_xena_rev_id(struct pci_dev *pdev);
+static void restore_xmsi_data(nic_t *nic);
+
+static int s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, lro_t **lro, RxD_t *rxdp, nic_t *sp);
+static void clear_lro_session(lro_t *lro);
+static void queue_rx_frame(struct sk_buff *skb);
+static void update_L3L4_header(nic_t *sp, lro_t *lro);
+static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, u32 tcp_len);
 #endif                         /* _S2IO_H */
index 7613947..66cf226 100644 (file)
@@ -59,7 +59,7 @@ static char version[] = "sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net)\n";
 #ifdef SB1000_DEBUG
 static int sb1000_debug = SB1000_DEBUG;
 #else
-static int sb1000_debug = 1;
+static const int sb1000_debug = 1;
 #endif
 
 static const int SB1000_IO_EXTENT = 8;
index aa4ca18..f2be9f8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001,2002,2003 Broadcom Corporation
+ * Copyright (C) 2001,2002,2003,2004 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -43,6 +43,7 @@
 #define SBMAC_ETH0_HWADDR "40:00:00:00:01:00"
 #define SBMAC_ETH1_HWADDR "40:00:00:00:01:01"
 #define SBMAC_ETH2_HWADDR "40:00:00:00:01:02"
+#define SBMAC_ETH3_HWADDR "40:00:00:00:01:03"
 #endif
 
 
@@ -57,7 +58,7 @@ static char version1[] __devinitdata =
 
 #define CONFIG_SBMAC_COALESCE
 
-#define MAX_UNITS 3            /* More are supported, limit only on options */
+#define MAX_UNITS 4            /* More are supported, limit only on options */
 
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  (2*HZ)
@@ -85,11 +86,11 @@ MODULE_PARM_DESC(noisy_mii, "MII status messages");
    The media type is usually passed in 'options[]'.
 */
 #ifdef MODULE
-static int options[MAX_UNITS] = {-1, -1, -1};
+static int options[MAX_UNITS] = {-1, -1, -1, -1};
 module_param_array(options, int, NULL, S_IRUGO);
 MODULE_PARM_DESC(options, "1-" __MODULE_STRING(MAX_UNITS));
 
-static int full_duplex[MAX_UNITS] = {-1, -1, -1};
+static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1};
 module_param_array(full_duplex, int, NULL, S_IRUGO);
 MODULE_PARM_DESC(full_duplex, "1-" __MODULE_STRING(MAX_UNITS));
 #endif
@@ -105,13 +106,26 @@ MODULE_PARM_DESC(int_timeout, "Timeout value");
 #endif
 
 #include <asm/sibyte/sb1250.h>
-#include <asm/sibyte/sb1250_defs.h>
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/bcm1480_int.h>
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
 #include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_mac.h>
-#include <asm/sibyte/sb1250_dma.h>
 #include <asm/sibyte/sb1250_int.h>
+#else
+#error invalid SiByte MAC configuation
+#endif
 #include <asm/sibyte/sb1250_scd.h>
+#include <asm/sibyte/sb1250_mac.h>
+#include <asm/sibyte/sb1250_dma.h>
 
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+#define UNIT_INT(n)            (K_BCM1480_INT_MAC_0 + ((n) * 2))
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
+#define UNIT_INT(n)            (K_INT_MAC_0 + (n))
+#else
+#error invalid SiByte MAC configuation
+#endif
 
 /**********************************************************************
  *  Simple types
@@ -1476,10 +1490,10 @@ static void sbmac_channel_start(struct sbmac_softc *s)
         * and make sure that RD_THRSH + WR_THRSH <=128 for pass2 and above
         * Use a larger RD_THRSH for gigabit
         */
-       if (periph_rev >= 2)
-               th_value = 64;
-       else
+       if (soc_type == K_SYS_SOC_TYPE_BCM1250 && periph_rev < 2)
                th_value = 28;
+       else
+               th_value = 64;
 
        fifo = V_MAC_TX_WR_THRSH(4) |   /* Must be '4' or '8' */
                ((s->sbm_speed == sbmac_speed_1000)
@@ -1589,13 +1603,17 @@ static void sbmac_channel_start(struct sbmac_softc *s)
         * Turn on the rest of the bits in the enable register
         */
 
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+       __raw_writeq(M_MAC_RXDMA_EN0 |
+                      M_MAC_TXDMA_EN0, s->sbm_macenable);
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
        __raw_writeq(M_MAC_RXDMA_EN0 |
                       M_MAC_TXDMA_EN0 |
                       M_MAC_RX_ENABLE |
                       M_MAC_TX_ENABLE, s->sbm_macenable);
-
-
-
+#else
+#error invalid SiByte MAC configuation
+#endif
 
 #ifdef CONFIG_SBMAC_COALESCE
        /*
@@ -1786,11 +1804,12 @@ static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
        reg &= ~M_MAC_IPHDR_OFFSET | V_MAC_IPHDR_OFFSET(15);
        __raw_writeq(reg, sc->sbm_rxfilter);
 
-       /* read system identification to determine revision */
-       if (periph_rev >= 2) {
-               sc->rx_hw_checksum = ENABLE;
-       } else {
+       /* BCM1250 pass1 didn't have hardware checksum.  Everything
+          later does.  */
+       if (soc_type == K_SYS_SOC_TYPE_BCM1250 && periph_rev < 2) {
                sc->rx_hw_checksum = DISABLE;
+       } else {
+               sc->rx_hw_checksum = ENABLE;
        }
 }
 
@@ -2220,7 +2239,7 @@ static void sbmac_setmulti(struct sbmac_softc *sc)
 
 
 
-#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR)
+#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR) || defined(SBMAC_ETH3_HWADDR)
 /**********************************************************************
  *  SBMAC_PARSE_XDIGIT(str)
  *
@@ -2792,7 +2811,7 @@ static int sbmac_close(struct net_device *dev)
 
 
 
-#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR)
+#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR) || defined(SBMAC_ETH3_HWADDR)
 static void
 sbmac_setup_hwaddr(int chan,char *addr)
 {
@@ -2818,25 +2837,7 @@ sbmac_init_module(void)
        unsigned long port;
        int chip_max_units;
 
-       /*
-        * For bringup when not using the firmware, we can pre-fill
-        * the MAC addresses using the environment variables
-        * specified in this file (or maybe from the config file?)
-        */
-#ifdef SBMAC_ETH0_HWADDR
-       sbmac_setup_hwaddr(0,SBMAC_ETH0_HWADDR);
-#endif
-#ifdef SBMAC_ETH1_HWADDR
-       sbmac_setup_hwaddr(1,SBMAC_ETH1_HWADDR);
-#endif
-#ifdef SBMAC_ETH2_HWADDR
-       sbmac_setup_hwaddr(2,SBMAC_ETH2_HWADDR);
-#endif
-
-       /*
-        * Walk through the Ethernet controllers and find
-        * those who have their MAC addresses set.
-        */
+       /* Set the number of available units based on the SOC type.  */
        switch (soc_type) {
        case K_SYS_SOC_TYPE_BCM1250:
        case K_SYS_SOC_TYPE_BCM1250_ALT:
@@ -2848,6 +2849,10 @@ sbmac_init_module(void)
        case K_SYS_SOC_TYPE_BCM1250_ALT2: /* Hybrid */
                chip_max_units = 2;
                break;
+       case K_SYS_SOC_TYPE_BCM1x55:
+       case K_SYS_SOC_TYPE_BCM1x80:
+               chip_max_units = 4;
+               break;
        default:
                chip_max_units = 0;
                break;
@@ -2855,6 +2860,32 @@ sbmac_init_module(void)
        if (chip_max_units > MAX_UNITS)
                chip_max_units = MAX_UNITS;
 
+       /*
+        * For bringup when not using the firmware, we can pre-fill
+        * the MAC addresses using the environment variables
+        * specified in this file (or maybe from the config file?)
+        */
+#ifdef SBMAC_ETH0_HWADDR
+       if (chip_max_units > 0)
+         sbmac_setup_hwaddr(0,SBMAC_ETH0_HWADDR);
+#endif
+#ifdef SBMAC_ETH1_HWADDR
+       if (chip_max_units > 1)
+         sbmac_setup_hwaddr(1,SBMAC_ETH1_HWADDR);
+#endif
+#ifdef SBMAC_ETH2_HWADDR
+       if (chip_max_units > 2)
+         sbmac_setup_hwaddr(2,SBMAC_ETH2_HWADDR);
+#endif
+#ifdef SBMAC_ETH3_HWADDR
+       if (chip_max_units > 3)
+         sbmac_setup_hwaddr(3,SBMAC_ETH3_HWADDR);
+#endif
+
+       /*
+        * Walk through the Ethernet controllers and find
+        * those who have their MAC addresses set.
+        */
        for (idx = 0; idx < chip_max_units; idx++) {
 
                /*
@@ -2886,7 +2917,7 @@ sbmac_init_module(void)
 
                printk(KERN_DEBUG "sbmac: configuring MAC at %lx\n", port);
 
-               dev->irq = K_INT_MAC_0 + idx;
+               dev->irq = UNIT_INT(idx);
                dev->base_addr = port;
                dev->mem_end = 0;
                if (sbmac_init(dev, idx)) {
index 79dca39..bcef03f 100644 (file)
@@ -46,6 +46,7 @@ static const char version[] =
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/bitops.h>
+#include <linux/jiffies.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -699,7 +700,7 @@ static void hardware_send_packet(struct net_device * dev, char *buf, int length)
        int ioaddr = dev->base_addr;
        int status = inw(SEEQ_STATUS);
        int transmit_ptr = 0;
-       int tmp;
+       unsigned long tmp;
 
        if (net_debug>4) {
                printk("%s: send 0x%04x\n",dev->name,length);
@@ -724,7 +725,7 @@ static void hardware_send_packet(struct net_device * dev, char *buf, int length)
        
        /* drain FIFO */
        tmp = jiffies;
-       while ( (((status=inw(SEEQ_STATUS)) & SEEQSTAT_FIFO_EMPTY) == 0) && (jiffies - tmp < HZ))
+       while ( (((status=inw(SEEQ_STATUS)) & SEEQSTAT_FIFO_EMPTY) == 0) && time_before(jiffies, tmp + HZ))
                mb();
        
        /* doit ! */
index a4614df..f95a5b0 100644 (file)
@@ -3,6 +3,9 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  */
+
+#undef DEBUG
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/errno.h>
@@ -59,8 +62,6 @@ static char *sgiseeqstr = "SGI Seeq8003";
                            sp->tx_old + (SEEQ_TX_BUFFERS - 1) - sp->tx_new : \
                            sp->tx_old - sp->tx_new - 1)
 
-#define DEBUG
-
 struct sgiseeq_rx_desc {
        volatile struct hpc_dma_desc rdma;
        volatile signed int buf_vaddr;
@@ -209,7 +210,7 @@ static int seeq_init_ring(struct net_device *dev)
 static struct sgiseeq_private *gpriv;
 static struct net_device *gdev;
 
-void sgiseeq_dump_rings(void)
+static void sgiseeq_dump_rings(void)
 {
        static int once;
        struct sgiseeq_rx_desc *r = gpriv->rx_desc;
@@ -311,9 +312,9 @@ static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp
                              struct sgiseeq_regs *sregs)
 {
        struct sgiseeq_rx_desc *rd;
-       struct sk_buff *skb = 0;
+       struct sk_buff *skb = NULL;
        unsigned char pkt_status;
-       unsigned char *pkt_pointer = 0;
+       unsigned char *pkt_pointer = NULL;
        int len = 0;
        unsigned int orig_end = PREV_RX(sp->rx_new);
 
@@ -515,12 +516,6 @@ static inline int sgiseeq_reset(struct net_device *dev)
        return 0;
 }
 
-void sgiseeq_my_reset(void)
-{
-       printk("RESET!\n");
-       sgiseeq_reset(gdev);
-}
-
 static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct sgiseeq_private *sp = netdev_priv(dev);
index 221354e..88e2120 100644 (file)
@@ -83,6 +83,7 @@
 #include <linux/if_arp.h>
 #include <linux/init.h>
 #include <linux/if_shaper.h>
+#include <linux/jiffies.h>
 
 #include <net/dst.h>
 #include <net/arp.h>
@@ -168,7 +169,7 @@ static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev)
                /*
                 *      Queue over time. Spill packet.
                 */
-               if(SHAPERCB(skb)->shapeclock-jiffies > SHAPER_LATENCY) {
+               if(time_after(SHAPERCB(skb)->shapeclock,jiffies + SHAPER_LATENCY)) {
                        dev_kfree_skb(skb);
                        shaper->stats.tx_dropped++;
                } else
index ed4bc91..31dd3f0 100644 (file)
@@ -366,7 +366,7 @@ static const u32 sis190_intr_mask =
  * Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
  * The chips use a 64 element hash table based on the Ethernet CRC.
  */
-static int multicast_filter_limit = 32;
+static const int multicast_filter_limit = 32;
 
 static void __mdio_cmd(void __iomem *ioaddr, u32 ctl)
 {
index 7a952fe..a1cb07c 100644 (file)
@@ -100,7 +100,7 @@ enum {
        SIS_900 = 0,
        SIS_7016
 };
-static char * card_names[] = {
+static const char * card_names[] = {
        "SiS 900 PCI Fast Ethernet",
        "SiS 7016 PCI Fast Ethernet"
 };
@@ -115,7 +115,7 @@ MODULE_DEVICE_TABLE (pci, sis900_pci_tbl);
 
 static void sis900_read_mode(struct net_device *net_dev, int *speed, int *duplex);
 
-static struct mii_chip_info {
+static const struct mii_chip_info {
        const char * name;
        u16 phy_id0;
        u16 phy_id1;
@@ -400,7 +400,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
        void *ring_space;
        long ioaddr;
        int i, ret;
-       char *card_name = card_names[pci_id->driver_data];
+       const char *card_name = card_names[pci_id->driver_data];
        const char *dev_name = pci_name(pci_dev);
 
 /* when built into the kernel, we only print version if device is found */
@@ -1275,7 +1275,7 @@ static void sis900_timer(unsigned long data)
        struct net_device *net_dev = (struct net_device *)data;
        struct sis900_private *sis_priv = net_dev->priv;
        struct mii_phy *mii_phy = sis_priv->mii;
-       static int next_tick = 5*HZ;
+       static const int next_tick = 5*HZ;
        u16 status;
 
        if (!sis_priv->autong_complete){
index 3a2ea4a..423ad06 100644 (file)
@@ -236,18 +236,6 @@ extern     int     SkAddrMcClear(
        SK_U32  PortNumber,
        int     Flags);
 
-extern int     SkAddrXmacMcClear(
-       SK_AC   *pAC,
-       SK_IOC  IoC,
-       SK_U32  PortNumber,
-       int     Flags);
-
-extern int     SkAddrGmacMcClear(
-       SK_AC   *pAC,
-       SK_IOC  IoC,
-       SK_U32  PortNumber,
-       int     Flags);
-
 extern int     SkAddrMcAdd(
        SK_AC           *pAC,
        SK_IOC          IoC,
@@ -255,35 +243,11 @@ extern    int     SkAddrMcAdd(
        SK_MAC_ADDR     *pMc,
        int             Flags);
 
-extern int     SkAddrXmacMcAdd(
-       SK_AC           *pAC,
-       SK_IOC          IoC,
-       SK_U32          PortNumber,
-       SK_MAC_ADDR     *pMc,
-       int             Flags);
-
-extern int     SkAddrGmacMcAdd(
-       SK_AC           *pAC,
-       SK_IOC          IoC,
-       SK_U32          PortNumber,
-       SK_MAC_ADDR     *pMc,
-       int             Flags);
-
 extern int     SkAddrMcUpdate(
        SK_AC   *pAC,
        SK_IOC  IoC,
        SK_U32  PortNumber);
 
-extern int     SkAddrXmacMcUpdate(
-       SK_AC   *pAC,
-       SK_IOC  IoC,
-       SK_U32  PortNumber);
-
-extern int     SkAddrGmacMcUpdate(
-       SK_AC   *pAC,
-       SK_IOC  IoC,
-       SK_U32  PortNumber);
-
 extern int     SkAddrOverride(
        SK_AC           *pAC,
        SK_IOC          IoC,
@@ -297,18 +261,6 @@ extern     int     SkAddrPromiscuousChange(
        SK_U32  PortNumber,
        int     NewPromMode);
 
-extern int     SkAddrXmacPromiscuousChange(
-       SK_AC   *pAC,
-       SK_IOC  IoC,
-       SK_U32  PortNumber,
-       int     NewPromMode);
-
-extern int     SkAddrGmacPromiscuousChange(
-       SK_AC   *pAC,
-       SK_IOC  IoC,
-       SK_U32  PortNumber,
-       int     NewPromMode);   
-
 #ifndef SK_SLIM
 extern int     SkAddrSwap(
        SK_AC   *pAC,
index 2b94adb..6e256bd 100644 (file)
@@ -203,12 +203,6 @@ extern SKCS_STATUS SkCsGetReceiveInfo(
        unsigned        Checksum2,
        int                     NetNumber);
 
-extern void SkCsGetSendInfo(
-       SK_AC                           *pAc,
-       void                            *pIpHeader,
-       SKCS_PACKET_INFO        *pPacketInfo,
-       int                                     NetNumber);
-
 extern void SkCsSetReceiveFlags(
        SK_AC           *pAc,
        unsigned        ReceiveFlags,
index 184f47c..143e635 100644 (file)
@@ -464,12 +464,6 @@ typedef    struct s_GeInit {
 /*
  * public functions in skgeinit.c
  */
-extern void    SkGePollRxD(
-       SK_AC   *pAC,
-       SK_IOC  IoC,
-       int             Port,
-       SK_BOOL PollRxD);
-
 extern void    SkGePollTxD(
        SK_AC   *pAC,
        SK_IOC  IoC,
@@ -522,10 +516,6 @@ extern void        SkGeXmitLED(
        int             Led,
        int             Mode);
 
-extern void    SkGeInitRamIface(
-       SK_AC   *pAC,
-       SK_IOC  IoC);
-
 extern int     SkGeInitAssignRamToQueues(
        SK_AC   *pAC,
        int             ActivePort,
@@ -549,11 +539,6 @@ extern void        SkMacHardRst(
        SK_IOC  IoC,
        int             Port);
 
-extern void    SkMacClearRst(
-       SK_AC   *pAC,
-       SK_IOC  IoC,
-       int             Port);
-
 extern void    SkXmInitMac(
        SK_AC   *pAC,
        SK_IOC  IoC,
@@ -580,11 +565,6 @@ extern void        SkMacFlushTxFifo(
        SK_IOC  IoC,
        int             Port);
 
-extern void    SkMacFlushRxFifo(
-       SK_AC   *pAC,
-       SK_IOC  IoC,
-       int             Port);
-
 extern void    SkMacIrq(
        SK_AC   *pAC,
        SK_IOC  IoC,
@@ -601,12 +581,6 @@ extern void        SkMacAutoNegLipaPhy(
        int             Port,
        SK_U16  IStatus);
 
-extern void  SkMacSetRxTxEn(
-       SK_AC   *pAC,
-       SK_IOC  IoC,
-       int             Port,
-       int             Para);
-
 extern int  SkMacRxTxEnable(
        SK_AC   *pAC,
        SK_IOC  IoC,
@@ -659,16 +633,6 @@ extern void        SkXmClrExactAddr(
        int             StartNum,
        int             StopNum);
 
-extern void    SkXmInitDupMd(
-       SK_AC   *pAC,
-       SK_IOC  IoC,
-       int             Port);
-
-extern void    SkXmInitPauseMd(
-       SK_AC   *pAC,
-       SK_IOC  IoC,
-       int             Port);
-
 extern void    SkXmAutoNegLipaXmac(
        SK_AC   *pAC,
        SK_IOC  IoC,
@@ -729,17 +693,6 @@ extern int SkGmCableDiagStatus(
        int             Port,
        SK_BOOL StartTest);
 
-extern int SkGmEnterLowPowerMode(
-       SK_AC   *pAC,
-       SK_IOC  IoC,
-       int             Port,
-       SK_U8   Mode);
-
-extern int SkGmLeaveLowPowerMode(
-       SK_AC   *pAC,
-       SK_IOC  IoC,
-       int             Port);
-
 #ifdef SK_DIAG
 extern void    SkGePhyRead(
        SK_AC   *pAC,
@@ -782,7 +735,6 @@ extern void SkXmSendCont(
 /*
  * public functions in skgeinit.c
  */
-extern void    SkGePollRxD();
 extern void    SkGePollTxD();
 extern void    SkGeYellowLED();
 extern int     SkGeCfgSync();
@@ -792,7 +744,6 @@ extern int  SkGeInit();
 extern void    SkGeDeInit();
 extern int     SkGeInitPort();
 extern void    SkGeXmitLED();
-extern void    SkGeInitRamIface();
 extern int     SkGeInitAssignRamToQueues();
 
 /*
@@ -801,18 +752,15 @@ extern int        SkGeInitAssignRamToQueues();
 extern void SkMacRxTxDisable();
 extern void    SkMacSoftRst();
 extern void    SkMacHardRst();
-extern void    SkMacClearRst();
 extern void SkMacInitPhy();
 extern int  SkMacRxTxEnable();
 extern void SkMacPromiscMode();
 extern void SkMacHashing();
 extern void SkMacIrqDisable();
 extern void    SkMacFlushTxFifo();
-extern void    SkMacFlushRxFifo();
 extern void    SkMacIrq();
 extern int     SkMacAutoNegDone();
 extern void    SkMacAutoNegLipaPhy();
-extern void SkMacSetRxTxEn();
 extern void    SkXmInitMac();
 extern void    SkXmPhyRead();
 extern void    SkXmPhyWrite();
@@ -820,8 +768,6 @@ extern void SkGmInitMac();
 extern void    SkGmPhyRead();
 extern void    SkGmPhyWrite();
 extern void    SkXmClrExactAddr();
-extern void    SkXmInitDupMd();
-extern void    SkXmInitPauseMd();
 extern void    SkXmAutoNegLipaXmac();
 extern int     SkXmUpdateStats();
 extern int     SkGmUpdateStats();
@@ -832,8 +778,6 @@ extern int  SkGmResetCounter();
 extern int     SkXmOverflowStatus();
 extern int     SkGmOverflowStatus();
 extern int     SkGmCableDiagStatus();
-extern int     SkGmEnterLowPowerMode();
-extern int     SkGmLeaveLowPowerMode();
 
 #ifdef SK_DIAG
 extern void    SkGePhyRead();
index 3b2773e..1ed214c 100644 (file)
@@ -946,10 +946,6 @@ typedef struct s_PnmiData {
  * Function prototypes
  */
 extern int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int Level);
-extern int SkPnmiGetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf,
-       unsigned int* pLen, SK_U32 Instance, SK_U32 NetIndex);
-extern int SkPnmiPreSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id,
-       void* pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
 extern int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf,
        unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
 extern int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
index b486bd9..3eec627 100644 (file)
 
 extern void SkGeSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus);
 extern int  SkGeSirqEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
-extern void SkHWLinkUp(SK_AC *pAC, SK_IOC IoC, int Port);
 extern void SkHWLinkDown(SK_AC *pAC, SK_IOC IoC, int Port);
 
 #endif /* _INC_SKGESIRQ_H_ */
index 598bb42..6a63f4a 100644 (file)
@@ -162,9 +162,6 @@ typedef     struct  s_I2c {
 } SK_I2C;
 
 extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level);
-extern int SkI2cWrite(SK_AC *pAC, SK_IOC IoC, SK_U32 Data, int Dev, int Size,
-                                          int Reg, int Burst);
-extern int SkI2cReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen);
 #ifdef SK_DIAG
 extern SK_U32 SkI2cRead(SK_AC *pAC, SK_IOC IoC, int Dev, int Size, int Reg,
                                                 int Burst);
index daa9a8d..fdd9e48 100644 (file)
@@ -183,14 +183,6 @@ extern SK_U32      VpdReadDWord(
        int                     addr);
 #endif /* SKDIAG */
 
-extern int     VpdSetupPara(
-       SK_AC           *pAC,
-       const char      *key,
-       const char      *buf,
-       int                     len,
-       int                     type,
-       int                     op);
-
 extern SK_VPD_STATUS   *VpdStat(
        SK_AC           *pAC,
        SK_IOC          IoC);
@@ -227,11 +219,6 @@ extern int VpdUpdate(
        SK_AC           *pAC,
        SK_IOC          IoC);
 
-extern void    VpdErrLog(
-       SK_AC           *pAC,
-       SK_IOC          IoC,
-       char            *msg);
-
 #ifdef SKDIAG
 extern int     VpdReadBlock(
        SK_AC           *pAC,
@@ -249,7 +236,6 @@ extern int  VpdWriteBlock(
 #endif /* SKDIAG */
 #else  /* SK_KR_PROTO */
 extern SK_U32  VpdReadDWord();
-extern int     VpdSetupPara();
 extern SK_VPD_STATUS   *VpdStat();
 extern int     VpdKeys();
 extern int     VpdRead();
@@ -257,7 +243,6 @@ extern SK_BOOL      VpdMayWrite();
 extern int     VpdWrite();
 extern int     VpdDelete();
 extern int     VpdUpdate();
-extern void    VpdErrLog();
 #endif /* SK_KR_PROTO */
 
 #endif /* __INC_SKVPD_H_ */
index a7e25ed..6e6c56a 100644 (file)
@@ -87,6 +87,21 @@ static const SK_U16  OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
 static int     Next0[SK_MAX_MACS] = {0};
 #endif /* DEBUG */
 
+static int SkAddrGmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
+                          SK_MAC_ADDR *pMc, int Flags);
+static int SkAddrGmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
+                            int Flags);
+static int SkAddrGmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
+static int SkAddrGmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
+                                      SK_U32 PortNumber, int NewPromMode);
+static int SkAddrXmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
+                          SK_MAC_ADDR *pMc, int Flags);
+static int SkAddrXmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
+                            int Flags);
+static int SkAddrXmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
+static int SkAddrXmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
+                                      SK_U32 PortNumber, int NewPromMode);
+
 /* functions ******************************************************************/
 
 /******************************************************************************
@@ -372,7 +387,7 @@ int         Flags)          /* permanent/non-perm, sw-only */
  *     SK_ADDR_SUCCESS
  *     SK_ADDR_ILLEGAL_PORT
  */
-int    SkAddrXmacMcClear(
+static int     SkAddrXmacMcClear(
 SK_AC  *pAC,           /* adapter context */
 SK_IOC IoC,            /* I/O context */
 SK_U32 PortNumber,     /* Index of affected port */
@@ -429,7 +444,7 @@ int         Flags)          /* permanent/non-perm, sw-only */
  *     SK_ADDR_SUCCESS
  *     SK_ADDR_ILLEGAL_PORT
  */
-int    SkAddrGmacMcClear(
+static int     SkAddrGmacMcClear(
 SK_AC  *pAC,           /* adapter context */
 SK_IOC IoC,            /* I/O context */
 SK_U32 PortNumber,     /* Index of affected port */
@@ -519,7 +534,7 @@ int         Flags)          /* permanent/non-perm, sw-only */
  * Returns:
  *     Hash value of multicast address.
  */
-SK_U32 SkXmacMcHash(
+static SK_U32 SkXmacMcHash(
 unsigned char *pMc)    /* Multicast address */
 {
        SK_U32 Idx;
@@ -557,7 +572,7 @@ unsigned char *pMc) /* Multicast address */
  * Returns:
  *     Hash value of multicast address.
  */
-SK_U32 SkGmacMcHash(
+static SK_U32 SkGmacMcHash(
 unsigned char *pMc)    /* Multicast address */
 {
        SK_U32 Data;
@@ -672,7 +687,7 @@ int                 Flags)          /* permanent/non-permanent */
  *     SK_MC_ILLEGAL_ADDRESS
  *     SK_MC_RLMT_OVERFLOW
  */
-int    SkAddrXmacMcAdd(
+static int     SkAddrXmacMcAdd(
 SK_AC          *pAC,           /* adapter context */
 SK_IOC         IoC,            /* I/O context */
 SK_U32         PortNumber,     /* Port Number */
@@ -778,7 +793,7 @@ int         Flags)          /* permanent/non-permanent */
  *     SK_MC_FILTERING_INEXACT
  *     SK_MC_ILLEGAL_ADDRESS
  */
-int    SkAddrGmacMcAdd(
+static int     SkAddrGmacMcAdd(
 SK_AC          *pAC,           /* adapter context */
 SK_IOC         IoC,            /* I/O context */
 SK_U32         PortNumber,     /* Port Number */
@@ -937,7 +952,7 @@ SK_U32      PortNumber)     /* Port Number */
  *     SK_MC_FILTERING_INEXACT
  *     SK_ADDR_ILLEGAL_PORT
  */
-int    SkAddrXmacMcUpdate(
+static int     SkAddrXmacMcUpdate(
 SK_AC  *pAC,           /* adapter context */
 SK_IOC IoC,            /* I/O context */
 SK_U32 PortNumber)     /* Port Number */
@@ -1082,7 +1097,7 @@ SK_U32    PortNumber)     /* Port Number */
  *     SK_MC_FILTERING_INEXACT
  *     SK_ADDR_ILLEGAL_PORT
  */
-int    SkAddrGmacMcUpdate(
+static int     SkAddrGmacMcUpdate(
 SK_AC  *pAC,           /* adapter context */
 SK_IOC IoC,            /* I/O context */
 SK_U32 PortNumber)     /* Port Number */
@@ -1468,7 +1483,7 @@ int               NewPromMode)    /* new promiscuous mode */
  *     SK_ADDR_SUCCESS
  *     SK_ADDR_ILLEGAL_PORT
  */
-int    SkAddrXmacPromiscuousChange(
+static int     SkAddrXmacPromiscuousChange(
 SK_AC  *pAC,                   /* adapter context */
 SK_IOC IoC,                    /* I/O context */
 SK_U32 PortNumber,             /* port whose promiscuous mode changes */
@@ -1585,7 +1600,7 @@ int               NewPromMode)    /* new promiscuous mode */
  *     SK_ADDR_SUCCESS
  *     SK_ADDR_ILLEGAL_PORT
  */
-int    SkAddrGmacPromiscuousChange(
+static int     SkAddrGmacPromiscuousChange(
 SK_AC  *pAC,                   /* adapter context */
 SK_IOC IoC,                    /* I/O context */
 SK_U32 PortNumber,             /* port whose promiscuous mode changes */
index 6cb49dd..67f1d6a 100644 (file)
@@ -57,34 +57,6 @@ static struct s_Config OemConfig = {
 #endif
 };
 
-/******************************************************************************
- *
- *     SkGePollRxD() - Enable / Disable Descriptor Polling of RxD Ring
- *
- * Description:
- *     Enable or disable the descriptor polling of the receive descriptor
- *     ring (RxD) for port 'Port'.
- *     The new configuration is *not* saved over any SkGeStopPort() and
- *     SkGeInitPort() calls.
- *
- * Returns:
- *     nothing
- */
-void SkGePollRxD(
-SK_AC  *pAC,           /* adapter context */
-SK_IOC IoC,            /* IO context */
-int            Port,           /* Port Index (MAC_1 + n) */
-SK_BOOL PollRxD)       /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */
-{
-       SK_GEPORT *pPrt;
-
-       pPrt = &pAC->GIni.GP[Port];
-
-       SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), (PollRxD) ?
-               CSR_ENA_POL : CSR_DIS_POL);
-}      /* SkGePollRxD */
-
-
 /******************************************************************************
  *
  *     SkGePollTxD() - Enable / Disable Descriptor Polling of TxD Rings
@@ -952,7 +924,7 @@ int         Port)           /* Port Index (MAC_1 + n) */
  * Returns:
  *     nothing
  */
-void SkGeInitRamIface(
+static void SkGeInitRamIface(
 SK_AC  *pAC,           /* adapter context */
 SK_IOC IoC)            /* IO context */
 {
@@ -1409,83 +1381,6 @@ SK_IOC   IoC)            /* IO context */
 
 }      /* SkGeInit0*/
 
-#ifdef SK_PCI_RESET
-
-/******************************************************************************
- *
- *     SkGePciReset() - Reset PCI interface
- *
- * Description:
- *     o Read PCI configuration.
- *     o Change power state to 3.
- *     o Change power state to 0.
- *     o Restore PCI configuration.
- *
- * Returns:
- *     0:      Success.
- *     1:      Power state could not be changed to 3.
- */
-static int SkGePciReset(
-SK_AC  *pAC,           /* adapter context */
-SK_IOC IoC)            /* IO context */
-{
-       int             i;
-       SK_U16  PmCtlSts;
-       SK_U32  Bp1;
-       SK_U32  Bp2;
-       SK_U16  PciCmd;
-       SK_U8   Cls;
-       SK_U8   Lat;
-       SK_U8   ConfigSpace[PCI_CFG_SIZE];
-
-       /*
-        * Note: Switching to D3 state is like a software reset.
-        *               Switching from D3 to D0 is a hardware reset.
-        *               We have to save and restore the configuration space.
-        */
-       for (i = 0; i < PCI_CFG_SIZE; i++) {
-               SkPciReadCfgDWord(pAC, i*4, &ConfigSpace[i]);
-       }
-
-       /* We know the RAM Interface Arbiter is enabled. */
-       SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, PCI_PM_STATE_D3);
-       SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &PmCtlSts);
-       
-       if ((PmCtlSts & PCI_PM_STATE_MSK) != PCI_PM_STATE_D3) {
-               return(1);
-       }
-
-       /* Return to D0 state. */
-       SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, PCI_PM_STATE_D0);
-
-       /* Check for D0 state. */
-       SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &PmCtlSts);
-       
-       if ((PmCtlSts & PCI_PM_STATE_MSK) != PCI_PM_STATE_D0) {
-               return(1);
-       }
-
-       /* Check PCI Config Registers. */
-       SkPciReadCfgWord(pAC, PCI_COMMAND, &PciCmd);
-       SkPciReadCfgByte(pAC, PCI_CACHE_LSZ, &Cls);
-       SkPciReadCfgDWord(pAC, PCI_BASE_1ST, &Bp1);
-       SkPciReadCfgDWord(pAC, PCI_BASE_2ND, &Bp2);
-       SkPciReadCfgByte(pAC, PCI_LAT_TIM, &Lat);
-       
-       if (PciCmd != 0 || Cls != (SK_U8)0 || Lat != (SK_U8)0 ||
-               (Bp1 & 0xfffffff0L) != 0 || Bp2 != 1) {
-               return(1);
-       }
-
-       /* Restore PCI Config Space. */
-       for (i = 0; i < PCI_CFG_SIZE; i++) {
-               SkPciWriteCfgDWord(pAC, i*4, ConfigSpace[i]);
-       }
-
-       return(0);
-}      /* SkGePciReset */
-
-#endif /* SK_PCI_RESET */
 
 /******************************************************************************
  *
@@ -1524,10 +1419,6 @@ SK_IOC   IoC)            /* IO context */
        /* save CLK_RUN bits (YUKON-Lite) */
        SK_IN16(IoC, B0_CTST, &CtrlStat);
 
-#ifdef SK_PCI_RESET
-       (void)SkGePciReset(pAC, IoC);
-#endif /* SK_PCI_RESET */
-
        /* do the SW-reset */
        SK_OUT8(IoC, B0_CTST, CS_RST_SET);
 
@@ -1991,11 +1882,6 @@ SK_IOC   IoC)            /* IO context */
        int     i;
        SK_U16  Word;
 
-#ifdef SK_PHY_LP_MODE
-       SK_U8   Byte;
-       SK_U16  PmCtlSts;
-#endif /* SK_PHY_LP_MODE */
-
 #if (!defined(SK_SLIM) && !defined(VCPU))
        /* ensure I2C is ready */
        SkI2cWaitIrq(pAC, IoC);
@@ -2010,38 +1896,6 @@ SK_IOC   IoC)            /* IO context */
                }
        }
 
-#ifdef SK_PHY_LP_MODE
-    /*
-        * for power saving purposes within mobile environments
-        * we set the PHY to coma mode and switch to D3 power state.
-        */
-       if (pAC->GIni.GIYukonLite &&
-               pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
-
-               /* for all ports switch PHY to coma mode */
-               for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-                       
-                       SkGmEnterLowPowerMode(pAC, IoC, i, PHY_PM_DEEP_SLEEP);
-               }
-
-               if (pAC->GIni.GIVauxAvail) {
-                       /* switch power to VAUX */
-                       Byte = PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF;
-
-                       SK_OUT8(IoC, B0_POWER_CTRL, Byte);
-               }
-               
-               /* switch to D3 state */
-               SK_IN16(IoC, PCI_C(PCI_PM_CTL_STS), &PmCtlSts);
-
-               PmCtlSts |= PCI_PM_STATE_D3;
-
-               SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-
-               SK_OUT16(IoC, PCI_C(PCI_PM_CTL_STS), PmCtlSts);
-       }
-#endif /* SK_PHY_LP_MODE */
-
        /* Reset all bits in the PCI STATUS register */
        /*
         * Note: PCI Cfg cycles cannot be used, because they are not
index 2991bc8..0a6f67a 100644 (file)
@@ -871,13 +871,6 @@ PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = {
                sizeof(SK_PNMI_CONF),
                SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyType),
                SK_PNMI_RO, MacPrivateConf, 0},
-#ifdef SK_PHY_LP_MODE
-               {OID_SKGE_PHY_LP_MODE,
-               SK_PNMI_MAC_ENTRIES,
-               sizeof(SK_PNMI_CONF),
-               SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyMode),
-               SK_PNMI_RW, MacPrivateConf, 0},
-#endif 
        {OID_SKGE_LINK_CAP,
                SK_PNMI_MAC_ENTRIES,
                sizeof(SK_PNMI_CONF),
index a386172..b36dd9a 100644 (file)
@@ -56,10 +56,6 @@ static const char SysKonnectFileId[] =
  * Public Function prototypes
  */
 int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level);
-int SkPnmiGetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
-       unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
-int SkPnmiPreSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
-       unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
 int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
        unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
 int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
@@ -587,7 +583,7 @@ int Level)          /* Initialization level */
  *                           exist (e.g. port instance 3 on a two port
  *                              adapter.
  */
-int SkPnmiGetVar(
+static int SkPnmiGetVar(
 SK_AC *pAC,            /* Pointer to adapter context */
 SK_IOC IoC,            /* IO context handle */
 SK_U32 Id,             /* Object ID that is to be processed */
@@ -629,7 +625,7 @@ SK_U32 NetIndex)    /* NetIndex (0..n), in single net mode always zero */
  *                           exist (e.g. port instance 3 on a two port
  *                              adapter.
  */
-int SkPnmiPreSetVar(
+static int SkPnmiPreSetVar(
 SK_AC *pAC,            /* Pointer to adapter context */
 SK_IOC IoC,            /* IO context handle */
 SK_U32 Id,             /* Object ID that is to be processed */
@@ -5062,9 +5058,6 @@ SK_U32 NetIndex)  /* NetIndex (0..n), in single net mode always zero */
                case OID_SKGE_SPEED_CAP:
                case OID_SKGE_SPEED_MODE:
                case OID_SKGE_SPEED_STATUS:
-#ifdef SK_PHY_LP_MODE
-               case OID_SKGE_PHY_LP_MODE:
-#endif
                        if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) {
 
                                *pLen = (Limit - LogPortIndex) * sizeof(SK_U8);
@@ -5140,28 +5133,6 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
                                Offset += sizeof(SK_U32);
                                break;
 
-#ifdef SK_PHY_LP_MODE
-                       case OID_SKGE_PHY_LP_MODE:
-                               if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-                                       if (LogPortIndex == 0) {
-                                               continue;
-                                       }
-                                       else {
-                                               /* Get value for physical ports */
-                                               PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
-                                               Val8 = (SK_U8) pAC->GIni.GP[PhysPortIndex].PPhyPowerState;
-                                               *pBufPtr = Val8;
-                                       }
-                               }
-                               else { /* DualNetMode */
-                                       
-                                       Val8 = (SK_U8) pAC->GIni.GP[PhysPortIndex].PPhyPowerState;
-                                       *pBufPtr = Val8;
-                               }
-                               Offset += sizeof(SK_U8);
-                               break;
-#endif
-
                        case OID_SKGE_LINK_CAP:
                                if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
                                        if (LogPortIndex == 0) {
@@ -5478,16 +5449,6 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
                }
                break;
 
-#ifdef SK_PHY_LP_MODE
-       case OID_SKGE_PHY_LP_MODE:
-               if (*pLen < Limit - LogPortIndex) {
-
-                       *pLen = Limit - LogPortIndex;
-                       return (SK_PNMI_ERR_TOO_SHORT);
-               }
-               break;
-#endif
-
        case OID_SKGE_MTU:
                if (*pLen < sizeof(SK_U32)) {
 
@@ -5845,116 +5806,6 @@ SK_U32 NetIndex)        /* NetIndex (0..n), in single net mode always zero */
                        Offset += sizeof(SK_U32);
                        break;
                
-#ifdef SK_PHY_LP_MODE
-               case OID_SKGE_PHY_LP_MODE:
-                       /* The preset ends here */
-                       if (Action == SK_PNMI_PRESET) {
-
-                               return (SK_PNMI_ERR_OK);
-                       }
-
-                       if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-                               if (LogPortIndex == 0) {
-                                       Offset = 0;
-                                       continue;
-                               }
-                               else {
-                                       /* Set value for physical ports */
-                                       PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
-
-                                       switch (*(pBuf + Offset)) {
-                                               case 0:
-                                                       /* If LowPowerMode is active, we can leave it. */
-                                                       if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState) {
-
-                                                               Val32 = SkGmLeaveLowPowerMode(pAC, IoC, PhysPortIndex);
-                                                               
-                                                               if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState < 3)     {
-                                                                       
-                                                                       SkDrvInitAdapter(pAC);
-                                                               }
-                                                               break;
-                                                       }
-                                                       else {
-                                                               *pLen = 0;
-                                                               return (SK_PNMI_ERR_GENERAL);
-                                                       }
-                                               case 1:
-                                               case 2:
-                                               case 3:
-                                               case 4:
-                                                       /* If no LowPowerMode is active, we can enter it. */
-                                                       if (!pAC->GIni.GP[PhysPortIndex].PPhyPowerState) {
-
-                                                               if ((*(pBuf + Offset)) < 3)     {
-                                                               
-                                                                       SkDrvDeInitAdapter(pAC);
-                                                               }
-
-                                                               Val32 = SkGmEnterLowPowerMode(pAC, IoC, PhysPortIndex, *pBuf);
-                                                               break;
-                                                       }
-                                                       else {
-                                                               *pLen = 0;
-                                                               return (SK_PNMI_ERR_GENERAL);
-                                                       }
-                                               default:
-                                                       *pLen = 0;
-                                                       return (SK_PNMI_ERR_BAD_VALUE);
-                                       }
-                               }
-                       }
-                       else { /* DualNetMode */
-                               
-                               switch (*(pBuf + Offset)) {
-                                       case 0:
-                                               /* If we are in a LowPowerMode, we can leave it. */
-                                               if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState) {
-
-                                                       Val32 = SkGmLeaveLowPowerMode(pAC, IoC, PhysPortIndex);
-                                                       
-                                                       if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState < 3)     {
-
-                                                               SkDrvInitAdapter(pAC);
-                                                       }
-                                                       break;
-                                               }
-                                               else {
-                                                       *pLen = 0;
-                                                       return (SK_PNMI_ERR_GENERAL);
-                                               }
-                                       
-                                       case 1:
-                                       case 2:
-                                       case 3:
-                                       case 4:
-                                               /* If we are not already in LowPowerMode, we can enter it. */
-                                               if (!pAC->GIni.GP[PhysPortIndex].PPhyPowerState) {
-
-                                                       if ((*(pBuf + Offset)) < 3)     {
-
-                                                               SkDrvDeInitAdapter(pAC);
-                                                       }
-                                                       else {
-
-                                                               Val32 = SkGmEnterLowPowerMode(pAC, IoC, PhysPortIndex, *pBuf);
-                                                       }
-                                                       break;
-                                               }
-                                               else {
-                                                       *pLen = 0;
-                                                       return (SK_PNMI_ERR_GENERAL);
-                                               }
-                                       
-                                       default:
-                                               *pLen = 0;
-                                               return (SK_PNMI_ERR_BAD_VALUE);
-                               }
-                       }
-                       Offset += sizeof(SK_U8);
-                       break;
-#endif
-
                default:
             SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
                 ("MacPrivateConf: Unknown OID should be handled before set"));
index 87520f0..ab66d80 100644 (file)
@@ -265,7 +265,7 @@ int         Port)           /* Port Index (MAC_1 + n) */
  *
  * Returns: N/A
  */
-void SkHWLinkUp(
+static void SkHWLinkUp(
 SK_AC  *pAC,   /* adapter context */
 SK_IOC IoC,    /* IO context */
 int            Port)   /* Port Index (MAC_1 + n) */
@@ -612,14 +612,6 @@ SK_U32     Istatus)        /* Interrupt status word */
                                 * we ignore those
                                 */
                                pPrt->HalfDupTimerActive = SK_TRUE;
-#ifdef XXX
-                               Len = sizeof(SK_U64);
-                               SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets,
-                                       &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, 0),
-                                       pAC->Rlmt.Port[0].Net->NetNumber);
-                               
-                               pPrt->LastOctets = Octets;
-#endif /* XXX */
                                /* Snap statistic counters */
                                (void)SkXmUpdateStats(pAC, IoC, 0);
 
@@ -653,14 +645,6 @@ SK_U32     Istatus)        /* Interrupt status word */
                                 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
                                !pPrt->HalfDupTimerActive) {
                                pPrt->HalfDupTimerActive = SK_TRUE;
-#ifdef XXX
-                               Len = sizeof(SK_U64);
-                               SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets,
-                                       &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, 1),
-                                       pAC->Rlmt.Port[1].Net->NetNumber);
-                               
-                               pPrt->LastOctets = Octets;
-#endif /* XXX */
                                /* Snap statistic counters */
                                (void)SkXmUpdateStats(pAC, IoC, 1);
 
@@ -2085,12 +2069,6 @@ SK_EVPARA        Para)           /* Event specific Parameter */
                        pPrt->HalfDupTimerActive = SK_FALSE;
                        if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
                                pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) {
-#ifdef XXX
-                               Len = sizeof(SK_U64);
-                               SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets,
-                                       &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port),
-                                       pAC->Rlmt.Port[Port].Net->NetNumber);
-#endif /* XXX */
                                /* Snap statistic counters */
                                (void)SkXmUpdateStats(pAC, IoC, Port);
 
index 075a046..79bf57c 100644 (file)
@@ -396,7 +396,7 @@ int         Rw)             /* Read / Write Flag */
  *                     1:      error,   transfer does not complete, I2C transfer
  *                                              killed, wait loop terminated.
  */
-int    SkI2cWait(
+static int     SkI2cWait(
 SK_AC  *pAC,   /* Adapter Context */
 SK_IOC IoC,    /* I/O Context */
 int            Event)  /* complete event to wait for (I2C_READ or I2C_WRITE) */
@@ -481,7 +481,7 @@ SK_IOC      IoC)    /* I/O Context */
  * returns     0:      success
  *                     1:      error
  */
-int SkI2cWrite(
+static int SkI2cWrite(
 SK_AC  *pAC,           /* Adapter Context */
 SK_IOC IoC,            /* I/O Context */
 SK_U32 I2cData,        /* I2C Data to write */
@@ -538,7 +538,7 @@ int         I2cBurst)       /* I2C Burst Flag */
  *             1 if the read is completed
  *             0 if the read must be continued (I2C Bus still allocated)
  */
-int    SkI2cReadSensor(
+static int     SkI2cReadSensor(
 SK_AC          *pAC,   /* Adapter Context */
 SK_IOC         IoC,    /* I/O Context */
 SK_SENSOR      *pSen)  /* Sensor to be read */
index 68292d1..a204f5b 100644 (file)
@@ -34,79 +34,7 @@ static const char SysKonnectFileId[] =
 #include "h/lm80.h"
 #include "h/skdrv2nd.h"                /* Adapter Control- and Driver specific Def. */
 
-#ifdef SK_DIAG
-#define        BREAK_OR_WAIT(pAC,IoC,Event)    SkI2cWait(pAC,IoC,Event)
-#else  /* nSK_DIAG */
 #define        BREAK_OR_WAIT(pAC,IoC,Event)    break
-#endif /* nSK_DIAG */
-
-#ifdef SK_DIAG
-/*
- * read the register 'Reg' from the device 'Dev'
- *
- * return      read error      -1
- *             success         the read value
- */
-int    SkLm80RcvReg(
-SK_IOC IoC,            /* Adapter Context */
-int            Dev,            /* I2C device address */
-int            Reg)            /* register to read */
-{
-       int     Val = 0;
-       int     TempExt;
-
-       /* Signal device number */
-       if (SkI2cSndDev(IoC, Dev, I2C_WRITE)) {
-               return(-1);
-       }
-
-       if (SkI2cSndByte(IoC, Reg)) {
-               return(-1);
-       }
-
-       /* repeat start */
-       if (SkI2cSndDev(IoC, Dev, I2C_READ)) {
-               return(-1);
-       }
-
-       switch (Reg) {
-       case LM80_TEMP_IN:
-               Val = (int)SkI2cRcvByte(IoC, 1);
-
-               /* First: correct the value: it might be negative */
-               if ((Val & 0x80) != 0) {
-                       /* Value is negative */
-                       Val = Val - 256;
-               }
-               Val = Val * SK_LM80_TEMP_LSB;
-               SkI2cStop(IoC);
-               
-               TempExt = (int)SkLm80RcvReg(IoC, LM80_ADDR, LM80_TEMP_CTRL);
-               
-               if (Val > 0) {
-                       Val += ((TempExt >> 7) * SK_LM80_TEMPEXT_LSB);
-               }
-               else {
-                       Val -= ((TempExt >> 7) * SK_LM80_TEMPEXT_LSB);
-               }
-               return(Val);
-               break;
-       case LM80_VT0_IN:
-       case LM80_VT1_IN:
-       case LM80_VT2_IN:
-       case LM80_VT3_IN:
-               Val = (int)SkI2cRcvByte(IoC, 1) * SK_LM80_VT_LSB;
-               break;
-       
-       default:
-               Val = (int)SkI2cRcvByte(IoC, 1);
-               break;
-       }
-
-       SkI2cStop(IoC);
-       return(Val);
-}
-#endif /* SK_DIAG */
 
 /*
  * read a sensors value (LM80 specific)
index 9ea11ab..be8d1cc 100644 (file)
@@ -282,7 +282,6 @@ typedef struct s_SpTreeRlmtPacket {
 
 SK_MAC_ADDR    SkRlmtMcAddr =  {{0x01,  0x00,  0x5A,  0x52,  0x4C,  0x4D}};
 SK_MAC_ADDR    BridgeMcAddr =  {{0x01,  0x80,  0xC2,  0x00,  0x00,  0x00}};
-SK_MAC_ADDR    BcAddr =                {{0xFF,  0xFF,  0xFF,  0xFF,  0xFF,  0xFF}};
 
 /* local variables ************************************************************/
 
index eb3c898..1778605 100644 (file)
@@ -132,65 +132,6 @@ int                addr)   /* VPD address */
 
 #endif /* SKDIAG */
 
-#if 0
-
-/*
-       Write the dword 'data' at address 'addr' into the VPD EEPROM, and
-       verify that the data is written.
-
- Needed Time:
-
-.                              MIN             MAX
-. -------------------------------------------------------------------
-. write                                1.8 ms          3.6 ms
-. internal write cyles         0.7 ms          7.0 ms
-. -------------------------------------------------------------------
-. over all program time                2.5 ms          10.6 ms
-. read                         1.3 ms          2.6 ms
-. -------------------------------------------------------------------
-. over all                     3.8 ms          13.2 ms
-.
-
-
- Returns       0:      success
-                       1:      error,  I2C transfer does not terminate
-                       2:      error,  data verify error
-
- */
-static int VpdWriteDWord(
-SK_AC  *pAC,   /* pAC pointer */
-SK_IOC IoC,    /* IO Context */
-int            addr,   /* VPD address */
-SK_U32 data)   /* VPD data to write */
-{
-       /* start VPD write */
-       /* Don't swap here, it's a data stream of bytes */
-       SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-               ("VPD write dword at addr 0x%x, data = 0x%x\n",addr,data));
-       VPD_OUT32(pAC, IoC, PCI_VPD_DAT_REG, (SK_U32)data);
-       /* But do it here */
-       addr |= VPD_WRITE;
-
-       VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)(addr | VPD_WRITE));
-
-       /* this may take up to 10,6 ms */
-       if (VpdWait(pAC, IoC, VPD_WRITE)) {
-               SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-                       ("Write Timed Out\n"));
-               return(1);
-       };
-
-       /* verify data */
-       if (VpdReadDWord(pAC, IoC, addr) != data) {
-               SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-                       ("Data Verify Error\n"));
-               return(2);
-       }
-       return(0);
-}      /* VpdWriteDWord */
-
-#endif /* 0 */
-
 /*
  *     Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
  *     or to the I2C EEPROM.
@@ -728,7 +669,7 @@ char        *etp)           /* end pointer input position */
  *             6:      fatal VPD error
  *
  */
-int    VpdSetupPara(
+static int     VpdSetupPara(
 SK_AC  *pAC,           /* common data base */
 const char     *key,   /* keyword to insert */
 const char     *buf,   /* buffer with the keyword value */
@@ -1148,50 +1089,3 @@ SK_IOC   IoC)    /* IO Context */
        return(0);
 }
 
-
-
-/*
- *     Read the contents of the VPD EEPROM and copy it to the VPD buffer
- *     if not already done. If the keyword "VF" is not present it will be
- *     created and the error log message will be stored to this keyword.
- *     If "VF" is not present the error log message will be stored to the
- *     keyword "VL". "VL" will created or overwritten if "VF" is present.
- *     The VPD read/write area is saved to the VPD EEPROM.
- *
- * returns nothing, errors will be ignored.
- */
-void VpdErrLog(
-SK_AC  *pAC,   /* common data base */
-SK_IOC IoC,    /* IO Context */
-char   *msg)   /* error log message */
-{
-       SK_VPD_PARA *v, vf;     /* VF */
-       int len;
-
-       SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX,
-               ("VPD error log msg %s\n", msg));
-       if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
-               if (VpdInit(pAC, IoC) != 0) {
-                       SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-                               ("VPD init error\n"));
-                       return;
-               }
-       }
-
-       len = strlen(msg);
-       if (len > VPD_MAX_LEN) {
-               /* cut it */
-               len = VPD_MAX_LEN;
-       }
-       if ((v = vpd_find_para(pAC, VPD_VF, &vf)) != NULL) {
-               SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("overwrite VL\n"));
-               (void)VpdSetupPara(pAC, VPD_VL, msg, len, VPD_RW_KEY, OWR_KEY);
-       }
-       else {
-               SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("write VF\n"));
-               (void)VpdSetupPara(pAC, VPD_VF, msg, len, VPD_RW_KEY, ADD_KEY);
-       }
-
-       (void)VpdUpdate(pAC, IoC);
-}
-
index 42d2d96..b4e7502 100644 (file)
@@ -41,13 +41,13 @@ static const char SysKonnectFileId[] =
 #endif
 
 #ifdef GENESIS
-BCOM_HACK BcomRegA1Hack[] = {
+static BCOM_HACK BcomRegA1Hack[] = {
  { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
  { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
  { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
  { 0, 0 }
 };
-BCOM_HACK BcomRegC0Hack[] = {
+static BCOM_HACK BcomRegC0Hack[] = {
  { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
  { 0x15, 0x0A04 }, { 0x18, 0x0420 },
  { 0, 0 }
@@ -790,7 +790,7 @@ int         Port)   /* Port Index (MAC_1 + n) */
  * Returns:
  *     nothing
  */
-void SkMacFlushRxFifo(
+static void SkMacFlushRxFifo(
 SK_AC  *pAC,   /* adapter context */
 SK_IOC IoC,    /* IO context */
 int            Port)   /* Port Index (MAC_1 + n) */
@@ -1231,38 +1231,6 @@ int              Port)   /* Port Index (MAC_1 + n) */
 }      /* SkMacHardRst */
 
 
-/******************************************************************************
- *
- *     SkMacClearRst() - Clear the MAC reset
- *
- * Description:        calls a clear MAC reset routine dep. on board type
- *
- * Returns:
- *     nothing
- */
-void SkMacClearRst(
-SK_AC  *pAC,   /* adapter context */
-SK_IOC IoC,    /* IO context */
-int            Port)   /* Port Index (MAC_1 + n) */
-{
-       
-#ifdef GENESIS
-       if (pAC->GIni.GIGenesis) {
-               
-               SkXmClearRst(pAC, IoC, Port);
-       }
-#endif /* GENESIS */
-       
-#ifdef YUKON
-       if (pAC->GIni.GIYukon) {
-               
-               SkGmClearRst(pAC, IoC, Port);
-       }
-#endif /* YUKON */
-
-}      /* SkMacClearRst */
-
-
 #ifdef GENESIS
 /******************************************************************************
  *
@@ -1713,7 +1681,7 @@ int               Port)           /* Port Index (MAC_1 + n) */
  * Returns:
  *     nothing
  */
-void SkXmInitDupMd(
+static void SkXmInitDupMd(
 SK_AC  *pAC,           /* adapter context */
 SK_IOC IoC,            /* IO context */
 int            Port)           /* Port Index (MAC_1 + n) */
@@ -1761,7 +1729,7 @@ int               Port)           /* Port Index (MAC_1 + n) */
  * Returns:
  *     nothing
  */
-void SkXmInitPauseMd(
+static void SkXmInitPauseMd(
 SK_AC  *pAC,           /* adapter context */
 SK_IOC IoC,            /* IO context */
 int            Port)           /* Port Index (MAC_1 + n) */
@@ -2076,283 +2044,7 @@ SK_BOOL DoLoop)         /* Should a Phy LoopBack be set-up? */
 }      /* SkXmInitPhyBcom */
 #endif /* GENESIS */
 
-
 #ifdef YUKON
-#ifndef SK_SLIM
-/******************************************************************************
- *
- *     SkGmEnterLowPowerMode()
- *
- * Description:        
- *     This function sets the Marvell Alaska PHY to the low power mode
- *     given by parameter mode.
- *     The following low power modes are available:
- *             
- *             - Coma Mode (Deep Sleep):
- *                     Power consumption: ~15 - 30 mW
- *                     The PHY cannot wake up on its own.
- *
- *             - IEEE 22.2.4.1.5 compatible power down mode
- *                     Power consumption: ~240 mW
- *                     The PHY cannot wake up on its own.
- *
- *             - energy detect mode
- *                     Power consumption: ~160 mW
- *                     The PHY can wake up on its own by detecting activity
- *                     on the CAT 5 cable.
- *
- *             - energy detect plus mode
- *                     Power consumption: ~150 mW
- *                     The PHY can wake up on its own by detecting activity
- *                     on the CAT 5 cable.
- *                     Connected devices can be woken up by sending normal link
- *                     pulses every one second.
- *
- * Note:
- *
- * Returns:
- *             0: ok
- *             1: error
- */
-int SkGmEnterLowPowerMode(
-SK_AC  *pAC,           /* adapter context */
-SK_IOC IoC,            /* IO context */
-int            Port,           /* Port Index (e.g. MAC_1) */
-SK_U8  Mode)           /* low power mode */
-{
-       SK_U16  Word;
-       SK_U32  DWord;
-       SK_U8   LastMode;
-       int             Ret = 0;
-
-       if (pAC->GIni.GIYukonLite &&
-           pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
-
-               /* save current power mode */
-               LastMode = pAC->GIni.GP[Port].PPhyPowerState;
-               pAC->GIni.GP[Port].PPhyPowerState = Mode;
-
-               switch (Mode) {
-                       /* coma mode (deep sleep) */
-                       case PHY_PM_DEEP_SLEEP:
-                               /* setup General Purpose Control Register */
-                               GM_OUT16(IoC, 0, GM_GP_CTRL, GM_GPCR_FL_PASS |
-                                       GM_GPCR_SPEED_100 | GM_GPCR_AU_ALL_DIS);
-
-                               /* apply COMA mode workaround */
-                               SkGmPhyWrite(pAC, IoC, Port, 29, 0x001f);
-                               SkGmPhyWrite(pAC, IoC, Port, 30, 0xfff3);
-
-                               SK_IN32(IoC, PCI_C(PCI_OUR_REG_1), &DWord);
-
-                               SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-                               
-                               /* Set PHY to Coma Mode */
-                               SK_OUT32(IoC, PCI_C(PCI_OUR_REG_1), DWord | PCI_PHY_COMA);
-                               
-                               SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-
-                       break;
-                       
-                       /* IEEE 22.2.4.1.5 compatible power down mode */
-                       case PHY_PM_IEEE_POWER_DOWN:
-                               /*
-                                * - disable MAC 125 MHz clock
-                                * - allow MAC power down
-                                */
-                               SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
-                               Word |= PHY_M_PC_DIS_125CLK;
-                               Word &= ~PHY_M_PC_MAC_POW_UP;
-                               SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
-
-                               /*
-                                * register changes must be followed by a software
-                                * reset to take effect
-                                */
-                               SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
-                               Word |= PHY_CT_RESET;
-                               SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
-
-                               /* switch IEEE compatible power down mode on */
-                               SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
-                               Word |= PHY_CT_PDOWN;
-                               SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
-                       break;
-
-                       /* energy detect and energy detect plus mode */
-                       case PHY_PM_ENERGY_DETECT:
-                       case PHY_PM_ENERGY_DETECT_PLUS:
-                               /*
-                                * - disable MAC 125 MHz clock
-                                */
-                               SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
-                               Word |= PHY_M_PC_DIS_125CLK;
-                               SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
-                               
-                               /* activate energy detect mode 1 */
-                               SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
-
-                               /* energy detect mode */
-                               if (Mode == PHY_PM_ENERGY_DETECT) {
-                                       Word |= PHY_M_PC_EN_DET;
-                               }
-                               /* energy detect plus mode */
-                               else {
-                                       Word |= PHY_M_PC_EN_DET_PLUS;
-                               }
-
-                               SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
-
-                               /*
-                                * reinitialize the PHY to force a software reset
-                                * which is necessary after the register settings
-                                * for the energy detect modes.
-                                * Furthermore reinitialisation prevents that the
-                                * PHY is running out of a stable state.
-                                */
-                               SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
-                       break;
-
-                       /* don't change current power mode */
-                       default:
-                               pAC->GIni.GP[Port].PPhyPowerState = LastMode;
-                               Ret = 1;
-                       break;
-               }
-       }
-       /* low power modes are not supported by this chip */
-       else {
-               Ret = 1;
-       }
-
-       return(Ret);
-
-}      /* SkGmEnterLowPowerMode */
-
-/******************************************************************************
- *
- *     SkGmLeaveLowPowerMode()
- *
- * Description:        
- *     Leave the current low power mode and switch to normal mode
- *
- * Note:
- *
- * Returns:
- *             0:      ok
- *             1:      error
- */
-int SkGmLeaveLowPowerMode(
-SK_AC  *pAC,           /* adapter context */
-SK_IOC IoC,            /* IO context */
-int            Port)           /* Port Index (e.g. MAC_1) */
-{
-       SK_U32  DWord;
-       SK_U16  Word;
-       SK_U8   LastMode;
-       int             Ret = 0;
-
-       if (pAC->GIni.GIYukonLite &&
-               pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
-
-               /* save current power mode */
-               LastMode = pAC->GIni.GP[Port].PPhyPowerState;
-               pAC->GIni.GP[Port].PPhyPowerState = PHY_PM_OPERATIONAL_MODE;
-
-               switch (LastMode) {
-                       /* coma mode (deep sleep) */
-                       case PHY_PM_DEEP_SLEEP:
-                               SK_IN32(IoC, PCI_C(PCI_OUR_REG_1), &DWord);
-
-                               SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-                               
-                               /* Release PHY from Coma Mode */
-                               SK_OUT32(IoC, PCI_C(PCI_OUR_REG_1), DWord & ~PCI_PHY_COMA);
-                               
-                               SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-                               
-                               SK_IN32(IoC, B2_GP_IO, &DWord);
-
-                               /* set to output */
-                               DWord |= (GP_DIR_9 | GP_IO_9);
-
-                               /* set PHY reset */
-                               SK_OUT32(IoC, B2_GP_IO, DWord);
-
-                               DWord &= ~GP_IO_9; /* clear PHY reset (active high) */
-
-                               /* clear PHY reset */
-                               SK_OUT32(IoC, B2_GP_IO, DWord);
-                       break;
-                       
-                       /* IEEE 22.2.4.1.5 compatible power down mode */
-                       case PHY_PM_IEEE_POWER_DOWN:
-                               /*
-                                * - enable MAC 125 MHz clock
-                                * - set MAC power up
-                                */
-                               SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
-                               Word &= ~PHY_M_PC_DIS_125CLK;
-                               Word |= PHY_M_PC_MAC_POW_UP;
-                               SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
-
-                               /*
-                                * register changes must be followed by a software
-                                * reset to take effect
-                                */
-                               SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
-                               Word |= PHY_CT_RESET;
-                               SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
-
-                               /* switch IEEE compatible power down mode off */
-                               SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
-                               Word &= ~PHY_CT_PDOWN;
-                               SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
-                       break;
-
-                       /* energy detect and energy detect plus mode */
-                       case PHY_PM_ENERGY_DETECT:
-                       case PHY_PM_ENERGY_DETECT_PLUS:
-                               /*
-                                * - enable MAC 125 MHz clock
-                                */
-                               SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
-                               Word &= ~PHY_M_PC_DIS_125CLK;
-                               SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
-                               
-                               /* disable energy detect mode */
-                               SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
-                               Word &= ~PHY_M_PC_EN_DET_MSK;
-                               SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
-
-                               /*
-                                * reinitialize the PHY to force a software reset
-                                * which is necessary after the register settings
-                                * for the energy detect modes.
-                                * Furthermore reinitialisation prevents that the
-                                * PHY is running out of a stable state.
-                                */
-                               SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
-                       break;
-
-                       /* don't change current power mode */
-                       default:
-                               pAC->GIni.GP[Port].PPhyPowerState = LastMode;
-                               Ret = 1;
-                       break;
-               }
-       }
-       /* low power modes are not supported by this chip */
-       else {
-               Ret = 1;
-       }
-
-       return(Ret);
-
-}      /* SkGmLeaveLowPowerMode */
-#endif /* !SK_SLIM */
-
-
 /******************************************************************************
  *
  *     SkGmInitPhyMarv() - Initialize the Marvell Phy registers
@@ -3420,145 +3112,6 @@ int             Port)           /* Port Index (MAC_1 + n) */
 }      /* SkMacAutoNegDone */
 
 
-#ifdef GENESIS
-/******************************************************************************
- *
- *     SkXmSetRxTxEn() - Special Set Rx/Tx Enable and some features in XMAC
- *
- * Description:
- *  sets MAC or PHY LoopBack and Duplex Mode in the MMU Command Reg.
- *  enables Rx/Tx
- *
- * Returns: N/A
- */
-static void SkXmSetRxTxEn(
-SK_AC  *pAC,           /* Adapter Context */
-SK_IOC IoC,            /* IO context */
-int            Port,           /* Port Index (MAC_1 + n) */
-int            Para)           /* Parameter to set: MAC or PHY LoopBack, Duplex Mode */
-{
-       SK_U16  Word;
-
-       XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
-
-       switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
-       case SK_MAC_LOOPB_ON:
-               Word |= XM_MMU_MAC_LB;
-               break;
-       case SK_MAC_LOOPB_OFF:
-               Word &= ~XM_MMU_MAC_LB;
-               break;
-       }
-
-       switch (Para & (SK_PHY_LOOPB_ON | SK_PHY_LOOPB_OFF)) {
-       case SK_PHY_LOOPB_ON:
-               Word |= XM_MMU_GMII_LOOP;
-               break;
-       case SK_PHY_LOOPB_OFF:
-               Word &= ~XM_MMU_GMII_LOOP;
-               break;
-       }
-       
-       switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
-       case SK_PHY_FULLD_ON:
-               Word |= XM_MMU_GMII_FD;
-               break;
-       case SK_PHY_FULLD_OFF:
-               Word &= ~XM_MMU_GMII_FD;
-               break;
-       }
-       
-       XM_OUT16(IoC, Port, XM_MMU_CMD, Word | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
-
-       /* dummy read to ensure writing */
-       XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
-
-}      /* SkXmSetRxTxEn */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *     SkGmSetRxTxEn() - Special Set Rx/Tx Enable and some features in GMAC
- *
- * Description:
- *  sets MAC LoopBack and Duplex Mode in the General Purpose Control Reg.
- *  enables Rx/Tx
- *
- * Returns: N/A
- */
-static void SkGmSetRxTxEn(
-SK_AC  *pAC,           /* Adapter Context */
-SK_IOC IoC,            /* IO context */
-int            Port,           /* Port Index (MAC_1 + n) */
-int            Para)           /* Parameter to set: MAC LoopBack, Duplex Mode */
-{
-       SK_U16  Ctrl;
-       
-       GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
-
-       switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
-       case SK_MAC_LOOPB_ON:
-               Ctrl |= GM_GPCR_LOOP_ENA;
-               break;
-       case SK_MAC_LOOPB_OFF:
-               Ctrl &= ~GM_GPCR_LOOP_ENA;
-               break;
-       }
-
-       switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
-       case SK_PHY_FULLD_ON:
-               Ctrl |= GM_GPCR_DUP_FULL;
-               break;
-       case SK_PHY_FULLD_OFF:
-               Ctrl &= ~GM_GPCR_DUP_FULL;
-               break;
-       }
-       
-    GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Ctrl | GM_GPCR_RX_ENA |
-               GM_GPCR_TX_ENA));
-
-       /* dummy read to ensure writing */
-       GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
-
-}      /* SkGmSetRxTxEn */
-#endif /* YUKON */
-
-
-#ifndef SK_SLIM
-/******************************************************************************
- *
- *     SkMacSetRxTxEn() - Special Set Rx/Tx Enable and parameters
- *
- * Description:        calls the Special Set Rx/Tx Enable routines dep. on board type
- *
- * Returns: N/A
- */
-void SkMacSetRxTxEn(
-SK_AC  *pAC,           /* Adapter Context */
-SK_IOC IoC,            /* IO context */
-int            Port,           /* Port Index (MAC_1 + n) */
-int            Para)
-{
-#ifdef GENESIS
-       if (pAC->GIni.GIGenesis) {
-               
-               SkXmSetRxTxEn(pAC, IoC, Port, Para);
-       }
-#endif /* GENESIS */
-       
-#ifdef YUKON
-       if (pAC->GIni.GIYukon) {
-               
-               SkGmSetRxTxEn(pAC, IoC, Port, Para);
-       }
-#endif /* YUKON */
-
-}      /* SkMacSetRxTxEn */
-#endif /* !SK_SLIM */
-
-
 /******************************************************************************
  *
  *     SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
@@ -3976,7 +3529,7 @@ SK_U16    PhyStat)        /* PHY Status word to analyse */
  * Returns:
  *     nothing
  */
-void SkXmIrq(
+static void SkXmIrq(
 SK_AC  *pAC,           /* adapter context */
 SK_IOC IoC,            /* IO context */
 int            Port)           /* Port Index (MAC_1 + n) */
@@ -4112,7 +3665,7 @@ int               Port)           /* Port Index (MAC_1 + n) */
  * Returns:
  *     nothing
  */
-void SkGmIrq(
+static void SkGmIrq(
 SK_AC  *pAC,           /* adapter context */
 SK_IOC IoC,            /* IO context */
 int            Port)           /* Port Index (MAC_1 + n) */
index a2ed47f..a4b2b69 100644 (file)
@@ -89,21 +89,21 @@ static const u_short my_sagp = 0xffff ;     /* short group address (n.u.) */
 /*
  * useful interrupt bits
  */
-static int mac_imsk1u = FM_STXABRS | FM_STXABRA0 | FM_SXMTABT ;
-static int mac_imsk1l = FM_SQLCKS | FM_SQLCKA0 | FM_SPCEPDS | FM_SPCEPDA0|
+static const int mac_imsk1u = FM_STXABRS | FM_STXABRA0 | FM_SXMTABT ;
+static const int mac_imsk1l = FM_SQLCKS | FM_SQLCKA0 | FM_SPCEPDS | FM_SPCEPDA0|
                        FM_STBURS | FM_STBURA0 ;
 
        /* delete FM_SRBFL after tests */
-static int mac_imsk2u = FM_SERRSF | FM_SNFSLD | FM_SRCVOVR | FM_SRBFL |
+static const int mac_imsk2u = FM_SERRSF | FM_SNFSLD | FM_SRCVOVR | FM_SRBFL |
                        FM_SMYCLM ;
-static int mac_imsk2l = FM_STRTEXR | FM_SDUPCLM | FM_SFRMCTR |
+static const int mac_imsk2l = FM_STRTEXR | FM_SDUPCLM | FM_SFRMCTR |
                        FM_SERRCTR | FM_SLSTCTR |
                        FM_STRTEXP | FM_SMULTDA | FM_SRNGOP ;
 
-static int mac_imsk3u = FM_SRCVOVR2 | FM_SRBFL2 ;
-static int mac_imsk3l = FM_SRPERRQ2 | FM_SRPERRQ1 ;
+static const int mac_imsk3u = FM_SRCVOVR2 | FM_SRBFL2 ;
+static const int mac_imsk3l = FM_SRPERRQ2 | FM_SRPERRQ1 ;
 
-static int mac_beacon_imsk2u = FM_SOTRBEC | FM_SMYBEC | FM_SBEC |
+static const int mac_beacon_imsk2u = FM_SOTRBEC | FM_SMYBEC | FM_SBEC |
                        FM_SLOCLM | FM_SHICLM | FM_SMYCLM | FM_SCLM ;
 
 
index cd0aa4c..74e129f 100644 (file)
@@ -186,7 +186,7 @@ static      const struct plt {
  * Do we need the EBUF error during signaling, too, to detect SUPERNET_3
  * PLL bug?
  */
-static int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
+static const int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
                        PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR;
 #else  /* SUPERNET_3 */
 /*
@@ -195,7 +195,7 @@ static int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
 static int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
                        PL_PCM_ENABLED | PL_SELF_TEST ;
 #endif /* SUPERNET_3 */
-static int plc_imsk_act = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
+static const int plc_imsk_act = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
                        PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR;
 
 /* external functions */
index 4b5ed2c..c7fb613 100644 (file)
@@ -67,7 +67,7 @@
 /* each new release!!! */
 #define VERSION                "2.07"
 
-static const char *boot_msg = 
+static const char * const boot_msg = 
        "SysKonnect FDDI PCI Adapter driver v" VERSION " for\n"
        "  SK-55xx/SK-58xx adapters (SK-NET FDDI-FP/UP/LP)";
 
index d167ded..35b1805 100644 (file)
@@ -201,7 +201,7 @@ static int max_interrupt_work = 20;
 static int mtu;
 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
    The Starfire has a 512 element hash table based on the Ethernet CRC. */
-static int multicast_filter_limit = 512;
+static const int multicast_filter_limit = 512;
 /* Whether to do TCP/UDP checksums in hardware */
 static int enable_hw_cksum = 1;
 
@@ -463,7 +463,7 @@ static struct pci_device_id starfire_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, starfire_pci_tbl);
 
 /* A chip capabilities table, matching the CH_xxx entries in xxx_pci_tbl[] above. */
-static struct chip_info {
+static const struct chip_info {
        const char *name;
        int drv_flags;
 } netdrv_tbl[] __devinitdata = {
@@ -2084,6 +2084,38 @@ static int netdev_close(struct net_device *dev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int starfire_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+
+       if (netif_running(dev)) {
+               netif_device_detach(dev);
+               netdev_close(dev);
+       }
+
+       pci_save_state(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev,state));
+
+       return 0;
+}
+
+static int starfire_resume(struct pci_dev *pdev)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+
+       if (netif_running(dev)) {
+               netdev_open(dev);
+               netif_device_attach(dev);
+       }
+
+       return 0;
+}
+#endif /* CONFIG_PM */
+
 
 static void __devexit starfire_remove_one (struct pci_dev *pdev)
 {
@@ -2115,6 +2147,10 @@ static struct pci_driver starfire_driver = {
        .name           = DRV_NAME,
        .probe          = starfire_init_one,
        .remove         = __devexit_p(starfire_remove_one),
+#ifdef CONFIG_PM
+       .suspend        = starfire_suspend,
+       .resume         = starfire_resume,
+#endif /* CONFIG_PM */
        .id_table       = starfire_pci_tbl,
 };
 
index 0ab9c38..61eec46 100644 (file)
 static int debug = 1;                  /* 1 normal messages, 0 quiet .. 7 verbose. */
 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
    Typical is a 64 element hash table based on the Ethernet CRC.  */
-static int multicast_filter_limit = 32;
+static const int multicast_filter_limit = 32;
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
    Setting to > 1518 effectively disables this feature.
@@ -298,7 +298,7 @@ enum {
 struct pci_id_info {
         const char *name;
 };
-static struct pci_id_info pci_id_tbl[] = {
+static const struct pci_id_info pci_id_tbl[] = {
        {"D-Link DFE-550TX FAST Ethernet Adapter"},
        {"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"},
        {"D-Link DFE-580TX 4 port Server Adapter"},
@@ -633,9 +633,13 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
 
        np->phys[0] = 1;                /* Default setting */
        np->mii_preamble_required++;
+       /*
+        * It seems some phys doesn't deal well with address 0 being accessed
+        * first, so leave address zero to the end of the loop (32 & 31).
+        */
        for (phy = 1; phy <= 32 && phy_idx < MII_CNT; phy++) {
-               int mii_status = mdio_read(dev, phy, MII_BMSR);
                int phyx = phy & 0x1f;
+               int mii_status = mdio_read(dev, phyx, MII_BMSR);
                if (mii_status != 0xffff  &&  mii_status != 0x0000) {
                        np->phys[phy_idx++] = phyx;
                        np->mii_if.advertising = mdio_read(dev, phyx, MII_ADVERTISE);
index d3ddb41..cb0aba9 100644 (file)
@@ -39,7 +39,7 @@
 #include "sungem_phy.h"
 
 /* Link modes of the BCM5400 PHY */
-static int phy_BCM5400_link_table[8][3] = {
+static const int phy_BCM5400_link_table[8][3] = {
        { 0, 0, 0 },    /* No link */
        { 0, 0, 0 },    /* 10BT Half Duplex */
        { 1, 0, 0 },    /* 10BT Full Duplex */
index b8f1524..bd49b25 100644 (file)
@@ -7802,7 +7802,7 @@ static int tg3_test_link(struct tg3 *tp)
 }
 
 /* Only test the commonly used registers */
-static int tg3_test_registers(struct tg3 *tp)
+static const int tg3_test_registers(struct tg3 *tp)
 {
        int i, is_5705;
        u32 offset, read_mask, write_mask, val, save_val, read_val;
@@ -8016,7 +8016,7 @@ out:
 
 static int tg3_do_mem_test(struct tg3 *tp, u32 offset, u32 len)
 {
-       static u32 test_pattern[] = { 0x00000000, 0xffffffff, 0xaa55a55a };
+       static const u32 test_pattern[] = { 0x00000000, 0xffffffff, 0xaa55a55a };
        int i;
        u32 j;
 
@@ -9552,12 +9552,36 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                }
        }
 
-       /* Find msi capability. */
+       /* The EPB bridge inside 5714, 5715, and 5780 cannot support
+        * DMA addresses > 40-bit. This bridge may have other additional
+        * 57xx devices behind it in some 4-port NIC designs for example.
+        * Any tg3 device found behind the bridge will also need the 40-bit
+        * DMA workaround.
+        */
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
                tp->tg3_flags2 |= TG3_FLG2_5780_CLASS;
+               tp->tg3_flags |= TG3_FLAG_40BIT_DMA_BUG;
                tp->msi_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_MSI);
        }
+       else {
+               struct pci_dev *bridge = NULL;
+
+               do {
+                       bridge = pci_get_device(PCI_VENDOR_ID_SERVERWORKS,
+                                               PCI_DEVICE_ID_SERVERWORKS_EPB,
+                                               bridge);
+                       if (bridge && bridge->subordinate &&
+                           (bridge->subordinate->number <=
+                            tp->pdev->bus->number) &&
+                           (bridge->subordinate->subordinate >=
+                            tp->pdev->bus->number)) {
+                               tp->tg3_flags |= TG3_FLAG_40BIT_DMA_BUG;
+                               pci_dev_put(bridge);
+                               break;
+                       }
+               } while (bridge);
+       }
 
        /* Initialize misc host control in PCI block. */
        tp->misc_host_ctrl |= (misc_ctrl_reg &
@@ -10303,7 +10327,14 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
                        u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f);
 
-                       if (ccval == 0x6 || ccval == 0x7)
+                       /* If the 5704 is behind the EPB bridge, we can
+                        * do the less restrictive ONE_DMA workaround for
+                        * better performance.
+                        */
+                       if ((tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG) &&
+                           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
+                               tp->dma_rwctrl |= 0x8000;
+                       else if (ccval == 0x6 || ccval == 0x7)
                                tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
 
                        /* Set bit 23 to enable PCIX hw bug fix */
@@ -10759,19 +10790,20 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                goto err_out_iounmap;
        }
 
-       /* 5714, 5715 and 5780 cannot support DMA addresses > 40-bit.
+       /* The EPB bridge inside 5714, 5715, and 5780 and any
+        * device behind the EPB cannot support DMA addresses > 40-bit.
         * On 64-bit systems with IOMMU, use 40-bit dma_mask.
         * On 64-bit systems without IOMMU, use 64-bit dma_mask and
         * do DMA address check in tg3_start_xmit().
         */
-       if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
+       if (tp->tg3_flags2 & TG3_FLG2_IS_5788)
+               persist_dma_mask = dma_mask = DMA_32BIT_MASK;
+       else if (tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG) {
                persist_dma_mask = dma_mask = DMA_40BIT_MASK;
 #ifdef CONFIG_HIGHMEM
                dma_mask = DMA_64BIT_MASK;
 #endif
-       } else if (tp->tg3_flags2 & TG3_FLG2_IS_5788)
-               persist_dma_mask = dma_mask = DMA_32BIT_MASK;
-       else
+       } else
                persist_dma_mask = dma_mask = DMA_64BIT_MASK;
 
        /* Configure DMA attributes. */
@@ -10908,8 +10940,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
               (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0,
               (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0,
               (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
-       printk(KERN_INFO "%s: dma_rwctrl[%08x]\n",
-              dev->name, tp->dma_rwctrl);
+       printk(KERN_INFO "%s: dma_rwctrl[%08x] dma_mask[%d-bit]\n",
+              dev->name, tp->dma_rwctrl,
+              (pdev->dma_mask == DMA_32BIT_MASK) ? 32 :
+               (((u64) pdev->dma_mask == DMA_40BIT_MASK) ? 40 : 64));
 
        return 0;
 
index 7f4b7f6..7e3b613 100644 (file)
@@ -2163,6 +2163,7 @@ struct tg3 {
 #define TG3_FLAG_10_100_ONLY           0x01000000
 #define TG3_FLAG_PAUSE_AUTONEG         0x02000000
 #define TG3_FLAG_IN_RESET_TASK         0x04000000
+#define TG3_FLAG_40BIT_DMA_BUG         0x08000000
 #define TG3_FLAG_BROKEN_CHECKSUMS      0x10000000
 #define TG3_FLAG_GOT_SERDES_FLOWCTL    0x20000000
 #define TG3_FLAG_SPLIT_MODE            0x40000000
index 97712c3..c58a4c3 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/version.h>
 #include <linux/bitops.h>
+#include <linux/jiffies.h>
 
 #include <net/checksum.h>
 
@@ -512,7 +513,7 @@ static int streamer_reset(struct net_device *dev)
 
        while (!((readw(streamer_mmio + SISR)) & SISR_SRB_REPLY)) {
                msleep_interruptible(100);
-               if (jiffies - t > 40 * HZ) {
+               if (time_after(jiffies, t + 40 * HZ)) {
                        printk(KERN_ERR
                               "IBM PCI tokenring card not responding\n");
                        release_region(dev->base_addr, STREAMER_IO_SPACE);
index 05477d2..23032a7 100644 (file)
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/bitops.h>
+#include <linux/jiffies.h>
 
 #include <net/checksum.h>
 
@@ -307,7 +308,7 @@ static int __devinit olympic_init(struct net_device *dev)
        t=jiffies;
        while((readl(olympic_mmio+BCTL)) & BCTL_SOFTRESET) {
                schedule();             
-               if(jiffies-t > 40*HZ) {
+               if(time_after(jiffies, t + 40*HZ)) {
                        printk(KERN_ERR "IBM PCI tokenring card not responding.\n");
                        return -ENODEV;
                }
@@ -359,7 +360,7 @@ static int __devinit olympic_init(struct net_device *dev)
                t=jiffies;
                while (!readl(olympic_mmio+CLKCTL) & CLKCTL_PAUSE) { 
                        schedule() ; 
-                       if(jiffies-t > 2*HZ) { 
+                       if(time_after(jiffies, t + 2*HZ)) {
                                printk(KERN_ERR "IBM Cardbus tokenring adapter not responsing.\n") ; 
                                return -ENODEV;
                        }
@@ -373,7 +374,7 @@ static int __devinit olympic_init(struct net_device *dev)
        t=jiffies;
        while(!((readl(olympic_mmio+SISR_RR)) & SISR_SRB_REPLY)) {
                schedule();             
-               if(jiffies-t > 15*HZ) {
+               if(time_after(jiffies, t + 15*HZ)) {
                        printk(KERN_ERR "IBM PCI tokenring card not responding.\n");
                        return -ENODEV;
                }
@@ -519,7 +520,7 @@ static int olympic_open(struct net_device *dev)
                                olympic_priv->srb_queued=0;
                                break;
                        }
-                       if ((jiffies-t) > 10*HZ) { 
+                       if (time_after(jiffies, t + 10*HZ)) {
                                printk(KERN_WARNING "%s: SRB timed out. \n",dev->name) ; 
                                olympic_priv->srb_queued=0;
                                break ; 
index 2d0cfbc..6299e18 100644 (file)
@@ -402,8 +402,7 @@ static void de_rx (struct de_private *de)
                unsigned copying_skb, buflen;
 
                skb = de->rx_skb[rx_tail].skb;
-               if (!skb)
-                       BUG();
+               BUG_ON(!skb);
                rmb();
                status = le32_to_cpu(de->rx_ring[rx_tail].opts1);
                if (status & DescOwn)
@@ -545,8 +544,7 @@ static void de_tx (struct de_private *de)
                        break;
 
                skb = de->tx_skb[tx_tail].skb;
-               if (!skb)
-                       BUG();
+               BUG_ON(!skb);
                if (unlikely(skb == DE_DUMMY_SKB))
                        goto next;
 
@@ -789,8 +787,7 @@ static void __de_set_rx_mode (struct net_device *dev)
 
        de->tx_head = NEXT_TX(entry);
 
-       if (TX_BUFFS_AVAIL(de) < 0)
-               BUG();
+       BUG_ON(TX_BUFFS_AVAIL(de) < 0);
        if (TX_BUFFS_AVAIL(de) == 0)
                netif_stop_queue(dev);
 
@@ -916,8 +913,7 @@ static void de_set_media (struct de_private *de)
        unsigned media = de->media_type;
        u32 macmode = dr32(MacMode);
 
-       if (de_is_running(de))
-               BUG();
+       BUG_ON(de_is_running(de));
 
        if (de->de21040)
                dw32(CSR11, FULL_DUPLEX_MAGIC);
@@ -1153,8 +1149,7 @@ static void de_media_interrupt (struct de_private *de, u32 status)
                return;
        }
        
-       if (!(status & LinkFail))
-               BUG();
+       BUG_ON(!(status & LinkFail));
 
        if (netif_carrier_ok(de->dev)) {
                de_link_down(de);
@@ -2092,8 +2087,7 @@ static void __exit de_remove_one (struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata(pdev);
        struct de_private *de = dev->priv;
 
-       if (!dev)
-               BUG();
+       BUG_ON(!dev);
        unregister_netdev(dev);
        kfree(de->ee_data);
        iounmap(de->regs);
index d9980bd..ca7e532 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/jiffies.h>
 #include "tulip.h"
 
 
@@ -68,7 +69,7 @@ void pnic_lnk_change(struct net_device *dev, int csr5)
                 */
                if (tulip_media_cap[dev->if_port] & MediaIsMII)
                        return;
-               if (! tp->nwayset  ||  jiffies - dev->trans_start > 1*HZ) {
+               if (! tp->nwayset  ||  time_after(jiffies, dev->trans_start + 1*HZ)) {
                        tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff);
                        iowrite32(tp->csr6, ioaddr + CSR6);
                        iowrite32(0x30, ioaddr + CSR12);
index 5b1af39..ba05ded 100644 (file)
@@ -1645,7 +1645,7 @@ static int w840_suspend (struct pci_dev *pdev, pm_message_t state)
 
                /* no more hardware accesses behind this line. */
 
-               if (np->csr6) BUG();
+               BUG_ON(np->csr6);
                if (ioread32(ioaddr + IntrEnable)) BUG();
 
                /* pci_power_off(pdev, -1); */
index 60d1e05..5634410 100644 (file)
@@ -32,6 +32,9 @@
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
+#ifdef CONFIG_NET_POLL_CONTROLLER
+#include <asm/irq.h>
+#endif
 
 #ifdef DEBUG
 #define enter(x)   printk("Enter: %s, %s line %i\n",x,__FILE__,__LINE__)
@@ -598,10 +601,8 @@ static void setup_descriptors(struct xircom_private *card)
        enter("setup_descriptors");
 
 
-       if (card->rx_buffer == NULL)
-               BUG();
-       if (card->tx_buffer == NULL)
-               BUG();
+       BUG_ON(card->rx_buffer == NULL);
+       BUG_ON(card->tx_buffer == NULL);
 
        /* Receive descriptors */
        memset(card->rx_buffer, 0, 128);        /* clear the descriptors */
index 4c76cb7..cde35dd 100644 (file)
@@ -178,7 +178,7 @@ enum typhoon_cards {
 };
 
 /* directly indexed by enum typhoon_cards, above */
-static struct typhoon_card_info typhoon_card_info[] __devinitdata = {
+static const struct typhoon_card_info typhoon_card_info[] __devinitdata = {
        { "3Com Typhoon (3C990-TX)",
                TYPHOON_CRYPTO_NONE},
        { "3Com Typhoon (3CR990-TX-95)",
index 18c27e1..883cf7d 100644 (file)
@@ -459,7 +459,7 @@ config WANPIPE_FR
        bool "WANPIPE Frame Relay support"
        depends on VENDOR_SANGOMA
        help
-         Connect a WANPIPE card to a Frame Relay network, or use Frame Felay
+         Connect a WANPIPE card to a Frame Relay network, or use Frame Relay
          API to develop custom applications.
 
          Contains the Ethernet Bridging over Frame Relay feature, where
index 7db1d1d..cf5c805 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/ioport.h>
 #include <net/arp.h>
 
+#include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/byteorder.h>
index 5380ddf..050e854 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <net/arp.h>
 
+#include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/byteorder.h>
index ef85d76..5b0a19a 100644 (file)
@@ -6,7 +6,8 @@ menu "Wireless LAN (non-hamradio)"
        depends on NETDEVICES
 
 config NET_RADIO
-       bool "Wireless LAN drivers (non-hamradio) & Wireless Extensions"
+       bool "Wireless LAN drivers (non-hamradio)"
+       select WIRELESS_EXT
        ---help---
          Support for wireless LANs and everything having to do with radio,
          but not with amateur radio or FM broadcasting.
@@ -135,8 +136,9 @@ comment "Wireless 802.11b ISA/PCI cards support"
 
 config IPW2100
        tristate "Intel PRO/Wireless 2100 Network Connection"
-       depends on NET_RADIO && PCI && IEEE80211
+       depends on NET_RADIO && PCI
        select FW_LOADER
+       select IEEE80211
        ---help---
           A driver for the Intel PRO/Wireless 2100 Network 
          Connection 802.11b wireless network adapter.
@@ -188,8 +190,9 @@ config IPW2100_DEBUG
 
 config IPW2200
        tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
-       depends on NET_RADIO && IEEE80211 && PCI
+       depends on NET_RADIO && PCI
        select FW_LOADER
+       select IEEE80211
        ---help---
           A driver for the Intel PRO/Wireless 2200BG and 2915ABG Network
          Connection adapters. 
@@ -201,7 +204,7 @@ config IPW2200
          In order to use this driver, you will need a firmware image for it.
           You can obtain the firmware from
          <http://ipw2200.sf.net/>.  See the above referenced README.ipw2200 
-         for information on where to install the firmare images.
+         for information on where to install the firmware images.
 
           You will also very likely need the Wireless Tools in order to
           configure your card:
@@ -213,6 +216,19 @@ config IPW2200
           say M here and read <file:Documentation/modules.txt>.  The module
           will be called ipw2200.ko.
 
+config IPW2200_MONITOR
+        bool "Enable promiscuous mode"
+        depends on IPW2200
+        ---help---
+         Enables promiscuous/monitor mode support for the ipw2200 driver.
+         With this feature compiled into the driver, you can switch to 
+         promiscuous mode via the Wireless Tool's Monitor mode.  While in this
+         mode, no packets can be sent.
+
+config IPW_QOS
+        bool "Enable QoS support"
+        depends on IPW2200 && EXPERIMENTAL
+
 config IPW2200_DEBUG
        bool "Enable full debugging output in IPW2200 module."
        depends on IPW2200
@@ -239,13 +255,14 @@ config IPW2200_DEBUG
 
 config AIRO
        tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
-       depends on NET_RADIO && ISA_DMA_API && CRYPTO && (PCI || BROKEN)
+       depends on NET_RADIO && ISA_DMA_API && (PCI || BROKEN)
+       select CRYPTO
        ---help---
          This is the standard Linux driver to support Cisco/Aironet ISA and
          PCI 802.11 wireless cards.
          It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X
          - with or without encryption) as well as card before the Cisco
-         aquisition (Aironet 4500, Aironet 4800, Aironet 4800B).
+         acquisition (Aironet 4500, Aironet 4800, Aironet 4800B).
 
          This driver support both the standard Linux Wireless Extensions
          and Cisco proprietary API, so both the Linux Wireless Tools and the
@@ -387,13 +404,14 @@ config PCMCIA_SPECTRUM
 config AIRO_CS
        tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards"
        depends on NET_RADIO && PCMCIA && (BROKEN || !M32R)
+       select CRYPTO
        ---help---
          This is the standard Linux driver to support Cisco/Aironet PCMCIA
          802.11 wireless cards.  This driver is the same as the Aironet
          driver part of the Linux Pcmcia package.
          It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X
          - with or without encryption) as well as card before the Cisco
-         aquisition (Aironet 4500, Aironet 4800, Aironet 4800B). It also
+         acquisition (Aironet 4500, Aironet 4800, Aironet 4800B). It also
          supports OEM of Cisco such as the DELL TrueMobile 4800 and Xircom
          802.11b cards.
 
index a4c7ae9..864937a 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/in.h>
 #include <linux/bitops.h>
 #include <linux/scatterlist.h>
+#include <linux/crypto.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -87,14 +88,6 @@ static struct pci_driver airo_driver = {
 #include <linux/delay.h>
 #endif
 
-/* Support Cisco MIC feature */
-#define MICSUPPORT
-
-#if defined(MICSUPPORT) && !defined(CONFIG_CRYPTO)
-#warning MIC support requires Crypto API
-#undef MICSUPPORT
-#endif
-
 /* Hack to do some power saving */
 #define POWER_ON_DOWN
 
@@ -1118,7 +1111,6 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp);
 static int writerids(struct net_device *dev, aironet_ioctl *comp);
 static int flashcard(struct net_device *dev, aironet_ioctl *comp);
 #endif /* CISCO_EXT */
-#ifdef MICSUPPORT
 static void micinit(struct airo_info *ai);
 static int micsetup(struct airo_info *ai);
 static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len);
@@ -1127,9 +1119,6 @@ static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket,
 static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi);
 static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm);
 
-#include <linux/crypto.h>
-#endif
-
 struct airo_info {
        struct net_device_stats stats;
        struct net_device             *dev;
@@ -1190,12 +1179,10 @@ struct airo_info {
        unsigned long           scan_timestamp; /* Time started to scan */
        struct iw_spy_data      spy_data;
        struct iw_public_data   wireless_data;
-#ifdef MICSUPPORT
        /* MIC stuff */
        struct crypto_tfm       *tfm;
        mic_module              mod[2];
        mic_statistics          micstats;
-#endif
        HostRxDesc rxfids[MPI_MAX_FIDS]; // rx/tx/config MPI350 descriptors
        HostTxDesc txfids[MPI_MAX_FIDS];
        HostRidDesc config_desc;
@@ -1229,7 +1216,6 @@ static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime);
 static int flashputbuf(struct airo_info *ai);
 static int flashrestart(struct airo_info *ai,struct net_device *dev);
 
-#ifdef MICSUPPORT
 /***********************************************************************
  *                              MIC ROUTINES                           *
  ***********************************************************************
@@ -1686,7 +1672,6 @@ static void emmh32_final(emmh32_context *context, u8 digest[4])
        digest[2] = (val>>8) & 0xFF;
        digest[3] = val & 0xFF;
 }
-#endif
 
 static int readBSSListRid(struct airo_info *ai, int first,
                      BSSListRid *list) {
@@ -2005,7 +1990,6 @@ static int mpi_send_packet (struct net_device *dev)
         * Firmware automaticly puts 802 header on so
         * we don't need to account for it in the length
         */
-#ifdef MICSUPPORT
        if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled &&
                (ntohs(((u16 *)buffer)[6]) != 0x888E)) {
                MICBuffer pMic;
@@ -2022,9 +2006,7 @@ static int mpi_send_packet (struct net_device *dev)
                memcpy (sendbuf, &pMic, sizeof(pMic));
                sendbuf += sizeof(pMic);
                memcpy (sendbuf, buffer, len - sizeof(etherHead));
-       } else
-#endif
-       {
+       } else {
                *payloadLen = cpu_to_le16(len - sizeof(etherHead));
 
                dev->trans_start = jiffies;
@@ -2400,9 +2382,7 @@ void stop_airo_card( struct net_device *dev, int freeres )
                                ai->shared, ai->shared_dma);
                }
         }
-#ifdef MICSUPPORT
        crypto_free_tfm(ai->tfm);
-#endif
        del_airo_dev( dev );
        free_netdev( dev );
 }
@@ -2726,9 +2706,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
        ai->thr_pid = kernel_thread(airo_thread, dev, CLONE_FS | CLONE_FILES);
        if (ai->thr_pid < 0)
                goto err_out_free;
-#ifdef MICSUPPORT
        ai->tfm = NULL;
-#endif
        rc = add_airo_dev( dev );
        if (rc)
                goto err_out_thr;
@@ -2969,10 +2947,8 @@ static int airo_thread(void *data) {
                        airo_read_wireless_stats(ai);
                else if (test_bit(JOB_PROMISC, &ai->flags))
                        airo_set_promisc(ai);
-#ifdef MICSUPPORT
                else if (test_bit(JOB_MIC, &ai->flags))
                        micinit(ai);
-#endif
                else if (test_bit(JOB_EVENT, &ai->flags))
                        airo_send_event(dev);
                else if (test_bit(JOB_AUTOWEP, &ai->flags))
@@ -3010,12 +2986,10 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
 
                if ( status & EV_MIC ) {
                        OUT4500( apriv, EVACK, EV_MIC );
-#ifdef MICSUPPORT
                        if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) {
                                set_bit(JOB_MIC, &apriv->flags);
                                wake_up_interruptible(&apriv->thr_wait);
                        }
-#endif
                }
                if ( status & EV_LINK ) {
                        union iwreq_data        wrqu;
@@ -3194,11 +3168,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
                                }
                                bap_read (apriv, buffer + hdrlen/2, len, BAP0);
                        } else {
-#ifdef MICSUPPORT
                                MICBuffer micbuf;
-#endif
                                bap_read (apriv, buffer, ETH_ALEN*2, BAP0);
-#ifdef MICSUPPORT
                                if (apriv->micstats.enabled) {
                                        bap_read (apriv,(u16*)&micbuf,sizeof(micbuf),BAP0);
                                        if (ntohs(micbuf.typelen) > 0x05DC)
@@ -3211,15 +3182,10 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
                                                skb_trim (skb, len + hdrlen);
                                        }
                                }
-#endif
                                bap_read(apriv,buffer+ETH_ALEN,len,BAP0);
-#ifdef MICSUPPORT
                                if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) {
 badmic:
                                        dev_kfree_skb_irq (skb);
-#else
-                               if (0) {
-#endif
 badrx:
                                        OUT4500( apriv, EVACK, EV_RX);
                                        goto exitrx;
@@ -3430,10 +3396,8 @@ static void mpi_receive_802_3(struct airo_info *ai)
        int len = 0;
        struct sk_buff *skb;
        char *buffer;
-#ifdef MICSUPPORT
        int off = 0;
        MICBuffer micbuf;
-#endif
 
        memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd));
        /* Make sure we got something */
@@ -3448,7 +3412,6 @@ static void mpi_receive_802_3(struct airo_info *ai)
                        goto badrx;
                }
                buffer = skb_put(skb,len);
-#ifdef MICSUPPORT
                memcpy(buffer, ai->rxfids[0].virtual_host_addr, ETH_ALEN * 2);
                if (ai->micstats.enabled) {
                        memcpy(&micbuf,
@@ -3470,9 +3433,6 @@ badmic:
                        dev_kfree_skb_irq (skb);
                        goto badrx;
                }
-#else
-               memcpy(buffer, ai->rxfids[0].virtual_host_addr, len);
-#endif
 #ifdef WIRELESS_SPY
                if (ai->spy_data.spy_number > 0) {
                        char *sa;
@@ -3689,13 +3649,11 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
                ai->config.authType = AUTH_OPEN;
                ai->config.modulation = MOD_CCK;
 
-#ifdef MICSUPPORT
                if ((cap_rid.len>=sizeof(cap_rid)) && (cap_rid.extSoftCap&1) &&
                    (micsetup(ai) == SUCCESS)) {
                        ai->config.opmode |= MODE_MIC;
                        set_bit(FLAG_MIC_CAPABLE, &ai->flags);
                }
-#endif
 
                /* Save off the MAC */
                for( i = 0; i < ETH_ALEN; i++ ) {
@@ -4170,15 +4128,12 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket)
        }
        len -= ETH_ALEN * 2;
 
-#ifdef MICSUPPORT
        if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled && 
            (ntohs(((u16 *)pPacket)[6]) != 0x888E)) {
                if (encapsulate(ai,(etherHead *)pPacket,&pMic,len) != SUCCESS)
                        return ERROR;
                miclen = sizeof(pMic);
        }
-#endif
-
        // packet is destination[6], source[6], payload[len-12]
        // write the payload length and dst/src/payload
        if (bap_setup(ai, txFid, 0x0036, BAP1) != SUCCESS) return ERROR;
@@ -5081,7 +5036,6 @@ static int set_wep_key(struct airo_info *ai, u16 index,
                wkr.len = sizeof(wkr);
                wkr.kindex = 0xffff;
                wkr.mac[0] = (char)index;
-               if (perm) printk(KERN_INFO "Setting transmit key to %d\n", index);
                if (perm) ai->defindex = (char)index;
        } else {
 // We are actually setting the key
@@ -5090,7 +5044,6 @@ static int set_wep_key(struct airo_info *ai, u16 index,
                wkr.klen = keylen;
                memcpy( wkr.key, key, keylen );
                memcpy( wkr.mac, macaddr, ETH_ALEN );
-               printk(KERN_INFO "Setting key %d\n", index);
        }
 
        if (perm) disable_MAC(ai, lock);
@@ -5801,11 +5754,13 @@ static int airo_set_wap(struct net_device *dev,
        Cmd cmd;
        Resp rsp;
        APListRid APList_rid;
-       static const unsigned char bcast[ETH_ALEN] = { 255, 255, 255, 255, 255, 255 };
+       static const u8 any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+       static const u8 off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
        if (awrq->sa_family != ARPHRD_ETHER)
                return -EINVAL;
-       else if (!memcmp(bcast, awrq->sa_data, ETH_ALEN)) {
+       else if (!memcmp(any, awrq->sa_data, ETH_ALEN) ||
+                !memcmp(off, awrq->sa_data, ETH_ALEN)) {
                memset(&cmd, 0, sizeof(cmd));
                cmd.cmd=CMD_LOSE_SYNC;
                if (down_interruptible(&local->sem))
@@ -6294,6 +6249,272 @@ static int airo_get_encode(struct net_device *dev,
        return 0;
 }
 
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set extended Encryption parameters
+ */
+static int airo_set_encodeext(struct net_device *dev,
+                          struct iw_request_info *info,
+                           union iwreq_data *wrqu,
+                           char *extra)
+{
+       struct airo_info *local = dev->priv;
+       struct iw_point *encoding = &wrqu->encoding;
+       struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+       CapabilityRid cap_rid;          /* Card capability info */
+       int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 );
+       u16 currentAuthType = local->config.authType;
+       int idx, key_len, alg = ext->alg, set_key = 1;
+       wep_key_t key;
+
+       /* Is WEP supported ? */
+       readCapabilityRid(local, &cap_rid, 1);
+       /* Older firmware doesn't support this...
+       if(!(cap_rid.softCap & 2)) {
+               return -EOPNOTSUPP;
+       } */
+       readConfigRid(local, 1);
+
+       /* Determine and validate the key index */
+       idx = encoding->flags & IW_ENCODE_INDEX;
+       if (idx) {
+               if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1))
+                       return -EINVAL;
+               idx--;
+       } else
+               idx = get_wep_key(local, 0xffff);
+
+       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.
+                */
+               set_wep_key(local, idx, NULL, 0, perm, 1);
+               set_key = ext->key_len > 0 ? 1 : 0;
+       }
+
+       if (set_key) {
+               /* Set the requested key first */
+               memset(key.key, 0, MAX_KEY_SIZE);
+               switch (alg) {
+               case IW_ENCODE_ALG_NONE:
+                       key.len = 0;
+                       break;
+               case IW_ENCODE_ALG_WEP:
+                       if (ext->key_len > MIN_KEY_SIZE) {
+                               key.len = MAX_KEY_SIZE;
+                       } else if (ext->key_len > 0) {
+                               key.len = MIN_KEY_SIZE;
+                       } else {
+                               return -EINVAL;
+                       }
+                       key_len = min (ext->key_len, key.len);
+                       memcpy(key.key, ext->key, key_len);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               /* Send the key to the card */
+               set_wep_key(local, idx, key.key, key.len, perm, 1);
+       }
+
+       /* Read the flags */
+       if(encoding->flags & IW_ENCODE_DISABLED)
+               local->config.authType = AUTH_OPEN;     // disable encryption
+       if(encoding->flags & IW_ENCODE_RESTRICTED)
+               local->config.authType = AUTH_SHAREDKEY;        // Only Both
+       if(encoding->flags & IW_ENCODE_OPEN)
+               local->config.authType = AUTH_ENCRYPT;  // Only Wep
+       /* Commit the changes to flags if needed */
+       if (local->config.authType != currentAuthType)
+               set_bit (FLAG_COMMIT, &local->flags);
+
+       return -EINPROGRESS;
+}
+
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get extended Encryption parameters
+ */
+static int airo_get_encodeext(struct net_device *dev,
+                           struct iw_request_info *info,
+                           union iwreq_data *wrqu,
+                           char *extra)
+{
+       struct airo_info *local = dev->priv;
+       struct iw_point *encoding = &wrqu->encoding;
+       struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+       CapabilityRid cap_rid;          /* Card capability info */
+       int idx, max_key_len;
+
+       /* Is it supported ? */
+       readCapabilityRid(local, &cap_rid, 1);
+       if(!(cap_rid.softCap & 2)) {
+               return -EOPNOTSUPP;
+       }
+       readConfigRid(local, 1);
+
+       max_key_len = encoding->length - sizeof(*ext);
+       if (max_key_len < 0)
+               return -EINVAL;
+
+       idx = encoding->flags & IW_ENCODE_INDEX;
+       if (idx) {
+               if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1))
+                       return -EINVAL;
+               idx--;
+       } else
+               idx = get_wep_key(local, 0xffff);
+
+       encoding->flags = idx + 1;
+       memset(ext, 0, sizeof(*ext));
+
+       /* Check encryption mode */
+       switch(local->config.authType) {
+               case AUTH_ENCRYPT:
+                       encoding->flags = IW_ENCODE_ALG_WEP | IW_ENCODE_ENABLED;
+                       break;
+               case AUTH_SHAREDKEY:
+                       encoding->flags = IW_ENCODE_ALG_WEP | IW_ENCODE_ENABLED;
+                       break;
+               default:
+               case AUTH_OPEN:
+                       encoding->flags = IW_ENCODE_ALG_NONE | IW_ENCODE_DISABLED;
+                       break;
+       }
+       /* We can't return the key, so set the proper flag and return zero */
+       encoding->flags |= IW_ENCODE_NOKEY;
+       memset(extra, 0, 16);
+       
+       /* Copy the key to the user buffer */
+       ext->key_len = get_wep_key(local, idx);
+       if (ext->key_len > 16) {
+               ext->key_len=0;
+       }
+
+       return 0;
+}
+
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set extended authentication parameters
+ */
+static int airo_set_auth(struct net_device *dev,
+                              struct iw_request_info *info,
+                              union iwreq_data *wrqu, char *extra)
+{
+       struct airo_info *local = dev->priv;
+       struct iw_param *param = &wrqu->param;
+       u16 currentAuthType = local->config.authType;
+
+       switch (param->flags & IW_AUTH_INDEX) {
+       case IW_AUTH_WPA_VERSION:
+       case IW_AUTH_CIPHER_PAIRWISE:
+       case IW_AUTH_CIPHER_GROUP:
+       case IW_AUTH_KEY_MGMT:
+       case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+       case IW_AUTH_PRIVACY_INVOKED:
+               /*
+                * airo does not use these parameters
+                */
+               break;
+
+       case IW_AUTH_DROP_UNENCRYPTED:
+               if (param->value) {
+                       /* Only change auth type if unencrypted */
+                       if (currentAuthType == AUTH_OPEN)
+                               local->config.authType = AUTH_ENCRYPT;
+               } else {
+                       local->config.authType = AUTH_OPEN;
+               }
+
+               /* Commit the changes to flags if needed */
+               if (local->config.authType != currentAuthType)
+                       set_bit (FLAG_COMMIT, &local->flags);
+               break;
+
+       case IW_AUTH_80211_AUTH_ALG: {
+                       /* FIXME: What about AUTH_OPEN?  This API seems to
+                        * disallow setting our auth to AUTH_OPEN.
+                        */
+                       if (param->value & IW_AUTH_ALG_SHARED_KEY) {
+                               local->config.authType = AUTH_SHAREDKEY;
+                       } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
+                               local->config.authType = AUTH_ENCRYPT;
+                       } else
+                               return -EINVAL;
+                       break;
+
+                       /* Commit the changes to flags if needed */
+                       if (local->config.authType != currentAuthType)
+                               set_bit (FLAG_COMMIT, &local->flags);
+               }
+
+       case IW_AUTH_WPA_ENABLED:
+               /* Silently accept disable of WPA */
+               if (param->value > 0)
+                       return -EOPNOTSUPP;
+               break;
+
+       default:
+               return -EOPNOTSUPP;
+       }
+       return -EINPROGRESS;
+}
+
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get extended authentication parameters
+ */
+static int airo_get_auth(struct net_device *dev,
+                              struct iw_request_info *info,
+                              union iwreq_data *wrqu, char *extra)
+{
+       struct airo_info *local = dev->priv;
+       struct iw_param *param = &wrqu->param;
+       u16 currentAuthType = local->config.authType;
+
+       switch (param->flags & IW_AUTH_INDEX) {
+       case IW_AUTH_DROP_UNENCRYPTED:
+               switch (currentAuthType) {
+               case AUTH_SHAREDKEY:
+               case AUTH_ENCRYPT:
+                       param->value = 1;
+                       break;
+               default:
+                       param->value = 0;
+                       break;
+               }
+               break;
+
+       case IW_AUTH_80211_AUTH_ALG:
+               switch (currentAuthType) {
+               case AUTH_SHAREDKEY:
+                       param->value = IW_AUTH_ALG_SHARED_KEY;
+                       break;
+               case AUTH_ENCRYPT:
+               default:
+                       param->value = IW_AUTH_ALG_OPEN_SYSTEM;
+                       break;
+               }
+               break;
+
+       case IW_AUTH_WPA_ENABLED:
+               param->value = 0;
+               break;
+
+       default:
+               return -EOPNOTSUPP;
+       }
+       return 0;
+}
+
+
 /*------------------------------------------------------------------*/
 /*
  * Wireless Handler : set Tx-Power
@@ -7050,6 +7271,15 @@ static const iw_handler          airo_handler[] =
        (iw_handler) airo_get_encode,           /* SIOCGIWENCODE */
        (iw_handler) airo_set_power,            /* SIOCSIWPOWER */
        (iw_handler) airo_get_power,            /* SIOCGIWPOWER */
+       (iw_handler) NULL,                      /* -- hole -- */
+       (iw_handler) NULL,                      /* -- hole -- */
+       (iw_handler) NULL,                      /* SIOCSIWGENIE */
+       (iw_handler) NULL,                      /* SIOCGIWGENIE */
+       (iw_handler) airo_set_auth,             /* SIOCSIWAUTH */
+       (iw_handler) airo_get_auth,             /* SIOCGIWAUTH */
+       (iw_handler) airo_set_encodeext,        /* SIOCSIWENCODEEXT */
+       (iw_handler) airo_get_encodeext,        /* SIOCGIWENCODEEXT */
+       (iw_handler) NULL,                      /* SIOCSIWPMKSA */
 };
 
 /* Note : don't describe AIROIDIFC and AIROOLDIDIFC in here.
@@ -7270,13 +7500,11 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
        case AIROGSTAT:     ridcode = RID_STATUS;       break;
        case AIROGSTATSD32: ridcode = RID_STATSDELTA;   break;
        case AIROGSTATSC32: ridcode = RID_STATS;        break;
-#ifdef MICSUPPORT
        case AIROGMICSTATS:
                if (copy_to_user(comp->data, &ai->micstats,
                                 min((int)comp->len,(int)sizeof(ai->micstats))))
                        return -EFAULT;
                return 0;
-#endif
        case AIRORRID:      ridcode = comp->ridnum;     break;
        default:
                return -EINVAL;
@@ -7308,9 +7536,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
 static int writerids(struct net_device *dev, aironet_ioctl *comp) {
        struct airo_info *ai = dev->priv;
        int  ridcode;
-#ifdef MICSUPPORT
         int  enabled;
-#endif
        Resp      rsp;
        static int (* writer)(struct airo_info *, u16 rid, const void *, int, int);
        unsigned char *iobuf;
@@ -7367,11 +7593,9 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
 
                PC4500_readrid(ai,RID_STATSDELTACLEAR,iobuf,RIDSIZE, 1);
 
-#ifdef MICSUPPORT
                enabled = ai->micstats.enabled;
                memset(&ai->micstats,0,sizeof(ai->micstats));
                ai->micstats.enabled = enabled;
-#endif
 
                if (copy_to_user(comp->data, iobuf,
                                 min((int)comp->len, (int)RIDSIZE))) {
index dfc2401..87afa68 100644 (file)
@@ -137,44 +137,6 @@ static struct {
 #define MAC_BOOT_COMPLETE       0x0010        // MAC boot has been completed
 #define MAC_INIT_OK             0x0002        // MAC boot has been completed
 
-#define C80211_SUBTYPE_MGMT_ASS_REQUEST                 0x00
-#define C80211_SUBTYPE_MGMT_ASS_RESPONSE                0x10
-#define C80211_SUBTYPE_MGMT_REASS_REQUEST               0x20
-#define C80211_SUBTYPE_MGMT_REASS_RESPONSE              0x30
-#define C80211_SUBTYPE_MGMT_ProbeRequest                0x40
-#define C80211_SUBTYPE_MGMT_ProbeResponse               0x50
-#define C80211_SUBTYPE_MGMT_BEACON                      0x80
-#define C80211_SUBTYPE_MGMT_ATIM                        0x90
-#define C80211_SUBTYPE_MGMT_DISASSOSIATION              0xA0
-#define C80211_SUBTYPE_MGMT_Authentication              0xB0
-#define C80211_SUBTYPE_MGMT_Deauthentication    0xC0
-
-#define C80211_MGMT_AAN_OPENSYSTEM              0x0000
-#define C80211_MGMT_AAN_SHAREDKEY               0x0001
-
-#define C80211_MGMT_CAPABILITY_ESS              0x0001  // see 802.11 p.58
-#define C80211_MGMT_CAPABILITY_IBSS             0x0002  //      - " -
-#define C80211_MGMT_CAPABILITY_CFPollable       0x0004  //      - " -
-#define C80211_MGMT_CAPABILITY_CFPollRequest    0x0008  //      - " -
-#define C80211_MGMT_CAPABILITY_Privacy          0x0010  //      - " -
-
-#define C80211_MGMT_SC_Success                  0
-#define C80211_MGMT_SC_Unspecified              1
-#define C80211_MGMT_SC_SupportCapabilities      10
-#define C80211_MGMT_SC_ReassDenied              11
-#define C80211_MGMT_SC_AssDenied                12
-#define C80211_MGMT_SC_AuthAlgNotSupported      13
-#define C80211_MGMT_SC_AuthTransSeqNumError     14
-#define C80211_MGMT_SC_AuthRejectChallenge      15
-#define C80211_MGMT_SC_AuthRejectTimeout        16
-#define C80211_MGMT_SC_AssDeniedHandleAP        17
-#define C80211_MGMT_SC_AssDeniedBSSRate         18
-
-#define C80211_MGMT_ElementID_SSID              0
-#define C80211_MGMT_ElementID_SupportedRates    1
-#define C80211_MGMT_ElementID_ChallengeText     16
-#define C80211_MGMT_CAPABILITY_ShortPreamble    0x0020
-
 #define MIB_MAX_DATA_BYTES    212
 #define MIB_HEADER_SIZE       4    /* first four fields */
 
@@ -2835,7 +2797,7 @@ static void handle_beacon_probe(struct atmel_private *priv, u16 capability,
                                u8 channel)
 {
        int rejoin = 0;
-       int new = capability  & C80211_MGMT_CAPABILITY_ShortPreamble ?
+       int new = capability & MFIE_TYPE_POWER_CONSTRAINT ?
                SHORT_PREAMBLE : LONG_PREAMBLE;
 
        if (priv->preamble != new) {
@@ -2921,11 +2883,11 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
        memcpy(header.addr2, priv->dev->dev_addr, 6);
        memcpy(header.addr3, priv->CurrentBSSID, 6);
 
-       body.capability = cpu_to_le16(C80211_MGMT_CAPABILITY_ESS);
+       body.capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
        if (priv->wep_is_on)
-               body.capability |= cpu_to_le16(C80211_MGMT_CAPABILITY_Privacy);
+               body.capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
        if (priv->preamble == SHORT_PREAMBLE)
-               body.capability |= cpu_to_le16(C80211_MGMT_CAPABILITY_ShortPreamble);
+               body.capability |= cpu_to_le16(MFIE_TYPE_POWER_CONSTRAINT);
 
        body.listen_interval = cpu_to_le16(priv->listen_interval * priv->beacon_period);
 
@@ -2939,10 +2901,10 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
                bodysize = 12 + priv->SSID_size;
        }
 
-       ssid_el_p[0] = C80211_MGMT_ElementID_SSID;
+       ssid_el_p[0] = MFIE_TYPE_SSID;
        ssid_el_p[1] = priv->SSID_size;
        memcpy(ssid_el_p + 2, priv->SSID, priv->SSID_size);
-       ssid_el_p[2 + priv->SSID_size] = C80211_MGMT_ElementID_SupportedRates;
+       ssid_el_p[2 + priv->SSID_size] = MFIE_TYPE_RATES;
        ssid_el_p[3 + priv->SSID_size] = 4; /* len of suported rates */
        memcpy(ssid_el_p + 4 + priv->SSID_size, atmel_basic_rates, 4);
 
@@ -3004,7 +2966,7 @@ static void store_bss_info(struct atmel_private *priv,
                           u16 beacon_period, u8 channel, u8 rssi, u8 ssid_len,
                           u8 *ssid, int is_beacon)
 {
-       u8 *bss = capability & C80211_MGMT_CAPABILITY_ESS ? header->addr2 : header->addr3;
+       u8 *bss = capability & WLAN_CAPABILITY_ESS ? header->addr2 : header->addr3;
        int i, index;
 
        for (index = -1, i = 0; i < priv->BSS_list_entries; i++)
@@ -3030,16 +2992,16 @@ static void store_bss_info(struct atmel_private *priv,
 
        priv->BSSinfo[index].channel = channel;
        priv->BSSinfo[index].beacon_period = beacon_period;
-       priv->BSSinfo[index].UsingWEP = capability & C80211_MGMT_CAPABILITY_Privacy;
+       priv->BSSinfo[index].UsingWEP = capability & WLAN_CAPABILITY_PRIVACY;
        memcpy(priv->BSSinfo[index].SSID, ssid, ssid_len);
        priv->BSSinfo[index].SSIDsize = ssid_len;
 
-       if (capability & C80211_MGMT_CAPABILITY_IBSS)
+       if (capability & WLAN_CAPABILITY_IBSS)
                priv->BSSinfo[index].BSStype = IW_MODE_ADHOC;
-       else if (capability & C80211_MGMT_CAPABILITY_ESS)
+       else if (capability & WLAN_CAPABILITY_ESS)
                priv->BSSinfo[index].BSStype =IW_MODE_INFRA;
 
-       priv->BSSinfo[index].preamble = capability & C80211_MGMT_CAPABILITY_ShortPreamble ?
+       priv->BSSinfo[index].preamble = capability & MFIE_TYPE_POWER_CONSTRAINT ?
                SHORT_PREAMBLE : LONG_PREAMBLE;
 }
 
@@ -3050,7 +3012,7 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
        u16 trans_seq_no = le16_to_cpu(auth->trans_seq);
        u16 system = le16_to_cpu(auth->alg);
 
-       if (status == C80211_MGMT_SC_Success && !priv->wep_is_on) {
+       if (status == WLAN_STATUS_SUCCESS && !priv->wep_is_on) {
                /* no WEP */
                if (priv->station_was_associated) {
                        atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
@@ -3063,19 +3025,19 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
                }
        }
 
-       if (status == C80211_MGMT_SC_Success && priv->wep_is_on) {
+       if (status == WLAN_STATUS_SUCCESS && priv->wep_is_on) {
                int should_associate = 0;
                /* WEP */
                if (trans_seq_no != priv->ExpectedAuthentTransactionSeqNum)
                        return;
 
-               if (system == C80211_MGMT_AAN_OPENSYSTEM) {
+               if (system == WLAN_AUTH_OPEN) {
                        if (trans_seq_no == 0x0002) {
                                should_associate = 1;
                        }
-               } else if (system == C80211_MGMT_AAN_SHAREDKEY) {
+               } else if (system == WLAN_AUTH_SHARED_KEY) {
                        if (trans_seq_no == 0x0002 &&
-                           auth->el_id == C80211_MGMT_ElementID_ChallengeText) {
+                           auth->el_id == MFIE_TYPE_CHALLENGE) {
                                send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len);
                                return;
                        } else if (trans_seq_no == 0x0004) {
@@ -3140,8 +3102,8 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
        if (frame_len < 8 + rates_len)
                return;
 
-       if (status == C80211_MGMT_SC_Success) {
-               if (subtype == C80211_SUBTYPE_MGMT_ASS_RESPONSE)
+       if (status == WLAN_STATUS_SUCCESS) {
+               if (subtype == IEEE80211_STYPE_ASSOC_RESP)
                        priv->AssociationRequestRetryCnt = 0;
                else
                        priv->ReAssociationRequestRetryCnt = 0;
@@ -3178,9 +3140,9 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
                return;
        }
 
-       if (subtype == C80211_SUBTYPE_MGMT_ASS_RESPONSE &&
-           status != C80211_MGMT_SC_AssDeniedBSSRate &&
-           status != C80211_MGMT_SC_SupportCapabilities &&
+       if (subtype == IEEE80211_STYPE_ASSOC_RESP &&
+           status != WLAN_STATUS_ASSOC_DENIED_RATES &&
+           status != WLAN_STATUS_CAPS_UNSUPPORTED &&
            priv->AssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) {
                mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
                priv->AssociationRequestRetryCnt++;
@@ -3188,9 +3150,9 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
                return;
        }
 
-       if (subtype == C80211_SUBTYPE_MGMT_REASS_RESPONSE &&
-           status != C80211_MGMT_SC_AssDeniedBSSRate &&
-           status != C80211_MGMT_SC_SupportCapabilities &&
+       if (subtype == IEEE80211_STYPE_REASSOC_RESP &&
+           status != WLAN_STATUS_ASSOC_DENIED_RATES &&
+           status != WLAN_STATUS_CAPS_UNSUPPORTED &&
            priv->AssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) {
                mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
                priv->ReAssociationRequestRetryCnt++;
@@ -3325,8 +3287,8 @@ static void atmel_management_frame(struct atmel_private *priv,
 
        subtype = le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_STYPE;
        switch (subtype) {
-       case C80211_SUBTYPE_MGMT_BEACON:
-       case C80211_SUBTYPE_MGMT_ProbeResponse:
+       case IEEE80211_STYPE_BEACON:
+       case IEEE80211_STYPE_PROBE_RESP:
 
                /* beacon frame has multiple variable-length fields -
                   never let an engineer loose with a data structure design. */
@@ -3384,19 +3346,19 @@ static void atmel_management_frame(struct atmel_private *priv,
                                               beacon_interval, channel, rssi,
                                               ssid_length,
                                               &beacon->rates_el_id,
-                                              subtype == C80211_SUBTYPE_MGMT_BEACON);
+                                              subtype == IEEE80211_STYPE_BEACON);
                }
                break;
 
-       case C80211_SUBTYPE_MGMT_Authentication:
+       case IEEE80211_STYPE_AUTH:
 
                if (priv->station_state == STATION_STATE_AUTHENTICATING)
                        authenticate(priv, frame_len);
 
                break;
 
-       case C80211_SUBTYPE_MGMT_ASS_RESPONSE:
-       case C80211_SUBTYPE_MGMT_REASS_RESPONSE:
+       case IEEE80211_STYPE_ASSOC_RESP:
+       case IEEE80211_STYPE_REASSOC_RESP:
 
                if (priv->station_state == STATION_STATE_ASSOCIATING ||
                    priv->station_state == STATION_STATE_REASSOCIATING)
@@ -3404,7 +3366,7 @@ static void atmel_management_frame(struct atmel_private *priv,
 
                break;
 
-       case C80211_SUBTYPE_MGMT_DISASSOSIATION:
+       case IEEE80211_STYPE_DISASSOC:
                if (priv->station_is_associated &&
                    priv->operating_mode == IW_MODE_INFRA &&
                    is_frame_from_current_bss(priv, header)) {
@@ -3417,7 +3379,7 @@ static void atmel_management_frame(struct atmel_private *priv,
 
                break;
 
-       case C80211_SUBTYPE_MGMT_Deauthentication:
+       case IEEE80211_STYPE_DEAUTH:
                if (priv->operating_mode == IW_MODE_INFRA &&
                    is_frame_from_current_bss(priv, header)) {
                        priv->station_was_associated = 0;
@@ -3453,12 +3415,12 @@ static void atmel_management_timer(u_long a)
                        priv->AuthenticationRequestRetryCnt = 0;
                        restart_search(priv);
                } else {
-                       int auth = C80211_MGMT_AAN_OPENSYSTEM;
+                       int auth = WLAN_AUTH_OPEN;
                        priv->AuthenticationRequestRetryCnt++;
                        priv->CurrentAuthentTransactionSeqNum = 0x0001;
                        mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
                        if (priv->wep_is_on && priv->exclude_unencrypted)
-                               auth = C80211_MGMT_AAN_SHAREDKEY;
+                               auth = WLAN_AUTH_SHARED_KEY;
                        send_authentication_request(priv, auth, NULL, 0);
          }
          break;
@@ -3558,14 +3520,14 @@ static void atmel_command_irq(struct atmel_private *priv)
                                priv->station_was_associated = priv->station_is_associated;
                                atmel_enter_state(priv, STATION_STATE_READY);
                        } else {
-                               int auth = C80211_MGMT_AAN_OPENSYSTEM;
+                               int auth = WLAN_AUTH_OPEN;
                                priv->AuthenticationRequestRetryCnt = 0;
                                atmel_enter_state(priv, STATION_STATE_AUTHENTICATING);
 
                                mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
                                priv->CurrentAuthentTransactionSeqNum = 0x0001;
                                if (priv->wep_is_on && priv->exclude_unencrypted)
-                                       auth = C80211_MGMT_AAN_SHAREDKEY;
+                                       auth = WLAN_AUTH_SHARED_KEY;
                                send_authentication_request(priv, auth, NULL, 0);
                        }
                        return;
index 6290c9f..72335c8 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms of version 2 of the GNU General Public License as
@@ -167,12 +167,12 @@ that only one external action is invoked at a time.
 
 #include "ipw2100.h"
 
-#define IPW2100_VERSION "1.1.3"
+#define IPW2100_VERSION "git-1.2.2"
 
 #define DRV_NAME       "ipw2100"
 #define DRV_VERSION    IPW2100_VERSION
 #define DRV_DESCRIPTION        "Intel(R) PRO/Wireless 2100 Network Driver"
-#define DRV_COPYRIGHT  "Copyright(c) 2003-2005 Intel Corporation"
+#define DRV_COPYRIGHT  "Copyright(c) 2003-2006 Intel Corporation"
 
 /* Debugging stuff */
 #ifdef CONFIG_IPW2100_DEBUG
@@ -1418,7 +1418,7 @@ static int ipw2100_enable_adapter(struct ipw2100_priv *priv)
        if (priv->status & STATUS_ENABLED)
                return 0;
 
-       down(&priv->adapter_sem);
+       mutex_lock(&priv->adapter_mutex);
 
        if (rf_kill_active(priv)) {
                IPW_DEBUG_HC("Command aborted due to RF kill active.\n");
@@ -1444,7 +1444,7 @@ static int ipw2100_enable_adapter(struct ipw2100_priv *priv)
        }
 
       fail_up:
-       up(&priv->adapter_sem);
+       mutex_unlock(&priv->adapter_mutex);
        return err;
 }
 
@@ -1576,7 +1576,7 @@ static int ipw2100_disable_adapter(struct ipw2100_priv *priv)
                cancel_delayed_work(&priv->hang_check);
        }
 
-       down(&priv->adapter_sem);
+       mutex_lock(&priv->adapter_mutex);
 
        err = ipw2100_hw_send_command(priv, &cmd);
        if (err) {
@@ -1595,7 +1595,7 @@ static int ipw2100_disable_adapter(struct ipw2100_priv *priv)
        IPW_DEBUG_INFO("TODO: implement scan state machine\n");
 
       fail_up:
-       up(&priv->adapter_sem);
+       mutex_unlock(&priv->adapter_mutex);
        return err;
 }
 
@@ -1672,6 +1672,18 @@ static int ipw2100_start_scan(struct ipw2100_priv *priv)
        return err;
 }
 
+static const struct ieee80211_geo ipw_geos[] = {
+       {                       /* Restricted */
+        "---",
+        .bg_channels = 14,
+        .bg = {{2412, 1}, {2417, 2}, {2422, 3},
+               {2427, 4}, {2432, 5}, {2437, 6},
+               {2442, 7}, {2447, 8}, {2452, 9},
+               {2457, 10}, {2462, 11}, {2467, 12},
+               {2472, 13}, {2484, 14}},
+        },
+};
+
 static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
 {
        unsigned long flags;
@@ -1727,6 +1739,13 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
                goto exit;
        }
 
+       /* Initialize the geo */
+       if (ieee80211_set_geo(priv->ieee, &ipw_geos[0])) {
+               printk(KERN_WARNING DRV_NAME "Could not set geo\n");
+               return 0;
+       }
+       priv->ieee->freq_band = IEEE80211_24GHZ_BAND;
+
        lock = LOCK_NONE;
        if (ipw2100_set_ordinal(priv, IPW_ORD_PERS_DB_LOCK, &lock, &ord_len)) {
                printk(KERN_ERR DRV_NAME
@@ -1869,7 +1888,7 @@ static void ipw2100_reset_adapter(struct ipw2100_priv *priv)
        priv->status |= STATUS_RESET_PENDING;
        spin_unlock_irqrestore(&priv->low_lock, flags);
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        /* stop timed checks so that they don't interfere with reset */
        priv->stop_hang_check = 1;
        cancel_delayed_work(&priv->hang_check);
@@ -1879,7 +1898,7 @@ static void ipw2100_reset_adapter(struct ipw2100_priv *priv)
                wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);
 
        ipw2100_up(priv, 0);
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
 
 }
 
@@ -2371,15 +2390,6 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
                IPW_DEBUG_DROP("Dropping packet while interface is not up.\n");
                return;
        }
-#ifdef CONFIG_IPW2100_MONITOR
-       if (unlikely(priv->ieee->iw_mode == IW_MODE_MONITOR &&
-                    priv->config & CFG_CRC_CHECK &&
-                    status->flags & IPW_STATUS_FLAG_CRC_ERROR)) {
-               IPW_DEBUG_RX("CRC error in packet.  Dropping.\n");
-               priv->ieee->stats.rx_errors++;
-               return;
-       }
-#endif
 
        if (unlikely(priv->ieee->iw_mode != IW_MODE_MONITOR &&
                     !(priv->status & STATUS_ASSOCIATED))) {
@@ -2427,6 +2437,89 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
        priv->rx_queue.drv[i].host_addr = packet->dma_addr;
 }
 
+#ifdef CONFIG_IPW2100_MONITOR
+
+static void isr_rx_monitor(struct ipw2100_priv *priv, int i,
+                  struct ieee80211_rx_stats *stats)
+{
+       struct ipw2100_status *status = &priv->status_queue.drv[i];
+       struct ipw2100_rx_packet *packet = &priv->rx_buffers[i];
+
+       /* Magic struct that slots into the radiotap header -- no reason
+        * to build this manually element by element, we can write it much
+        * more efficiently than we can parse it. ORDER MATTERS HERE */
+       struct ipw_rt_hdr {
+               struct ieee80211_radiotap_header rt_hdr;
+               s8 rt_dbmsignal; /* signal in dbM, kluged to signed */
+       } *ipw_rt;
+
+       IPW_DEBUG_RX("Handler...\n");
+
+       if (unlikely(status->frame_size > skb_tailroom(packet->skb) -
+                               sizeof(struct ipw_rt_hdr))) {
+               IPW_DEBUG_INFO("%s: frame_size (%u) > skb_tailroom (%u)!"
+                              "  Dropping.\n",
+                              priv->net_dev->name,
+                              status->frame_size,
+                              skb_tailroom(packet->skb));
+               priv->ieee->stats.rx_errors++;
+               return;
+       }
+
+       if (unlikely(!netif_running(priv->net_dev))) {
+               priv->ieee->stats.rx_errors++;
+               priv->wstats.discard.misc++;
+               IPW_DEBUG_DROP("Dropping packet while interface is not up.\n");
+               return;
+       }
+
+       if (unlikely(priv->config & CFG_CRC_CHECK &&
+                    status->flags & IPW_STATUS_FLAG_CRC_ERROR)) {
+               IPW_DEBUG_RX("CRC error in packet.  Dropping.\n");
+               priv->ieee->stats.rx_errors++;
+               return;
+       }
+
+       pci_unmap_single(priv->pci_dev, packet->dma_addr,
+                        sizeof(struct ipw2100_rx), PCI_DMA_FROMDEVICE);
+       memmove(packet->skb->data + sizeof(struct ipw_rt_hdr),
+               packet->skb->data, status->frame_size);
+
+       ipw_rt = (struct ipw_rt_hdr *) packet->skb->data;
+
+       ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
+       ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */
+       ipw_rt->rt_hdr.it_len = sizeof(struct ipw_rt_hdr); /* total hdr+data */
+
+       ipw_rt->rt_hdr.it_present = 1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL;
+
+       ipw_rt->rt_dbmsignal = status->rssi + IPW2100_RSSI_TO_DBM;
+
+       skb_put(packet->skb, status->frame_size + sizeof(struct ipw_rt_hdr));
+
+       if (!ieee80211_rx(priv->ieee, packet->skb, stats)) {
+               priv->ieee->stats.rx_errors++;
+
+               /* ieee80211_rx failed, so it didn't free the SKB */
+               dev_kfree_skb_any(packet->skb);
+               packet->skb = NULL;
+       }
+
+       /* We need to allocate a new SKB and attach it to the RDB. */
+       if (unlikely(ipw2100_alloc_skb(priv, packet))) {
+               IPW_DEBUG_WARNING(
+                       "%s: Unable to allocate SKB onto RBD ring - disabling "
+                       "adapter.\n", priv->net_dev->name);
+               /* TODO: schedule adapter shutdown */
+               IPW_DEBUG_INFO("TODO: Shutdown adapter...\n");
+       }
+
+       /* Update the RDB entry */
+       priv->rx_queue.drv[i].host_addr = packet->dma_addr;
+}
+
+#endif
+
 static int ipw2100_corruption_check(struct ipw2100_priv *priv, int i)
 {
        struct ipw2100_status *status = &priv->status_queue.drv[i];
@@ -2558,7 +2651,7 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv)
                case P8023_DATA_VAL:
 #ifdef CONFIG_IPW2100_MONITOR
                        if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
-                               isr_rx(priv, i, &stats);
+                               isr_rx_monitor(priv, i, &stats);
                                break;
                        }
 #endif
@@ -3750,7 +3843,7 @@ static ssize_t store_memory(struct device *d, struct device_attribute *attr,
        struct net_device *dev = priv->net_dev;
        const char *p = buf;
 
-       (void) dev; /* kill unused-var warning for debug-only code */
+       (void)dev;              /* kill unused-var warning for debug-only code */
 
        if (count < 1)
                return count;
@@ -3863,7 +3956,7 @@ static int ipw2100_switch_mode(struct ipw2100_priv *priv, u32 mode)
 #ifdef CONFIG_IPW2100_MONITOR
        case IW_MODE_MONITOR:
                priv->last_mode = priv->ieee->iw_mode;
-               priv->net_dev->type = ARPHRD_IEEE80211;
+               priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
                break;
 #endif                         /* CONFIG_IPW2100_MONITOR */
        }
@@ -4070,7 +4163,7 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr,
        unsigned long val;
        char *p = buffer;
 
-       (void) dev; /* kill unused-var warning for debug-only code */
+       (void)dev;              /* kill unused-var warning for debug-only code */
 
        IPW_DEBUG_INFO("enter\n");
 
@@ -4119,7 +4212,7 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio)
        IPW_DEBUG_RF_KILL("Manual SW RF Kill set to: RADIO  %s\n",
                          disable_radio ? "OFF" : "ON");
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
 
        if (disable_radio) {
                priv->status |= STATUS_RF_KILL_SW;
@@ -4137,7 +4230,7 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio)
                        schedule_reset(priv);
        }
 
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        return 1;
 }
 
@@ -5107,12 +5200,13 @@ static int ipw2100_set_tx_power(struct ipw2100_priv *priv, u32 tx_power)
                .host_command_length = 4
        };
        int err = 0;
+       u32 tmp = tx_power;
 
        if (tx_power != IPW_TX_POWER_DEFAULT)
-               tx_power = (tx_power - IPW_TX_POWER_MIN_DBM) * 16 /
-                   (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM);
+               tmp = (tx_power - IPW_TX_POWER_MIN_DBM) * 16 /
+                     (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM);
 
-       cmd.host_command_parameters[0] = tx_power;
+       cmd.host_command_parameters[0] = tmp;
 
        if (priv->ieee->iw_mode == IW_MODE_ADHOC)
                err = ipw2100_hw_send_command(priv, &cmd);
@@ -5365,9 +5459,12 @@ static int ipw2100_configure_security(struct ipw2100_priv *priv, int batch_mode)
                                                     SEC_LEVEL_0, 0, 1);
        } else {
                auth_mode = IPW_AUTH_OPEN;
-               if ((priv->ieee->sec.flags & SEC_AUTH_MODE) &&
-                   (priv->ieee->sec.auth_mode == WLAN_AUTH_SHARED_KEY))
-                       auth_mode = IPW_AUTH_SHARED;
+               if (priv->ieee->sec.flags & SEC_AUTH_MODE) {
+                       if (priv->ieee->sec.auth_mode == WLAN_AUTH_SHARED_KEY)
+                               auth_mode = IPW_AUTH_SHARED;
+                       else if (priv->ieee->sec.auth_mode == WLAN_AUTH_LEAP)
+                               auth_mode = IPW_AUTH_LEAP_CISCO_ID;
+               }
 
                sec_level = SEC_LEVEL_0;
                if (priv->ieee->sec.flags & SEC_LEVEL)
@@ -5437,7 +5534,7 @@ static void shim__set_security(struct net_device *dev,
        struct ipw2100_priv *priv = ieee80211_priv(dev);
        int i, force_update = 0;
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        if (!(priv->status & STATUS_INITIALIZED))
                goto done;
 
@@ -5510,7 +5607,7 @@ static void shim__set_security(struct net_device *dev,
        if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)))
                ipw2100_configure_security(priv, 0);
       done:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
 }
 
 static int ipw2100_adapter_setup(struct ipw2100_priv *priv)
@@ -5634,7 +5731,7 @@ static int ipw2100_set_address(struct net_device *dev, void *p)
        if (!is_valid_ether_addr(addr->sa_data))
                return -EADDRNOTAVAIL;
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
 
        priv->config |= CFG_CUSTOM_MAC;
        memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN);
@@ -5644,12 +5741,12 @@ static int ipw2100_set_address(struct net_device *dev, void *p)
                goto done;
 
        priv->reset_backoff = 0;
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        ipw2100_reset_adapter(priv);
        return 0;
 
       done:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        return err;
 }
 
@@ -5760,6 +5857,9 @@ static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value)
        } else if (value & IW_AUTH_ALG_OPEN_SYSTEM) {
                sec.auth_mode = WLAN_AUTH_OPEN;
                ieee->open_wep = 1;
+       } else if (value & IW_AUTH_ALG_LEAP) {
+               sec.auth_mode = WLAN_AUTH_LEAP;
+               ieee->open_wep = 1;
        } else
                return -EINVAL;
 
@@ -5771,8 +5871,8 @@ static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value)
        return ret;
 }
 
-void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv,
-                            char *wpa_ie, int wpa_ie_len)
+static void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv,
+                                   char *wpa_ie, int wpa_ie_len)
 {
 
        struct ipw2100_wpa_assoc_frame frame;
@@ -5989,8 +6089,8 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
        strcpy(priv->nick, "ipw2100");
 
        spin_lock_init(&priv->low_lock);
-       sema_init(&priv->action_sem, 1);
-       sema_init(&priv->adapter_sem, 1);
+       mutex_init(&priv->action_mutex);
+       mutex_init(&priv->adapter_mutex);
 
        init_waitqueue_head(&priv->wait_command_queue);
 
@@ -6155,7 +6255,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
         * member to call a function that then just turns and calls ipw2100_up.
         * net_dev->init is called after name allocation but before the
         * notifier chain is called */
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        err = register_netdev(dev);
        if (err) {
                printk(KERN_WARNING DRV_NAME
@@ -6191,12 +6291,12 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
 
        priv->status |= STATUS_INITIALIZED;
 
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
 
        return 0;
 
       fail_unlock:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
 
       fail:
        if (dev) {
@@ -6236,7 +6336,7 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
        struct net_device *dev;
 
        if (priv) {
-               down(&priv->action_sem);
+               mutex_lock(&priv->action_mutex);
 
                priv->status &= ~STATUS_INITIALIZED;
 
@@ -6251,9 +6351,9 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
                /* Take down the hardware */
                ipw2100_down(priv);
 
-               /* Release the semaphore so that the network subsystem can
+               /* Release the mutex so that the network subsystem can
                 * complete any needed calls into the driver... */
-               up(&priv->action_sem);
+               mutex_unlock(&priv->action_mutex);
 
                /* Unregister the device first - this results in close()
                 * being called if the device is open.  If we free storage
@@ -6292,7 +6392,7 @@ static int ipw2100_suspend(struct pci_dev *pci_dev, pm_message_t state)
 
        IPW_DEBUG_INFO("%s: Going into suspend...\n", dev->name);
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        if (priv->status & STATUS_INITIALIZED) {
                /* Take down the device; powers it off, etc. */
                ipw2100_down(priv);
@@ -6305,7 +6405,7 @@ static int ipw2100_suspend(struct pci_dev *pci_dev, pm_message_t state)
        pci_disable_device(pci_dev);
        pci_set_power_state(pci_dev, PCI_D3hot);
 
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
 
        return 0;
 }
@@ -6319,7 +6419,7 @@ static int ipw2100_resume(struct pci_dev *pci_dev)
        if (IPW2100_PM_DISABLED)
                return 0;
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
 
        IPW_DEBUG_INFO("%s: Coming out of suspend...\n", dev->name);
 
@@ -6345,7 +6445,7 @@ static int ipw2100_resume(struct pci_dev *pci_dev)
        if (!(priv->status & STATUS_RF_KILL_SW))
                ipw2100_up(priv, 0);
 
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
 
        return 0;
 }
@@ -6509,7 +6609,7 @@ static int ipw2100_wx_set_freq(struct net_device *dev,
        if (priv->ieee->iw_mode == IW_MODE_INFRA)
                return -EOPNOTSUPP;
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -6540,7 +6640,7 @@ static int ipw2100_wx_set_freq(struct net_device *dev,
        }
 
       done:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        return err;
 }
 
@@ -6581,7 +6681,7 @@ static int ipw2100_wx_set_mode(struct net_device *dev,
        if (wrqu->mode == priv->ieee->iw_mode)
                return 0;
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -6604,7 +6704,7 @@ static int ipw2100_wx_set_mode(struct net_device *dev,
        }
 
       done:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        return err;
 }
 
@@ -6786,7 +6886,7 @@ static int ipw2100_wx_set_wap(struct net_device *dev,
        if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
                return -EINVAL;
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -6815,7 +6915,7 @@ static int ipw2100_wx_set_wap(struct net_device *dev,
                     wrqu->ap_addr.sa_data[5] & 0xff);
 
       done:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        return err;
 }
 
@@ -6851,7 +6951,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
        int length = 0;
        int err = 0;
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -6888,7 +6988,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
        err = ipw2100_set_essid(priv, essid, length, 0);
 
       done:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        return err;
 }
 
@@ -6969,7 +7069,7 @@ static int ipw2100_wx_set_rate(struct net_device *dev,
        u32 rate;
        int err = 0;
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -6996,7 +7096,7 @@ static int ipw2100_wx_set_rate(struct net_device *dev,
 
        IPW_DEBUG_WX("SET Rate -> %04X \n", rate);
       done:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        return err;
 }
 
@@ -7016,7 +7116,7 @@ static int ipw2100_wx_get_rate(struct net_device *dev,
                return 0;
        }
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7048,7 +7148,7 @@ static int ipw2100_wx_get_rate(struct net_device *dev,
        IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value);
 
       done:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        return err;
 }
 
@@ -7063,7 +7163,7 @@ static int ipw2100_wx_set_rts(struct net_device *dev,
        if (wrqu->rts.fixed == 0)
                return -EINVAL;
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7083,7 +7183,7 @@ static int ipw2100_wx_set_rts(struct net_device *dev,
 
        IPW_DEBUG_WX("SET RTS Threshold -> 0x%08X \n", value);
       done:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        return err;
 }
 
@@ -7134,7 +7234,7 @@ static int ipw2100_wx_set_txpow(struct net_device *dev,
                value = wrqu->txpower.value;
        }
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7145,7 +7245,7 @@ static int ipw2100_wx_set_txpow(struct net_device *dev,
        IPW_DEBUG_WX("SET TX Power -> %d \n", value);
 
       done:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        return err;
 }
 
@@ -7237,7 +7337,7 @@ static int ipw2100_wx_set_retry(struct net_device *dev,
        if (!(wrqu->retry.flags & IW_RETRY_LIMIT))
                return 0;
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7264,7 +7364,7 @@ static int ipw2100_wx_set_retry(struct net_device *dev,
        IPW_DEBUG_WX("SET Both Retry Limits -> %d \n", wrqu->retry.value);
 
       done:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        return err;
 }
 
@@ -7307,7 +7407,7 @@ static int ipw2100_wx_set_scan(struct net_device *dev,
        struct ipw2100_priv *priv = ieee80211_priv(dev);
        int err = 0;
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7322,7 +7422,7 @@ static int ipw2100_wx_set_scan(struct net_device *dev,
        }
 
       done:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        return err;
 }
 
@@ -7372,7 +7472,7 @@ static int ipw2100_wx_set_power(struct net_device *dev,
        struct ipw2100_priv *priv = ieee80211_priv(dev);
        int err = 0;
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7405,7 +7505,7 @@ static int ipw2100_wx_set_power(struct net_device *dev,
        IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n", priv->power_mode);
 
       done:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        return err;
 
 }
@@ -7709,7 +7809,7 @@ static int ipw2100_wx_set_promisc(struct net_device *dev,
        int enable = (parms[0] > 0);
        int err = 0;
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7727,7 +7827,7 @@ static int ipw2100_wx_set_promisc(struct net_device *dev,
                        err = ipw2100_switch_mode(priv, priv->last_mode);
        }
       done:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        return err;
 }
 
@@ -7750,7 +7850,7 @@ static int ipw2100_wx_set_powermode(struct net_device *dev,
        struct ipw2100_priv *priv = ieee80211_priv(dev);
        int err = 0, mode = *(int *)extra;
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7762,7 +7862,7 @@ static int ipw2100_wx_set_powermode(struct net_device *dev,
        if (priv->power_mode != mode)
                err = ipw2100_set_power_mode(priv, mode);
       done:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        return err;
 }
 
@@ -7814,7 +7914,7 @@ static int ipw2100_wx_set_preamble(struct net_device *dev,
        struct ipw2100_priv *priv = ieee80211_priv(dev);
        int err, mode = *(int *)extra;
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7832,7 +7932,7 @@ static int ipw2100_wx_set_preamble(struct net_device *dev,
        err = ipw2100_system_config(priv, 0);
 
       done:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        return err;
 }
 
@@ -7862,7 +7962,7 @@ static int ipw2100_wx_set_crc_check(struct net_device *dev,
        struct ipw2100_priv *priv = ieee80211_priv(dev);
        int err, mode = *(int *)extra;
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7879,7 +7979,7 @@ static int ipw2100_wx_set_crc_check(struct net_device *dev,
        err = 0;
 
       done:
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
        return err;
 }
 
@@ -8184,11 +8284,11 @@ static void ipw2100_wx_event_work(struct ipw2100_priv *priv)
        if (priv->status & STATUS_STOPPING)
                return;
 
-       down(&priv->action_sem);
+       mutex_lock(&priv->action_mutex);
 
        IPW_DEBUG_WX("enter\n");
 
-       up(&priv->action_sem);
+       mutex_unlock(&priv->action_mutex);
 
        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
 
@@ -8211,7 +8311,7 @@ static void ipw2100_wx_event_work(struct ipw2100_priv *priv)
 
        if (!(priv->status & STATUS_ASSOCIATED)) {
                IPW_DEBUG_WX("Configuring ESSID\n");
-               down(&priv->action_sem);
+               mutex_lock(&priv->action_mutex);
                /* This is a disassociation event, so kick the firmware to
                 * look for another AP */
                if (priv->config & CFG_STATIC_ESSID)
@@ -8219,7 +8319,7 @@ static void ipw2100_wx_event_work(struct ipw2100_priv *priv)
                                          0);
                else
                        ipw2100_set_essid(priv, NULL, 0, 0);
-               up(&priv->action_sem);
+               mutex_unlock(&priv->action_mutex);
        }
 
        wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);
index f6c5144..55b7227 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
+  Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms of version 2 of the GNU General Public License as
 
 #include <net/ieee80211.h>
 
+#ifdef CONFIG_IPW2100_MONITOR
+#include <net/ieee80211_radiotap.h>
+#endif
+
 #include <linux/workqueue.h>
+#include <linux/mutex.h>
 
 struct ipw2100_priv;
 struct ipw2100_tx_packet;
@@ -392,8 +397,10 @@ struct ipw2100_notification {
 #define IPW_WEP104_CIPHER (1<<5)
 #define IPW_CKIP_CIPHER   (1<<6)
 
-#define        IPW_AUTH_OPEN     0
-#define        IPW_AUTH_SHARED   1
+#define        IPW_AUTH_OPEN           0
+#define        IPW_AUTH_SHARED         1
+#define IPW_AUTH_LEAP          2
+#define IPW_AUTH_LEAP_CISCO_ID 0x80
 
 struct statistic {
        int value;
@@ -588,8 +595,8 @@ struct ipw2100_priv {
        int inta_other;
 
        spinlock_t low_lock;
-       struct semaphore action_sem;
-       struct semaphore adapter_sem;
+       struct mutex action_mutex;
+       struct mutex adapter_mutex;
 
        wait_queue_head_t wait_command_queue;
 };
index 287676a..9dce522 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved.
 
   802.11 status code portion of this file from ethereal-0.10.6:
     Copyright 2000, Axis Communications AB
@@ -33,9 +33,9 @@
 #include "ipw2200.h"
 #include <linux/version.h>
 
-#define IPW2200_VERSION "git-1.0.8"
+#define IPW2200_VERSION "git-1.1.1"
 #define DRV_DESCRIPTION        "Intel(R) PRO/Wireless 2200/2915 Network Driver"
-#define DRV_COPYRIGHT  "Copyright(c) 2003-2005 Intel Corporation"
+#define DRV_COPYRIGHT  "Copyright(c) 2003-2006 Intel Corporation"
 #define DRV_VERSION     IPW2200_VERSION
 
 #define ETH_P_80211_STATS (ETH_P_80211_RAW + 1)
@@ -55,7 +55,9 @@ static int associate = 1;
 static int auto_create = 1;
 static int led = 0;
 static int disable = 0;
-static int hwcrypto = 1;
+static int bt_coexist = 0;
+static int hwcrypto = 0;
+static int roaming = 1;
 static const char ipw_modes[] = {
        'a', 'b', 'g', '?'
 };
@@ -151,12 +153,6 @@ static int init_supported_rates(struct ipw_priv *priv,
 static void ipw_set_hwcrypto_keys(struct ipw_priv *);
 static void ipw_send_wep_keys(struct ipw_priv *, int);
 
-static int ipw_is_valid_channel(struct ieee80211_device *, u8);
-static int ipw_channel_to_index(struct ieee80211_device *, u8);
-static u8 ipw_freq_to_channel(struct ieee80211_device *, u32);
-static int ipw_set_geo(struct ieee80211_device *, const struct ieee80211_geo *);
-static const struct ieee80211_geo *ipw_get_geo(struct ieee80211_device *);
-
 static int snprint_line(char *buf, size_t count,
                        const u8 * data, u32 len, u32 ofs)
 {
@@ -227,12 +223,15 @@ static int snprintk_buf(u8 * output, size_t size, const u8 * data, size_t len)
        return total;
 }
 
+/* alias for 32-bit indirect read (for SRAM/reg above 4K), with debug wrapper */
 static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg);
 #define ipw_read_reg32(a, b) _ipw_read_reg32(a, b)
 
+/* alias for 8-bit indirect read (for SRAM/reg above 4K), with debug wrapper */
 static u8 _ipw_read_reg8(struct ipw_priv *ipw, u32 reg);
 #define ipw_read_reg8(a, b) _ipw_read_reg8(a, b)
 
+/* 8-bit indirect write (for SRAM/reg above 4K), with debug wrapper */
 static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value);
 static inline void ipw_write_reg8(struct ipw_priv *a, u32 b, u8 c)
 {
@@ -241,6 +240,7 @@ static inline void ipw_write_reg8(struct ipw_priv *a, u32 b, u8 c)
        _ipw_write_reg8(a, b, c);
 }
 
+/* 16-bit indirect write (for SRAM/reg above 4K), with debug wrapper */
 static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value);
 static inline void ipw_write_reg16(struct ipw_priv *a, u32 b, u16 c)
 {
@@ -249,6 +249,7 @@ static inline void ipw_write_reg16(struct ipw_priv *a, u32 b, u16 c)
        _ipw_write_reg16(a, b, c);
 }
 
+/* 32-bit indirect write (for SRAM/reg above 4K), with debug wrapper */
 static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value);
 static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c)
 {
@@ -257,48 +258,70 @@ static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c)
        _ipw_write_reg32(a, b, c);
 }
 
+/* 8-bit direct write (low 4K) */
 #define _ipw_write8(ipw, ofs, val) writeb((val), (ipw)->hw_base + (ofs))
+
+/* 8-bit direct write (for low 4K of SRAM/regs), with debug wrapper */
 #define ipw_write8(ipw, ofs, val) \
  IPW_DEBUG_IO("%s %d: write_direct8(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
  _ipw_write8(ipw, ofs, val)
 
+/* 16-bit direct write (low 4K) */
 #define _ipw_write16(ipw, ofs, val) writew((val), (ipw)->hw_base + (ofs))
+
+/* 16-bit direct write (for low 4K of SRAM/regs), with debug wrapper */
 #define ipw_write16(ipw, ofs, val) \
  IPW_DEBUG_IO("%s %d: write_direct16(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
  _ipw_write16(ipw, ofs, val)
 
+/* 32-bit direct write (low 4K) */
 #define _ipw_write32(ipw, ofs, val) writel((val), (ipw)->hw_base + (ofs))
+
+/* 32-bit direct write (for low 4K of SRAM/regs), with debug wrapper */
 #define ipw_write32(ipw, ofs, val) \
  IPW_DEBUG_IO("%s %d: write_direct32(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
  _ipw_write32(ipw, ofs, val)
 
+/* 8-bit direct read (low 4K) */
 #define _ipw_read8(ipw, ofs) readb((ipw)->hw_base + (ofs))
+
+/* 8-bit direct read (low 4K), with debug wrapper */
 static inline u8 __ipw_read8(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
 {
        IPW_DEBUG_IO("%s %d: read_direct8(0x%08X)\n", f, l, (u32) (ofs));
        return _ipw_read8(ipw, ofs);
 }
 
+/* alias to 8-bit direct read (low 4K of SRAM/regs), with debug wrapper */
 #define ipw_read8(ipw, ofs) __ipw_read8(__FILE__, __LINE__, ipw, ofs)
 
+/* 16-bit direct read (low 4K) */
 #define _ipw_read16(ipw, ofs) readw((ipw)->hw_base + (ofs))
+
+/* 16-bit direct read (low 4K), with debug wrapper */
 static inline u16 __ipw_read16(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
 {
        IPW_DEBUG_IO("%s %d: read_direct16(0x%08X)\n", f, l, (u32) (ofs));
        return _ipw_read16(ipw, ofs);
 }
 
+/* alias to 16-bit direct read (low 4K of SRAM/regs), with debug wrapper */
 #define ipw_read16(ipw, ofs) __ipw_read16(__FILE__, __LINE__, ipw, ofs)
 
+/* 32-bit direct read (low 4K) */
 #define _ipw_read32(ipw, ofs) readl((ipw)->hw_base + (ofs))
+
+/* 32-bit direct read (low 4K), with debug wrapper */
 static inline u32 __ipw_read32(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
 {
        IPW_DEBUG_IO("%s %d: read_direct32(0x%08X)\n", f, l, (u32) (ofs));
        return _ipw_read32(ipw, ofs);
 }
 
+/* alias to 32-bit direct read (low 4K of SRAM/regs), with debug wrapper */
 #define ipw_read32(ipw, ofs) __ipw_read32(__FILE__, __LINE__, ipw, ofs)
 
+/* multi-byte read (above 4K), with debug wrapper */
 static void _ipw_read_indirect(struct ipw_priv *, u32, u8 *, int);
 static inline void __ipw_read_indirect(const char *f, int l,
                                       struct ipw_priv *a, u32 b, u8 * c, int d)
@@ -308,15 +331,17 @@ static inline void __ipw_read_indirect(const char *f, int l,
        _ipw_read_indirect(a, b, c, d);
 }
 
+/* alias to multi-byte read (SRAM/regs above 4K), with debug wrapper */
 #define ipw_read_indirect(a, b, c, d) __ipw_read_indirect(__FILE__, __LINE__, a, b, c, d)
 
+/* alias to multi-byte read (SRAM/regs above 4K), with debug wrapper */
 static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * data,
                                int num);
 #define ipw_write_indirect(a, b, c, d) \
        IPW_DEBUG_IO("%s %d: write_indirect(0x%08X) %d bytes\n", __FILE__, __LINE__, (u32)(b), d); \
        _ipw_write_indirect(a, b, c, d)
 
-/* indirect write s */
+/* 32-bit indirect write (above 4K) */
 static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value)
 {
        IPW_DEBUG_IO(" %p : reg = 0x%8X : value = 0x%8X\n", priv, reg, value);
@@ -324,22 +349,29 @@ static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value)
        _ipw_write32(priv, IPW_INDIRECT_DATA, value);
 }
 
+/* 8-bit indirect write (above 4K) */
 static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value)
 {
+       u32 aligned_addr = reg & IPW_INDIRECT_ADDR_MASK;        /* dword align */
+       u32 dif_len = reg - aligned_addr;
+
        IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value);
-       _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK);
-       _ipw_write8(priv, IPW_INDIRECT_DATA, value);
+       _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr);
+       _ipw_write8(priv, IPW_INDIRECT_DATA + dif_len, value);
 }
 
+/* 16-bit indirect write (above 4K) */
 static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value)
 {
+       u32 aligned_addr = reg & IPW_INDIRECT_ADDR_MASK;        /* dword align */
+       u32 dif_len = (reg - aligned_addr) & (~0x1ul);
+
        IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value);
-       _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK);
-       _ipw_write16(priv, IPW_INDIRECT_DATA, value);
+       _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr);
+       _ipw_write16(priv, IPW_INDIRECT_DATA + dif_len, value);
 }
 
-/* indirect read s */
-
+/* 8-bit indirect read (above 4K) */
 static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg)
 {
        u32 word;
@@ -349,6 +381,7 @@ static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg)
        return (word >> ((reg & 0x3) * 8)) & 0xff;
 }
 
+/* 32-bit indirect read (above 4K) */
 static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg)
 {
        u32 value;
@@ -361,11 +394,12 @@ static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg)
        return value;
 }
 
-/* iterative/auto-increment 32 bit reads and writes */
+/* General purpose, no alignment requirement, iterative (multi-byte) read, */
+/*    for area above 1st 4K of SRAM/reg space */
 static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
                               int num)
 {
-       u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK;
+       u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK;       /* dword align */
        u32 dif_len = addr - aligned_addr;
        u32 i;
 
@@ -375,7 +409,7 @@ static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
                return;
        }
 
-       /* Read the first nibble byte by byte */
+       /* Read the first dword (or portion) byte by byte */
        if (unlikely(dif_len)) {
                _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr);
                /* Start reading at aligned_addr + dif_len */
@@ -384,11 +418,12 @@ static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
                aligned_addr += 4;
        }
 
+       /* Read all of the middle dwords as dwords, with auto-increment */
        _ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr);
        for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4)
                *(u32 *) buf = _ipw_read32(priv, IPW_AUTOINC_DATA);
 
-       /* Copy the last nibble */
+       /* Read the last dword (or portion) byte by byte */
        if (unlikely(num)) {
                _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr);
                for (i = 0; num > 0; i++, num--)
@@ -396,10 +431,12 @@ static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
        }
 }
 
+/* General purpose, no alignment requirement, iterative (multi-byte) write, */
+/*    for area above 1st 4K of SRAM/reg space */
 static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
                                int num)
 {
-       u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK;
+       u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK;       /* dword align */
        u32 dif_len = addr - aligned_addr;
        u32 i;
 
@@ -409,20 +446,21 @@ static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
                return;
        }
 
-       /* Write the first nibble byte by byte */
+       /* Write the first dword (or portion) byte by byte */
        if (unlikely(dif_len)) {
                _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr);
-               /* Start reading at aligned_addr + dif_len */
+               /* Start writing at aligned_addr + dif_len */
                for (i = dif_len; ((i < 4) && (num > 0)); i++, num--, buf++)
                        _ipw_write8(priv, IPW_INDIRECT_DATA + i, *buf);
                aligned_addr += 4;
        }
 
+       /* Write all of the middle dwords as dwords, with auto-increment */
        _ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr);
        for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4)
                _ipw_write32(priv, IPW_AUTOINC_DATA, *(u32 *) buf);
 
-       /* Copy the last nibble */
+       /* Write the last dword (or portion) byte by byte */
        if (unlikely(num)) {
                _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr);
                for (i = 0; num > 0; i++, num--, buf++)
@@ -430,17 +468,21 @@ static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
        }
 }
 
+/* General purpose, no alignment requirement, iterative (multi-byte) write, */
+/*    for 1st 4K of SRAM/regs space */
 static void ipw_write_direct(struct ipw_priv *priv, u32 addr, void *buf,
                             int num)
 {
        memcpy_toio((priv->hw_base + addr), buf, num);
 }
 
+/* Set bit(s) in low 4K of SRAM/regs */
 static inline void ipw_set_bit(struct ipw_priv *priv, u32 reg, u32 mask)
 {
        ipw_write32(priv, reg, ipw_read32(priv, reg) | mask);
 }
 
+/* Clear bit(s) in low 4K of SRAM/regs */
 static inline void ipw_clear_bit(struct ipw_priv *priv, u32 reg, u32 mask)
 {
        ipw_write32(priv, reg, ipw_read32(priv, reg) & ~mask);
@@ -701,7 +743,7 @@ static void ipw_init_ordinals(struct ipw_priv *priv)
 
 }
 
-u32 ipw_register_toggle(u32 reg)
+static u32 ipw_register_toggle(u32 reg)
 {
        reg &= ~IPW_START_STANDBY;
        if (reg & IPW_GATE_ODMA)
@@ -722,11 +764,11 @@ u32 ipw_register_toggle(u32 reg)
  * - On radio OFF, turn off any LEDs started during radio on
  *
  */
-#define LD_TIME_LINK_ON 300
-#define LD_TIME_LINK_OFF 2700
-#define LD_TIME_ACT_ON 250
+#define LD_TIME_LINK_ON msecs_to_jiffies(300)
+#define LD_TIME_LINK_OFF msecs_to_jiffies(2700)
+#define LD_TIME_ACT_ON msecs_to_jiffies(250)
 
-void ipw_led_link_on(struct ipw_priv *priv)
+static void ipw_led_link_on(struct ipw_priv *priv)
 {
        unsigned long flags;
        u32 led;
@@ -764,12 +806,12 @@ void ipw_led_link_on(struct ipw_priv *priv)
 static void ipw_bg_led_link_on(void *data)
 {
        struct ipw_priv *priv = data;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ipw_led_link_on(data);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
-void ipw_led_link_off(struct ipw_priv *priv)
+static void ipw_led_link_off(struct ipw_priv *priv)
 {
        unsigned long flags;
        u32 led;
@@ -808,9 +850,9 @@ void ipw_led_link_off(struct ipw_priv *priv)
 static void ipw_bg_led_link_off(void *data)
 {
        struct ipw_priv *priv = data;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ipw_led_link_off(data);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
 static void __ipw_led_activity_on(struct ipw_priv *priv)
@@ -847,6 +889,7 @@ static void __ipw_led_activity_on(struct ipw_priv *priv)
        }
 }
 
+#if 0
 void ipw_led_activity_on(struct ipw_priv *priv)
 {
        unsigned long flags;
@@ -854,8 +897,9 @@ void ipw_led_activity_on(struct ipw_priv *priv)
        __ipw_led_activity_on(priv);
        spin_unlock_irqrestore(&priv->lock, flags);
 }
+#endif  /*  0  */
 
-void ipw_led_activity_off(struct ipw_priv *priv)
+static void ipw_led_activity_off(struct ipw_priv *priv)
 {
        unsigned long flags;
        u32 led;
@@ -885,12 +929,12 @@ void ipw_led_activity_off(struct ipw_priv *priv)
 static void ipw_bg_led_activity_off(void *data)
 {
        struct ipw_priv *priv = data;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ipw_led_activity_off(data);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
-void ipw_led_band_on(struct ipw_priv *priv)
+static void ipw_led_band_on(struct ipw_priv *priv)
 {
        unsigned long flags;
        u32 led;
@@ -925,7 +969,7 @@ void ipw_led_band_on(struct ipw_priv *priv)
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-void ipw_led_band_off(struct ipw_priv *priv)
+static void ipw_led_band_off(struct ipw_priv *priv)
 {
        unsigned long flags;
        u32 led;
@@ -948,24 +992,24 @@ void ipw_led_band_off(struct ipw_priv *priv)
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-void ipw_led_radio_on(struct ipw_priv *priv)
+static void ipw_led_radio_on(struct ipw_priv *priv)
 {
        ipw_led_link_on(priv);
 }
 
-void ipw_led_radio_off(struct ipw_priv *priv)
+static void ipw_led_radio_off(struct ipw_priv *priv)
 {
        ipw_led_activity_off(priv);
        ipw_led_link_off(priv);
 }
 
-void ipw_led_link_up(struct ipw_priv *priv)
+static void ipw_led_link_up(struct ipw_priv *priv)
 {
        /* Set the Link Led on for all nic types */
        ipw_led_link_on(priv);
 }
 
-void ipw_led_link_down(struct ipw_priv *priv)
+static void ipw_led_link_down(struct ipw_priv *priv)
 {
        ipw_led_activity_off(priv);
        ipw_led_link_off(priv);
@@ -974,7 +1018,7 @@ void ipw_led_link_down(struct ipw_priv *priv)
                ipw_led_radio_off(priv);
 }
 
-void ipw_led_init(struct ipw_priv *priv)
+static void ipw_led_init(struct ipw_priv *priv)
 {
        priv->nic_type = priv->eeprom[EEPROM_NIC_TYPE];
 
@@ -1025,7 +1069,7 @@ void ipw_led_init(struct ipw_priv *priv)
        }
 }
 
-void ipw_led_shutdown(struct ipw_priv *priv)
+static void ipw_led_shutdown(struct ipw_priv *priv)
 {
        ipw_led_activity_off(priv);
        ipw_led_link_off(priv);
@@ -1074,6 +1118,7 @@ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
 
 static inline u32 ipw_get_event_log_len(struct ipw_priv *priv)
 {
+       /* length = 1st dword in log */
        return ipw_read_reg32(priv, ipw_read32(priv, IPW_EVENT_LOG));
 }
 
@@ -1603,7 +1648,7 @@ static ssize_t store_speed_scan(struct device *d, struct device_attribute *attr,
                        break;
                }
 
-               if (ipw_is_valid_channel(priv->ieee, channel))
+               if (ieee80211_is_valid_channel(priv->ieee, channel))
                        priv->speed_scan[pos++] = channel;
                else
                        IPW_WARNING("Skipping invalid channel request: %d\n",
@@ -1751,9 +1796,9 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
        }
 
        if (inta & IPW_INTA_BIT_FATAL_ERROR) {
-               IPW_ERROR("Firmware error detected.  Restarting.\n");
+               IPW_WARNING("Firmware error detected.  Restarting.\n");
                if (priv->error) {
-                       IPW_ERROR("Sysfs 'error' log already exists.\n");
+                       IPW_DEBUG_FW("Sysfs 'error' log already exists.\n");
 #ifdef CONFIG_IPW2200_DEBUG
                        if (ipw_debug_level & IPW_DL_FW_ERRORS) {
                                struct ipw_fw_error *error =
@@ -1766,10 +1811,10 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
                } else {
                        priv->error = ipw_alloc_error_log(priv);
                        if (priv->error)
-                               IPW_ERROR("Sysfs 'error' log captured.\n");
+                               IPW_DEBUG_FW("Sysfs 'error' log captured.\n");
                        else
-                               IPW_ERROR("Error allocating sysfs 'error' "
-                                         "log.\n");
+                               IPW_DEBUG_FW("Error allocating sysfs 'error' "
+                                            "log.\n");
 #ifdef CONFIG_IPW2200_DEBUG
                        if (ipw_debug_level & IPW_DL_FW_ERRORS)
                                ipw_dump_error_log(priv, priv->error);
@@ -1870,7 +1915,8 @@ static char *get_cmd_string(u8 cmd)
 }
 
 #define HOST_COMPLETE_TIMEOUT HZ
-static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
+
+static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
 {
        int rc = 0;
        unsigned long flags;
@@ -1897,9 +1943,15 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
        IPW_DEBUG_HC("%s command (#%d) %d bytes: 0x%08X\n",
                     get_cmd_string(cmd->cmd), cmd->cmd, cmd->len,
                     priv->status);
-       printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len);
 
-       rc = ipw_queue_tx_hcmd(priv, cmd->cmd, &cmd->param, cmd->len, 0);
+#ifndef DEBUG_CMD_WEP_KEY
+       if (cmd->cmd == IPW_CMD_WEP_KEY)
+               IPW_DEBUG_HC("WEP_KEY command masked out for secure.\n");
+       else
+#endif
+               printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len);
+
+       rc = ipw_queue_tx_hcmd(priv, cmd->cmd, cmd->param, cmd->len, 0);
        if (rc) {
                priv->status &= ~STATUS_HCMD_ACTIVE;
                IPW_ERROR("Failed to send %s: Reason %d\n",
@@ -1942,61 +1994,62 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
        return rc;
 }
 
-static int ipw_send_host_complete(struct ipw_priv *priv)
+static int ipw_send_cmd_simple(struct ipw_priv *priv, u8 command)
+{
+       struct host_cmd cmd = {
+               .cmd = command,
+       };
+
+       return __ipw_send_cmd(priv, &cmd);
+}
+
+static int ipw_send_cmd_pdu(struct ipw_priv *priv, u8 command, u8 len,
+                           void *data)
 {
        struct host_cmd cmd = {
-               .cmd = IPW_CMD_HOST_COMPLETE,
-               .len = 0
+               .cmd = command,
+               .len = len,
+               .param = data,
        };
 
+       return __ipw_send_cmd(priv, &cmd);
+}
+
+static int ipw_send_host_complete(struct ipw_priv *priv)
+{
        if (!priv) {
                IPW_ERROR("Invalid args\n");
                return -1;
        }
 
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_simple(priv, IPW_CMD_HOST_COMPLETE);
 }
 
 static int ipw_send_system_config(struct ipw_priv *priv,
                                  struct ipw_sys_config *config)
 {
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_SYSTEM_CONFIG,
-               .len = sizeof(*config)
-       };
-
        if (!priv || !config) {
                IPW_ERROR("Invalid args\n");
                return -1;
        }
 
-       memcpy(cmd.param, config, sizeof(*config));
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_pdu(priv, IPW_CMD_SYSTEM_CONFIG, sizeof(*config),
+                               config);
 }
 
 static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len)
 {
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_SSID,
-               .len = min(len, IW_ESSID_MAX_SIZE)
-       };
-
        if (!priv || !ssid) {
                IPW_ERROR("Invalid args\n");
                return -1;
        }
 
-       memcpy(cmd.param, ssid, cmd.len);
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_pdu(priv, IPW_CMD_SSID, min(len, IW_ESSID_MAX_SIZE),
+                               ssid);
 }
 
 static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac)
 {
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_ADAPTER_ADDRESS,
-               .len = ETH_ALEN
-       };
-
        if (!priv || !mac) {
                IPW_ERROR("Invalid args\n");
                return -1;
@@ -2005,8 +2058,7 @@ static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac)
        IPW_DEBUG_INFO("%s: Setting MAC to " MAC_FMT "\n",
                       priv->net_dev->name, MAC_ARG(mac));
 
-       memcpy(cmd.param, mac, ETH_ALEN);
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_pdu(priv, IPW_CMD_ADAPTER_ADDRESS, ETH_ALEN, mac);
 }
 
 /*
@@ -2036,9 +2088,9 @@ static void ipw_adapter_restart(void *adapter)
 static void ipw_bg_adapter_restart(void *data)
 {
        struct ipw_priv *priv = data;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ipw_adapter_restart(data);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
 #define IPW_SCAN_CHECK_WATCHDOG (5 * HZ)
@@ -2048,8 +2100,8 @@ static void ipw_scan_check(void *data)
        struct ipw_priv *priv = data;
        if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) {
                IPW_DEBUG_SCAN("Scan completion watchdog resetting "
-                              "adapter (%dms).\n",
-                              IPW_SCAN_CHECK_WATCHDOG / 100);
+                              "adapter after (%dms).\n",
+                              jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG));
                queue_work(priv->workqueue, &priv->adapter_restart);
        }
 }
@@ -2057,59 +2109,48 @@ static void ipw_scan_check(void *data)
 static void ipw_bg_scan_check(void *data)
 {
        struct ipw_priv *priv = data;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ipw_scan_check(data);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
 static int ipw_send_scan_request_ext(struct ipw_priv *priv,
                                     struct ipw_scan_request_ext *request)
 {
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_SCAN_REQUEST_EXT,
-               .len = sizeof(*request)
-       };
-
-       memcpy(cmd.param, request, sizeof(*request));
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_pdu(priv, IPW_CMD_SCAN_REQUEST_EXT,
+                               sizeof(*request), request);
 }
 
 static int ipw_send_scan_abort(struct ipw_priv *priv)
 {
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_SCAN_ABORT,
-               .len = 0
-       };
-
        if (!priv) {
                IPW_ERROR("Invalid args\n");
                return -1;
        }
 
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_simple(priv, IPW_CMD_SCAN_ABORT);
 }
 
 static int ipw_set_sensitivity(struct ipw_priv *priv, u16 sens)
 {
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_SENSITIVITY_CALIB,
-               .len = sizeof(struct ipw_sensitivity_calib)
+       struct ipw_sensitivity_calib calib = {
+               .beacon_rssi_raw = sens,
        };
-       struct ipw_sensitivity_calib *calib = (struct ipw_sensitivity_calib *)
-           &cmd.param;
-       calib->beacon_rssi_raw = sens;
-       return ipw_send_cmd(priv, &cmd);
+
+       return ipw_send_cmd_pdu(priv, IPW_CMD_SENSITIVITY_CALIB, sizeof(calib),
+                               &calib);
 }
 
 static int ipw_send_associate(struct ipw_priv *priv,
                              struct ipw_associate *associate)
 {
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_ASSOCIATE,
-               .len = sizeof(*associate)
-       };
-
        struct ipw_associate tmp_associate;
+
+       if (!priv || !associate) {
+               IPW_ERROR("Invalid args\n");
+               return -1;
+       }
+
        memcpy(&tmp_associate, associate, sizeof(*associate));
        tmp_associate.policy_support =
            cpu_to_le16(tmp_associate.policy_support);
@@ -2122,85 +2163,60 @@ static int ipw_send_associate(struct ipw_priv *priv,
            cpu_to_le16(tmp_associate.beacon_interval);
        tmp_associate.atim_window = cpu_to_le16(tmp_associate.atim_window);
 
-       if (!priv || !associate) {
-               IPW_ERROR("Invalid args\n");
-               return -1;
-       }
-
-       memcpy(cmd.param, &tmp_associate, sizeof(*associate));
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_pdu(priv, IPW_CMD_ASSOCIATE, sizeof(tmp_associate),
+                               &tmp_associate);
 }
 
 static int ipw_send_supported_rates(struct ipw_priv *priv,
                                    struct ipw_supported_rates *rates)
 {
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_SUPPORTED_RATES,
-               .len = sizeof(*rates)
-       };
-
        if (!priv || !rates) {
                IPW_ERROR("Invalid args\n");
                return -1;
        }
 
-       memcpy(cmd.param, rates, sizeof(*rates));
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_pdu(priv, IPW_CMD_SUPPORTED_RATES, sizeof(*rates),
+                               rates);
 }
 
 static int ipw_set_random_seed(struct ipw_priv *priv)
 {
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_SEED_NUMBER,
-               .len = sizeof(u32)
-       };
+       u32 val;
 
        if (!priv) {
                IPW_ERROR("Invalid args\n");
                return -1;
        }
 
-       get_random_bytes(&cmd.param, sizeof(u32));
+       get_random_bytes(&val, sizeof(val));
 
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_pdu(priv, IPW_CMD_SEED_NUMBER, sizeof(val), &val);
 }
 
 static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off)
 {
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_CARD_DISABLE,
-               .len = sizeof(u32)
-       };
-
        if (!priv) {
                IPW_ERROR("Invalid args\n");
                return -1;
        }
 
-       *((u32 *) & cmd.param) = phy_off;
-
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_pdu(priv, IPW_CMD_CARD_DISABLE, sizeof(phy_off),
+                               &phy_off);
 }
 
 static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power)
 {
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_TX_POWER,
-               .len = sizeof(*power)
-       };
-
        if (!priv || !power) {
                IPW_ERROR("Invalid args\n");
                return -1;
        }
 
-       memcpy(cmd.param, power, sizeof(*power));
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_pdu(priv, IPW_CMD_TX_POWER, sizeof(*power), power);
 }
 
 static int ipw_set_tx_power(struct ipw_priv *priv)
 {
-       const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee);
+       const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee);
        struct ipw_tx_power tx_power;
        s8 max_power;
        int i;
@@ -2247,18 +2263,14 @@ static int ipw_send_rts_threshold(struct ipw_priv *priv, u16 rts)
        struct ipw_rts_threshold rts_threshold = {
                .rts_threshold = rts,
        };
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_RTS_THRESHOLD,
-               .len = sizeof(rts_threshold)
-       };
 
        if (!priv) {
                IPW_ERROR("Invalid args\n");
                return -1;
        }
 
-       memcpy(cmd.param, &rts_threshold, sizeof(rts_threshold));
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_pdu(priv, IPW_CMD_RTS_THRESHOLD,
+                               sizeof(rts_threshold), &rts_threshold);
 }
 
 static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag)
@@ -2266,27 +2278,19 @@ static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag)
        struct ipw_frag_threshold frag_threshold = {
                .frag_threshold = frag,
        };
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_FRAG_THRESHOLD,
-               .len = sizeof(frag_threshold)
-       };
 
        if (!priv) {
                IPW_ERROR("Invalid args\n");
                return -1;
        }
 
-       memcpy(cmd.param, &frag_threshold, sizeof(frag_threshold));
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_pdu(priv, IPW_CMD_FRAG_THRESHOLD,
+                               sizeof(frag_threshold), &frag_threshold);
 }
 
 static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode)
 {
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_POWER_MODE,
-               .len = sizeof(u32)
-       };
-       u32 *param = (u32 *) (&cmd.param);
+       u32 param;
 
        if (!priv) {
                IPW_ERROR("Invalid args\n");
@@ -2297,17 +2301,18 @@ static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode)
         * level */
        switch (mode) {
        case IPW_POWER_BATTERY:
-               *param = IPW_POWER_INDEX_3;
+               param = IPW_POWER_INDEX_3;
                break;
        case IPW_POWER_AC:
-               *param = IPW_POWER_MODE_CAM;
+               param = IPW_POWER_MODE_CAM;
                break;
        default:
-               *param = mode;
+               param = mode;
                break;
        }
 
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_pdu(priv, IPW_CMD_POWER_MODE, sizeof(param),
+                               &param);
 }
 
 static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit)
@@ -2316,18 +2321,14 @@ static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit)
                .short_retry_limit = slimit,
                .long_retry_limit = llimit
        };
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_RETRY_LIMIT,
-               .len = sizeof(retry_limit)
-       };
 
        if (!priv) {
                IPW_ERROR("Invalid args\n");
                return -1;
        }
 
-       memcpy(cmd.param, &retry_limit, sizeof(retry_limit));
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_pdu(priv, IPW_CMD_RETRY_LIMIT, sizeof(retry_limit),
+                               &retry_limit);
 }
 
 /*
@@ -2454,7 +2455,7 @@ static void ipw_eeprom_init_sram(struct ipw_priv *priv)
        /*
           If the data looks correct, then copy it to our private
           copy.  Otherwise let the firmware know to perform the operation
-          on it's own
+          on its own.
         */
        if (priv->eeprom[EEPROM_VERSION] != 0) {
                IPW_DEBUG_INFO("Writing EEPROM data into SRAM\n");
@@ -2707,22 +2708,25 @@ static int ipw_fw_dma_add_buffer(struct ipw_priv *priv,
 
 static int ipw_fw_dma_wait(struct ipw_priv *priv)
 {
-       u32 current_index = 0;
+       u32 current_index = 0, previous_index;
        u32 watchdog = 0;
 
        IPW_DEBUG_FW(">> : \n");
 
        current_index = ipw_fw_dma_command_block_index(priv);
-       IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%8X\n",
+       IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%08X\n",
                          (int)priv->sram_desc.last_cb_index);
 
        while (current_index < priv->sram_desc.last_cb_index) {
                udelay(50);
+               previous_index = current_index;
                current_index = ipw_fw_dma_command_block_index(priv);
 
-               watchdog++;
-
-               if (watchdog > 400) {
+               if (previous_index < current_index) {
+                       watchdog = 0;
+                       continue;
+               }
+               if (++watchdog > 400) {
                        IPW_DEBUG_FW_INFO("Timeout\n");
                        ipw_fw_dma_dump_command_block(priv);
                        ipw_fw_dma_abort(priv);
@@ -2772,6 +2776,7 @@ static inline int ipw_alive(struct ipw_priv *priv)
        return ipw_read32(priv, 0x90) == 0xd55555d5;
 }
 
+/* timeout in msec, attempted in 10-msec quanta */
 static int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask,
                               int timeout)
 {
@@ -2800,10 +2805,11 @@ static int ipw_stop_master(struct ipw_priv *priv)
        /* stop master. typical delay - 0 */
        ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_STOP_MASTER);
 
+       /* timeout is in msec, polled in 10-msec quanta */
        rc = ipw_poll_bit(priv, IPW_RESET_REG,
                          IPW_RESET_REG_MASTER_DISABLED, 100);
        if (rc < 0) {
-               IPW_ERROR("stop master failed in 10ms\n");
+               IPW_ERROR("wait for stop master failed after 100ms\n");
                return -1;
        }
 
@@ -2823,33 +2829,11 @@ static void ipw_arc_release(struct ipw_priv *priv)
        mdelay(5);
 }
 
-struct fw_header {
-       u32 version;
-       u32 mode;
-};
-
 struct fw_chunk {
        u32 address;
        u32 length;
 };
 
-#define IPW_FW_MAJOR_VERSION 2
-#define IPW_FW_MINOR_VERSION 4
-
-#define IPW_FW_MINOR(x) ((x & 0xff) >> 8)
-#define IPW_FW_MAJOR(x) (x & 0xff)
-
-#define IPW_FW_VERSION ((IPW_FW_MINOR_VERSION << 8) | IPW_FW_MAJOR_VERSION)
-
-#define IPW_FW_PREFIX "ipw-" __stringify(IPW_FW_MAJOR_VERSION) \
-"." __stringify(IPW_FW_MINOR_VERSION) "-"
-
-#if IPW_FW_MAJOR_VERSION >= 2 && IPW_FW_MINOR_VERSION > 0
-#define IPW_FW_NAME(x) IPW_FW_PREFIX "" x ".fw"
-#else
-#define IPW_FW_NAME(x) "ipw2200_" x ".fw"
-#endif
-
 static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len)
 {
        int rc = 0, i, addr;
@@ -2890,8 +2874,8 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len)
        mdelay(1);
 
        /* enable ucode store */
-       ipw_write_reg8(priv, DINO_CONTROL_REG, 0x0);
-       ipw_write_reg8(priv, DINO_CONTROL_REG, DINO_ENABLE_CS);
+       ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0x0);
+       ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, DINO_ENABLE_CS);
        mdelay(1);
 
        /* write ucode */
@@ -3036,7 +3020,7 @@ static int ipw_stop_nic(struct ipw_priv *priv)
        rc = ipw_poll_bit(priv, IPW_RESET_REG,
                          IPW_RESET_REG_MASTER_DISABLED, 500);
        if (rc < 0) {
-               IPW_ERROR("wait for reg master disabled failed\n");
+               IPW_ERROR("wait for reg master disabled failed after 500ms\n");
                return rc;
        }
 
@@ -3118,33 +3102,47 @@ static int ipw_reset_nic(struct ipw_priv *priv)
        return rc;
 }
 
+
+struct ipw_fw {
+       u32 ver;
+       u32 boot_size;
+       u32 ucode_size;
+       u32 fw_size;
+       u8 data[0];
+};
+
 static int ipw_get_fw(struct ipw_priv *priv,
-                     const struct firmware **fw, const char *name)
+                     const struct firmware **raw, const char *name)
 {
-       struct fw_header *header;
+       struct ipw_fw *fw;
        int rc;
 
        /* ask firmware_class module to get the boot firmware off disk */
-       rc = request_firmware(fw, name, &priv->pci_dev->dev);
+       rc = request_firmware(raw, name, &priv->pci_dev->dev);
        if (rc < 0) {
-               IPW_ERROR("%s load failed: Reason %d\n", name, rc);
+               IPW_ERROR("%s request_firmware failed: Reason %d\n", name, rc);
                return rc;
        }
 
-       header = (struct fw_header *)(*fw)->data;
-       if (IPW_FW_MAJOR(le32_to_cpu(header->version)) != IPW_FW_MAJOR_VERSION) {
-               IPW_ERROR("'%s' firmware version not compatible (%d != %d)\n",
-                         name,
-                         IPW_FW_MAJOR(le32_to_cpu(header->version)),
-                         IPW_FW_MAJOR_VERSION);
+       if ((*raw)->size < sizeof(*fw)) {
+               IPW_ERROR("%s is too small (%zd)\n", name, (*raw)->size);
+               return -EINVAL;
+       }
+
+       fw = (void *)(*raw)->data;
+
+       if ((*raw)->size < sizeof(*fw) +
+           fw->boot_size + fw->ucode_size + fw->fw_size) {
+               IPW_ERROR("%s is too small or corrupt (%zd)\n",
+                         name, (*raw)->size);
                return -EINVAL;
        }
 
-       IPW_DEBUG_INFO("Loading firmware '%s' file v%d.%d (%zd bytes)\n",
+       IPW_DEBUG_INFO("Read firmware '%s' image v%d.%d (%zd bytes)\n",
                       name,
-                      IPW_FW_MAJOR(le32_to_cpu(header->version)),
-                      IPW_FW_MINOR(le32_to_cpu(header->version)),
-                      (*fw)->size - sizeof(struct fw_header));
+                      le32_to_cpu(fw->ver) >> 16,
+                      le32_to_cpu(fw->ver) & 0xff,
+                      (*raw)->size - sizeof(*fw));
        return 0;
 }
 
@@ -3184,17 +3182,13 @@ static void ipw_rx_queue_reset(struct ipw_priv *priv,
 
 #ifdef CONFIG_PM
 static int fw_loaded = 0;
-static const struct firmware *bootfw = NULL;
-static const struct firmware *firmware = NULL;
-static const struct firmware *ucode = NULL;
+static const struct firmware *raw = NULL;
 
 static void free_firmware(void)
 {
        if (fw_loaded) {
-               release_firmware(bootfw);
-               release_firmware(ucode);
-               release_firmware(firmware);
-               bootfw = ucode = firmware = NULL;
+               release_firmware(raw);
+               raw = NULL;
                fw_loaded = 0;
        }
 }
@@ -3205,60 +3199,50 @@ static void free_firmware(void)
 static int ipw_load(struct ipw_priv *priv)
 {
 #ifndef CONFIG_PM
-       const struct firmware *bootfw = NULL;
-       const struct firmware *firmware = NULL;
-       const struct firmware *ucode = NULL;
+       const struct firmware *raw = NULL;
 #endif
+       struct ipw_fw *fw;
+       u8 *boot_img, *ucode_img, *fw_img;
+       u8 *name = NULL;
        int rc = 0, retries = 3;
 
-#ifdef CONFIG_PM
-       if (!fw_loaded) {
-#endif
-               rc = ipw_get_fw(priv, &bootfw, IPW_FW_NAME("boot"));
-               if (rc)
-                       goto error;
-
-               switch (priv->ieee->iw_mode) {
-               case IW_MODE_ADHOC:
-                       rc = ipw_get_fw(priv, &ucode,
-                                       IPW_FW_NAME("ibss_ucode"));
-                       if (rc)
-                               goto error;
-
-                       rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("ibss"));
-                       break;
-
+       switch (priv->ieee->iw_mode) {
+       case IW_MODE_ADHOC:
+               name = "ipw2200-ibss.fw";
+               break;
 #ifdef CONFIG_IPW2200_MONITOR
-               case IW_MODE_MONITOR:
-                       rc = ipw_get_fw(priv, &ucode,
-                                       IPW_FW_NAME("sniffer_ucode"));
-                       if (rc)
-                               goto error;
-
-                       rc = ipw_get_fw(priv, &firmware,
-                                       IPW_FW_NAME("sniffer"));
-                       break;
+       case IW_MODE_MONITOR:
+               name = "ipw2200-sniffer.fw";
+               break;
 #endif
-               case IW_MODE_INFRA:
-                       rc = ipw_get_fw(priv, &ucode, IPW_FW_NAME("bss_ucode"));
-                       if (rc)
-                               goto error;
-
-                       rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("bss"));
-                       break;
+       case IW_MODE_INFRA:
+               name = "ipw2200-bss.fw";
+               break;
+       }
 
-               default:
-                       rc = -EINVAL;
-               }
+       if (!name) {
+               rc = -EINVAL;
+               goto error;
+       }
 
-               if (rc)
+#ifdef CONFIG_PM
+       if (!fw_loaded) {
+#endif
+               rc = ipw_get_fw(priv, &raw, name);
+               if (rc < 0)
                        goto error;
-
 #ifdef CONFIG_PM
-               fw_loaded = 1;
        }
 #endif
 
+       fw = (void *)raw->data;
+       boot_img = &fw->data[0];
+       ucode_img = &fw->data[fw->boot_size];
+       fw_img = &fw->data[fw->boot_size + fw->ucode_size];
+
+       if (rc < 0)
+               goto error;
+
        if (!priv->rxq)
                priv->rxq = ipw_rx_queue_alloc(priv);
        else
@@ -3279,7 +3263,7 @@ static int ipw_load(struct ipw_priv *priv)
        ipw_stop_nic(priv);
 
        rc = ipw_reset_nic(priv);
-       if (rc) {
+       if (rc < 0) {
                IPW_ERROR("Unable to reset NIC\n");
                goto error;
        }
@@ -3288,8 +3272,7 @@ static int ipw_load(struct ipw_priv *priv)
                        IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND);
 
        /* DMA the initial boot firmware into the device */
-       rc = ipw_load_firmware(priv, bootfw->data + sizeof(struct fw_header),
-                              bootfw->size - sizeof(struct fw_header));
+       rc = ipw_load_firmware(priv, boot_img, fw->boot_size);
        if (rc < 0) {
                IPW_ERROR("Unable to load boot firmware: %d\n", rc);
                goto error;
@@ -3298,7 +3281,7 @@ static int ipw_load(struct ipw_priv *priv)
        /* kick start the device */
        ipw_start_nic(priv);
 
-       /* wait for the device to finish it's initial startup sequence */
+       /* wait for the device to finish its initial startup sequence */
        rc = ipw_poll_bit(priv, IPW_INTA_RW,
                          IPW_INTA_BIT_FW_INITIALIZATION_DONE, 500);
        if (rc < 0) {
@@ -3311,8 +3294,7 @@ static int ipw_load(struct ipw_priv *priv)
        ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE);
 
        /* DMA the ucode into the device */
-       rc = ipw_load_ucode(priv, ucode->data + sizeof(struct fw_header),
-                           ucode->size - sizeof(struct fw_header));
+       rc = ipw_load_ucode(priv, ucode_img, fw->ucode_size);
        if (rc < 0) {
                IPW_ERROR("Unable to load ucode: %d\n", rc);
                goto error;
@@ -3322,18 +3304,19 @@ static int ipw_load(struct ipw_priv *priv)
        ipw_stop_nic(priv);
 
        /* DMA bss firmware into the device */
-       rc = ipw_load_firmware(priv, firmware->data +
-                              sizeof(struct fw_header),
-                              firmware->size - sizeof(struct fw_header));
+       rc = ipw_load_firmware(priv, fw_img, fw->fw_size);
        if (rc < 0) {
                IPW_ERROR("Unable to load firmware: %d\n", rc);
                goto error;
        }
+#ifdef CONFIG_PM
+       fw_loaded = 1;
+#endif
 
        ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 0);
 
        rc = ipw_queue_reset(priv);
-       if (rc) {
+       if (rc < 0) {
                IPW_ERROR("Unable to initialize queues\n");
                goto error;
        }
@@ -3362,7 +3345,7 @@ static int ipw_load(struct ipw_priv *priv)
        rc = ipw_poll_bit(priv, IPW_INTA_RW,
                          IPW_INTA_BIT_FW_INITIALIZATION_DONE, 500);
        if (rc < 0) {
-               IPW_ERROR("device failed to start after 500ms\n");
+               IPW_ERROR("device failed to start within 500ms\n");
                goto error;
        }
        IPW_DEBUG_INFO("device response after %dms\n", rc);
@@ -3386,9 +3369,7 @@ static int ipw_load(struct ipw_priv *priv)
        ipw_write32(priv, IPW_INTA_RW, IPW_INTA_MASK_ALL);
 
 #ifndef CONFIG_PM
-       release_firmware(bootfw);
-       release_firmware(ucode);
-       release_firmware(firmware);
+       release_firmware(raw);
 #endif
        return 0;
 
@@ -3398,15 +3379,11 @@ static int ipw_load(struct ipw_priv *priv)
                priv->rxq = NULL;
        }
        ipw_tx_queue_free(priv);
-       if (bootfw)
-               release_firmware(bootfw);
-       if (ucode)
-               release_firmware(ucode);
-       if (firmware)
-               release_firmware(firmware);
+       if (raw)
+               release_firmware(raw);
 #ifdef CONFIG_PM
        fw_loaded = 0;
-       bootfw = ucode = firmware = NULL;
+       raw = NULL;
 #endif
 
        return rc;
@@ -3715,9 +3692,9 @@ static int ipw_disassociate(void *data)
 static void ipw_bg_disassociate(void *data)
 {
        struct ipw_priv *priv = data;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ipw_disassociate(data);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
 static void ipw_system_config(void *data)
@@ -4077,9 +4054,9 @@ static void ipw_gather_stats(struct ipw_priv *priv)
 static void ipw_bg_gather_stats(void *data)
 {
        struct ipw_priv *priv = data;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ipw_gather_stats(data);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
 /* Missed beacon behavior:
@@ -4121,8 +4098,9 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv,
                return;
        }
 
-       if (missed_count > priv->roaming_threshold &&
-           missed_count <= priv->disassociate_threshold) {
+       if (roaming &&
+           (missed_count > priv->roaming_threshold &&
+            missed_count <= priv->disassociate_threshold)) {
                /* If we are not already roaming, set the ROAM
                 * bit in the status and kick off a scan.
                 * This can happen several times before we reach
@@ -4150,7 +4128,6 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv,
        }
 
        IPW_DEBUG_NOTIF("Missed beacon: %d\n", missed_count);
-
 }
 
 /**
@@ -4527,10 +4504,9 @@ static void ipw_rx_notification(struct ipw_priv *priv,
 
                        if (notif->size == sizeof(*x)) {
                                IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE,
-                                         "link deterioration: '%s' " MAC_FMT
-                                         " \n", escape_essid(priv->essid,
-                                                             priv->essid_len),
-                                         MAC_ARG(priv->bssid));
+                                       "link deterioration: type %d, cnt %d\n",
+                                       x->silence_notification_type,
+                                       x->silence_count);
                                memcpy(&priv->last_link_deterioration, x,
                                       sizeof(*x));
                        } else {
@@ -4911,13 +4887,13 @@ static void ipw_rx_queue_replenish(void *data)
 static void ipw_bg_rx_queue_replenish(void *data)
 {
        struct ipw_priv *priv = data;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ipw_rx_queue_replenish(data);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
 /* Assumes that the skb field of the buffers in 'pool' is kept accurate.
- * If an SKB has been detached, the POOL needs to have it's SKB set to NULL
+ * If an SKB has been detached, the POOL needs to have its SKB set to NULL
  * This free routine walks the list of POOL entries and if SKB is set to
  * non NULL it is unmapped and freed
  */
@@ -5257,10 +5233,11 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
        if (priv->ieee->scan_age != 0 &&
            time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) {
                IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded "
-                               "because of age: %lums.\n",
+                               "because of age: %ums.\n",
                                escape_essid(network->ssid, network->ssid_len),
                                MAC_ARG(network->bssid),
-                               1000 * (jiffies - network->last_scanned) / HZ);
+                               jiffies_to_msecs(jiffies -
+                                                network->last_scanned));
                return 0;
        }
 
@@ -5369,7 +5346,7 @@ static void ipw_merge_adhoc_network(void *data)
                        return;
                }
 
-               down(&priv->sem);
+               mutex_lock(&priv->mutex);
                if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) {
                        IPW_DEBUG_MERGE("remove network %s\n",
                                        escape_essid(priv->essid,
@@ -5379,7 +5356,7 @@ static void ipw_merge_adhoc_network(void *data)
 
                ipw_disassociate(priv);
                priv->assoc_network = match.network;
-               up(&priv->sem);
+               mutex_unlock(&priv->mutex);
                return;
        }
 }
@@ -5467,11 +5444,12 @@ static int ipw_best_network(struct ipw_priv *priv,
        if (network->last_associate &&
            time_after(network->last_associate + (HZ * 3UL), jiffies)) {
                IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
-                               "because of storming (%lus since last "
+                               "because of storming (%ums since last "
                                "assoc attempt).\n",
                                escape_essid(network->ssid, network->ssid_len),
                                MAC_ARG(network->bssid),
-                               (jiffies - network->last_associate) / HZ);
+                               jiffies_to_msecs(jiffies -
+                                                network->last_associate));
                return 0;
        }
 
@@ -5479,10 +5457,11 @@ static int ipw_best_network(struct ipw_priv *priv,
        if (priv->ieee->scan_age != 0 &&
            time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) {
                IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
-                               "because of age: %lums.\n",
+                               "because of age: %ums.\n",
                                escape_essid(network->ssid, network->ssid_len),
                                MAC_ARG(network->bssid),
-                               1000 * (jiffies - network->last_scanned) / HZ);
+                               jiffies_to_msecs(jiffies -
+                                                network->last_scanned));
                return 0;
        }
 
@@ -5510,15 +5489,6 @@ static int ipw_best_network(struct ipw_priv *priv,
                return 0;
        }
 
-       if (!priv->ieee->wpa_enabled && (network->wpa_ie_len > 0 ||
-                                        network->rsn_ie_len > 0)) {
-               IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
-                               "because of WPA capability mismatch.\n",
-                               escape_essid(network->ssid, network->ssid_len),
-                               MAC_ARG(network->bssid));
-               return 0;
-       }
-
        if ((priv->config & CFG_STATIC_BSSID) &&
            memcmp(network->bssid, priv->bssid, ETH_ALEN)) {
                IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
@@ -5539,7 +5509,7 @@ static int ipw_best_network(struct ipw_priv *priv,
        }
 
        /* Filter out invalid channel in current GEO */
-       if (!ipw_is_valid_channel(priv->ieee, network->channel)) {
+       if (!ieee80211_is_valid_channel(priv->ieee, network->channel)) {
                IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
                                "because of invalid channel in current GEO\n",
                                escape_essid(network->ssid, network->ssid_len),
@@ -5584,7 +5554,7 @@ static int ipw_best_network(struct ipw_priv *priv,
 static void ipw_adhoc_create(struct ipw_priv *priv,
                             struct ieee80211_network *network)
 {
-       const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee);
+       const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee);
        int i;
 
        /*
@@ -5599,10 +5569,10 @@ static void ipw_adhoc_create(struct ipw_priv *priv,
         * FW fatal error.
         *
         */
-       switch (ipw_is_valid_channel(priv->ieee, priv->channel)) {
+       switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) {
        case IEEE80211_52GHZ_BAND:
                network->mode = IEEE_A;
-               i = ipw_channel_to_index(priv->ieee, priv->channel);
+               i = ieee80211_channel_to_index(priv->ieee, priv->channel);
                if (i == -1)
                        BUG();
                if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) {
@@ -5616,7 +5586,7 @@ static void ipw_adhoc_create(struct ipw_priv *priv,
                        network->mode = IEEE_G;
                else
                        network->mode = IEEE_B;
-               i = ipw_channel_to_index(priv->ieee, priv->channel);
+               i = ieee80211_channel_to_index(priv->ieee, priv->channel);
                if (i == -1)
                        BUG();
                if (geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY) {
@@ -5671,54 +5641,44 @@ static void ipw_adhoc_create(struct ipw_priv *priv,
 
 static void ipw_send_tgi_tx_key(struct ipw_priv *priv, int type, int index)
 {
-       struct ipw_tgi_tx_key *key;
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_TGI_TX_KEY,
-               .len = sizeof(*key)
-       };
+       struct ipw_tgi_tx_key key;
 
        if (!(priv->ieee->sec.flags & (1 << index)))
                return;
 
-       key = (struct ipw_tgi_tx_key *)&cmd.param;
-       key->key_id = index;
-       memcpy(key->key, priv->ieee->sec.keys[index], SCM_TEMPORAL_KEY_LENGTH);
-       key->security_type = type;
-       key->station_index = 0; /* always 0 for BSS */
-       key->flags = 0;
+       key.key_id = index;
+       memcpy(key.key, priv->ieee->sec.keys[index], SCM_TEMPORAL_KEY_LENGTH);
+       key.security_type = type;
+       key.station_index = 0;  /* always 0 for BSS */
+       key.flags = 0;
        /* 0 for new key; previous value of counter (after fatal error) */
-       key->tx_counter[0] = 0;
-       key->tx_counter[1] = 0;
+       key.tx_counter[0] = 0;
+       key.tx_counter[1] = 0;
 
-       ipw_send_cmd(priv, &cmd);
+       ipw_send_cmd_pdu(priv, IPW_CMD_TGI_TX_KEY, sizeof(key), &key);
 }
 
 static void ipw_send_wep_keys(struct ipw_priv *priv, int type)
 {
-       struct ipw_wep_key *key;
+       struct ipw_wep_key key;
        int i;
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_WEP_KEY,
-               .len = sizeof(*key)
-       };
 
-       key = (struct ipw_wep_key *)&cmd.param;
-       key->cmd_id = DINO_CMD_WEP_KEY;
-       key->seq_num = 0;
+       key.cmd_id = DINO_CMD_WEP_KEY;
+       key.seq_num = 0;
 
        /* Note: AES keys cannot be set for multiple times.
         * Only set it at the first time. */
        for (i = 0; i < 4; i++) {
-               key->key_index = i | type;
+               key.key_index = i | type;
                if (!(priv->ieee->sec.flags & (1 << i))) {
-                       key->key_size = 0;
+                       key.key_size = 0;
                        continue;
                }
 
-               key->key_size = priv->ieee->sec.key_sizes[i];
-               memcpy(key->key, priv->ieee->sec.keys[i], key->key_size);
+               key.key_size = priv->ieee->sec.key_sizes[i];
+               memcpy(key.key, priv->ieee->sec.keys[i], key.key_size);
 
-               ipw_send_cmd(priv, &cmd);
+               ipw_send_cmd_pdu(priv, IPW_CMD_WEP_KEY, sizeof(key), &key);
        }
 }
 
@@ -5822,9 +5782,9 @@ static void ipw_adhoc_check(void *data)
 static void ipw_bg_adhoc_check(void *data)
 {
        struct ipw_priv *priv = data;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ipw_adhoc_check(data);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
 #ifdef CONFIG_IPW2200_DEBUG
@@ -5950,7 +5910,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv,
        const struct ieee80211_geo *geo;
        int i;
 
-       geo = ipw_get_geo(priv->ieee);
+       geo = ieee80211_get_geo(priv->ieee);
 
        if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) {
                int start = channel_index;
@@ -6010,7 +5970,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv,
                                channel_index++;
                                scan->channels_list[channel_index] = channel;
                                index =
-                                   ipw_channel_to_index(priv->ieee, channel);
+                                   ieee80211_channel_to_index(priv->ieee, channel);
                                ipw_set_scan_type(scan, channel_index,
                                                  geo->bg[index].
                                                  flags &
@@ -6051,7 +6011,7 @@ static int ipw_request_scan(struct ipw_priv *priv)
            (priv->status & STATUS_EXIT_PENDING))
                return 0;
 
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
 
        if (priv->status & STATUS_SCANNING) {
                IPW_DEBUG_HC("Concurrent scan requested.  Ignoring.\n");
@@ -6092,7 +6052,7 @@ static int ipw_request_scan(struct ipw_priv *priv)
                u8 channel;
                u8 band = 0;
 
-               switch (ipw_is_valid_channel(priv->ieee, priv->channel)) {
+               switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) {
                case IEEE80211_52GHZ_BAND:
                        band = (u8) (IPW_A_MODE << 6) | 1;
                        channel = priv->channel;
@@ -6159,16 +6119,16 @@ static int ipw_request_scan(struct ipw_priv *priv)
        queue_delayed_work(priv->workqueue, &priv->scan_check,
                           IPW_SCAN_CHECK_WATCHDOG);
       done:
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return err;
 }
 
 static void ipw_bg_abort_scan(void *data)
 {
        struct ipw_priv *priv = data;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ipw_abort_scan(data);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
 static int ipw_wpa_enable(struct ipw_priv *priv, int value)
@@ -6193,6 +6153,9 @@ static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value)
        } else if (value & IW_AUTH_ALG_OPEN_SYSTEM) {
                sec.auth_mode = WLAN_AUTH_OPEN;
                ieee->open_wep = 1;
+       } else if (value & IW_AUTH_ALG_LEAP) {
+               sec.auth_mode = WLAN_AUTH_LEAP;
+               ieee->open_wep = 1;
        } else
                return -EINVAL;
 
@@ -6204,7 +6167,8 @@ static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value)
        return ret;
 }
 
-void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, int wpa_ie_len)
+static void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie,
+                               int wpa_ie_len)
 {
        /* make sure WPA is enabled */
        ipw_wpa_enable(priv, 1);
@@ -6215,15 +6179,10 @@ void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, int wpa_ie_len)
 static int ipw_set_rsn_capa(struct ipw_priv *priv,
                            char *capabilities, int length)
 {
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_RSN_CAPABILITIES,
-               .len = length,
-       };
-
        IPW_DEBUG_HC("HOST_CMD_RSN_CAPABILITIES\n");
 
-       memcpy(cmd.param, capabilities, length);
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_pdu(priv, IPW_CMD_RSN_CAPABILITIES, length,
+                               capabilities);
 }
 
 /*
@@ -6244,7 +6203,7 @@ static int ipw_wx_set_genie(struct net_device *dev,
            (wrqu->data.length && extra == NULL))
                return -EINVAL;
 
-       //down(&priv->sem);
+       //mutex_lock(&priv->mutex);
 
        //if (!ieee->wpa_enabled) {
        //      err = -EOPNOTSUPP;
@@ -6270,7 +6229,7 @@ static int ipw_wx_set_genie(struct net_device *dev,
 
        ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len);
       out:
-       //up(&priv->sem);
+       //mutex_unlock(&priv->mutex);
        return err;
 }
 
@@ -6283,7 +6242,7 @@ static int ipw_wx_get_genie(struct net_device *dev,
        struct ieee80211_device *ieee = priv->ieee;
        int err = 0;
 
-       //down(&priv->sem);
+       //mutex_lock(&priv->mutex);
 
        //if (!ieee->wpa_enabled) {
        //      err = -EOPNOTSUPP;
@@ -6304,7 +6263,7 @@ static int ipw_wx_get_genie(struct net_device *dev,
        memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len);
 
       out:
-       //up(&priv->sem);
+       //mutex_unlock(&priv->mutex);
        return err;
 }
 
@@ -6556,7 +6515,7 @@ static int ipw_wx_set_mlme(struct net_device *dev,
 * get the modulation type of the current network or
 * the card current mode
 */
-u8 ipw_qos_current_mode(struct ipw_priv * priv)
+static u8 ipw_qos_current_mode(struct ipw_priv * priv)
 {
        u8 mode = 0;
 
@@ -6964,12 +6923,12 @@ static void ipw_bg_qos_activate(void *data)
        if (priv == NULL)
                return;
 
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
 
        if (priv->status & STATUS_ASSOCIATED)
                ipw_qos_activate(priv, &(priv->assoc_network->qos_data));
 
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
 static int ipw_handle_probe_response(struct net_device *dev,
@@ -7010,25 +6969,15 @@ static int ipw_handle_assoc_response(struct net_device *dev,
 static int ipw_send_qos_params_command(struct ipw_priv *priv, struct ieee80211_qos_parameters
                                       *qos_param)
 {
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_QOS_PARAMETERS,
-               .len = (sizeof(struct ieee80211_qos_parameters) * 3)
-       };
-
-       memcpy(cmd.param, qos_param, sizeof(*qos_param) * 3);
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_pdu(priv, IPW_CMD_QOS_PARAMETERS,
+                               sizeof(*qos_param) * 3, qos_param);
 }
 
 static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element
                                     *qos_param)
 {
-       struct host_cmd cmd = {
-               .cmd = IPW_CMD_WME_INFO,
-               .len = sizeof(*qos_param)
-       };
-
-       memcpy(cmd.param, qos_param, sizeof(*qos_param));
-       return ipw_send_cmd(priv, &cmd);
+       return ipw_send_cmd_pdu(priv, IPW_CMD_WME_INFO, sizeof(*qos_param),
+                               qos_param);
 }
 
 #endif                         /* CONFIG_IPW_QOS */
@@ -7052,19 +7001,21 @@ static int ipw_associate_network(struct ipw_priv *priv,
 
        memset(&priv->assoc_request, 0, sizeof(priv->assoc_request));
        priv->assoc_request.channel = network->channel;
+       priv->assoc_request.auth_key = 0;
+
        if ((priv->capability & CAP_PRIVACY_ON) &&
-           (priv->capability & CAP_SHARED_KEY)) {
+           (priv->ieee->sec.auth_mode == WLAN_AUTH_SHARED_KEY)) {
                priv->assoc_request.auth_type = AUTH_SHARED_KEY;
                priv->assoc_request.auth_key = priv->ieee->sec.active_key;
 
-               if ((priv->capability & CAP_PRIVACY_ON) &&
-                   (priv->ieee->sec.level == SEC_LEVEL_1) &&
-                   !(priv->ieee->host_encrypt || priv->ieee->host_decrypt))
+               if (priv->ieee->sec.level == SEC_LEVEL_1)
                        ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_WEP);
-       } else {
+
+       } else if ((priv->capability & CAP_PRIVACY_ON) &&
+                  (priv->ieee->sec.auth_mode == WLAN_AUTH_LEAP))
+               priv->assoc_request.auth_type = AUTH_LEAP;
+       else
                priv->assoc_request.auth_type = AUTH_OPEN;
-               priv->assoc_request.auth_key = 0;
-       }
 
        if (priv->ieee->wpa_ie_len) {
                priv->assoc_request.policy_support = 0x02;      /* RSN active */
@@ -7278,9 +7229,9 @@ static void ipw_roam(void *data)
 static void ipw_bg_roam(void *data)
 {
        struct ipw_priv *priv = data;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ipw_roam(data);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
 static int ipw_associate(void *data)
@@ -7375,9 +7326,9 @@ static int ipw_associate(void *data)
 static void ipw_bg_associate(void *data)
 {
        struct ipw_priv *priv = data;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ipw_associate(data);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
 static void ipw_rebuild_decrypted_skb(struct ipw_priv *priv,
@@ -7811,12 +7762,10 @@ static void ipw_rx(struct ipw_priv *priv)
 
        while (i != r) {
                rxb = priv->rxq->queue[i];
-#ifdef CONFIG_IPW2200_DEBUG
                if (unlikely(rxb == NULL)) {
                        printk(KERN_CRIT "Queue not allocated!\n");
                        break;
                }
-#endif
                priv->rxq->queue[i] = NULL;
 
                pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
@@ -7835,7 +7784,8 @@ static void ipw_rx(struct ipw_priv *priv)
                                            le16_to_cpu(pkt->u.frame.rssi_dbm) -
                                            IPW_RSSI_TO_DBM,
                                        .signal =
-                                           le16_to_cpu(pkt->u.frame.signal),
+                                           le16_to_cpu(pkt->u.frame.rssi_dbm) -
+                                           IPW_RSSI_TO_DBM + 0x100,
                                        .noise =
                                            le16_to_cpu(pkt->u.frame.noise),
                                        .rate = pkt->u.frame.rate,
@@ -7899,7 +7849,8 @@ static void ipw_rx(struct ipw_priv *priv)
                                             le16_to_cpu(pkt->u.frame.length));
 
                                if (le16_to_cpu(pkt->u.frame.length) <
-                                   frame_hdr_len(header)) {
+                                   ieee80211_get_hdrlen(le16_to_cpu(
+                                                   header->frame_ctl))) {
                                        IPW_DEBUG_DROP
                                            ("Received packet is too small. "
                                             "Dropping.\n");
@@ -7989,7 +7940,14 @@ static void ipw_rx(struct ipw_priv *priv)
 #define        DEFAULT_SHORT_RETRY_LIMIT 7U
 #define        DEFAULT_LONG_RETRY_LIMIT  4U
 
-static int ipw_sw_reset(struct ipw_priv *priv, int init)
+/**
+ * ipw_sw_reset
+ * @option: options to control different reset behaviour
+ *         0 = reset everything except the 'disable' module_param
+ *         1 = reset everything and print out driver info (for probe only)
+ *         2 = reset everything
+ */
+static int ipw_sw_reset(struct ipw_priv *priv, int option)
 {
        int band, modulation;
        int old_mode = priv->ieee->iw_mode;
@@ -8016,7 +7974,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init)
        priv->essid_len = 0;
        memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
 
-       if (disable) {
+       if (disable && option) {
                priv->status |= STATUS_RF_KILL_SW;
                IPW_DEBUG_INFO("Radio disabled.\n");
        }
@@ -8068,7 +8026,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init)
 
        if ((priv->pci_dev->device == 0x4223) ||
            (priv->pci_dev->device == 0x4224)) {
-               if (init)
+               if (option == 1)
                        printk(KERN_INFO DRV_NAME
                               ": Detected Intel PRO/Wireless 2915ABG Network "
                               "Connection\n");
@@ -8079,7 +8037,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init)
                priv->adapter = IPW_2915ABG;
                priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B;
        } else {
-               if (init)
+               if (option == 1)
                        printk(KERN_INFO DRV_NAME
                               ": Detected Intel PRO/Wireless 2200BG Network "
                               "Connection\n");
@@ -8126,7 +8084,7 @@ static int ipw_wx_get_name(struct net_device *dev,
                           union iwreq_data *wrqu, char *extra)
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        if (priv->status & STATUS_RF_KILL_MASK)
                strcpy(wrqu->name, "radio off");
        else if (!(priv->status & STATUS_ASSOCIATED))
@@ -8135,7 +8093,7 @@ static int ipw_wx_get_name(struct net_device *dev,
                snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c",
                         ipw_modes[priv->assoc_request.ieee_mode]);
        IPW_DEBUG_WX("Name: %s\n", wrqu->name);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return 0;
 }
 
@@ -8196,7 +8154,7 @@ static int ipw_wx_set_freq(struct net_device *dev,
                           union iwreq_data *wrqu, char *extra)
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
-       const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee);
+       const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee);
        struct iw_freq *fwrq = &wrqu->freq;
        int ret = 0, i;
        u8 channel, flags;
@@ -8204,24 +8162,24 @@ static int ipw_wx_set_freq(struct net_device *dev,
 
        if (fwrq->m == 0) {
                IPW_DEBUG_WX("SET Freq/Channel -> any\n");
-               down(&priv->sem);
+               mutex_lock(&priv->mutex);
                ret = ipw_set_channel(priv, 0);
-               up(&priv->sem);
+               mutex_unlock(&priv->mutex);
                return ret;
        }
        /* if setting by freq convert to channel */
        if (fwrq->e == 1) {
-               channel = ipw_freq_to_channel(priv->ieee, fwrq->m);
+               channel = ieee80211_freq_to_channel(priv->ieee, fwrq->m);
                if (channel == 0)
                        return -EINVAL;
        } else
                channel = fwrq->m;
 
-       if (!(band = ipw_is_valid_channel(priv->ieee, channel)))
+       if (!(band = ieee80211_is_valid_channel(priv->ieee, channel)))
                return -EINVAL;
 
        if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
-               i = ipw_channel_to_index(priv->ieee, channel);
+               i = ieee80211_channel_to_index(priv->ieee, channel);
                if (i == -1)
                        return -EINVAL;
 
@@ -8234,9 +8192,9 @@ static int ipw_wx_set_freq(struct net_device *dev,
        }
 
        IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m);
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ret = ipw_set_channel(priv, channel);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return ret;
 }
 
@@ -8250,14 +8208,14 @@ static int ipw_wx_get_freq(struct net_device *dev,
 
        /* If we are associated, trying to associate, or have a statically
         * configured CHANNEL then return that; otherwise return ANY */
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        if (priv->config & CFG_STATIC_CHANNEL ||
            priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED))
                wrqu->freq.m = priv->channel;
        else
                wrqu->freq.m = 0;
 
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel);
        return 0;
 }
@@ -8287,7 +8245,7 @@ static int ipw_wx_set_mode(struct net_device *dev,
        if (wrqu->mode == priv->ieee->iw_mode)
                return 0;
 
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
 
        ipw_sw_reset(priv, 0);
 
@@ -8310,7 +8268,7 @@ static int ipw_wx_set_mode(struct net_device *dev,
        priv->ieee->iw_mode = wrqu->mode;
 
        queue_work(priv->workqueue, &priv->adapter_restart);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return err;
 }
 
@@ -8319,10 +8277,10 @@ static int ipw_wx_get_mode(struct net_device *dev,
                           union iwreq_data *wrqu, char *extra)
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        wrqu->mode = priv->ieee->iw_mode;
        IPW_DEBUG_WX("Get MODE -> %d\n", wrqu->mode);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return 0;
 }
 
@@ -8349,7 +8307,7 @@ static int ipw_wx_get_range(struct net_device *dev,
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
        struct iw_range *range = (struct iw_range *)extra;
-       const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee);
+       const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee);
        int i = 0, j;
 
        wrqu->data.length = sizeof(*range);
@@ -8361,7 +8319,7 @@ static int ipw_wx_get_range(struct net_device *dev,
        range->max_qual.qual = 100;
        /* TODO: Find real max RSSI and stick here */
        range->max_qual.level = 0;
-       range->max_qual.noise = priv->ieee->worst_rssi + 0x100;
+       range->max_qual.noise = 0;
        range->max_qual.updated = 7;    /* Updated all three */
 
        range->avg_qual.qual = 70;
@@ -8369,7 +8327,7 @@ static int ipw_wx_get_range(struct net_device *dev,
        range->avg_qual.level = 0;      /* FIXME to real average level */
        range->avg_qual.noise = 0;
        range->avg_qual.updated = 7;    /* Updated all three */
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        range->num_bitrates = min(priv->rates.num_rates, (u8) IW_MAX_BITRATES);
 
        for (i = 0; i < range->num_bitrates; i++)
@@ -8387,31 +8345,39 @@ static int ipw_wx_get_range(struct net_device *dev,
 
        /* Set the Wireless Extension versions */
        range->we_version_compiled = WIRELESS_EXT;
-       range->we_version_source = 16;
+       range->we_version_source = 18;
 
        i = 0;
        if (priv->ieee->mode & (IEEE_B | IEEE_G)) {
-               for (j = 0; j < geo->bg_channels && i < IW_MAX_FREQUENCIES;
-                    i++, j++) {
+               for (j = 0; j < geo->bg_channels && i < IW_MAX_FREQUENCIES; j++) {
+                       if ((priv->ieee->iw_mode == IW_MODE_ADHOC) &&
+                           (geo->bg[j].flags & IEEE80211_CH_PASSIVE_ONLY))
+                               continue;
+
                        range->freq[i].i = geo->bg[j].channel;
                        range->freq[i].m = geo->bg[j].freq * 100000;
                        range->freq[i].e = 1;
+                       i++;
                }
        }
 
        if (priv->ieee->mode & IEEE_A) {
-               for (j = 0; j < geo->a_channels && i < IW_MAX_FREQUENCIES;
-                    i++, j++) {
+               for (j = 0; j < geo->a_channels && i < IW_MAX_FREQUENCIES; j++) {
+                       if ((priv->ieee->iw_mode == IW_MODE_ADHOC) &&
+                           (geo->a[j].flags & IEEE80211_CH_PASSIVE_ONLY))
+                               continue;
+
                        range->freq[i].i = geo->a[j].channel;
                        range->freq[i].m = geo->a[j].freq * 100000;
                        range->freq[i].e = 1;
+                       i++;
                }
        }
 
        range->num_channels = i;
        range->num_frequency = i;
 
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 
        /* Event capability (kernel + driver) */
        range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
@@ -8419,6 +8385,9 @@ static int ipw_wx_get_range(struct net_device *dev,
                                IW_EVENT_CAPA_MASK(SIOCGIWAP));
        range->event_capa[1] = IW_EVENT_CAPA_K_1;
 
+       range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+               IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+
        IPW_DEBUG_WX("GET Range\n");
        return 0;
 }
@@ -8438,7 +8407,7 @@ static int ipw_wx_set_wap(struct net_device *dev,
 
        if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
                return -EINVAL;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) ||
            !memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) {
                /* we disable mandatory BSSID association */
@@ -8447,14 +8416,14 @@ static int ipw_wx_set_wap(struct net_device *dev,
                IPW_DEBUG_ASSOC("Attempting to associate with new "
                                "parameters.\n");
                ipw_associate(priv);
-               up(&priv->sem);
+               mutex_unlock(&priv->mutex);
                return 0;
        }
 
        priv->config |= CFG_STATIC_BSSID;
        if (!memcmp(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN)) {
                IPW_DEBUG_WX("BSSID set to current BSSID.\n");
-               up(&priv->sem);
+               mutex_unlock(&priv->mutex);
                return 0;
        }
 
@@ -8468,7 +8437,7 @@ static int ipw_wx_set_wap(struct net_device *dev,
        if (!ipw_disassociate(priv))
                ipw_associate(priv);
 
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return 0;
 }
 
@@ -8479,7 +8448,7 @@ static int ipw_wx_get_wap(struct net_device *dev,
        struct ipw_priv *priv = ieee80211_priv(dev);
        /* If we are associated, trying to associate, or have a statically
         * configured BSSID then return that; otherwise return ANY */
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        if (priv->config & CFG_STATIC_BSSID ||
            priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
                wrqu->ap_addr.sa_family = ARPHRD_ETHER;
@@ -8489,7 +8458,7 @@ static int ipw_wx_get_wap(struct net_device *dev,
 
        IPW_DEBUG_WX("Getting WAP BSSID: " MAC_FMT "\n",
                     MAC_ARG(wrqu->ap_addr.sa_data));
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return 0;
 }
 
@@ -8500,7 +8469,7 @@ static int ipw_wx_set_essid(struct net_device *dev,
        struct ipw_priv *priv = ieee80211_priv(dev);
        char *essid = "";       /* ANY */
        int length = 0;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        if (wrqu->essid.flags && wrqu->essid.length) {
                length = wrqu->essid.length - 1;
                essid = extra;
@@ -8515,7 +8484,7 @@ static int ipw_wx_set_essid(struct net_device *dev,
                        priv->config &= ~CFG_STATIC_ESSID;
                        ipw_associate(priv);
                }
-               up(&priv->sem);
+               mutex_unlock(&priv->mutex);
                return 0;
        }
 
@@ -8525,7 +8494,7 @@ static int ipw_wx_set_essid(struct net_device *dev,
 
        if (priv->essid_len == length && !memcmp(priv->essid, extra, length)) {
                IPW_DEBUG_WX("ESSID set to current ESSID.\n");
-               up(&priv->sem);
+               mutex_unlock(&priv->mutex);
                return 0;
        }
 
@@ -8540,7 +8509,7 @@ static int ipw_wx_set_essid(struct net_device *dev,
        if (!ipw_disassociate(priv))
                ipw_associate(priv);
 
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return 0;
 }
 
@@ -8552,7 +8521,7 @@ static int ipw_wx_get_essid(struct net_device *dev,
 
        /* If we are associated, trying to associate, or have a statically
         * configured ESSID then return that; otherwise return ANY */
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        if (priv->config & CFG_STATIC_ESSID ||
            priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
                IPW_DEBUG_WX("Getting essid: '%s'\n",
@@ -8565,7 +8534,7 @@ static int ipw_wx_get_essid(struct net_device *dev,
                wrqu->essid.length = 0;
                wrqu->essid.flags = 0;  /* active */
        }
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return 0;
 }
 
@@ -8578,12 +8547,12 @@ static int ipw_wx_set_nick(struct net_device *dev,
        IPW_DEBUG_WX("Setting nick to '%s'\n", extra);
        if (wrqu->data.length > IW_ESSID_MAX_SIZE)
                return -E2BIG;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick));
        memset(priv->nick, 0, sizeof(priv->nick));
        memcpy(priv->nick, extra, wrqu->data.length);
        IPW_DEBUG_TRACE("<<\n");
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return 0;
 
 }
@@ -8594,11 +8563,57 @@ static int ipw_wx_get_nick(struct net_device *dev,
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
        IPW_DEBUG_WX("Getting nick\n");
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        wrqu->data.length = strlen(priv->nick) + 1;
        memcpy(extra, priv->nick, wrqu->data.length);
        wrqu->data.flags = 1;   /* active */
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
+       return 0;
+}
+
+static int ipw_wx_set_sens(struct net_device *dev,
+                           struct iw_request_info *info,
+                           union iwreq_data *wrqu, char *extra)
+{
+       struct ipw_priv *priv = ieee80211_priv(dev);
+       int err = 0;
+
+       IPW_DEBUG_WX("Setting roaming threshold to %d\n", wrqu->sens.value);
+       IPW_DEBUG_WX("Setting disassociate threshold to %d\n", 3*wrqu->sens.value);
+       mutex_lock(&priv->mutex);
+
+       if (wrqu->sens.fixed == 0)
+       {
+               priv->roaming_threshold = IPW_MB_ROAMING_THRESHOLD_DEFAULT;
+               priv->disassociate_threshold = IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT;
+               goto out;
+       }
+       if ((wrqu->sens.value > IPW_MB_ROAMING_THRESHOLD_MAX) ||
+           (wrqu->sens.value < IPW_MB_ROAMING_THRESHOLD_MIN)) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       priv->roaming_threshold = wrqu->sens.value;
+       priv->disassociate_threshold = 3*wrqu->sens.value;
+      out:
+       mutex_unlock(&priv->mutex);
+       return err;
+}
+
+static int ipw_wx_get_sens(struct net_device *dev,
+                           struct iw_request_info *info,
+                           union iwreq_data *wrqu, char *extra)
+{
+       struct ipw_priv *priv = ieee80211_priv(dev);
+       mutex_lock(&priv->mutex);
+       wrqu->sens.fixed = 1;
+       wrqu->sens.value = priv->roaming_threshold;
+       mutex_unlock(&priv->mutex);
+
+       IPW_DEBUG_WX("GET roaming threshold -> %s %d \n",
+                    wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value);
+
        return 0;
 }
 
@@ -8691,7 +8706,7 @@ static int ipw_wx_set_rate(struct net_device *dev,
       apply:
        IPW_DEBUG_WX("Setting rate mask to 0x%08X [%s]\n",
                     mask, fixed ? "fixed" : "sub-rates");
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        if (mask == IEEE80211_DEFAULT_RATES_MASK) {
                priv->config &= ~CFG_FIXED_RATE;
                ipw_set_fixed_rate(priv, priv->ieee->mode);
@@ -8700,7 +8715,7 @@ static int ipw_wx_set_rate(struct net_device *dev,
 
        if (priv->rates_mask == mask) {
                IPW_DEBUG_WX("Mask set to current mask.\n");
-               up(&priv->sem);
+               mutex_unlock(&priv->mutex);
                return 0;
        }
 
@@ -8711,7 +8726,7 @@ static int ipw_wx_set_rate(struct net_device *dev,
        if (!ipw_disassociate(priv))
                ipw_associate(priv);
 
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return 0;
 }
 
@@ -8720,9 +8735,9 @@ static int ipw_wx_get_rate(struct net_device *dev,
                           union iwreq_data *wrqu, char *extra)
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        wrqu->bitrate.value = priv->last_rate;
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value);
        return 0;
 }
@@ -8732,20 +8747,20 @@ static int ipw_wx_set_rts(struct net_device *dev,
                          union iwreq_data *wrqu, char *extra)
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        if (wrqu->rts.disabled)
                priv->rts_threshold = DEFAULT_RTS_THRESHOLD;
        else {
                if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
                    wrqu->rts.value > MAX_RTS_THRESHOLD) {
-                       up(&priv->sem);
+                       mutex_unlock(&priv->mutex);
                        return -EINVAL;
                }
                priv->rts_threshold = wrqu->rts.value;
        }
 
        ipw_send_rts_threshold(priv, priv->rts_threshold);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        IPW_DEBUG_WX("SET RTS Threshold -> %d \n", priv->rts_threshold);
        return 0;
 }
@@ -8755,11 +8770,11 @@ static int ipw_wx_get_rts(struct net_device *dev,
                          union iwreq_data *wrqu, char *extra)
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        wrqu->rts.value = priv->rts_threshold;
        wrqu->rts.fixed = 0;    /* no auto select */
        wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        IPW_DEBUG_WX("GET RTS Threshold -> %d \n", wrqu->rts.value);
        return 0;
 }
@@ -8771,7 +8786,7 @@ static int ipw_wx_set_txpow(struct net_device *dev,
        struct ipw_priv *priv = ieee80211_priv(dev);
        int err = 0;
 
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        if (ipw_radio_kill_sw(priv, wrqu->power.disabled)) {
                err = -EINPROGRESS;
                goto out;
@@ -8794,7 +8809,7 @@ static int ipw_wx_set_txpow(struct net_device *dev,
        priv->tx_power = wrqu->power.value;
        err = ipw_set_tx_power(priv);
       out:
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return err;
 }
 
@@ -8803,12 +8818,12 @@ static int ipw_wx_get_txpow(struct net_device *dev,
                            union iwreq_data *wrqu, char *extra)
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        wrqu->power.value = priv->tx_power;
        wrqu->power.fixed = 1;
        wrqu->power.flags = IW_TXPOW_DBM;
        wrqu->power.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0;
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 
        IPW_DEBUG_WX("GET TX Power -> %s %d \n",
                     wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value);
@@ -8821,13 +8836,13 @@ static int ipw_wx_set_frag(struct net_device *dev,
                           union iwreq_data *wrqu, char *extra)
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        if (wrqu->frag.disabled)
                priv->ieee->fts = DEFAULT_FTS;
        else {
                if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
                    wrqu->frag.value > MAX_FRAG_THRESHOLD) {
-                       up(&priv->sem);
+                       mutex_unlock(&priv->mutex);
                        return -EINVAL;
                }
 
@@ -8835,7 +8850,7 @@ static int ipw_wx_set_frag(struct net_device *dev,
        }
 
        ipw_send_frag_threshold(priv, wrqu->frag.value);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        IPW_DEBUG_WX("SET Frag Threshold -> %d \n", wrqu->frag.value);
        return 0;
 }
@@ -8845,11 +8860,11 @@ static int ipw_wx_get_frag(struct net_device *dev,
                           union iwreq_data *wrqu, char *extra)
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        wrqu->frag.value = priv->ieee->fts;
        wrqu->frag.fixed = 0;   /* no auto select */
        wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FTS);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value);
 
        return 0;
@@ -8870,7 +8885,7 @@ static int ipw_wx_set_retry(struct net_device *dev,
        if (wrqu->retry.value < 0 || wrqu->retry.value > 255)
                return -EINVAL;
 
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        if (wrqu->retry.flags & IW_RETRY_MIN)
                priv->short_retry_limit = (u8) wrqu->retry.value;
        else if (wrqu->retry.flags & IW_RETRY_MAX)
@@ -8882,7 +8897,7 @@ static int ipw_wx_set_retry(struct net_device *dev,
 
        ipw_send_retry_limit(priv, priv->short_retry_limit,
                             priv->long_retry_limit);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        IPW_DEBUG_WX("SET retry limit -> short:%d long:%d\n",
                     priv->short_retry_limit, priv->long_retry_limit);
        return 0;
@@ -8894,11 +8909,11 @@ static int ipw_wx_get_retry(struct net_device *dev,
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
 
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        wrqu->retry.disabled = 0;
 
        if ((wrqu->retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
-               up(&priv->sem);
+               mutex_unlock(&priv->mutex);
                return -EINVAL;
        }
 
@@ -8912,7 +8927,7 @@ static int ipw_wx_get_retry(struct net_device *dev,
                wrqu->retry.flags = IW_RETRY_LIMIT;
                wrqu->retry.value = priv->short_retry_limit;
        }
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 
        IPW_DEBUG_WX("GET retry -> %d \n", wrqu->retry.value);
 
@@ -8929,7 +8944,7 @@ static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid,
            (priv->status & STATUS_EXIT_PENDING))
                return 0;
 
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
 
        if (priv->status & STATUS_RF_KILL_MASK) {
                IPW_DEBUG_HC("Aborting scan due to RF kill activation\n");
@@ -8981,7 +8996,7 @@ static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid,
        priv->status |= STATUS_SCANNING;
 
       done:
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return err;
 }
 
@@ -9024,7 +9039,7 @@ static int ipw_wx_set_encode(struct net_device *dev,
        int ret;
        u32 cap = priv->capability;
 
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ret = ieee80211_wx_set_encode(priv->ieee, info, wrqu, key);
 
        /* In IBSS mode, we need to notify the firmware to update
@@ -9034,7 +9049,7 @@ static int ipw_wx_set_encode(struct net_device *dev,
            priv->status & STATUS_ASSOCIATED)
                ipw_disassociate(priv);
 
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return ret;
 }
 
@@ -9052,17 +9067,17 @@ static int ipw_wx_set_power(struct net_device *dev,
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
        int err;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        if (wrqu->power.disabled) {
                priv->power_mode = IPW_POWER_LEVEL(priv->power_mode);
                err = ipw_send_power_mode(priv, IPW_POWER_MODE_CAM);
                if (err) {
                        IPW_DEBUG_WX("failed setting power mode.\n");
-                       up(&priv->sem);
+                       mutex_unlock(&priv->mutex);
                        return err;
                }
                IPW_DEBUG_WX("SET Power Management Mode -> off\n");
-               up(&priv->sem);
+               mutex_unlock(&priv->mutex);
                return 0;
        }
 
@@ -9074,7 +9089,7 @@ static int ipw_wx_set_power(struct net_device *dev,
        default:                /* Otherwise we don't support it */
                IPW_DEBUG_WX("SET PM Mode: %X not supported.\n",
                             wrqu->power.flags);
-               up(&priv->sem);
+               mutex_unlock(&priv->mutex);
                return -EOPNOTSUPP;
        }
 
@@ -9087,12 +9102,12 @@ static int ipw_wx_set_power(struct net_device *dev,
        err = ipw_send_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode));
        if (err) {
                IPW_DEBUG_WX("failed setting power mode.\n");
-               up(&priv->sem);
+               mutex_unlock(&priv->mutex);
                return err;
        }
 
        IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n", priv->power_mode);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return 0;
 }
 
@@ -9101,13 +9116,13 @@ static int ipw_wx_get_power(struct net_device *dev,
                            union iwreq_data *wrqu, char *extra)
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        if (!(priv->power_mode & IPW_POWER_ENABLED))
                wrqu->power.disabled = 1;
        else
                wrqu->power.disabled = 0;
 
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        IPW_DEBUG_WX("GET Power Management Mode -> %02X\n", priv->power_mode);
 
        return 0;
@@ -9120,7 +9135,7 @@ static int ipw_wx_set_powermode(struct net_device *dev,
        struct ipw_priv *priv = ieee80211_priv(dev);
        int mode = *(int *)extra;
        int err;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        if ((mode < 1) || (mode > IPW_POWER_LIMIT)) {
                mode = IPW_POWER_AC;
                priv->power_mode = mode;
@@ -9133,11 +9148,11 @@ static int ipw_wx_set_powermode(struct net_device *dev,
 
                if (err) {
                        IPW_DEBUG_WX("failed setting power mode.\n");
-                       up(&priv->sem);
+                       mutex_unlock(&priv->mutex);
                        return err;
                }
        }
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return 0;
 }
 
@@ -9186,7 +9201,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
                IPW_WARNING("Attempt to set invalid wireless mode: %d\n", mode);
                return -EINVAL;
        }
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        if (priv->adapter == IPW_2915ABG) {
                priv->ieee->abg_true = 1;
                if (mode & IEEE_A) {
@@ -9198,7 +9213,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
                if (mode & IEEE_A) {
                        IPW_WARNING("Attempt to set 2200BG into "
                                    "802.11a mode\n");
-                       up(&priv->sem);
+                       mutex_unlock(&priv->mutex);
                        return -EINVAL;
                }
 
@@ -9235,7 +9250,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
        IPW_DEBUG_WX("PRIV SET MODE: %c%c%c\n",
                     mode & IEEE_A ? 'a' : '.',
                     mode & IEEE_B ? 'b' : '.', mode & IEEE_G ? 'g' : '.');
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return 0;
 }
 
@@ -9244,7 +9259,7 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev,
                                    union iwreq_data *wrqu, char *extra)
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        switch (priv->ieee->mode) {
        case IEEE_A:
                strncpy(extra, "802.11a (1)", MAX_WX_STRING);
@@ -9275,7 +9290,7 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev,
        IPW_DEBUG_WX("PRIV GET MODE: %s\n", extra);
 
        wrqu->data.length = strlen(extra) + 1;
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 
        return 0;
 }
@@ -9286,7 +9301,7 @@ static int ipw_wx_set_preamble(struct net_device *dev,
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
        int mode = *(int *)extra;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        /* Switching from SHORT -> LONG requires a disassociation */
        if (mode == 1) {
                if (!(priv->config & CFG_PREAMBLE_LONG)) {
@@ -9305,11 +9320,11 @@ static int ipw_wx_set_preamble(struct net_device *dev,
                priv->config &= ~CFG_PREAMBLE_LONG;
                goto done;
        }
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return -EINVAL;
 
       done:
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return 0;
 }
 
@@ -9318,12 +9333,12 @@ static int ipw_wx_get_preamble(struct net_device *dev,
                               union iwreq_data *wrqu, char *extra)
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        if (priv->config & CFG_PREAMBLE_LONG)
                snprintf(wrqu->name, IFNAMSIZ, "long (1)");
        else
                snprintf(wrqu->name, IFNAMSIZ, "auto (0)");
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return 0;
 }
 
@@ -9335,7 +9350,7 @@ static int ipw_wx_set_monitor(struct net_device *dev,
        struct ipw_priv *priv = ieee80211_priv(dev);
        int *parms = (int *)extra;
        int enable = (parms[0] > 0);
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]);
        if (enable) {
                if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
@@ -9350,13 +9365,13 @@ static int ipw_wx_set_monitor(struct net_device *dev,
                ipw_set_channel(priv, parms[1]);
        } else {
                if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
-                       up(&priv->sem);
+                       mutex_unlock(&priv->mutex);
                        return 0;
                }
                priv->net_dev->type = ARPHRD_ETHER;
                queue_work(priv->workqueue, &priv->adapter_restart);
        }
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return 0;
 }
 
@@ -9386,9 +9401,9 @@ static int ipw_wx_sw_reset(struct net_device *dev,
 
        IPW_DEBUG_WX("SW_RESET\n");
 
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
 
-       ret = ipw_sw_reset(priv, 0);
+       ret = ipw_sw_reset(priv, 2);
        if (!ret) {
                free_firmware();
                ipw_adapter_restart(priv);
@@ -9398,9 +9413,9 @@ static int ipw_wx_sw_reset(struct net_device *dev,
         * module parameter, so take appropriate action */
        ipw_radio_kill_sw(priv, priv->status & STATUS_RF_KILL_SW);
 
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        ieee80211_wx_set_encode(priv->ieee, info, &wrqu_sec, NULL);
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
 
        if (!(priv->status & STATUS_RF_KILL_MASK)) {
                /* Configuration likely changed -- force [re]association */
@@ -9410,7 +9425,7 @@ static int ipw_wx_sw_reset(struct net_device *dev,
                        ipw_associate(priv);
        }
 
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 
        return 0;
 }
@@ -9423,6 +9438,8 @@ static iw_handler ipw_wx_handlers[] = {
        IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq,
        IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode,
        IW_IOCTL(SIOCGIWMODE) = ipw_wx_get_mode,
+       IW_IOCTL(SIOCSIWSENS) = ipw_wx_set_sens,
+       IW_IOCTL(SIOCGIWSENS) = ipw_wx_get_sens,
        IW_IOCTL(SIOCGIWRANGE) = ipw_wx_get_range,
        IW_IOCTL(SIOCSIWAP) = ipw_wx_set_wap,
        IW_IOCTL(SIOCGIWAP) = ipw_wx_get_wap,
@@ -9568,7 +9585,7 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev)
        wstats->qual.level = average_value(&priv->average_rssi);
        wstats->qual.noise = average_value(&priv->average_noise);
        wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
-           IW_QUAL_NOISE_UPDATED;
+           IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM;
 
        wstats->miss.beacon = average_value(&priv->average_missed_beacons);
        wstats->discard.retries = priv->last_tx_failures;
@@ -9586,7 +9603,7 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev)
 static  void init_sys_config(struct ipw_sys_config *sys_config)
 {
        memset(sys_config, 0, sizeof(struct ipw_sys_config));
-       sys_config->bt_coexistence = 1; /* We may need to look into prvStaBtConfig */
+       sys_config->bt_coexistence = 0;
        sys_config->answer_broadcast_ssid_probe = 0;
        sys_config->accept_all_data_frames = 0;
        sys_config->accept_non_directed_frames = 1;
@@ -9594,12 +9611,13 @@ static  void init_sys_config(struct ipw_sys_config *sys_config)
        sys_config->disable_unicast_decryption = 1;
        sys_config->exclude_multicast_unencrypted = 0;
        sys_config->disable_multicast_decryption = 1;
-       sys_config->antenna_diversity = CFG_SYS_ANTENNA_BOTH;
+       sys_config->antenna_diversity = CFG_SYS_ANTENNA_SLOW_DIV;
        sys_config->pass_crc_to_host = 0;       /* TODO: See if 1 gives us FCS */
        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->silence_threshold = 0x1e;
 }
 
 static int ipw_net_open(struct net_device *dev)
@@ -9607,11 +9625,11 @@ static int ipw_net_open(struct net_device *dev)
        struct ipw_priv *priv = ieee80211_priv(dev);
        IPW_DEBUG_INFO("dev->open\n");
        /* we should be verifying the device is ready to be opened */
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        if (!(priv->status & STATUS_RF_KILL_MASK) &&
            (priv->status & STATUS_ASSOCIATED))
                netif_start_queue(dev);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return 0;
 }
 
@@ -9647,11 +9665,6 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
        u16 remaining_bytes;
        int fc;
 
-       /* If there isn't room in the queue, we return busy and let the
-        * network stack requeue the packet for us */
-       if (ipw_queue_space(q) < q->high_mark)
-               return NETDEV_TX_BUSY;
-
        switch (priv->ieee->iw_mode) {
        case IW_MODE_ADHOC:
                hdr_len = IEEE80211_3ADDR_LEN;
@@ -9817,6 +9830,9 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
        q->first_empty = ipw_queue_inc_wrap(q->first_empty, q->n_bd);
        ipw_write32(priv, q->reg_w, q->first_empty);
 
+       if (ipw_queue_space(q) < q->high_mark)
+               netif_stop_queue(priv->net_dev);
+
        return NETDEV_TX_OK;
 
       drop:
@@ -9890,13 +9906,13 @@ static int ipw_net_set_mac_address(struct net_device *dev, void *p)
        struct sockaddr *addr = p;
        if (!is_valid_ether_addr(addr->sa_data))
                return -EADDRNOTAVAIL;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        priv->config |= CFG_CUSTOM_MAC;
        memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN);
        printk(KERN_INFO "%s: Setting MAC to " MAC_FMT "\n",
               priv->net_dev->name, MAC_ARG(priv->mac_addr));
        queue_work(priv->workqueue, &priv->adapter_restart);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return 0;
 }
 
@@ -9940,9 +9956,9 @@ static int ipw_ethtool_get_eeprom(struct net_device *dev,
 
        if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE)
                return -EINVAL;
-       down(&p->sem);
+       mutex_lock(&p->mutex);
        memcpy(bytes, &p->eeprom[eeprom->offset], eeprom->len);
-       up(&p->sem);
+       mutex_unlock(&p->mutex);
        return 0;
 }
 
@@ -9954,12 +9970,11 @@ static int ipw_ethtool_set_eeprom(struct net_device *dev,
 
        if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE)
                return -EINVAL;
-       down(&p->sem);
+       mutex_lock(&p->mutex);
        memcpy(&p->eeprom[eeprom->offset], bytes, eeprom->len);
-       for (i = IPW_EEPROM_DATA;
-            i < IPW_EEPROM_DATA + IPW_EEPROM_IMAGE_SIZE; i++)
-               ipw_write8(p, i, p->eeprom[i]);
-       up(&p->sem);
+       for (i = 0; i < IPW_EEPROM_IMAGE_SIZE; i++)
+               ipw_write8(p, i + IPW_EEPROM_DATA, p->eeprom[i]);
+       mutex_unlock(&p->mutex);
        return 0;
 }
 
@@ -10054,12 +10069,12 @@ static void ipw_rf_kill(void *adapter)
 static void ipw_bg_rf_kill(void *data)
 {
        struct ipw_priv *priv = data;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ipw_rf_kill(data);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
-void ipw_link_up(struct ipw_priv *priv)
+static void ipw_link_up(struct ipw_priv *priv)
 {
        priv->last_seq_num = -1;
        priv->last_frag_num = -1;
@@ -10089,12 +10104,12 @@ void ipw_link_up(struct ipw_priv *priv)
 static void ipw_bg_link_up(void *data)
 {
        struct ipw_priv *priv = data;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ipw_link_up(data);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
-void ipw_link_down(struct ipw_priv *priv)
+static void ipw_link_down(struct ipw_priv *priv)
 {
        ipw_led_link_down(priv);
        netif_carrier_off(priv->net_dev);
@@ -10117,9 +10132,9 @@ void ipw_link_down(struct ipw_priv *priv)
 static void ipw_bg_link_down(void *data)
 {
        struct ipw_priv *priv = data;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ipw_link_down(data);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
 static int ipw_setup_deferred_work(struct ipw_priv *priv)
@@ -10292,6 +10307,20 @@ static int ipw_config(struct ipw_priv *priv)
 
        /* set basic system config settings */
        init_sys_config(&priv->sys_config);
+
+       /* Support Bluetooth if we have BT h/w on board, and user wants to.
+        * Does not support BT priority yet (don't abort or defer our Tx) */
+       if (bt_coexist) {
+               unsigned char bt_caps = priv->eeprom[EEPROM_SKU_CAPABILITY];
+
+               if (bt_caps & EEPROM_SKU_CAP_BT_CHANNEL_SIG)
+                       priv->sys_config.bt_coexistence
+                           |= CFG_BT_COEXISTENCE_SIGNAL_CHNL;
+               if (bt_caps & EEPROM_SKU_CAP_BT_OOB)
+                       priv->sys_config.bt_coexistence
+                           |= CFG_BT_COEXISTENCE_OOB;
+       }
+
        if (priv->ieee->iw_mode == IW_MODE_ADHOC)
                priv->sys_config.answer_broadcast_ssid_probe = 1;
        else
@@ -10349,6 +10378,9 @@ static int ipw_config(struct ipw_priv *priv)
  * not intended for resale of the above mentioned Intel adapters has
  * not been tested.
  *
+ * Remember to update the table in README.ipw2200 when changing this
+ * table.
+ *
  */
 static const struct ieee80211_geo ipw_geos[] = {
        {                       /* Restricted */
@@ -10596,96 +10628,6 @@ static const struct ieee80211_geo ipw_geos[] = {
         }
 };
 
-/* GEO code borrowed from ieee80211_geo.c */
-static int ipw_is_valid_channel(struct ieee80211_device *ieee, u8 channel)
-{
-       int i;
-
-       /* Driver needs to initialize the geography map before using
-        * these helper functions */
-       BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
-
-       if (ieee->freq_band & IEEE80211_24GHZ_BAND)
-               for (i = 0; i < ieee->geo.bg_channels; i++)
-                       /* NOTE: If G mode is currently supported but
-                        * this is a B only channel, we don't see it
-                        * as valid. */
-                       if ((ieee->geo.bg[i].channel == channel) &&
-                           (!(ieee->mode & IEEE_G) ||
-                            !(ieee->geo.bg[i].flags & IEEE80211_CH_B_ONLY)))
-                               return IEEE80211_24GHZ_BAND;
-
-       if (ieee->freq_band & IEEE80211_52GHZ_BAND)
-               for (i = 0; i < ieee->geo.a_channels; i++)
-                       if (ieee->geo.a[i].channel == channel)
-                               return IEEE80211_52GHZ_BAND;
-
-       return 0;
-}
-
-static int ipw_channel_to_index(struct ieee80211_device *ieee, u8 channel)
-{
-       int i;
-
-       /* Driver needs to initialize the geography map before using
-        * these helper functions */
-       BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
-
-       if (ieee->freq_band & IEEE80211_24GHZ_BAND)
-               for (i = 0; i < ieee->geo.bg_channels; i++)
-                       if (ieee->geo.bg[i].channel == channel)
-                               return i;
-
-       if (ieee->freq_band & IEEE80211_52GHZ_BAND)
-               for (i = 0; i < ieee->geo.a_channels; i++)
-                       if (ieee->geo.a[i].channel == channel)
-                               return i;
-
-       return -1;
-}
-
-static u8 ipw_freq_to_channel(struct ieee80211_device *ieee, u32 freq)
-{
-       int i;
-
-       /* Driver needs to initialize the geography map before using
-        * these helper functions */
-       BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
-
-       freq /= 100000;
-
-       if (ieee->freq_band & IEEE80211_24GHZ_BAND)
-               for (i = 0; i < ieee->geo.bg_channels; i++)
-                       if (ieee->geo.bg[i].freq == freq)
-                               return ieee->geo.bg[i].channel;
-
-       if (ieee->freq_band & IEEE80211_52GHZ_BAND)
-               for (i = 0; i < ieee->geo.a_channels; i++)
-                       if (ieee->geo.a[i].freq == freq)
-                               return ieee->geo.a[i].channel;
-
-       return 0;
-}
-
-static int ipw_set_geo(struct ieee80211_device *ieee,
-                      const struct ieee80211_geo *geo)
-{
-       memcpy(ieee->geo.name, geo->name, 3);
-       ieee->geo.name[3] = '\0';
-       ieee->geo.bg_channels = geo->bg_channels;
-       ieee->geo.a_channels = geo->a_channels;
-       memcpy(ieee->geo.bg, geo->bg, geo->bg_channels *
-              sizeof(struct ieee80211_channel));
-       memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels *
-              sizeof(struct ieee80211_channel));
-       return 0;
-}
-
-static const struct ieee80211_geo *ipw_get_geo(struct ieee80211_device *ieee)
-{
-       return &ieee->geo;
-}
-
 #define MAX_HW_RESTARTS 5
 static int ipw_up(struct ipw_priv *priv)
 {
@@ -10732,14 +10674,11 @@ static int ipw_up(struct ipw_priv *priv)
                                    priv->eeprom[EEPROM_COUNTRY_CODE + 2]);
                        j = 0;
                }
-               if (ipw_set_geo(priv->ieee, &ipw_geos[j])) {
+               if (ieee80211_set_geo(priv->ieee, &ipw_geos[j])) {
                        IPW_WARNING("Could not set geography.");
                        return 0;
                }
 
-               IPW_DEBUG_INFO("Geography %03d [%s] detected.\n",
-                              j, priv->ieee->geo.name);
-
                if (priv->status & STATUS_RF_KILL_SW) {
                        IPW_WARNING("Radio disabled by module parameter.\n");
                        return 0;
@@ -10782,9 +10721,9 @@ static int ipw_up(struct ipw_priv *priv)
 static void ipw_bg_up(void *data)
 {
        struct ipw_priv *priv = data;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ipw_up(data);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
 static void ipw_deinit(struct ipw_priv *priv)
@@ -10853,23 +10792,23 @@ static void ipw_down(struct ipw_priv *priv)
 static void ipw_bg_down(void *data)
 {
        struct ipw_priv *priv = data;
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
        ipw_down(data);
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 }
 
 /* Called by register_netdev() */
 static int ipw_net_init(struct net_device *dev)
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
 
        if (ipw_up(priv)) {
-               up(&priv->sem);
+               mutex_unlock(&priv->mutex);
                return -EIO;
        }
 
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        return 0;
 }
 
@@ -10959,7 +10898,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++)
                INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
 
-       init_MUTEX(&priv->sem);
+       mutex_init(&priv->mutex);
        if (pci_enable_device(pdev)) {
                err = -ENODEV;
                goto out_free_ieee80211;
@@ -11017,7 +10956,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        SET_MODULE_OWNER(net_dev);
        SET_NETDEV_DEV(net_dev, &pdev->dev);
 
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
 
        priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit;
        priv->ieee->set_security = shim__set_security;
@@ -11050,16 +10989,22 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        err = sysfs_create_group(&pdev->dev.kobj, &ipw_attribute_group);
        if (err) {
                IPW_ERROR("failed to create sysfs device attributes\n");
-               up(&priv->sem);
+               mutex_unlock(&priv->mutex);
                goto out_release_irq;
        }
 
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
        err = register_netdev(net_dev);
        if (err) {
                IPW_ERROR("failed to register network device\n");
                goto out_remove_sysfs;
        }
+
+       printk(KERN_INFO DRV_NAME ": Detected geography %s (%d 802.11bg "
+              "channels, %d 802.11a channels)\n",
+              priv->ieee->geo.name, priv->ieee->geo.bg_channels,
+              priv->ieee->geo.a_channels);
+
        return 0;
 
       out_remove_sysfs:
@@ -11091,13 +11036,13 @@ static void ipw_pci_remove(struct pci_dev *pdev)
        if (!priv)
                return;
 
-       down(&priv->sem);
+       mutex_lock(&priv->mutex);
 
        priv->status |= STATUS_EXIT_PENDING;
        ipw_down(priv);
        sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group);
 
-       up(&priv->sem);
+       mutex_unlock(&priv->mutex);
 
        unregister_netdev(priv->net_dev);
 
@@ -11250,8 +11195,10 @@ MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)");
 module_param(led, int, 0444);
 MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)\n");
 
+#ifdef CONFIG_IPW2200_DEBUG
 module_param(debug, int, 0444);
 MODULE_PARM_DESC(debug, "debug output mask");
+#endif
 
 module_param(channel, int, 0444);
 MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])");
@@ -11281,12 +11228,18 @@ module_param(mode, int, 0444);
 MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)");
 #endif
 
+module_param(bt_coexist, int, 0444);
+MODULE_PARM_DESC(bt_coexist, "enable bluetooth coexistence (default off)");
+
 module_param(hwcrypto, int, 0444);
-MODULE_PARM_DESC(hwcrypto, "enable hardware crypto (default on)");
+MODULE_PARM_DESC(hwcrypto, "enable hardware crypto (default off)");
 
 module_param(cmdlog, int, 0444);
 MODULE_PARM_DESC(cmdlog,
                 "allocate a ring buffer for logging firmware commands");
 
+module_param(roaming, int, 0444);
+MODULE_PARM_DESC(roaming, "enable roaming support (default on)");
+
 module_exit(ipw_exit);
 module_init(ipw_init);
index e65620a..4b98049 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms of version 2 of the GNU General Public License as
@@ -33,6 +33,7 @@
 #include <linux/moduleparam.h>
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/mutex.h>
 
 #include <linux/pci.h>
 #include <linux/netdevice.h>
@@ -46,6 +47,7 @@
 #include <linux/firmware.h>
 #include <linux/wireless.h>
 #include <linux/dma-mapping.h>
+#include <linux/jiffies.h>
 #include <asm/io.h>
 
 #include <net/ieee80211.h>
@@ -244,8 +246,10 @@ enum connection_manager_assoc_states {
 #define HOST_NOTIFICATION_S36_MEASUREMENT_REFUSED       31
 
 #define HOST_NOTIFICATION_STATUS_BEACON_MISSING         1
-#define IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT           24
+#define IPW_MB_ROAMING_THRESHOLD_MIN                    1
 #define IPW_MB_ROAMING_THRESHOLD_DEFAULT                8
+#define IPW_MB_ROAMING_THRESHOLD_MAX                    30
+#define IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT           3*IPW_MB_ROAMING_THRESHOLD_DEFAULT
 #define IPW_REAL_RATE_RX_PACKET_THRESHOLD               300
 
 #define MACADRR_BYTE_LEN                     6
@@ -616,13 +620,16 @@ struct notif_tgi_tx_key {
        u8 reserved;
 } __attribute__ ((packed));
 
+#define SILENCE_OVER_THRESH (1)
+#define SILENCE_UNDER_THRESH (2)
+
 struct notif_link_deterioration {
        struct ipw_cmd_stats stats;
        u8 rate;
        u8 modulation;
        struct rate_histogram histogram;
-       u8 reserved1;
-       u16 reserved2;
+       u8 silence_notification_type;   /* SILENCE_OVER/UNDER_THRESH */
+       u16 silence_count;
 } __attribute__ ((packed));
 
 struct notif_association {
@@ -780,7 +787,7 @@ struct ipw_sys_config {
        u8 enable_cts_to_self;
        u8 enable_multicast_filtering;
        u8 bt_coexist_collision_thr;
-       u8 reserved2;
+       u8 silence_threshold;
        u8 accept_all_mgmt_bcpr;
        u8 accept_all_mgtm_frames;
        u8 pass_noise_stats_to_host;
@@ -852,7 +859,7 @@ struct ipw_scan_request_ext {
        u16 dwell_time[IPW_SCAN_TYPES];
 } __attribute__ ((packed));
 
-extern inline u8 ipw_get_scan_type(struct ipw_scan_request_ext *scan, u8 index)
+static inline u8 ipw_get_scan_type(struct ipw_scan_request_ext *scan, u8 index)
 {
        if (index % 2)
                return scan->scan_type[index / 2] & 0x0F;
@@ -860,7 +867,7 @@ extern inline u8 ipw_get_scan_type(struct ipw_scan_request_ext *scan, u8 index)
                return (scan->scan_type[index / 2] & 0xF0) >> 4;
 }
 
-extern inline void ipw_set_scan_type(struct ipw_scan_request_ext *scan,
+static inline void ipw_set_scan_type(struct ipw_scan_request_ext *scan,
                                     u8 index, u8 scan_type)
 {
        if (index % 2)
@@ -1120,7 +1127,7 @@ struct ipw_priv {
        struct ieee80211_device *ieee;
 
        spinlock_t lock;
-       struct semaphore sem;
+       struct mutex mutex;
 
        /* basic pci-network driver stuff */
        struct pci_dev *pci_dev;
@@ -1406,13 +1413,6 @@ do { if (ipw_debug_level & (level)) \
 * Register bit definitions
 */
 
-/* Dino control registers bits */
-
-#define DINO_ENABLE_SYSTEM 0x80
-#define DINO_ENABLE_CS     0x40
-#define DINO_RXFIFO_DATA   0x01
-#define DINO_CONTROL_REG   0x00200000
-
 #define IPW_INTA_RW       0x00000008
 #define IPW_INTA_MASK_R   0x0000000C
 #define IPW_INDIRECT_ADDR 0x00000010
@@ -1459,6 +1459,11 @@ do { if (ipw_debug_level & (level)) \
 #define IPW_DOMAIN_0_END 0x1000
 #define CLX_MEM_BAR_SIZE 0x1000
 
+/* Dino/baseband control registers bits */
+
+#define DINO_ENABLE_SYSTEM 0x80        /* 1 = baseband processor on, 0 = reset */
+#define DINO_ENABLE_CS     0x40        /* 1 = enable ucode load */
+#define DINO_RXFIFO_DATA   0x01        /* 1 = data available */
 #define IPW_BASEBAND_CONTROL_STATUS    0X00200000
 #define IPW_BASEBAND_TX_FIFO_WRITE     0X00200004
 #define IPW_BASEBAND_RX_FIFO_READ      0X00200004
@@ -1567,13 +1572,18 @@ do { if (ipw_debug_level & (level)) \
 #define EEPROM_BSS_CHANNELS_BG  (GET_EEPROM_ADDR(0x2c,LSB))    /* 2 bytes  */
 #define EEPROM_HW_VERSION       (GET_EEPROM_ADDR(0x72,LSB))    /* 2 bytes  */
 
-/* NIC type as found in the one byte EEPROM_NIC_TYPE  offset*/
+/* NIC type as found in the one byte EEPROM_NIC_TYPE offset */
 #define EEPROM_NIC_TYPE_0 0
 #define EEPROM_NIC_TYPE_1 1
 #define EEPROM_NIC_TYPE_2 2
 #define EEPROM_NIC_TYPE_3 3
 #define EEPROM_NIC_TYPE_4 4
 
+/* Bluetooth Coexistence capabilities as found in EEPROM_SKU_CAPABILITY */
+#define EEPROM_SKU_CAP_BT_CHANNEL_SIG  0x01    /* we can tell BT our channel # */
+#define EEPROM_SKU_CAP_BT_PRIORITY     0x02    /* BT can take priority over us */
+#define EEPROM_SKU_CAP_BT_OOB          0x04    /* we can signal BT out-of-band */
+
 #define FW_MEM_REG_LOWER_BOUND          0x00300000
 #define FW_MEM_REG_EEPROM_ACCESS        (FW_MEM_REG_LOWER_BOUND + 0x40)
 #define IPW_EVENT_REG                   (FW_MEM_REG_LOWER_BOUND + 0x04)
@@ -1658,9 +1668,10 @@ enum {
        IPW_FW_ERROR_FATAL_ERROR
 };
 
-#define AUTH_OPEN       0
-#define AUTH_SHARED_KEY 1
-#define AUTH_IGNORE     3
+#define AUTH_OPEN      0
+#define AUTH_SHARED_KEY        1
+#define AUTH_LEAP      2
+#define AUTH_IGNORE    3
 
 #define HC_ASSOCIATE      0
 #define HC_REASSOCIATE    1
@@ -1860,7 +1871,7 @@ struct host_cmd {
        u8 cmd;
        u8 len;
        u16 reserved;
-       u32 param[TFD_CMD_IMMEDIATE_PAYLOAD_LENGTH];
+       u32 *param;
 } __attribute__ ((packed));
 
 struct ipw_cmd_log {
@@ -1869,21 +1880,24 @@ struct ipw_cmd_log {
        struct host_cmd cmd;
 };
 
-#define CFG_BT_COEXISTENCE_MIN                  0x00
-#define CFG_BT_COEXISTENCE_DEFER                0x02
-#define CFG_BT_COEXISTENCE_KILL                 0x04
-#define CFG_BT_COEXISTENCE_WME_OVER_BT          0x08
-#define CFG_BT_COEXISTENCE_OOB                  0x10
-#define CFG_BT_COEXISTENCE_MAX                  0xFF
-#define CFG_BT_COEXISTENCE_DEF                  0x80   /* read Bt from EEPROM */
-
-#define CFG_CTS_TO_ITSELF_ENABLED_MIN  0x0
-#define CFG_CTS_TO_ITSELF_ENABLED_MAX  0x1
+/* SysConfig command parameters ... */
+/* bt_coexistence param */
+#define CFG_BT_COEXISTENCE_SIGNAL_CHNL  0x01   /* tell BT our chnl # */
+#define CFG_BT_COEXISTENCE_DEFER        0x02   /* defer our Tx if BT traffic */
+#define CFG_BT_COEXISTENCE_KILL         0x04   /* kill our Tx if BT traffic */
+#define CFG_BT_COEXISTENCE_WME_OVER_BT  0x08   /* multimedia extensions */
+#define CFG_BT_COEXISTENCE_OOB          0x10   /* signal BT via out-of-band */
+
+/* clear-to-send to self param */
+#define CFG_CTS_TO_ITSELF_ENABLED_MIN  0x00
+#define CFG_CTS_TO_ITSELF_ENABLED_MAX  0x01
 #define CFG_CTS_TO_ITSELF_ENABLED_DEF  CFG_CTS_TO_ITSELF_ENABLED_MIN
 
-#define CFG_SYS_ANTENNA_BOTH                      0x000
-#define CFG_SYS_ANTENNA_A                         0x001
-#define CFG_SYS_ANTENNA_B                         0x003
+/* Antenna diversity param (h/w can select best antenna, based on signal) */
+#define CFG_SYS_ANTENNA_BOTH            0x00   /* NIC selects best antenna */
+#define CFG_SYS_ANTENNA_A               0x01   /* force antenna A */
+#define CFG_SYS_ANTENNA_B               0x03   /* force antenna B */
+#define CFG_SYS_ANTENNA_SLOW_DIV        0x02   /* consider background noise */
 
 /*
  * The definitions below were lifted off the ipw2100 driver, which only
@@ -1899,27 +1913,4 @@ struct ipw_cmd_log {
 
 #define IPW_MAX_CONFIG_RETRIES 10
 
-static inline u32 frame_hdr_len(struct ieee80211_hdr_4addr *hdr)
-{
-       u32 retval;
-       u16 fc;
-
-       retval = sizeof(struct ieee80211_hdr_3addr);
-       fc = le16_to_cpu(hdr->frame_ctl);
-
-       /*
-        * Function     ToDS    FromDS
-        * IBSS         0       0
-        * To AP        1       0
-        * From AP      0       1
-        * WDS (bridge) 1       1
-        *
-        * Only WDS frames use Address4 among them. --YZ
-        */
-       if (!(fc & IEEE80211_FCTL_TODS) || !(fc & IEEE80211_FCTL_FROMDS))
-               retval -= ETH_ALEN;
-
-       return retval;
-}
-
 #endif                         /* __ipw2200_h__ */
index bf6271e..75ce6dd 100644 (file)
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/bitops.h>
-#ifdef CONFIG_NET_RADIO
 #include <linux/wireless.h>
 #include <net/iw_handler.h>
-#endif
 
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
index 18baacf..18a4458 100644 (file)
@@ -112,7 +112,7 @@ static const char StripVersion[] = "1.3A-STUART.CHESHIRE";
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/time.h>
-
+#include <linux/jiffies.h>
 
 /************************************************************************/
 /* Useful structures and definitions                                   */
@@ -1569,7 +1569,7 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev)
        del_timer(&strip_info->idle_timer);
 
 
-       if (jiffies - strip_info->pps_timer > HZ) {
+       if (time_after(jiffies, strip_info->pps_timer + HZ)) {
                unsigned long t = jiffies - strip_info->pps_timer;
                unsigned long rx_pps_count = (strip_info->rx_pps_count * HZ * 8 + t / 2) / t;
                unsigned long tx_pps_count = (strip_info->tx_pps_count * HZ * 8 + t / 2) / t;
index 166e28b..5cb0bc8 100644 (file)
  * characteristics of the hardware.  Applications such as mobile IP may
  * take advantage of it.
  *
- * You will need to enable the CONFIG_NET_RADIO define in the kernel
- * configuration to enable the wireless extensions (this is the one
- * giving access to the radio network device choice).
- *
- * It might also be a good idea as well to fetch the wireless tools to
+ * It might be a good idea as well to fetch the wireless tools to
  * configure the device and play a bit.
  */
 
index f2d5975..451f627 100644 (file)
  * caracteristics of the hardware in a standard way and support for
  * applications for taking advantage of it (like Mobile IP).
  *
- * You will need to enable the CONFIG_NET_RADIO define in the kernel
- * configuration to enable the wireless extensions (this is the one
- * giving access to the radio network device choice).
- *
- * It might also be a good idea as well to fetch the wireless tools to
+ * It might be a good idea as well to fetch the wireless tools to
  * configure the device and play a bit.
  */
 
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <linux/ethtool.h>
-
-#ifdef CONFIG_NET_RADIO
 #include <linux/wireless.h>            /* Wireless extensions */
 #include <net/iw_handler.h>            /* New driver API */
-#endif
 
 /* Pcmcia headers that we need */
 #include <pcmcia/cs_types.h>
index 1c25065..75d56bf 100644 (file)
@@ -69,8 +69,8 @@ static int fifo_cfg = 0x0020;                         /* Bypass external Tx FIFO. */
 static int dma_ctrl = 0x00CAC277;                      /* Override when loading module! */
 static int fifo_cfg = 0x0028;
 #else
-static int dma_ctrl = 0x004A0263;                      /* Constrained by errata */
-static int fifo_cfg = 0x0020;                          /* Bypass external Tx FIFO. */
+static const int dma_ctrl = 0x004A0263;                        /* Constrained by errata */
+static const int fifo_cfg = 0x0020;                            /* Bypass external Tx FIFO. */
 #endif
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
@@ -266,7 +266,7 @@ struct pci_id_info {
         int drv_flags;                          /* Driver use, intended as capability flags. */
 };
 
-static struct pci_id_info pci_id_tbl[] = {
+static const struct pci_id_info pci_id_tbl[] = {
        {"Yellowfin G-NIC Gigabit Ethernet", { 0x07021000, 0xffffffff},
         PCI_IOTYPE, YELLOWFIN_SIZE,
         FullTxStatus | IsGigabit | HasMulticastBug | HasMACAddrBug | DontUseEeprom},
index 8ab6e12..7610216 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/zorro.h>
+#include <linux/jiffies.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
@@ -151,7 +152,7 @@ static int __devinit zorro8390_init(struct net_device *dev,
        z_writeb(z_readb(ioaddr + NE_RESET), ioaddr + NE_RESET);
 
        while ((z_readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
-           if (jiffies - reset_start_time > 2*HZ/100) {
+           if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
                printk(KERN_WARNING " not found (no reset ack).\n");
                return -ENODEV;
            }
@@ -273,7 +274,7 @@ static void zorro8390_reset_8390(struct net_device *dev)
 
     /* This check _should_not_ be necessary, omit eventually. */
     while ((z_readb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0)
-       if (jiffies - reset_start_time > 2*HZ/100) {
+       if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
            printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n",
                   dev->name);
            break;
@@ -400,7 +401,7 @@ static void zorro8390_block_output(struct net_device *dev, int count,
     dma_start = jiffies;
 
     while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
-       if (jiffies - dma_start > 2*HZ/100) {           /* 20ms */
+       if (time_after(jiffies, dma_start + 2*HZ/100)) {        /* 20ms */
                printk(KERN_ERR "%s: timeout waiting for Tx RDC.\n",
                       dev->name);
                zorro8390_reset_8390(dev);
index 2e727f4..4413325 100644 (file)
@@ -273,7 +273,7 @@ removeseg:
        list_del(&dev_info->lh);
 
        del_gendisk(dev_info->gd);
-       blk_put_queue(dev_info->dcssblk_queue);
+       blk_cleanup_queue(dev_info->dcssblk_queue);
        dev_info->gd->queue = NULL;
        put_disk(dev_info->gd);
        device_unregister(dev);
@@ -491,7 +491,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
 unregister_dev:
        PRINT_ERR("device_create_file() failed!\n");
        list_del(&dev_info->lh);
-       blk_put_queue(dev_info->dcssblk_queue);
+       blk_cleanup_queue(dev_info->dcssblk_queue);
        dev_info->gd->queue = NULL;
        put_disk(dev_info->gd);
        device_unregister(&dev_info->dev);
@@ -505,7 +505,7 @@ list_del:
 unload_seg:
        segment_unload(local_buf);
 dealloc_gendisk:
-       blk_put_queue(dev_info->dcssblk_queue);
+       blk_cleanup_queue(dev_info->dcssblk_queue);
        dev_info->gd->queue = NULL;
        put_disk(dev_info->gd);
 free_dev_info:
@@ -562,7 +562,7 @@ dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const ch
        list_del(&dev_info->lh);
 
        del_gendisk(dev_info->gd);
-       blk_put_queue(dev_info->dcssblk_queue);
+       blk_cleanup_queue(dev_info->dcssblk_queue);
        dev_info->gd->queue = NULL;
        put_disk(dev_info->gd);
        device_unregister(&dev_info->dev);
index 1bbf231..3c77d65 100644 (file)
@@ -409,6 +409,9 @@ __init_channel_subsystem(struct subchannel_id schid, void *data)
                /* -ENXIO: no more subchannels. */
                case -ENXIO:
                        return ret;
+               /* -EIO: this subchannel set not supported. */
+               case -EIO:
+                       return ret;
                default:
                        return 0;
                }
index ae6d032..cd5eeb0 100644 (file)
@@ -202,7 +202,6 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
                filp->private_data = NULL;
        }
 
-       d_drop(filp->f_dentry);
        return 0;
 }
 
index 62cfd17..a9b3994 100644 (file)
@@ -3060,6 +3060,7 @@ int buffer_migrate_page(struct page *newpage, struct page *page)
 {
        struct address_space *mapping = page->mapping;
        struct buffer_head *bh, *head;
+       int rc;
 
        if (!mapping)
                return -EAGAIN;
@@ -3069,8 +3070,9 @@ int buffer_migrate_page(struct page *newpage, struct page *page)
 
        head = page_buffers(page);
 
-       if (migrate_page_remove_references(newpage, page, 3))
-               return -EAGAIN;
+       rc = migrate_page_remove_references(newpage, page, 3);
+       if (rc)
+               return rc;
 
        bh = head;
        do {
index 848044a..27f3e78 100644 (file)
@@ -1155,15 +1155,16 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
  * For writes, i_mutex is not held on entry; it is never taken.
  *
  * DIO_LOCKING (simple locking for regular files)
- * For writes we are called under i_mutex and return with i_mutex held, even though
- * it is internally dropped.
+ * For writes we are called under i_mutex and return with i_mutex held, even
+ * though it is internally dropped.
  * For reads, i_mutex is not held on entry, but it is taken and dropped before
  * returning.
  *
  * DIO_OWN_LOCKING (filesystem provides synchronisation and handling of
  *     uninitialised data, allowing parallel direct readers and writers)
  * For writes we are called without i_mutex, return without it, never touch it.
- * For reads, i_mutex is held on entry and will be released before returning.
+ * For reads we are called under i_mutex and return with i_mutex held, even
+ * though it may be internally dropped.
  *
  * Additional i_alloc_sem locking requirements described inline below.
  */
@@ -1182,7 +1183,8 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
        ssize_t retval = -EINVAL;
        loff_t end = offset;
        struct dio *dio;
-       int reader_with_isem = (rw == READ && dio_lock_type == DIO_OWN_LOCKING);
+       int release_i_mutex = 0;
+       int acquire_i_mutex = 0;
 
        if (rw & WRITE)
                current->flags |= PF_SYNCWRITE;
@@ -1225,7 +1227,6 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
         *      writers need to grab i_alloc_sem only (i_mutex is already held)
         * For regular files using DIO_OWN_LOCKING,
         *      neither readers nor writers take any locks here
-        *      (i_mutex is already held and release for writers here)
         */
        dio->lock_type = dio_lock_type;
        if (dio_lock_type != DIO_NO_LOCKING) {
@@ -1236,7 +1237,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
                        mapping = iocb->ki_filp->f_mapping;
                        if (dio_lock_type != DIO_OWN_LOCKING) {
                                mutex_lock(&inode->i_mutex);
-                               reader_with_isem = 1;
+                               release_i_mutex = 1;
                        }
 
                        retval = filemap_write_and_wait_range(mapping, offset,
@@ -1248,7 +1249,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 
                        if (dio_lock_type == DIO_OWN_LOCKING) {
                                mutex_unlock(&inode->i_mutex);
-                               reader_with_isem = 0;
+                               acquire_i_mutex = 1;
                        }
                }
 
@@ -1269,11 +1270,13 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
                                nr_segs, blkbits, get_blocks, end_io, dio);
 
        if (rw == READ && dio_lock_type == DIO_LOCKING)
-               reader_with_isem = 0;
+               release_i_mutex = 0;
 
 out:
-       if (reader_with_isem)
+       if (release_i_mutex)
                mutex_unlock(&inode->i_mutex);
+       else if (acquire_i_mutex)
+               mutex_lock(&inode->i_mutex);
        if (rw & WRITE)
                current->flags &= ~PF_SYNCWRITE;
        return retval;
index 7442bdd..b3dbd71 100644 (file)
@@ -256,11 +256,10 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
        unsigned long npages = dir_pages(inode);
        unsigned chunk_mask = ~(ext2_chunk_size(inode)-1);
        unsigned char *types = NULL;
-       int need_revalidate = (filp->f_version != inode->i_version);
-       int ret;
+       int need_revalidate = filp->f_version != inode->i_version;
 
        if (pos > inode->i_size - EXT2_DIR_REC_LEN(1))
-               goto success;
+               return 0;
 
        if (EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_FILETYPE))
                types = ext2_filetype_table;
@@ -275,12 +274,15 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
                                   "bad page in #%lu",
                                   inode->i_ino);
                        filp->f_pos += PAGE_CACHE_SIZE - offset;
-                       ret = -EIO;
-                       goto done;
+                       return -EIO;
                }
                kaddr = page_address(page);
-               if (need_revalidate) {
-                       offset = ext2_validate_entry(kaddr, offset, chunk_mask);
+               if (unlikely(need_revalidate)) {
+                       if (offset) {
+                               offset = ext2_validate_entry(kaddr, offset, chunk_mask);
+                               filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset;
+                       }
+                       filp->f_version = inode->i_version;
                        need_revalidate = 0;
                }
                de = (ext2_dirent *)(kaddr+offset);
@@ -289,9 +291,8 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
                        if (de->rec_len == 0) {
                                ext2_error(sb, __FUNCTION__,
                                        "zero-length directory entry");
-                               ret = -EIO;
                                ext2_put_page(page);
-                               goto done;
+                               return -EIO;
                        }
                        if (de->inode) {
                                int over;
@@ -306,19 +307,14 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
                                                le32_to_cpu(de->inode), d_type);
                                if (over) {
                                        ext2_put_page(page);
-                                       goto success;
+                                       return 0;
                                }
                        }
                        filp->f_pos += le16_to_cpu(de->rec_len);
                }
                ext2_put_page(page);
        }
-
-success:
-       ret = 0;
-done:
-       filp->f_version = inode->i_version;
-       return ret;
+       return 0;
 }
 
 /*
index 058a448..39c81a8 100644 (file)
@@ -1338,7 +1338,7 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
 
        new_ns = kmalloc(sizeof(struct namespace), GFP_KERNEL);
        if (!new_ns)
-               goto out;
+               return NULL;
 
        atomic_set(&new_ns->count, 1);
        INIT_LIST_HEAD(&new_ns->list);
@@ -1352,7 +1352,7 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
        if (!new_ns->root) {
                up_write(&namespace_sem);
                kfree(new_ns);
-               goto out;
+               return NULL;
        }
        spin_lock(&vfsmount_lock);
        list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
@@ -1393,7 +1393,6 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
        if (altrootmnt)
                mntput(altrootmnt);
 
-out:
        return new_ns;
 }
 
index 0d4cf94..1c72c7f 100644 (file)
@@ -98,10 +98,8 @@ asmlinkage sys_nfsservctl(int cmd, struct nfsctl_arg __user *arg, void __user *r
        if (copy_from_user(&version, &arg->ca_version, sizeof(int)))
                return -EFAULT;
 
-       if (version != NFSCTL_VERSION) {
-               printk(KERN_WARNING "nfsd: incompatible version in syscall.\n");
+       if (version != NFSCTL_VERSION)
                return -EINVAL;
-       }
 
        if (cmd < 0 || cmd >= sizeof(map)/sizeof(map[0]) || !map[cmd].name)
                return -EINVAL;
index eb2de8c..ec91d1f 100644 (file)
@@ -415,6 +415,9 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size
        return ret;
 }
 
+extern void disable_hlt(void);
+extern void enable_hlt(void);
+
 #endif /* __ASSEMBLY__ */
 
 #define arch_align_stack(x) (x)
index 78c9cc2..3f2b6d9 100644 (file)
@@ -96,6 +96,9 @@
 #ifndef cpu_has_ic_fills_f_dc
 #define cpu_has_ic_fills_f_dc  (cpu_data[0].icache.flags & MIPS_CACHE_IC_F_DC)
 #endif
+#ifndef cpu_has_pindexed_dcache
+#define cpu_has_pindexed_dcache        (cpu_data[0].dcache.flags & MIPS_CACHE_PINDEX)
+#endif
 
 /*
  * I-Cache snoops remote store.  This only matters on SMP.  Some multiprocessors
index d5cf519..140be1c 100644 (file)
@@ -39,6 +39,7 @@ struct cache_desc {
 #define MIPS_CACHE_ALIASES     0x00000004      /* Cache could have aliases */
 #define MIPS_CACHE_IC_F_DC     0x00000008      /* Ic can refill from D-cache */
 #define MIPS_IC_SNOOPS_REMOTE  0x00000010      /* Ic snoops remote stores */
+#define MIPS_CACHE_PINDEX      0x00000020      /* Physically indexed cache */
 
 struct cpuinfo_mips {
        unsigned long           udelay_val;
index 6111a0c..feb29a7 100644 (file)
@@ -3,7 +3,9 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2003, 2004 Ralf Baechle
+ * Copyright (C) 2003, 2004 Ralf Baechle <ralf@linux-mips.org>
+ * Copyright (C) MIPS Technologies, Inc.
+ *   written by Ralf Baechle <ralf@linux-mips.org>
  */
 #ifndef _ASM_HAZARDS_H
 #define _ASM_HAZARDS_H
@@ -74,8 +76,7 @@
 #define irq_disable_hazard
        _ehb
 
-#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000) || \
-      defined(CONFIG_CPU_SB1)
+#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000)
 
 /*
  * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
 #else /* __ASSEMBLY__ */
 
 __asm__(
-       "       .macro  _ssnop                                  \n\t"
-       "       sll     $0, $0, 1                               \n\t"
-       "       .endm                                           \n\t"
-       "                                                       \n\t"
-       "       .macro  _ehb                                    \n\t"
-       "       sll     $0, $0, 3                               \n\t"
-       "       .endm                                           \n\t");
+       "       .macro  _ssnop                                  \n"
+       "       sll     $0, $0, 1                               \n"
+       "       .endm                                           \n"
+       "                                                       \n"
+       "       .macro  _ehb                                    \n"
+       "       sll     $0, $0, 3                               \n"
+       "       .endm                                           \n");
 
 #ifdef CONFIG_CPU_RM9000
 
@@ -117,17 +118,21 @@ __asm__(
 
 #define mtc0_tlbw_hazard()                                             \
        __asm__ __volatile__(                                           \
-               ".set\tmips32\n\t"                                      \
-               "_ssnop; _ssnop; _ssnop; _ssnop\n\t"                    \
-               ".set\tmips0")
+       "       .set    mips32                                  \n"     \
+       "       _ssnop                                          \n"     \
+       "       _ssnop                                          \n"     \
+       "       _ssnop                                          \n"     \
+       "       _ssnop                                          \n"     \
+       "       .set    mips0                                   \n")
 
 #define tlbw_use_hazard()                                              \
        __asm__ __volatile__(                                           \
-               ".set\tmips32\n\t"                                      \
-               "_ssnop; _ssnop; _ssnop; _ssnop\n\t"                    \
-               ".set\tmips0")
-
-#define back_to_back_c0_hazard()       do { } while (0)
+       "       .set    mips32                                  \n"     \
+       "       _ssnop                                          \n"     \
+       "       _ssnop                                          \n"     \
+       "       _ssnop                                          \n"     \
+       "       _ssnop                                          \n"     \
+       "       .set    mips0                                   \n")
 
 #else
 
@@ -136,15 +141,25 @@ __asm__(
  */
 #define mtc0_tlbw_hazard()                                             \
        __asm__ __volatile__(                                           \
-               ".set noreorder\n\t"                                    \
-               "nop; nop; nop; nop; nop; nop;\n\t"                     \
-               ".set reorder\n\t")
+       "       .set    noreorder                               \n"     \
+       "       nop                                             \n"     \
+       "       nop                                             \n"     \
+       "       nop                                             \n"     \
+       "       nop                                             \n"     \
+       "       nop                                             \n"     \
+       "       nop                                             \n"     \
+       "       .set    reorder                                 \n")
 
 #define tlbw_use_hazard()                                              \
        __asm__ __volatile__(                                           \
-               ".set noreorder\n\t"                                    \
-               "nop; nop; nop; nop; nop; nop;\n\t"                     \
-               ".set reorder\n\t")
+       "       .set    noreorder                               \n"     \
+       "       nop                                             \n"     \
+       "       nop                                             \n"     \
+       "       nop                                             \n"     \
+       "       nop                                             \n"     \
+       "       nop                                             \n"     \
+       "       nop                                             \n"     \
+       "       .set    reorder                                 \n")
 
 #endif
 
@@ -156,49 +171,26 @@ __asm__(
 
 #ifdef CONFIG_CPU_MIPSR2
 
-__asm__(
-       "       .macro\tirq_enable_hazard                       \n\t"
-       "       _ehb                                            \n\t"
-       "       .endm                                           \n\t"
-       "                                                       \n\t"
-       "       .macro\tirq_disable_hazard                      \n\t"
-       "       _ehb                                            \n\t"
-       "       .endm                                           \n\t"
-       "                                                       \n\t"
-       "       .macro\tback_to_back_c0_hazard                  \n\t"
-       "       _ehb                                            \n\t"
-       "       .endm");
-
-#define irq_enable_hazard()                                            \
-       __asm__ __volatile__(                                           \
-       "irq_enable_hazard")
+__asm__("      .macro  irq_enable_hazard                       \n"
+       "       _ehb                                            \n"
+       "       .endm                                           \n"
+       "                                                       \n"
+       "       .macro  irq_disable_hazard                      \n"
+       "       _ehb                                            \n"
+       "       .endm                                           \n");
 
-#define irq_disable_hazard()                                           \
-       __asm__ __volatile__(                                           \
-       "irq_disable_hazard")
-
-#define back_to_back_c0_hazard()                                       \
-       __asm__ __volatile__(                                           \
-       "back_to_back_c0_hazard")
-
-#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000) || \
-      defined(CONFIG_CPU_SB1)
+#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000)
 
 /*
  * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
  */
 
 __asm__(
-       "       .macro\tirq_enable_hazard                       \n\t"
-       "       .endm                                           \n\t"
-       "                                                       \n\t"
-       "       .macro\tirq_disable_hazard                      \n\t"
-       "       .endm");
-
-#define irq_enable_hazard()    do { } while (0)
-#define irq_disable_hazard()   do { } while (0)
-
-#define back_to_back_c0_hazard()       do { } while (0)
+       "       .macro  irq_enable_hazard                       \n"
+       "       .endm                                           \n"
+       "                                                       \n"
+       "       .macro  irq_disable_hazard                      \n"
+       "       .endm                                           \n");
 
 #else
 
@@ -209,29 +201,63 @@ __asm__(
  */
 
 __asm__(
-       "       #                                               \n\t"
-       "       # There is a hazard but we do not care          \n\t"
-       "       #                                               \n\t"
-       "       .macro\tirq_enable_hazard                       \n\t"
-       "       .endm                                           \n\t"
-       "                                                       \n\t"
-       "       .macro\tirq_disable_hazard                      \n\t"
-       "       _ssnop; _ssnop; _ssnop                          \n\t"
-       "       .endm");
+       "       #                                               \n"
+       "       # There is a hazard but we do not care          \n"
+       "       #                                               \n"
+       "       .macro\tirq_enable_hazard                       \n"
+       "       .endm                                           \n"
+       "                                                       \n"
+       "       .macro\tirq_disable_hazard                      \n"
+       "       _ssnop                                          \n"
+       "       _ssnop                                          \n"
+       "       _ssnop                                          \n"
+       "       .endm                                           \n");
 
-#define irq_enable_hazard()    do { } while (0)
+#endif
+
+#define irq_enable_hazard()                                            \
+       __asm__ __volatile__("irq_enable_hazard")
 #define irq_disable_hazard()                                           \
-       __asm__ __volatile__(                                           \
-       "irq_disable_hazard")
+       __asm__ __volatile__("irq_disable_hazard")
 
-#define back_to_back_c0_hazard()                                       \
-       __asm__ __volatile__(                                           \
-       "       .set noreorder                          \n"             \
-       "       nop; nop; nop                           \n"             \
-       "       .set reorder                            \n")
+
+/*
+ * Back-to-back hazards -
+ *
+ * What is needed to separate a move to cp0 from a subsequent read from the
+ * same cp0 register?
+ */
+#ifdef CONFIG_CPU_MIPSR2
+
+__asm__("      .macro  back_to_back_c0_hazard                  \n"
+       "       _ehb                                            \n"
+       "       .endm                                           \n");
+
+#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000) || \
+      defined(CONFIG_CPU_SB1)
+
+__asm__("      .macro  back_to_back_c0_hazard                  \n"
+       "       .endm                                           \n");
+
+#else
+
+__asm__("      .macro  back_to_back_c0_hazard                  \n"
+       "       .set    noreorder                               \n"
+       "       _ssnop                                          \n"
+       "       _ssnop                                          \n"
+       "       _ssnop                                          \n"
+       "       .set    reorder                                 \n"
+       "       .endm");
 
 #endif
 
+#define back_to_back_c0_hazard()                                       \
+       __asm__ __volatile__("back_to_back_c0_hazard")
+
+
+/*
+ * Instruction execution hazard
+ */
 #ifdef CONFIG_CPU_MIPSR2
 /*
  * gcc has a tradition of misscompiling the previous construct using the
index 8c011aa..ba1d7bb 100644 (file)
@@ -4,7 +4,7 @@
  * for more details.
  *
  * Copyright (C) 1994, 1995 Waldorf GmbH
- * Copyright (C) 1994 - 2000 Ralf Baechle
+ * Copyright (C) 1994 - 2000, 06 Ralf Baechle
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  * Copyright (C) 2004, 2005  MIPS Technologies, Inc.  All rights reserved.
  *     Author: Maciej W. Rozycki <macro@mips.com>
  */
 extern const unsigned long mips_io_port_base;
 
-#define set_io_port_base(base) \
-       do { * (unsigned long *) &mips_io_port_base = (base); } while (0)
+/*
+ * Gcc will generate code to load the value of mips_io_port_base after each
+ * function call which may be fairly wasteful in some cases.  So we don't
+ * play quite by the book.  We tell gcc mips_io_port_base is a long variable
+ * which solves the code generation issue.  Now we need to violate the
+ * aliasing rules a little to make initialization possible and finally we
+ * will need the barrier() to fight side effects of the aliasing chat.
+ * This trickery will eventually collapse under gcc's optimizer.  Oh well.
+ */
+static inline void set_io_port_base(unsigned long base)
+{
+       * (unsigned long *) &mips_io_port_base = base;
+       barrier();
+}
 
 /*
  * Thanks to James van Artsdalen for a better timing-fix than
index 9632c27..0bcb79a 100644 (file)
@@ -257,7 +257,8 @@ static inline void blast_##pfx##cache##lsize##_page(unsigned long page)     \
                                                                        \
 static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
 {                                                                      \
-       unsigned long start = page;                                     \
+       unsigned long indexmask = current_cpu_data.desc.waysize - 1;    \
+       unsigned long start = INDEX_BASE + (page & indexmask);          \
        unsigned long end = start + PAGE_SIZE;                          \
        unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit;     \
        unsigned long ws_end = current_cpu_data.desc.ways <<            \
index a474c29..b09e16c 100644 (file)
@@ -45,8 +45,8 @@ extern unsigned int soc_type;
 extern unsigned int periph_rev;
 extern unsigned int zbbus_mhz;
 
+extern void sb1250_hpt_setup(void);
 extern void sb1250_time_init(void);
-extern unsigned long sb1250_gettimeoffset(void);
 extern void sb1250_mask_irq(int cpu, int irq);
 extern void sb1250_unmask_irq(int cpu, int irq);
 extern void sb1250_smp_finish(void);
index a667bc1..f4178bd 100644 (file)
  */
 
 #define V_SCD_TIMER_FREQ            1000000
+#define V_SCD_TIMER_WIDTH           23
 
 #define S_SCD_TIMER_INIT            0
-#define M_SCD_TIMER_INIT            _SB_MAKEMASK(20,S_SCD_TIMER_INIT)
+#define M_SCD_TIMER_INIT            _SB_MAKEMASK(V_SCD_TIMER_WIDTH,S_SCD_TIMER_INIT)
 #define V_SCD_TIMER_INIT(x)         _SB_MAKEVALUE(x,S_SCD_TIMER_INIT)
 #define G_SCD_TIMER_INIT(x)         _SB_GETVALUE(x,S_SCD_TIMER_INIT,M_SCD_TIMER_INIT)
 
 #define S_SCD_TIMER_CNT             0
-#define M_SCD_TIMER_CNT             _SB_MAKEMASK(20,S_SCD_TIMER_CNT)
+#define M_SCD_TIMER_CNT             _SB_MAKEMASK(V_SCD_TIMER_WIDTH,S_SCD_TIMER_CNT)
 #define V_SCD_TIMER_CNT(x)         _SB_MAKEVALUE(x,S_SCD_TIMER_CNT)
 #define G_SCD_TIMER_CNT(x)         _SB_GETVALUE(x,S_SCD_TIMER_CNT,M_SCD_TIMER_CNT)
 
index f80482c..cf79bc7 100644 (file)
@@ -38,6 +38,7 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,
 
 void pci_devs_phb_init(void);
 void pci_devs_phb_init_dynamic(struct pci_controller *phb);
+int setup_phb(struct device_node *dev, struct pci_controller *phb);
 void __devinit scan_phb(struct pci_controller *hose);
 
 /* From rtas_pci.h */
index 7198f12..231ba09 100644 (file)
@@ -206,7 +206,6 @@ struct ArcProto {
 
 extern struct ArcProto *arc_proto_map[256], *arc_proto_default,
        *arc_bcast_proto, *arc_raw_proto;
-extern struct ArcProto arc_proto_null;
 
 
 /*
@@ -334,17 +333,9 @@ void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc);
 #define arcnet_dump_skb(dev,skb,desc) ;
 #endif
 
-#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc,
-                       int take_arcnet_lock);
-#else
-#define arcnet_dump_packet(dev, bufnum, desc,take_arcnet_lock) ;
-#endif
-
 void arcnet_unregister_proto(struct ArcProto *proto);
 irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 struct net_device *alloc_arcdev(char *name);
-void arcnet_rx(struct net_device *dev, int bufnum);
 
 #endif                         /* __KERNEL__ */
 #endif                         /* _LINUX_ARCDEVICE_H */
index 860e7a4..56bb6a4 100644 (file)
@@ -58,7 +58,7 @@ struct cfq_io_context {
         * circular list of cfq_io_contexts belonging to a process io context
         */
        struct list_head list;
-       struct cfq_queue *cfqq;
+       struct cfq_queue *cfqq[2];
        void *key;
 
        struct io_context *ioc;
@@ -69,6 +69,8 @@ struct cfq_io_context {
        unsigned long ttime_samples;
        unsigned long ttime_mean;
 
+       struct list_head queue_list;
+
        void (*dtor)(struct cfq_io_context *);
        void (*exit)(struct cfq_io_context *);
 };
@@ -404,8 +406,6 @@ struct request_queue
 
        struct blk_queue_tag    *queue_tags;
 
-       atomic_t                refcnt;
-
        unsigned int            nr_sorted;
        unsigned int            in_flight;
 
@@ -424,6 +424,8 @@ struct request_queue
        struct request          pre_flush_rq, bar_rq, post_flush_rq;
        struct request          *orig_bar_rq;
        unsigned int            bi_size;
+
+       struct mutex            sysfs_lock;
 };
 
 #define RQ_INACTIVE            (-1)
@@ -725,7 +727,7 @@ extern long nr_blockdev_pages(void);
 int blk_get_queue(request_queue_t *);
 request_queue_t *blk_alloc_queue(gfp_t);
 request_queue_t *blk_alloc_queue_node(gfp_t, int);
-#define blk_put_queue(q) blk_cleanup_queue((q))
+extern void blk_put_queue(request_queue_t *);
 
 /*
  * tag stuff
index 18cf1f3..ad133fc 100644 (file)
@@ -48,10 +48,17 @@ struct elevator_ops
 
        elevator_init_fn *elevator_init_fn;
        elevator_exit_fn *elevator_exit_fn;
+       void (*trim)(struct io_context *);
 };
 
 #define ELV_NAME_MAX   (16)
 
+struct elv_fs_entry {
+       struct attribute attr;
+       ssize_t (*show)(elevator_t *, char *);
+       ssize_t (*store)(elevator_t *, const char *, size_t);
+};
+
 /*
  * identifies an elevator type, such as AS or deadline
  */
@@ -60,7 +67,7 @@ struct elevator_type
        struct list_head list;
        struct elevator_ops ops;
        struct elevator_type *elevator_type;
-       struct kobj_type *elevator_ktype;
+       struct elv_fs_entry *elevator_attrs;
        char elevator_name[ELV_NAME_MAX];
        struct module *elevator_owner;
 };
@@ -74,6 +81,7 @@ struct elevator_queue
        void *elevator_data;
        struct kobject kobj;
        struct elevator_type *elevator_type;
+       struct mutex sysfs_lock;
 };
 
 /*
index ce627d9..12c6f6d 100644 (file)
@@ -52,6 +52,9 @@
 /* Private (from user) interface flags (netdevice->priv_flags). */
 #define IFF_802_1Q_VLAN 0x1             /* 802.1Q VLAN device.          */
 #define IFF_EBRIDGE    0x2             /* Ethernet bridging device.    */
+#define IFF_SLAVE_INACTIVE     0x4     /* bonding slave not the curr. active */
+#define IFF_MASTER_8023AD      0x8     /* bonding master, 802.3ad.     */
+#define IFF_MASTER_ALB 0x10            /* bonding master, balance-alb. */
 
 #define IF_GET_IFACE   0x0001          /* for querying only */
 #define IF_GET_PROTO   0x0002
index 7a92c1c..ab08f35 100644 (file)
@@ -61,6 +61,7 @@
 #define ETH_P_8021Q    0x8100          /* 802.1Q VLAN Extended Header  */
 #define ETH_P_IPX      0x8137          /* IPX over DIX                 */
 #define ETH_P_IPV6     0x86DD          /* IPv6 over bluebook           */
+#define ETH_P_SLOW     0x8809          /* Slow Protocol. See 802.3ad 43B */
 #define ETH_P_WCCP     0x883E          /* Web-cache coordination protocol
                                         * defined in draft-wilson-wrec-wccp-v2-00.txt */
 #define ETH_P_PPP_DISC 0x8863          /* PPPoE discovery messages     */
index 0b08cd6..955d306 100644 (file)
@@ -1214,6 +1214,7 @@ struct mv64xxx_i2c_pdata {
 #define MV643XX_ETH_FORCE_BP_MODE_NO_JAM               0
 #define MV643XX_ETH_FORCE_BP_MODE_JAM_TX               (1<<7)
 #define MV643XX_ETH_FORCE_BP_MODE_JAM_TX_ON_RX_ERR     (1<<8)
+#define MV643XX_ETH_SERIAL_PORT_CONTROL_RESERVED       (1<<9)
 #define MV643XX_ETH_FORCE_LINK_FAIL                    0
 #define MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL             (1<<10)
 #define MV643XX_ETH_RETRANSMIT_16_ATTEMPTS             0
@@ -1243,6 +1244,8 @@ struct mv64xxx_i2c_pdata {
 #define MV643XX_ETH_SET_MII_SPEED_TO_10                        0
 #define MV643XX_ETH_SET_MII_SPEED_TO_100               (1<<24)
 
+#define MV643XX_ETH_MAX_RX_PACKET_MASK                 (0x7<<17)
+
 #define        MV643XX_ETH_PORT_SERIAL_CONTROL_DEFAULT_VALUE           \
                MV643XX_ETH_DO_NOT_FORCE_LINK_PASS      |       \
                MV643XX_ETH_ENABLE_AUTO_NEG_FOR_DUPLX   |       \
@@ -1285,23 +1288,15 @@ struct mv64xxx_i2c_pdata {
 #define MV643XX_ETH_NAME       "mv643xx_eth"
 
 struct mv643xx_eth_platform_data {
-       /* 
-        * Non-values for mac_addr, phy_addr, port_config, etc.
-        * override the default value.  Setting the corresponding
-        * force_* field, causes the default value to be overridden
-        * even when zero.
-        */
-       unsigned int    force_phy_addr:1;
-       unsigned int    force_port_config:1;
-       unsigned int    force_port_config_extend:1;
-       unsigned int    force_port_sdma_config:1;
-       unsigned int    force_port_serial_control:1;
-       int             phy_addr;
        char            *mac_addr;      /* pointer to mac address */
-       u32             port_config;
-       u32             port_config_extend;
-       u32             port_sdma_config;
-       u32             port_serial_control;
+       u16             force_phy_addr; /* force override if phy_addr == 0 */
+       u16             phy_addr;
+
+       /* If speed is 0, then speed and duplex are autonegotiated. */
+       int             speed;          /* 0, SPEED_10, SPEED_100, SPEED_1000 */
+       int             duplex;         /* DUPLEX_HALF or DUPLEX_FULL */
+
+       /* non-zero values of the following fields override defaults */
        u32             tx_queue_size;
        u32             rx_queue_size;
        u32             tx_sram_addr;
index 1709b50..751eea5 100644 (file)
 #define PCI_DEVICE_ID_SERVERWORKS_HE     0x0008
 #define PCI_DEVICE_ID_SERVERWORKS_LE     0x0009
 #define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017
+#define PCI_DEVICE_ID_SERVERWORKS_EPB    0x0103
 #define PCI_DEVICE_ID_SERVERWORKS_OSB4   0x0200
 #define PCI_DEVICE_ID_SERVERWORKS_CSB5   0x0201
 #define PCI_DEVICE_ID_SERVERWORKS_CSB6    0x0203
index 2250a18..d052b22 100644 (file)
@@ -110,8 +110,15 @@ enum {
 enum {
        AX25_PROTO_STD_SIMPLEX,
        AX25_PROTO_STD_DUPLEX,
+#ifdef CONFIG_AX25_DAMA_SLAVE
        AX25_PROTO_DAMA_SLAVE,
-       AX25_PROTO_DAMA_MASTER
+#ifdef CONFIG_AX25_DAMA_MASTER
+       AX25_PROTO_DAMA_MASTER,
+#define AX25_PROTO_MAX AX25_PROTO_DAMA_MASTER
+#endif
+#endif
+       __AX25_PROTO_MAX,
+       AX25_PROTO_MAX = __AX25_PROTO_MAX -1
 };
 
 enum {
index 9a92aef..4725ff8 100644 (file)
@@ -220,6 +220,7 @@ struct ieee80211_snap_hdr {
 /* Authentication algorithms */
 #define WLAN_AUTH_OPEN 0
 #define WLAN_AUTH_SHARED_KEY 1
+#define WLAN_AUTH_LEAP 2
 
 #define WLAN_AUTH_CHALLENGE_LEN 128
 
@@ -299,6 +300,23 @@ enum ieee80211_reasoncode {
        WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
 };
 
+/* Action categories - 802.11h */
+enum ieee80211_actioncategories {
+       WLAN_ACTION_SPECTRUM_MGMT = 0,
+       /* Reserved 1-127  */
+       /* Error    128-255 */
+};
+
+/* Action details - 802.11h */
+enum ieee80211_actiondetails {
+       WLAN_ACTION_CATEGORY_MEASURE_REQUEST = 0,
+       WLAN_ACTION_CATEGORY_MEASURE_REPORT = 1,
+       WLAN_ACTION_CATEGORY_TPC_REQUEST = 2,
+       WLAN_ACTION_CATEGORY_TPC_REPORT = 3,
+       WLAN_ACTION_CATEGORY_CHANNEL_SWITCH = 4,
+       /* 5 - 255 Reserved */
+};
+
 #define IEEE80211_STATMASK_SIGNAL (1<<0)
 #define IEEE80211_STATMASK_RSSI (1<<1)
 #define IEEE80211_STATMASK_NOISE (1<<2)
@@ -377,6 +395,8 @@ struct ieee80211_rx_stats {
        u8 mask;
        u8 freq;
        u16 len;
+       u64 tsf;
+       u32 beacon_time;
 };
 
 /* IEEE 802.11 requires that STA supports concurrent reception of at least
@@ -608,6 +628,28 @@ struct ieee80211_auth {
        struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
+struct ieee80211_channel_switch {
+       u8 id;
+       u8 len;
+       u8 mode;
+       u8 channel;
+       u8 count;
+} __attribute__ ((packed));
+
+struct ieee80211_action {
+       struct ieee80211_hdr_3addr header;
+       u8 category;
+       u8 action;
+       union {
+               struct ieee80211_action_exchange {
+                       u8 token;
+                       struct ieee80211_info_element info_element[0];
+               } exchange;
+               struct ieee80211_channel_switch channel_switch;
+
+       } format;
+} __attribute__ ((packed));
+
 struct ieee80211_disassoc {
        struct ieee80211_hdr_3addr header;
        __le16 reason;
@@ -692,7 +734,15 @@ struct ieee80211_txb {
 /* QoS structure */
 #define NETWORK_HAS_QOS_PARAMETERS      (1<<3)
 #define NETWORK_HAS_QOS_INFORMATION     (1<<4)
-#define NETWORK_HAS_QOS_MASK            (NETWORK_HAS_QOS_PARAMETERS | NETWORK_HAS_QOS_INFORMATION)
+#define NETWORK_HAS_QOS_MASK            (NETWORK_HAS_QOS_PARAMETERS | \
+                                        NETWORK_HAS_QOS_INFORMATION)
+
+/* 802.11h */
+#define NETWORK_HAS_POWER_CONSTRAINT    (1<<5)
+#define NETWORK_HAS_CSA                 (1<<6)
+#define NETWORK_HAS_QUIET               (1<<7)
+#define NETWORK_HAS_IBSS_DFS            (1<<8)
+#define NETWORK_HAS_TPC_REPORT          (1<<9)
 
 #define QOS_QUEUE_NUM                   4
 #define QOS_OUI_LEN                     3
@@ -748,6 +798,91 @@ struct ieee80211_tim_parameters {
 
 /*******************************************************/
 
+enum {                         /* ieee80211_basic_report.map */
+       IEEE80211_BASIC_MAP_BSS = (1 << 0),
+       IEEE80211_BASIC_MAP_OFDM = (1 << 1),
+       IEEE80211_BASIC_MAP_UNIDENTIFIED = (1 << 2),
+       IEEE80211_BASIC_MAP_RADAR = (1 << 3),
+       IEEE80211_BASIC_MAP_UNMEASURED = (1 << 4),
+       /* Bits 5-7 are reserved */
+
+};
+struct ieee80211_basic_report {
+       u8 channel;
+       __le64 start_time;
+       __le16 duration;
+       u8 map;
+} __attribute__ ((packed));
+
+enum {                         /* ieee80211_measurement_request.mode */
+       /* Bit 0 is reserved */
+       IEEE80211_MEASUREMENT_ENABLE = (1 << 1),
+       IEEE80211_MEASUREMENT_REQUEST = (1 << 2),
+       IEEE80211_MEASUREMENT_REPORT = (1 << 3),
+       /* Bits 4-7 are reserved */
+};
+
+enum {
+       IEEE80211_REPORT_BASIC = 0,     /* required */
+       IEEE80211_REPORT_CCA = 1,       /* optional */
+       IEEE80211_REPORT_RPI = 2,       /* optional */
+       /* 3-255 reserved */
+};
+
+struct ieee80211_measurement_params {
+       u8 channel;
+       __le64 start_time;
+       __le16 duration;
+} __attribute__ ((packed));
+
+struct ieee80211_measurement_request {
+       struct ieee80211_info_element ie;
+       u8 token;
+       u8 mode;
+       u8 type;
+       struct ieee80211_measurement_params params[0];
+} __attribute__ ((packed));
+
+struct ieee80211_measurement_report {
+       struct ieee80211_info_element ie;
+       u8 token;
+       u8 mode;
+       u8 type;
+       union {
+               struct ieee80211_basic_report basic[0];
+       } u;
+} __attribute__ ((packed));
+
+struct ieee80211_tpc_report {
+       u8 transmit_power;
+       u8 link_margin;
+} __attribute__ ((packed));
+
+struct ieee80211_channel_map {
+       u8 channel;
+       u8 map;
+} __attribute__ ((packed));
+
+struct ieee80211_ibss_dfs {
+       struct ieee80211_info_element ie;
+       u8 owner[ETH_ALEN];
+       u8 recovery_interval;
+       struct ieee80211_channel_map channel_map[0];
+};
+
+struct ieee80211_csa {
+       u8 mode;
+       u8 channel;
+       u8 count;
+} __attribute__ ((packed));
+
+struct ieee80211_quiet {
+       u8 count;
+       u8 period;
+       u8 duration;
+       u8 offset;
+} __attribute__ ((packed));
+
 struct ieee80211_network {
        /* These entries are used to identify a unique network */
        u8 bssid[ETH_ALEN];
@@ -767,7 +902,7 @@ struct ieee80211_network {
        u8 rates_ex_len;
        unsigned long last_scanned;
        u8 mode;
-       u8 flags;
+       u32 flags;
        u32 last_associate;
        u32 time_stamp[2];
        u16 beacon_interval;
@@ -779,6 +914,25 @@ struct ieee80211_network {
        u8 rsn_ie[MAX_WPA_IE_LEN];
        size_t rsn_ie_len;
        struct ieee80211_tim_parameters tim;
+
+       /* 802.11h info */
+
+       /* Power Constraint - mandatory if spctrm mgmt required */
+       u8 power_constraint;
+
+       /* TPC Report - mandatory if spctrm mgmt required */
+       struct ieee80211_tpc_report tpc_report;
+
+       /* IBSS DFS - mandatory if spctrm mgmt required and IBSS
+        * NOTE: This is variable length and so must be allocated dynamically */
+       struct ieee80211_ibss_dfs *ibss_dfs;
+
+       /* Channel Switch Announcement - optional if spctrm mgmt required */
+       struct ieee80211_csa csa;
+
+       /* Quiet - optional if spctrm mgmt required */
+       struct ieee80211_quiet quiet;
+
        struct list_head list;
 };
 
@@ -924,7 +1078,10 @@ struct ieee80211_device {
        int (*handle_auth) (struct net_device * dev,
                            struct ieee80211_auth * auth);
        int (*handle_deauth) (struct net_device * dev,
-                             struct ieee80211_auth * auth);
+                             struct ieee80211_deauth * auth);
+       int (*handle_action) (struct net_device * dev,
+                             struct ieee80211_action * action,
+                             struct ieee80211_rx_stats * stats);
        int (*handle_disassoc) (struct net_device * dev,
                                struct ieee80211_disassoc * assoc);
        int (*handle_beacon) (struct net_device * dev,
@@ -1093,6 +1250,7 @@ extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
                             struct ieee80211_hdr_4addr *header,
                             struct ieee80211_rx_stats *stats);
+extern void ieee80211_network_reset(struct ieee80211_network *network);
 
 /* ieee80211_geo.c */
 extern const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device
@@ -1105,6 +1263,11 @@ extern int ieee80211_is_valid_channel(struct ieee80211_device *ieee,
 extern int ieee80211_channel_to_index(struct ieee80211_device *ieee,
                                      u8 channel);
 extern u8 ieee80211_freq_to_channel(struct ieee80211_device *ieee, u32 freq);
+extern u8 ieee80211_get_channel_flags(struct ieee80211_device *ieee,
+                                     u8 channel);
+extern const struct ieee80211_channel *ieee80211_get_channel(struct
+                                                            ieee80211_device
+                                                            *ieee, u8 channel);
 
 /* ieee80211_wx.c */
 extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
@@ -1122,6 +1285,14 @@ extern int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
 extern int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
                                      struct iw_request_info *info,
                                      union iwreq_data *wrqu, char *extra);
+extern int ieee80211_wx_set_auth(struct net_device *dev,
+                                struct iw_request_info *info,
+                                union iwreq_data *wrqu,
+                                char *extra);
+extern int ieee80211_wx_get_auth(struct net_device *dev,
+                                struct iw_request_info *info,
+                                union iwreq_data *wrqu,
+                                char *extra);
 
 static inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
 {
index cd82c3e..eb47641 100644 (file)
@@ -47,7 +47,8 @@ struct ieee80211_crypto_ops {
        /* deinitialize crypto context and free allocated private data */
        void (*deinit) (void *priv);
 
-       int (*build_iv) (struct sk_buff * skb, int hdr_len, void *priv);
+       int (*build_iv) (struct sk_buff * skb, int hdr_len,
+                        u8 *key, int keylen, void *priv);
 
        /* encrypt/decrypt return < 0 on error or >= 0 on success. The return
         * value from decrypt_mpdu is passed as the keyidx value for
index 3075803..f63d0d5 100644 (file)
@@ -478,9 +478,9 @@ static inline void sk_add_backlog(struct sock *sk, struct sk_buff *skb)
        rc = __condition;                                       \
        if (!rc) {                                              \
                *(__timeo) = schedule_timeout(*(__timeo));      \
-               rc = __condition;                               \
        }                                                       \
        lock_sock(__sk);                                        \
+       rc = __condition;                                       \
        rc;                                                     \
 })
 
index 531aadc..d1e8d50 100644 (file)
@@ -807,8 +807,6 @@ fastcall NORET_TYPE void do_exit(long code)
                panic("Attempted to kill the idle task!");
        if (unlikely(tsk->pid == 1))
                panic("Attempted to kill init!");
-       if (tsk->io_context)
-               exit_io_context();
 
        if (unlikely(current->ptrace & PT_TRACE_EXIT)) {
                current->ptrace_message = code;
@@ -822,6 +820,8 @@ fastcall NORET_TYPE void do_exit(long code)
        if (unlikely(tsk->flags & PF_EXITING)) {
                printk(KERN_ALERT
                        "Fixing recursive fault but reboot is needed!\n");
+               if (tsk->io_context)
+                       exit_io_context();
                set_current_state(TASK_UNINTERRUPTIBLE);
                schedule();
        }
@@ -881,6 +881,9 @@ fastcall NORET_TYPE void do_exit(long code)
         */
        mutex_debug_check_no_locks_held(tsk);
 
+       if (tsk->io_context)
+               exit_io_context();
+
        /* PF_DEAD causes final put_task_struct after we schedule. */
        preempt_disable();
        BUG_ON(tsk->flags & PF_DEAD);
index ccdfbb1..b373322 100644 (file)
@@ -1478,9 +1478,7 @@ static int unshare_vm(unsigned long unshare_flags, struct mm_struct **new_mmp)
 
        if ((unshare_flags & CLONE_VM) &&
            (mm && atomic_read(&mm->mm_users) > 1)) {
-               *new_mmp = dup_mm(current);
-               if (!*new_mmp)
-                       return -ENOMEM;
+               return -EINVAL;
        }
 
        return 0;
@@ -1569,7 +1567,7 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
 
                if (new_sigh) {
                        sigh = current->sighand;
-                       current->sighand = new_sigh;
+                       rcu_assign_pointer(current->sighand, new_sigh);
                        new_sigh = sigh;
                }
 
index 216f574..fa895fc 100644 (file)
@@ -353,6 +353,7 @@ static int posix_timer_fn(void *data)
                                hrtimer_forward(&timr->it.real.timer,
                                                timr->it.real.interval);
                        ret = HRTIMER_RESTART;
+                       ++timr->it_requeue_pending;
                }
        }
 
index bf7c419..2410c18 100644 (file)
@@ -1354,8 +1354,8 @@ void __init init_timers(void)
 
 #ifdef CONFIG_TIME_INTERPOLATION
 
-struct time_interpolator *time_interpolator;
-static struct time_interpolator *time_interpolator_list;
+struct time_interpolator *time_interpolator __read_mostly;
+static struct time_interpolator *time_interpolator_list __read_mostly;
 static DEFINE_SPINLOCK(time_interpolator_lock);
 
 static inline u64 time_interpolator_get_cycles(unsigned int src)
index 9abc600..85e80a5 100644 (file)
@@ -623,11 +623,12 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
                        (*zap_work)--;
                        continue;
                }
+
+               (*zap_work) -= PAGE_SIZE;
+
                if (pte_present(ptent)) {
                        struct page *page;
 
-                       (*zap_work) -= PAGE_SIZE;
-
                        page = vm_normal_page(vma, addr, ptent);
                        if (unlikely(details) && page) {
                                /*
index 954981b..b21869a 100644 (file)
@@ -330,9 +330,19 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end,
        int err;
        struct vm_area_struct *first, *vma, *prev;
 
-       /* Clear the LRU lists so pages can be isolated */
-       if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL))
+       if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) {
+               /* Must have swap device for migration */
+               if (nr_swap_pages <= 0)
+                       return ERR_PTR(-ENODEV);
+
+               /*
+                * Clear the LRU lists so pages can be isolated.
+                * Note that pages may be moved off the LRU after we have
+                * drained them. Those pages will fail to migrate like other
+                * pages that may be busy.
+                */
                lru_add_drain_all();
+       }
 
        first = find_vma(mm, start);
        if (!first)
@@ -748,7 +758,7 @@ long do_mbind(unsigned long start, unsigned long len,
                                      MPOL_MF_MOVE | MPOL_MF_MOVE_ALL))
            || mode > MPOL_MAX)
                return -EINVAL;
-       if ((flags & MPOL_MF_MOVE_ALL) && !capable(CAP_SYS_RESOURCE))
+       if ((flags & MPOL_MF_MOVE_ALL) && !capable(CAP_SYS_NICE))
                return -EPERM;
 
        if (start & ~PAGE_MASK)
@@ -942,20 +952,20 @@ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,
         */
        if ((current->euid != task->suid) && (current->euid != task->uid) &&
            (current->uid != task->suid) && (current->uid != task->uid) &&
-           !capable(CAP_SYS_ADMIN)) {
+           !capable(CAP_SYS_NICE)) {
                err = -EPERM;
                goto out;
        }
 
        task_nodes = cpuset_mems_allowed(task);
        /* Is the user allowed to access the target nodes? */
-       if (!nodes_subset(new, task_nodes) && !capable(CAP_SYS_ADMIN)) {
+       if (!nodes_subset(new, task_nodes) && !capable(CAP_SYS_NICE)) {
                err = -EPERM;
                goto out;
        }
 
        err = do_migrate_pages(mm, &old, &new,
-               capable(CAP_SYS_ADMIN) ? MPOL_MF_MOVE_ALL : MPOL_MF_MOVE);
+               capable(CAP_SYS_NICE) ? MPOL_MF_MOVE_ALL : MPOL_MF_MOVE);
 out:
        mmput(mm);
        return err;
index e9ec06d..b524ea9 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -393,7 +393,8 @@ void pagevec_strip(struct pagevec *pvec)
                struct page *page = pvec->pages[i];
 
                if (PagePrivate(page) && !TestSetPageLocked(page)) {
-                       try_to_release_page(page, 0);
+                       if (PagePrivate(page))
+                               try_to_release_page(page, 0);
                        unlock_page(page);
                }
        }
index 7ccf763..4fe7e3a 100644 (file)
@@ -700,7 +700,7 @@ int migrate_page_remove_references(struct page *newpage,
         * the page.
         */
        if (!mapping || page_mapcount(page) + nr_refs != page_count(page))
-               return 1;
+               return -EAGAIN;
 
        /*
         * Establish swap ptes for anonymous pages or destroy pte
@@ -721,13 +721,15 @@ int migrate_page_remove_references(struct page *newpage,
         * If the page was not migrated then the PageSwapCache bit
         * is still set and the operation may continue.
         */
-       try_to_unmap(page, 1);
+       if (try_to_unmap(page, 1) == SWAP_FAIL)
+               /* A vma has VM_LOCKED set -> Permanent failure */
+               return -EPERM;
 
        /*
         * Give up if we were unable to remove all mappings.
         */
        if (page_mapcount(page))
-               return 1;
+               return -EAGAIN;
 
        write_lock_irq(&mapping->tree_lock);
 
@@ -738,7 +740,7 @@ int migrate_page_remove_references(struct page *newpage,
        if (!page_mapping(page) || page_count(page) != nr_refs ||
                        *radix_pointer != page) {
                write_unlock_irq(&mapping->tree_lock);
-               return 1;
+               return -EAGAIN;
        }
 
        /*
@@ -813,10 +815,14 @@ EXPORT_SYMBOL(migrate_page_copy);
  */
 int migrate_page(struct page *newpage, struct page *page)
 {
+       int rc;
+
        BUG_ON(PageWriteback(page));    /* Writeback must be complete */
 
-       if (migrate_page_remove_references(newpage, page, 2))
-               return -EAGAIN;
+       rc = migrate_page_remove_references(newpage, page, 2);
+
+       if (rc)
+               return rc;
 
        migrate_page_copy(newpage, page);
 
index 5126f58..4193cdc 100644 (file)
@@ -224,6 +224,9 @@ source "net/irda/Kconfig"
 source "net/bluetooth/Kconfig"
 source "net/ieee80211/Kconfig"
 
+config WIRELESS_EXT
+       bool
+
 endif   # if NET
 endmenu # Networking
 
index f67711f..894a225 100644 (file)
@@ -24,7 +24,7 @@ static int min_t3[1],                 max_t3[] = {3600 * HZ};
 static int min_idle[1],                max_idle[] = {65535 * HZ};
 static int min_n2[] = {1},             max_n2[] = {31};
 static int min_paclen[] = {1},         max_paclen[] = {512};
-static int min_proto[1],               max_proto[] = {3};
+static int min_proto[1],               max_proto[] = { AX25_PROTO_MAX };
 static int min_ds_timeout[1],          max_ds_timeout[] = {65535 * HZ};
 
 static struct ctl_table_header *ax25_table_header;
index 630da0f..79fe12c 100644 (file)
@@ -14,5 +14,5 @@ obj-$(CONFIG_XFRM) += flow.o
 obj-$(CONFIG_SYSFS) += net-sysfs.o
 obj-$(CONFIG_NET_DIVERT) += dv.o
 obj-$(CONFIG_NET_PKTGEN) += pktgen.o
-obj-$(CONFIG_NET_RADIO) += wireless.o
+obj-$(CONFIG_WIRELESS_EXT) += wireless.o
 obj-$(CONFIG_NETPOLL) += netpoll.o
index 2afb0de..ef56c03 100644 (file)
 #include <linux/netpoll.h>
 #include <linux/rcupdate.h>
 #include <linux/delay.h>
-#ifdef CONFIG_NET_RADIO
-#include <linux/wireless.h>            /* Note : will define WIRELESS_EXT */
+#include <linux/wireless.h>
 #include <net/iw_handler.h>
-#endif /* CONFIG_NET_RADIO */
 #include <asm/current.h>
 
 /*
@@ -1448,8 +1446,29 @@ static inline struct net_device *skb_bond(struct sk_buff *skb)
 {
        struct net_device *dev = skb->dev;
 
-       if (dev->master)
+       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;
+               
+                       kfree_skb(skb);
+                       return NULL;
+               }
+keep:
                skb->dev = dev->master;
+       }
 
        return dev;
 }
@@ -1593,6 +1612,9 @@ int netif_receive_skb(struct sk_buff *skb)
 
        orig_dev = skb_bond(skb);
 
+       if (!orig_dev)
+               return NET_RX_DROP;
+
        __get_cpu_var(netdev_rx_stat).total++;
 
        skb->h.raw = skb->nh.raw = skb->data;
@@ -2028,7 +2050,7 @@ static struct file_operations softnet_seq_fops = {
        .release = seq_release,
 };
 
-#ifdef WIRELESS_EXT
+#ifdef CONFIG_WIRELESS_EXT
 extern int wireless_proc_init(void);
 #else
 #define wireless_proc_init() 0
@@ -2582,7 +2604,7 @@ int dev_ioctl(unsigned int cmd, void __user *arg)
                                        ret = -EFAULT;
                                return ret;
                        }
-#ifdef WIRELESS_EXT
+#ifdef CONFIG_WIRELESS_EXT
                        /* Take care of Wireless Extensions */
                        if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
                                /* If command is `set a parameter', or
@@ -2603,7 +2625,7 @@ int dev_ioctl(unsigned int cmd, void __user *arg)
                                        ret = -EFAULT;
                                return ret;
                        }
-#endif /* WIRELESS_EXT */
+#endif /* CONFIG_WIRELESS_EXT */
                        return -EINVAL;
        }
 }
index ecc9bb1..cb71d79 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/string.h>
 #include <net/ieee80211.h>
 
-
 MODULE_AUTHOR("Jouni Malinen");
 MODULE_DESCRIPTION("HostAP crypto");
 MODULE_LICENSE("GPL");
@@ -33,11 +32,11 @@ static DEFINE_SPINLOCK(ieee80211_crypto_lock);
 
 void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
 {
-       struct ieee80211_crypt_data *entry, *next;
+       struct ieee80211_crypt_data *entry, *next;
        unsigned long flags;
 
        spin_lock_irqsave(&ieee->lock, flags);
-       list_for_each_entry_safe(entry, next, &ieee->crypt_deinit_list, list) {
+       list_for_each_entry_safe(entry, next, &ieee->crypt_deinit_list, list) {
                if (atomic_read(&entry->refcnt) != 0 && !force)
                        continue;
 
@@ -141,9 +140,9 @@ int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
        spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
        return -EINVAL;
 
- found:
     found:
        printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
-                         "'%s'\n", ops->name);
+              "'%s'\n", ops->name);
        list_del(&alg->list);
        spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
        kfree(alg);
@@ -163,7 +162,7 @@ struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name)
        spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
        return NULL;
 
- found:
     found:
        spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
        return alg->ops;
 }
index 4702217..78b2d13 100644 (file)
@@ -131,7 +131,7 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
        a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
                       (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS));
        qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
-                      (WLAN_FC_GET_STYPE(fc) & 0x08));
+                      (WLAN_FC_GET_STYPE(fc) & IEEE80211_STYPE_QOS_DATA));
        aad_len = 22;
        if (a4_included)
                aad_len += 6;
@@ -190,7 +190,8 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
        ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
 }
 
-static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv)
+static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len,
+                             u8 *aeskey, int keylen, void *priv)
 {
        struct ieee80211_ccmp_data *key = priv;
        int i;
@@ -199,6 +200,9 @@ static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv)
        if (skb_headroom(skb) < CCMP_HDR_LEN || skb->len < hdr_len)
                return -1;
 
+       if (aeskey != NULL && keylen >= CCMP_TK_LEN)
+               memcpy(aeskey, key->key, CCMP_TK_LEN);
+
        pos = skb_push(skb, CCMP_HDR_LEN);
        memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
        pos += hdr_len;
@@ -238,7 +242,7 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
                return -1;
 
        data_len = skb->len - hdr_len;
-       len = ieee80211_ccmp_hdr(skb, hdr_len, priv);
+       len = ieee80211_ccmp_hdr(skb, hdr_len, NULL, 0, priv);
        if (len < 0)
                return -1;
 
index e098832..93def94 100644 (file)
@@ -80,10 +80,9 @@ static void *ieee80211_tkip_init(int key_idx)
 {
        struct ieee80211_tkip_data *priv;
 
-       priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
+       priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
        if (priv == NULL)
                goto fail;
-       memset(priv, 0, sizeof(*priv));
 
        priv->key_idx = key_idx;
 
@@ -271,34 +270,33 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
 #endif
 }
 
-static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv)
+static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
+                             u8 * rc4key, int keylen, void *priv)
 {
        struct ieee80211_tkip_data *tkey = priv;
        int len;
-       u8 *rc4key, *pos, *icv;
+       u8 *pos;
        struct ieee80211_hdr_4addr *hdr;
-       u32 crc;
 
        hdr = (struct ieee80211_hdr_4addr *)skb->data;
 
        if (skb_headroom(skb) < 8 || skb->len < hdr_len)
-               return NULL;
+               return -1;
+
+       if (rc4key == NULL || keylen < 16)
+               return -1;
 
        if (!tkey->tx_phase1_done) {
                tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
                                   tkey->tx_iv32);
                tkey->tx_phase1_done = 1;
        }
-       rc4key = kmalloc(16, GFP_ATOMIC);
-       if (!rc4key)
-               return NULL;
        tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
 
        len = skb->len - hdr_len;
        pos = skb_push(skb, 8);
        memmove(pos, pos + 8, hdr_len);
        pos += hdr_len;
-       icv = skb_put(skb, 4);
 
        *pos++ = *rc4key;
        *pos++ = *(rc4key + 1);
@@ -309,28 +307,28 @@ static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv)
        *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
        *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
 
-       crc = ~crc32_le(~0, pos, len);
-       icv[0] = crc;
-       icv[1] = crc >> 8;
-       icv[2] = crc >> 16;
-       icv[3] = crc >> 24;
+       tkey->tx_iv16++;
+       if (tkey->tx_iv16 == 0) {
+               tkey->tx_phase1_done = 0;
+               tkey->tx_iv32++;
+       }
 
-       return rc4key;
+       return 8;
 }
 
 static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
 {
        struct ieee80211_tkip_data *tkey = priv;
        int len;
-       const u8 *rc4key;
-       u8 *pos;
+       u8 rc4key[16], *pos, *icv;
+       u32 crc;
        struct scatterlist sg;
 
        if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
                if (net_ratelimit()) {
                        struct ieee80211_hdr_4addr *hdr =
                            (struct ieee80211_hdr_4addr *)skb->data;
-                       printk(KERN_DEBUG "TKIP countermeasures: dropped "
+                       printk(KERN_DEBUG "TKIP countermeasures: dropped "
                               "TX packet to " MAC_FMT "\n",
                               MAC_ARG(hdr->addr1));
                }
@@ -343,22 +341,23 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
        len = skb->len - hdr_len;
        pos = skb->data + hdr_len;
 
-       rc4key = ieee80211_tkip_hdr(skb, hdr_len, priv);
-       if (!rc4key)
+       if ((ieee80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0)
                return -1;
 
+       icv = skb_put(skb, 4);
+
+       crc = ~crc32_le(~0, pos, len);
+       icv[0] = crc;
+       icv[1] = crc >> 8;
+       icv[2] = crc >> 16;
+       icv[3] = crc >> 24;
+
        crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
        sg.page = virt_to_page(pos);
        sg.offset = offset_in_page(pos);
        sg.length = len + 4;
        crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4);
 
-       tkey->tx_iv16++;
-       if (tkey->tx_iv16 == 0) {
-               tkey->tx_phase1_done = 0;
-               tkey->tx_iv32++;
-       }
-
        return 0;
 }
 
@@ -379,7 +378,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 
        if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
                if (net_ratelimit()) {
-                       printk(KERN_DEBUG "TKIP countermeasures: dropped "
+                       printk(KERN_DEBUG "TKIP countermeasures: dropped "
                               "received packet from " MAC_FMT "\n",
                               MAC_ARG(hdr->addr2));
                }
@@ -695,6 +694,7 @@ static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
        .name = "TKIP",
        .init = ieee80211_tkip_init,
        .deinit = ieee80211_tkip_deinit,
+       .build_iv = ieee80211_tkip_hdr,
        .encrypt_mpdu = ieee80211_tkip_encrypt,
        .decrypt_mpdu = ieee80211_tkip_decrypt,
        .encrypt_msdu = ieee80211_michael_mic_add,
index f8dca31..649e581 100644 (file)
@@ -76,7 +76,8 @@ static void prism2_wep_deinit(void *priv)
 }
 
 /* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */
-static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len, void *priv)
+static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len,
+                              u8 *key, int keylen, void *priv)
 {
        struct prism2_wep_data *wep = priv;
        u32 klen, len;
@@ -131,7 +132,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
                return -1;
        
        /* add the IV to the frame */
-       if (prism2_wep_build_iv(skb, hdr_len, priv))
+       if (prism2_wep_build_iv(skb, hdr_len, NULL, 0, priv))
                return -1;
        
        /* Copy the IV into the first 3 bytes of the key */
index 610cc5c..192243a 100644 (file)
@@ -50,7 +50,8 @@ int ieee80211_is_valid_channel(struct ieee80211_device *ieee, u8 channel)
 
        /* Driver needs to initialize the geography map before using
         * these helper functions */
-       BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
+       if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
+               return 0;
 
        if (ieee->freq_band & IEEE80211_24GHZ_BAND)
                for (i = 0; i < ieee->geo.bg_channels; i++)
@@ -58,13 +59,15 @@ int ieee80211_is_valid_channel(struct ieee80211_device *ieee, u8 channel)
                         * this is a B only channel, we don't see it
                         * as valid. */
                        if ((ieee->geo.bg[i].channel == channel) &&
+                           !(ieee->geo.bg[i].flags & IEEE80211_CH_INVALID) &&
                            (!(ieee->mode & IEEE_G) ||
                             !(ieee->geo.bg[i].flags & IEEE80211_CH_B_ONLY)))
                                return IEEE80211_24GHZ_BAND;
 
        if (ieee->freq_band & IEEE80211_52GHZ_BAND)
                for (i = 0; i < ieee->geo.a_channels; i++)
-                       if (ieee->geo.a[i].channel == channel)
+                       if ((ieee->geo.a[i].channel == channel) &&
+                           !(ieee->geo.a[i].flags & IEEE80211_CH_INVALID))
                                return IEEE80211_52GHZ_BAND;
 
        return 0;
@@ -76,7 +79,8 @@ int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel)
 
        /* Driver needs to initialize the geography map before using
         * these helper functions */
-       BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
+       if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
+               return -1;
 
        if (ieee->freq_band & IEEE80211_24GHZ_BAND)
                for (i = 0; i < ieee->geo.bg_channels; i++)
@@ -97,7 +101,8 @@ u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq)
 
        /* Driver needs to initialize the geography map before using
         * these helper functions */
-       BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
+       if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
+               return 0;
 
        freq /= 100000;
 
@@ -133,6 +138,41 @@ const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device *ieee)
        return &ieee->geo;
 }
 
+u8 ieee80211_get_channel_flags(struct ieee80211_device * ieee, u8 channel)
+{
+       int index = ieee80211_channel_to_index(ieee, channel);
+
+       if (index == -1)
+               return IEEE80211_CH_INVALID;
+
+       if (channel <= IEEE80211_24GHZ_CHANNELS)
+               return ieee->geo.bg[index].flags;
+
+       return ieee->geo.a[index].flags;
+}
+
+static const struct ieee80211_channel bad_channel = {
+       .channel = 0,
+       .flags = IEEE80211_CH_INVALID,
+       .max_power = 0,
+};
+
+const struct ieee80211_channel *ieee80211_get_channel(struct ieee80211_device
+                                                     *ieee, u8 channel)
+{
+       int index = ieee80211_channel_to_index(ieee, channel);
+
+       if (index == -1)
+               return &bad_channel;
+
+       if (channel <= IEEE80211_24GHZ_CHANNELS)
+               return &ieee->geo.bg[index];
+
+       return &ieee->geo.a[index];
+}
+
+EXPORT_SYMBOL(ieee80211_get_channel);
+EXPORT_SYMBOL(ieee80211_get_channel_flags);
 EXPORT_SYMBOL(ieee80211_is_valid_channel);
 EXPORT_SYMBOL(ieee80211_freq_to_channel);
 EXPORT_SYMBOL(ieee80211_channel_to_index);
index 90d18b7..2cb84d8 100644 (file)
@@ -82,10 +82,28 @@ static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
        return 0;
 }
 
+void ieee80211_network_reset(struct ieee80211_network *network)
+{
+       if (!network)
+               return;
+
+       if (network->ibss_dfs) {
+               kfree(network->ibss_dfs);
+               network->ibss_dfs = NULL;
+       }
+}
+
 static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
 {
+       int i;
+
        if (!ieee->networks)
                return;
+
+       for (i = 0; i < MAX_NETWORK_COUNT; i++)
+               if (ieee->networks[i].ibss_dfs)
+                       kfree(ieee->networks[i].ibss_dfs);
+
        kfree(ieee->networks);
        ieee->networks = NULL;
 }
@@ -195,7 +213,7 @@ void free_ieee80211(struct net_device *dev)
 
 static int debug = 0;
 u32 ieee80211_debug_level = 0;
-struct proc_dir_entry *ieee80211_proc = NULL;
+static struct proc_dir_entry *ieee80211_proc = NULL;
 
 static int show_debug_level(char *page, char **start, off_t offset,
                            int count, int *eof, void *data)
index b410ab8..a7f2a64 100644 (file)
@@ -369,8 +369,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 
        /* Put this code here so that we avoid duplicating it in all
         * Rx paths. - Jean II */
+#ifdef CONFIG_WIRELESS_EXT
 #ifdef IW_WIRELESS_SPY         /* defined in iw_handler.h */
-#ifdef CONFIG_NET_RADIO
        /* If spy monitoring on */
        if (ieee->spy_data.spy_number > 0) {
                struct iw_quality wstats;
@@ -397,8 +397,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                /* Update spy records */
                wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
        }
-#endif                         /* CONFIG_NET_RADIO */
 #endif                         /* IW_WIRELESS_SPY */
+#endif                         /* CONFIG_WIRELESS_EXT */
 
 #ifdef NOT_YET
        hostap_update_rx_stats(local->ap, hdr, rx_stats);
@@ -574,7 +574,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
        /* skb: hdr + (possibly fragmented) plaintext payload */
        // PR: FIXME: hostap has additional conditions in the "if" below:
        // ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
-       if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) {
+       if ((frag != 0) || (fc & IEEE80211_FCTL_MOREFRAGS)) {
                int flen;
                struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr);
                IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
@@ -754,7 +754,14 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                memset(skb->cb, 0, sizeof(skb->cb));
                skb->dev = dev;
                skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
-               netif_rx(skb);
+               if (netif_rx(skb) == NET_RX_DROP) {
+                       /* netif_rx always succeeds, but it might drop
+                        * the packet.  If it drops the packet, we log that
+                        * in our stats. */
+                       IEEE80211_DEBUG_DROP
+                           ("RX: netif_rx dropped the packet\n");
+                       stats->rx_dropped++;
+               }
        }
 
       rx_exit:
@@ -930,6 +937,45 @@ static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
        return rc;
 }
 
+#ifdef CONFIG_IEEE80211_DEBUG
+#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x
+
+static const char *get_info_element_string(u16 id)
+{
+       switch (id) {
+               MFIE_STRING(SSID);
+               MFIE_STRING(RATES);
+               MFIE_STRING(FH_SET);
+               MFIE_STRING(DS_SET);
+               MFIE_STRING(CF_SET);
+               MFIE_STRING(TIM);
+               MFIE_STRING(IBSS_SET);
+               MFIE_STRING(COUNTRY);
+               MFIE_STRING(HOP_PARAMS);
+               MFIE_STRING(HOP_TABLE);
+               MFIE_STRING(REQUEST);
+               MFIE_STRING(CHALLENGE);
+               MFIE_STRING(POWER_CONSTRAINT);
+               MFIE_STRING(POWER_CAPABILITY);
+               MFIE_STRING(TPC_REQUEST);
+               MFIE_STRING(TPC_REPORT);
+               MFIE_STRING(SUPP_CHANNELS);
+               MFIE_STRING(CSA);
+               MFIE_STRING(MEASURE_REQUEST);
+               MFIE_STRING(MEASURE_REPORT);
+               MFIE_STRING(QUIET);
+               MFIE_STRING(IBSS_DFS);
+               MFIE_STRING(ERP_INFO);
+               MFIE_STRING(RSN);
+               MFIE_STRING(RATES_EX);
+               MFIE_STRING(GENERIC);
+               MFIE_STRING(QOS_PARAMETER);
+       default:
+               return "UNKNOWN";
+       }
+}
+#endif
+
 static int ieee80211_parse_info_param(struct ieee80211_info_element
                                      *info_element, u16 length,
                                      struct ieee80211_network *network)
@@ -1040,7 +1086,9 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
                        break;
 
                case MFIE_TYPE_TIM:
-                       IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: ignored\n");
+                       network->tim.tim_count = info_element->data[0];
+                       network->tim.tim_period = info_element->data[1];
+                       IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n");
                        break;
 
                case MFIE_TYPE_ERP_INFO:
@@ -1091,10 +1139,49 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
                        printk(KERN_ERR
                               "QoS Error need to parse QOS_PARAMETER IE\n");
                        break;
+                       /* 802.11h */
+               case MFIE_TYPE_POWER_CONSTRAINT:
+                       network->power_constraint = info_element->data[0];
+                       network->flags |= NETWORK_HAS_POWER_CONSTRAINT;
+                       break;
+
+               case MFIE_TYPE_CSA:
+                       network->power_constraint = info_element->data[0];
+                       network->flags |= NETWORK_HAS_CSA;
+                       break;
+
+               case MFIE_TYPE_QUIET:
+                       network->quiet.count = info_element->data[0];
+                       network->quiet.period = info_element->data[1];
+                       network->quiet.duration = info_element->data[2];
+                       network->quiet.offset = info_element->data[3];
+                       network->flags |= NETWORK_HAS_QUIET;
+                       break;
+
+               case MFIE_TYPE_IBSS_DFS:
+                       if (network->ibss_dfs)
+                               break;
+                       network->ibss_dfs =
+                           kmalloc(info_element->len, GFP_ATOMIC);
+                       if (!network->ibss_dfs)
+                               return 1;
+                       memcpy(network->ibss_dfs, info_element->data,
+                              info_element->len);
+                       network->flags |= NETWORK_HAS_IBSS_DFS;
+                       break;
+
+               case MFIE_TYPE_TPC_REPORT:
+                       network->tpc_report.transmit_power =
+                           info_element->data[0];
+                       network->tpc_report.link_margin = info_element->data[1];
+                       network->flags |= NETWORK_HAS_TPC_REPORT;
+                       break;
 
                default:
-                       IEEE80211_DEBUG_MGMT("unsupported IE %d\n",
-                                            info_element->id);
+                       IEEE80211_DEBUG_MGMT
+                           ("Unsupported info element: %s (%d)\n",
+                            get_info_element_string(info_element->id),
+                            info_element->id);
                        break;
                }
 
@@ -1110,7 +1197,9 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
 static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response
                                       *frame, struct ieee80211_rx_stats *stats)
 {
-       struct ieee80211_network network_resp;
+       struct ieee80211_network network_resp = {
+               .ibss_dfs = NULL,
+       };
        struct ieee80211_network *network = &network_resp;
        struct net_device *dev = ieee->dev;
 
@@ -1253,7 +1342,22 @@ static void update_network(struct ieee80211_network *dst,
        int qos_active;
        u8 old_param;
 
-       memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
+       ieee80211_network_reset(dst);
+       dst->ibss_dfs = src->ibss_dfs;
+
+       /* We only update the statistics if they were created by receiving
+        * the network information on the actual channel the network is on.
+        * 
+        * This keeps beacons received on neighbor channels from bringing
+        * down the signal level of an AP. */
+       if (dst->channel == src->stats.received_channel)
+               memcpy(&dst->stats, &src->stats,
+                      sizeof(struct ieee80211_rx_stats));
+       else
+               IEEE80211_DEBUG_SCAN("Network " MAC_FMT " info received "
+                       "off channel (%d vs. %d)\n", MAC_ARG(src->bssid),
+                       dst->channel, src->stats.received_channel);
+
        dst->capability = src->capability;
        memcpy(dst->rates, src->rates, src->rates_len);
        dst->rates_len = src->rates_len;
@@ -1269,6 +1373,7 @@ static void update_network(struct ieee80211_network *dst,
        dst->listen_interval = src->listen_interval;
        dst->atim_window = src->atim_window;
        dst->erp_value = src->erp_value;
+       dst->tim = src->tim;
 
        memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
        dst->wpa_ie_len = src->wpa_ie_len;
@@ -1313,7 +1418,9 @@ static void ieee80211_process_probe_response(struct ieee80211_device
                                                    *stats)
 {
        struct net_device *dev = ieee->dev;
-       struct ieee80211_network network;
+       struct ieee80211_network network = {
+               .ibss_dfs = NULL,
+       };
        struct ieee80211_network *target;
        struct ieee80211_network *oldest = NULL;
 #ifdef CONFIG_IEEE80211_DEBUG
@@ -1386,6 +1493,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
                                             escape_essid(target->ssid,
                                                          target->ssid_len),
                                             MAC_ARG(target->bssid));
+                       ieee80211_network_reset(target);
                } else {
                        /* Otherwise just pull from the free list */
                        target = list_entry(ieee->network_free_list.next,
@@ -1402,6 +1510,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
                                     "BEACON" : "PROBE RESPONSE");
 #endif
                memcpy(target, &network, sizeof(*target));
+               network.ibss_dfs = NULL;
                list_add_tail(&target->list, &ieee->network_list);
        } else {
                IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
@@ -1411,16 +1520,17 @@ static void ieee80211_process_probe_response(struct ieee80211_device
                                     is_beacon(beacon->header.frame_ctl) ?
                                     "BEACON" : "PROBE RESPONSE");
                update_network(target, &network);
+               network.ibss_dfs = NULL;
        }
 
        spin_unlock_irqrestore(&ieee->lock, flags);
 
        if (is_beacon(beacon->header.frame_ctl)) {
                if (ieee->handle_beacon != NULL)
-                       ieee->handle_beacon(dev, beacon, &network);
+                       ieee->handle_beacon(dev, beacon, target);
        } else {
                if (ieee->handle_probe_response != NULL)
-                       ieee->handle_probe_response(dev, beacon, &network);
+                       ieee->handle_probe_response(dev, beacon, target);
        }
 }
 
@@ -1495,10 +1605,43 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
                                              header);
                break;
 
+       case IEEE80211_STYPE_ACTION:
+               IEEE80211_DEBUG_MGMT("ACTION\n");
+               if (ieee->handle_action)
+                       ieee->handle_action(ieee->dev,
+                                           (struct ieee80211_action *)
+                                           header, stats);
+               break;
+
+       case IEEE80211_STYPE_REASSOC_REQ:
+               IEEE80211_DEBUG_MGMT("received reassoc (%d)\n",
+                                    WLAN_FC_GET_STYPE(le16_to_cpu
+                                                      (header->frame_ctl)));
+
+               IEEE80211_WARNING("%s: IEEE80211_REASSOC_REQ received\n",
+                                 ieee->dev->name);
+               if (ieee->handle_reassoc_request != NULL)
+                       ieee->handle_reassoc_request(ieee->dev,
+                                                   (struct ieee80211_reassoc_request *)
+                                                    header);
+               break;
+
+       case IEEE80211_STYPE_ASSOC_REQ:
+               IEEE80211_DEBUG_MGMT("received assoc (%d)\n",
+                                    WLAN_FC_GET_STYPE(le16_to_cpu
+                                                      (header->frame_ctl)));
+
+               IEEE80211_WARNING("%s: IEEE80211_ASSOC_REQ received\n",
+                                 ieee->dev->name);
+               if (ieee->handle_assoc_request != NULL)
+                       ieee->handle_assoc_request(ieee->dev);
+               break;
+
        case IEEE80211_STYPE_DEAUTH:
-               printk("DEAUTH from AP\n");
+               IEEE80211_DEBUG_MGMT("DEAUTH\n");
                if (ieee->handle_deauth != NULL)
-                       ieee->handle_deauth(ieee->dev, (struct ieee80211_auth *)
+                       ieee->handle_deauth(ieee->dev,
+                                           (struct ieee80211_deauth *)
                                            header);
                break;
        default:
index 8fdd943..8b4332f 100644 (file)
@@ -56,7 +56,18 @@ Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  Frame  |  fcs |
       `--------------------------------------------------|         |------'
 Total: 28 non-data bytes                                 `----.----'
                                                               |
-       .- 'Frame data' expands to <---------------------------'
+       .- 'Frame data' expands, if WEP enabled, to <----------'
+       |
+       V
+      ,-----------------------.
+Bytes |  4  |   0-2296  |  4  |
+      |-----|-----------|-----|
+Desc. | IV  | Encrypted | ICV |
+      |     | Packet    |     |
+      `-----|           |-----'
+            `-----.-----'
+                  |
+       .- 'Encrypted Packet' expands to
        |
        V
       ,---------------------------------------------------.
@@ -65,18 +76,7 @@ Bytes |  1   |  1   |    1    |    3     |  2   |  0-2304 |
 Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP      |
       | DSAP | SSAP |         |          |      | Packet  |
       | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8|      |         |
-      `-----------------------------------------|         |
-Total: 8 non-data bytes                         `----.----'
-                                                     |
-       .- 'IP Packet' expands, if WEP enabled, to <--'
-       |
-       V
-      ,-----------------------.
-Bytes |  4  |   0-2296  |  4  |
-      |-----|-----------|-----|
-Desc. | IV  | Encrypted | ICV |
-      |     | IP Packet |     |
-      `-----------------------'
+      `----------------------------------------------------
 Total: 8 non-data bytes
 
 802.3 Ethernet Data Frame
@@ -470,7 +470,9 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
                        atomic_inc(&crypt->refcnt);
                        if (crypt->ops->build_iv)
                                crypt->ops->build_iv(skb_frag, hdr_len,
-                                                    crypt->priv);
+                                     ieee->sec.keys[ieee->sec.active_key],
+                                     ieee->sec.key_sizes[ieee->sec.active_key],
+                                     crypt->priv);
                        atomic_dec(&crypt->refcnt);
                }
 
index f87c6b8..af7f9bb 100644 (file)
@@ -149,9 +149,7 @@ static char *ipw2100_translate_scan(struct ieee80211_device *ieee,
                iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID |
                    IW_QUAL_LEVEL_INVALID;
                iwe.u.qual.qual = 0;
-               iwe.u.qual.level = 0;
        } else {
-               iwe.u.qual.level = network->stats.rssi;
                if (ieee->perfect_rssi == ieee->worst_rssi)
                        iwe.u.qual.qual = 100;
                else
@@ -179,6 +177,13 @@ static char *ipw2100_translate_scan(struct ieee80211_device *ieee,
                iwe.u.qual.noise = network->stats.noise;
        }
 
+       if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL)) {
+               iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
+               iwe.u.qual.level = 0;
+       } else {
+               iwe.u.qual.level = network->stats.signal;
+       }
+
        start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
 
        iwe.cmd = IWEVCUSTOM;
@@ -188,33 +193,21 @@ static char *ipw2100_translate_scan(struct ieee80211_device *ieee,
        if (iwe.u.data.length)
                start = iwe_stream_add_point(start, stop, &iwe, custom);
 
+       memset(&iwe, 0, sizeof(iwe));
        if (network->wpa_ie_len) {
-               char buf[MAX_WPA_IE_LEN * 2 + 30];
-
-               u8 *p = buf;
-               p += sprintf(p, "wpa_ie=");
-               for (i = 0; i < network->wpa_ie_len; i++) {
-                       p += sprintf(p, "%02x", network->wpa_ie[i]);
-               }
-
-               memset(&iwe, 0, sizeof(iwe));
-               iwe.cmd = IWEVCUSTOM;
-               iwe.u.data.length = strlen(buf);
+               char buf[MAX_WPA_IE_LEN];
+               memcpy(buf, network->wpa_ie, network->wpa_ie_len);
+               iwe.cmd = IWEVGENIE;
+               iwe.u.data.length = network->wpa_ie_len;
                start = iwe_stream_add_point(start, stop, &iwe, buf);
        }
 
+       memset(&iwe, 0, sizeof(iwe));
        if (network->rsn_ie_len) {
-               char buf[MAX_WPA_IE_LEN * 2 + 30];
-
-               u8 *p = buf;
-               p += sprintf(p, "rsn_ie=");
-               for (i = 0; i < network->rsn_ie_len; i++) {
-                       p += sprintf(p, "%02x", network->rsn_ie[i]);
-               }
-
-               memset(&iwe, 0, sizeof(iwe));
-               iwe.cmd = IWEVCUSTOM;
-               iwe.u.data.length = strlen(buf);
+               char buf[MAX_WPA_IE_LEN];
+               memcpy(buf, network->rsn_ie, network->rsn_ie_len);
+               iwe.cmd = IWEVGENIE;
+               iwe.u.data.length = network->rsn_ie_len;
                start = iwe_stream_add_point(start, stop, &iwe, buf);
        }
 
@@ -229,6 +222,28 @@ static char *ipw2100_translate_scan(struct ieee80211_device *ieee,
        if (iwe.u.data.length)
                start = iwe_stream_add_point(start, stop, &iwe, custom);
 
+       /* Add spectrum management information */
+       iwe.cmd = -1;
+       p = custom;
+       p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Channel flags: ");
+
+       if (ieee80211_get_channel_flags(ieee, network->channel) &
+           IEEE80211_CH_INVALID) {
+               iwe.cmd = IWEVCUSTOM;
+               p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "INVALID ");
+       }
+
+       if (ieee80211_get_channel_flags(ieee, network->channel) &
+           IEEE80211_CH_RADAR_DETECT) {
+               iwe.cmd = IWEVCUSTOM;
+               p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "DFS ");
+       }
+
+       if (iwe.cmd == IWEVCUSTOM) {
+               iwe.u.data.length = p - custom;
+               start = iwe_stream_add_point(start, stop, &iwe, custom);
+       }
+
        return start;
 }
 
@@ -734,9 +749,98 @@ int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
        return 0;
 }
 
+int ieee80211_wx_set_auth(struct net_device *dev,
+                         struct iw_request_info *info,
+                         union iwreq_data *wrqu,
+                         char *extra)
+{
+       struct ieee80211_device *ieee = netdev_priv(dev);
+       unsigned long flags;
+       int err = 0;
+
+       spin_lock_irqsave(&ieee->lock, flags);
+       
+       switch (wrqu->param.flags & IW_AUTH_INDEX) {
+       case IW_AUTH_WPA_VERSION:
+       case IW_AUTH_CIPHER_PAIRWISE:
+       case IW_AUTH_CIPHER_GROUP:
+       case IW_AUTH_KEY_MGMT:
+               /*
+                * Host AP driver does not use these parameters and allows
+                * wpa_supplicant to control them internally.
+                */
+               break;
+       case IW_AUTH_TKIP_COUNTERMEASURES:
+               break;          /* FIXME */
+       case IW_AUTH_DROP_UNENCRYPTED:
+               ieee->drop_unencrypted = !!wrqu->param.value;
+               break;
+       case IW_AUTH_80211_AUTH_ALG:
+               break;          /* FIXME */
+       case IW_AUTH_WPA_ENABLED:
+               ieee->privacy_invoked = ieee->wpa_enabled = !!wrqu->param.value;
+               break;
+       case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+               ieee->ieee802_1x = !!wrqu->param.value;
+               break;
+       case IW_AUTH_PRIVACY_INVOKED:
+               ieee->privacy_invoked = !!wrqu->param.value;
+               break;
+       default:
+               err = -EOPNOTSUPP;
+               break;
+       }
+       spin_unlock_irqrestore(&ieee->lock, flags);
+       return err;
+}
+
+int ieee80211_wx_get_auth(struct net_device *dev,
+                         struct iw_request_info *info,
+                         union iwreq_data *wrqu,
+                         char *extra)
+{
+       struct ieee80211_device *ieee = netdev_priv(dev);
+       unsigned long flags;
+       int err = 0;
+
+       spin_lock_irqsave(&ieee->lock, flags);
+       
+       switch (wrqu->param.flags & IW_AUTH_INDEX) {
+       case IW_AUTH_WPA_VERSION:
+       case IW_AUTH_CIPHER_PAIRWISE:
+       case IW_AUTH_CIPHER_GROUP:
+       case IW_AUTH_KEY_MGMT:
+       case IW_AUTH_TKIP_COUNTERMEASURES:              /* FIXME */
+       case IW_AUTH_80211_AUTH_ALG:                    /* FIXME */
+               /*
+                * Host AP driver does not use these parameters and allows
+                * wpa_supplicant to control them internally.
+                */
+               err = -EOPNOTSUPP;
+               break;
+       case IW_AUTH_DROP_UNENCRYPTED:
+               wrqu->param.value = ieee->drop_unencrypted;
+               break;
+       case IW_AUTH_WPA_ENABLED:
+               wrqu->param.value = ieee->wpa_enabled;
+               break;
+       case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+               wrqu->param.value = ieee->ieee802_1x;
+               break;
+       default:
+               err = -EOPNOTSUPP;
+               break;
+       }
+       spin_unlock_irqrestore(&ieee->lock, flags);
+       return err;
+}
+
 EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
 EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
 
 EXPORT_SYMBOL(ieee80211_wx_get_scan);
 EXPORT_SYMBOL(ieee80211_wx_set_encode);
 EXPORT_SYMBOL(ieee80211_wx_get_encode);
+
+EXPORT_SYMBOL_GPL(ieee80211_wx_set_auth);
+EXPORT_SYMBOL_GPL(ieee80211_wx_get_auth);
index a00851f..7e1bdef 100644 (file)
 #include <linux/compat.h>
 #include <linux/kmod.h>
 #include <linux/audit.h>
-
-#ifdef CONFIG_NET_RADIO
-#include <linux/wireless.h>            /* Note : will define WIRELESS_EXT */
-#endif /* CONFIG_NET_RADIO */
+#include <linux/wireless.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -840,11 +837,11 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
        if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
                err = dev_ioctl(cmd, argp);
        } else
-#ifdef WIRELESS_EXT
+#ifdef CONFIG_WIRELESS_EXT
        if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
                err = dev_ioctl(cmd, argp);
        } else
-#endif /* WIRELESS_EXT */
+#endif /* CONFIG_WIRELESS_EXT */
        switch (cmd) {
                case FIOSETOWN:
                case SIOCSPGRP:
index f70ff13..b8b2a56 100644 (file)
@@ -508,12 +508,7 @@ buf_printf(struct buffer *buf, const char *fmt, ...)
        
        va_start(ap, fmt);
        len = vsnprintf(tmp, SZ, fmt, ap);
-       if (buf->size - buf->pos < len + 1) {
-               buf->size += 128;
-               buf->p = realloc(buf->p, buf->size);
-       }
-       strncpy(buf->p + buf->pos, tmp, len + 1);
-       buf->pos += len;
+       buf_write(buf, tmp, len);
        va_end(ap);
 }
 
@@ -521,7 +516,7 @@ void
 buf_write(struct buffer *buf, const char *s, int len)
 {
        if (buf->size - buf->pos < len) {
-               buf->size += len;
+               buf->size += len + SZ;
                buf->p = realloc(buf->p, buf->size);
        }
        strncpy(buf->p + buf->pos, s, len);