]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
authorDavid S. Miller <davem@davemloft.net>
Fri, 18 Jul 2008 09:39:39 +0000 (02:39 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 18 Jul 2008 09:39:39 +0000 (02:39 -0700)
Conflicts:

Documentation/powerpc/booting-without-of.txt
drivers/atm/Makefile
drivers/net/fs_enet/fs_enet-main.c
drivers/pci/pci-acpi.c
net/8021q/vlan.c
net/iucv/iucv.c

38 files changed:
1  2 
Documentation/feature-removal-schedule.txt
Documentation/powerpc/booting-without-of.txt
MAINTAINERS
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/cxgb3/common.h
drivers/net/cxgb3/cxgb3_ctl_defs.h
drivers/net/cxgb3/cxgb3_offload.c
drivers/net/fs_enet/fs_enet-main.c
drivers/net/ibm_newemac/core.c
drivers/net/macb.c
drivers/net/macvlan.c
drivers/net/myri10ge/myri10ge.c
drivers/net/ppp_generic.c
drivers/net/tun.c
drivers/net/ucc_geth.c
drivers/net/wireless/atmel.c
drivers/net/wireless/libertas/if_cs.c
drivers/net/wireless/libertas/if_usb.c
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00pci.h
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/zd1201.c
drivers/s390/net/qeth_l3_main.c
fs/compat_ioctl.c
include/linux/pci_ids.h
lib/textsearch.c
net/8021q/vlan.c
net/bridge/br_fdb.c
net/bridge/br_stp.c
net/core/dev.c
net/irda/irnet/irnet_ppp.c
net/iucv/af_iucv.c
net/iucv/iucv.c
net/netfilter/nf_conntrack_netlink.c
net/sunrpc/auth_gss/auth_gss.c

index db300e09c9ac5f98dde04c74f63e5eb2bead0b64,65a1482457a89ec9d6c5beec89464bc049f3f5e2..86334b6f8238409409debbcab2e89f60f4b080f1
@@@ -222,13 -222,6 +222,6 @@@ Who:      Thomas Gleixner <tglx@linutronix.d
  
  ---------------------------
  
- What: i2c-i810, i2c-prosavage and i2c-savage4
- When: May 2008
- Why:  These drivers are superseded by i810fb, intelfb and savagefb.
- Who:  Jean Delvare <khali@linux-fr.org>
- ---------------------------
  What (Why):
        - include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files
          (superseded by xt_TOS/xt_tos target & match)
@@@ -315,31 -308,9 +308,31 @@@ Who:     Matthew Wilcox <willy@linux.intel.
  
  ---------------------------
  
 +What: SCTP_GET_PEER_ADDRS_NUM_OLD, SCTP_GET_PEER_ADDRS_OLD,
 +      SCTP_GET_LOCAL_ADDRS_NUM_OLD, SCTP_GET_LOCAL_ADDRS_OLD
 +When:         June 2009
 +Why:    A newer version of the options have been introduced in 2005 that
 +      removes the limitions of the old API.  The sctp library has been
 +        converted to use these new options at the same time.  Any user
 +      space app that directly uses the old options should convert to using
 +      the new options.
 +Who:  Vlad Yasevich <vladislav.yasevich@hp.com>
 +
 +---------------------------
 +
  What: CONFIG_THERMAL_HWMON
  When: January 2009
  Why:  This option was introduced just to allow older lm-sensors userspace
        to keep working over the upgrade to 2.6.26. At the scheduled time of
        removal fixed lm-sensors (2.x or 3.x) should be readily available.
  Who:  Rene Herman <rene.herman@gmail.com>
 +
 +---------------------------
 +
 +What: Code that is now under CONFIG_WIRELESS_EXT_SYSFS
 +      (in net/core/net-sysfs.c)
 +When: After the only user (hal) has seen a release with the patches
 +      for enough time, probably some time in 2010.
 +Why:  Over 1K .text/.data size reduction, data is available in other
 +      ways (ioctls)
 +Who:  Johannes Berg <johannes@sipsolutions.net>
index 46a9dba11f2f003334f2ef44d275895b2477856f,de2e5c05d6e7ec70ada6cdff403d173d872ed36d..aee243a846a21f78ae7c68f64f0dc439c92ad83f
@@@ -41,24 -41,12 +41,24 @@@ Table of Content
    VI - System-on-a-chip devices and nodes
      1) Defining child nodes of an SOC
      2) Representing devices without a current OF specification
 -      a) PHY nodes
 -      b) Interrupt controllers
 -      c) CFI or JEDEC memory-mapped NOR flash
 -      d) 4xx/Axon EMAC ethernet nodes
 -      e) Xilinx IP cores
 -      f) USB EHCI controllers
 +      a) MDIO IO device
 +      b) Gianfar-compatible ethernet nodes
 +      c) PHY nodes
 +      d) Interrupt controllers
 +      e) I2C
 +      f) Freescale SOC USB controllers
 +      g) Freescale SOC SEC Security Engines
 +      h) Board Control and Status (BCSR)
 +      i) Freescale QUICC Engine module (QE)
 +      j) CFI or JEDEC memory-mapped NOR flash
 +      k) Global Utilities Block
 +      l) Freescale Communications Processor Module
 +      m) Chipselect/Local Bus
 +      n) 4xx/Axon EMAC ethernet nodes
 +      o) Xilinx IP cores
 +      p) Freescale Synchronous Serial Interface
 +        q) USB EHCI controllers
 +      r) MDIO on GPIOs
  
    VII - Marvell Discovery mv64[345]6x System Controller chips
      1) The /system-controller node
@@@ -1247,80 -1235,7 +1247,7 @@@ descriptions for the SOC devices for wh
  defined; this list will expand as more and more SOC-containing
  platforms are moved over to use the flattened-device-tree model.
  
-   a) MDIO IO device
-   The MDIO is a bus to which the PHY devices are connected.  For each
-   device that exists on this bus, a child node should be created.  See
-   the definition of the PHY node below for an example of how to define
-   a PHY.
-   Required properties:
-     - reg : Offset and length of the register set for the device
-     - compatible : Should define the compatible device type for the
-       mdio.  Currently, this is most likely to be "fsl,gianfar-mdio"
-   Example:
-       mdio@24520 {
-               reg = <24520 20>;
-               compatible = "fsl,gianfar-mdio";
-               ethernet-phy@0 {
-                       ......
-               };
-       };
-   b) Gianfar-compatible ethernet nodes
-   Required properties:
-     - device_type : Should be "network"
-     - model : Model of the device.  Can be "TSEC", "eTSEC", or "FEC"
-     - compatible : Should be "gianfar"
-     - reg : Offset and length of the register set for the device
-     - mac-address : List of bytes representing the ethernet address of
-       this controller
-     - interrupts : <a b> where a is the interrupt number and b is a
-       field that represents an encoding of the sense and level
-       information for the interrupt.  This should be encoded based on
-       the information in section 2) depending on the type of interrupt
-       controller you have.
-     - interrupt-parent : the phandle for the interrupt controller that
-       services interrupts for this device.
-     - phy-handle : The phandle for the PHY connected to this ethernet
-       controller.
-     - fixed-link : <a b c d e> where a is emulated phy id - choose any,
-       but unique to the all specified fixed-links, b is duplex - 0 half,
-       1 full, c is link speed - d#10/d#100/d#1000, d is pause - 0 no
-       pause, 1 pause, e is asym_pause - 0 no asym_pause, 1 asym_pause.
-   Recommended properties:
-     - phy-connection-type : a string naming the controller/PHY interface type,
-       i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id", "sgmii",
-       "tbi", or "rtbi".  This property is only really needed if the connection
-       is of type "rgmii-id", as all other connection types are detected by
-       hardware.
-   Example:
-       ethernet@24000 {
-               #size-cells = <0>;
-               device_type = "network";
-               model = "TSEC";
-               compatible = "gianfar";
-               reg = <24000 1000>;
-               mac-address = [ 00 E0 0C 00 73 00 ];
-               interrupts = <d 3 e 3 12 3>;
-               interrupt-parent = <40000>;
-               phy-handle = <2452000>
-       };
-    c) PHY nodes
+    a) PHY nodes
  
     Required properties:
  
        };
  
  
-    d) Interrupt controllers
+    b) Interrupt controllers
  
     Some SOC devices contain interrupt controllers that are different
     from the standard Open PIC specification.  The SOC device nodes for
  
        pic@40000 {
                linux,phandle = <40000>;
-               clock-frequency = <0>;
                interrupt-controller;
                #address-cells = <0>;
                reg = <40000 40000>;
-               built-in;
                compatible = "chrp,open-pic";
                device_type = "open-pic";
-               big-endian;
-       };
-    e) I2C
-    Required properties :
-     - device_type : Should be "i2c"
-     - reg : Offset and length of the register set for the device
-    Recommended properties :
-     - compatible : Should be "fsl-i2c" for parts compatible with
-       Freescale I2C specifications.
-     - interrupts : <a b> where a is the interrupt number and b is a
-       field that represents an encoding of the sense and level
-       information for the interrupt.  This should be encoded based on
-       the information in section 2) depending on the type of interrupt
-       controller you have.
-     - interrupt-parent : the phandle for the interrupt controller that
-       services interrupts for this device.
-     - dfsrr : boolean; if defined, indicates that this I2C device has
-       a digital filter sampling rate register
-     - fsl5200-clocking : boolean; if defined, indicated that this device
-       uses the FSL 5200 clocking mechanism.
-    Example :
-       i2c@3000 {
-               interrupt-parent = <40000>;
-               interrupts = <1b 3>;
-               reg = <3000 18>;
-               device_type = "i2c";
-               compatible  = "fsl-i2c";
-               dfsrr;
-       };
-    f) Freescale SOC USB controllers
-    The device node for a USB controller that is part of a Freescale
-    SOC is as described in the document "Open Firmware Recommended
-    Practice : Universal Serial Bus" with the following modifications
-    and additions :  
-    Required properties :
-     - compatible : Should be "fsl-usb2-mph" for multi port host USB
-       controllers, or "fsl-usb2-dr" for dual role USB controllers
-     - phy_type : For multi port host USB controllers, should be one of
-       "ulpi", or "serial". For dual role USB controllers, should be
-       one of "ulpi", "utmi", "utmi_wide", or "serial".
-     - reg : Offset and length of the register set for the device
-     - port0 : boolean; if defined, indicates port0 is connected for
-       fsl-usb2-mph compatible controllers.  Either this property or
-       "port1" (or both) must be defined for "fsl-usb2-mph" compatible 
-       controllers.
-     - port1 : boolean; if defined, indicates port1 is connected for
-       fsl-usb2-mph compatible controllers.  Either this property or
-       "port0" (or both) must be defined for "fsl-usb2-mph" compatible 
-       controllers.
-     - dr_mode : indicates the working mode for "fsl-usb2-dr" compatible
-       controllers.  Can be "host", "peripheral", or "otg".  Default to
-       "host" if not defined for backward compatibility.
-    Recommended properties :
-     - interrupts : <a b> where a is the interrupt number and b is a
-       field that represents an encoding of the sense and level
-       information for the interrupt.  This should be encoded based on
-       the information in section 2) depending on the type of interrupt
-       controller you have.
-     - interrupt-parent : the phandle for the interrupt controller that
-       services interrupts for this device.
-    Example multi port host USB controller device node :
-       usb@22000 {
-               compatible = "fsl-usb2-mph";
-               reg = <22000 1000>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-               interrupt-parent = <700>;
-               interrupts = <27 1>;
-               phy_type = "ulpi";
-               port0;
-               port1;
        };
  
-    Example dual role USB controller device node :
-       usb@23000 {
-               compatible = "fsl-usb2-dr";
-               reg = <23000 1000>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-               interrupt-parent = <700>;
-               interrupts = <26 1>;
-               dr_mode = "otg";
-               phy = "ulpi";
-       };
-    g) Freescale SOC SEC Security Engines
-    Required properties:
-     - device_type : Should be "crypto"
-     - model : Model of the device.  Should be "SEC1" or "SEC2"
-     - compatible : Should be "talitos"
-     - reg : Offset and length of the register set for the device
-     - interrupts : <a b> where a is the interrupt number and b is a
-       field that represents an encoding of the sense and level
-       information for the interrupt.  This should be encoded based on
-       the information in section 2) depending on the type of interrupt
-       controller you have.
-     - interrupt-parent : the phandle for the interrupt controller that
-       services interrupts for this device.
-     - num-channels : An integer representing the number of channels
-       available.
-     - channel-fifo-len : An integer representing the number of
-       descriptor pointers each channel fetch fifo can hold.
-     - exec-units-mask : The bitmask representing what execution units
-       (EUs) are available. It's a single 32-bit cell. EU information
-       should be encoded following the SEC's Descriptor Header Dword
-       EU_SEL0 field documentation, i.e. as follows:
-         bit 0 = reserved - should be 0
-         bit 1 = set if SEC has the ARC4 EU (AFEU)
-         bit 2 = set if SEC has the DES/3DES EU (DEU)
-         bit 3 = set if SEC has the message digest EU (MDEU)
-         bit 4 = set if SEC has the random number generator EU (RNG)
-         bit 5 = set if SEC has the public key EU (PKEU)
-         bit 6 = set if SEC has the AES EU (AESU)
-         bit 7 = set if SEC has the Kasumi EU (KEU)
-       bits 8 through 31 are reserved for future SEC EUs.
-     - descriptor-types-mask : The bitmask representing what descriptors
-       are available. It's a single 32-bit cell. Descriptor type
-       information should be encoded following the SEC's Descriptor
-       Header Dword DESC_TYPE field documentation, i.e. as follows:
-         bit 0  = set if SEC supports the aesu_ctr_nonsnoop desc. type
-         bit 1  = set if SEC supports the ipsec_esp descriptor type
-         bit 2  = set if SEC supports the common_nonsnoop desc. type
-         bit 3  = set if SEC supports the 802.11i AES ccmp desc. type
-         bit 4  = set if SEC supports the hmac_snoop_no_afeu desc. type
-         bit 5  = set if SEC supports the srtp descriptor type
-         bit 6  = set if SEC supports the non_hmac_snoop_no_afeu desc.type
-         bit 7  = set if SEC supports the pkeu_assemble descriptor type
-         bit 8  = set if SEC supports the aesu_key_expand_output desc.type
-         bit 9  = set if SEC supports the pkeu_ptmul descriptor type
-         bit 10 = set if SEC supports the common_nonsnoop_afeu desc. type
-         bit 11 = set if SEC supports the pkeu_ptadd_dbl descriptor type
-       ..and so on and so forth.
-    Example:
-        /* MPC8548E */
-        crypto@30000 {
-                device_type = "crypto";
-                model = "SEC2";
-                compatible = "talitos";
-                reg = <30000 10000>;
-                interrupts = <1d 3>;
-                interrupt-parent = <40000>;
-                num-channels = <4>;
-                channel-fifo-len = <18>;
-                exec-units-mask = <000000fe>;
-                descriptor-types-mask = <012b0ebf>;
-        };
-    h) Board Control and Status (BCSR)
-    Required properties:
-     - device_type : Should be "board-control"
-     - reg : Offset and length of the register set for the device
-     Example:
-       bcsr@f8000000 {
-               device_type = "board-control";
-               reg = <f8000000 8000>;
-       };
-    i) Freescale QUICC Engine module (QE)
-    This represents qe module that is installed on PowerQUICC II Pro.
-    NOTE:  This is an interim binding; it should be updated to fit
-    in with the CPM binding later in this document.
-    Basically, it is a bus of devices, that could act more or less
-    as a complete entity (UCC, USB etc ). All of them should be siblings on
-    the "root" qe node, using the common properties from there.
-    The description below applies to the qe of MPC8360 and
-    more nodes and properties would be extended in the future.
-    i) Root QE device
-    Required properties:
-    - compatible : should be "fsl,qe";
-    - model : precise model of the QE, Can be "QE", "CPM", or "CPM2"
-    - reg : offset and length of the device registers.
-    - bus-frequency : the clock frequency for QUICC Engine.
-    Recommended properties
-    - brg-frequency : the internal clock source frequency for baud-rate
-      generators in Hz.
-    Example:
-       qe@e0100000 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               #interrupt-cells = <2>;
-               compatible = "fsl,qe";
-               ranges = <0 e0100000 00100000>;
-               reg = <e0100000 480>;
-               brg-frequency = <0>;
-               bus-frequency = <179A7B00>;
-       }
-    ii) SPI (Serial Peripheral Interface)
-    Required properties:
-    - cell-index : SPI controller index.
-    - compatible : should be "fsl,spi".
-    - mode : the SPI operation mode, it can be "cpu" or "cpu-qe".
-    - reg : Offset and length of the register set for the device
-    - interrupts : <a b> where a is the interrupt number and b is a
-      field that represents an encoding of the sense and level
-      information for the interrupt.  This should be encoded based on
-      the information in section 2) depending on the type of interrupt
-      controller you have.
-    - interrupt-parent : the phandle for the interrupt controller that
-      services interrupts for this device.
-    Example:
-       spi@4c0 {
-               cell-index = <0>;
-               compatible = "fsl,spi";
-               reg = <4c0 40>;
-               interrupts = <82 0>;
-               interrupt-parent = <700>;
-               mode = "cpu";
-       };
-    iii) USB (Universal Serial Bus Controller)
-    Required properties:
-    - compatible : could be "qe_udc" or "fhci-hcd".
-    - mode : the could be "host" or "slave".
-    - reg : Offset and length of the register set for the device
-    - interrupts : <a b> where a is the interrupt number and b is a
-      field that represents an encoding of the sense and level
-      information for the interrupt.  This should be encoded based on
-      the information in section 2) depending on the type of interrupt
-      controller you have.
-    - interrupt-parent : the phandle for the interrupt controller that
-      services interrupts for this device.
-    Example(slave):
-       usb@6c0 {
-               compatible = "qe_udc";
-               reg = <6c0 40>;
-               interrupts = <8b 0>;
-               interrupt-parent = <700>;
-               mode = "slave";
-       };
-    iv) UCC (Unified Communications Controllers)
-    Required properties:
-    - device_type : should be "network", "hldc", "uart", "transparent"
-      "bisync", "atm", or "serial".
-    - compatible : could be "ucc_geth" or "fsl_atm" and so on.
-    - cell-index : the ucc number(1-8), corresponding to UCCx in UM.
-    - reg : Offset and length of the register set for the device
-    - interrupts : <a b> where a is the interrupt number and b is a
-      field that represents an encoding of the sense and level
-      information for the interrupt.  This should be encoded based on
-      the information in section 2) depending on the type of interrupt
-      controller you have.
-    - interrupt-parent : the phandle for the interrupt controller that
-      services interrupts for this device.
-    - pio-handle : The phandle for the Parallel I/O port configuration.
-    - port-number : for UART drivers, the port number to use, between 0 and 3.
-      This usually corresponds to the /dev/ttyQE device, e.g. <0> = /dev/ttyQE0.
-      The port number is added to the minor number of the device.  Unlike the
-      CPM UART driver, the port-number is required for the QE UART driver.
-    - soft-uart : for UART drivers, if specified this means the QE UART device
-      driver should use "Soft-UART" mode, which is needed on some SOCs that have
-      broken UART hardware.  Soft-UART is provided via a microcode upload.
-    - rx-clock-name: the UCC receive clock source
-      "none": clock source is disabled
-      "brg1" through "brg16": clock source is BRG1-BRG16, respectively
-      "clk1" through "clk24": clock source is CLK1-CLK24, respectively
-    - tx-clock-name: the UCC transmit clock source
-      "none": clock source is disabled
-      "brg1" through "brg16": clock source is BRG1-BRG16, respectively
-      "clk1" through "clk24": clock source is CLK1-CLK24, respectively
-    The following two properties are deprecated.  rx-clock has been replaced
-    with rx-clock-name, and tx-clock has been replaced with tx-clock-name.
-    Drivers that currently use the deprecated properties should continue to
-    do so, in order to support older device trees, but they should be updated
-    to check for the new properties first.
-    - rx-clock : represents the UCC receive clock source.
-      0x00 : clock source is disabled;
-      0x1~0x10 : clock source is BRG1~BRG16 respectively;
-      0x11~0x28: clock source is QE_CLK1~QE_CLK24 respectively.
-    - tx-clock: represents the UCC transmit clock source;
-      0x00 : clock source is disabled;
-      0x1~0x10 : clock source is BRG1~BRG16 respectively;
-      0x11~0x28: clock source is QE_CLK1~QE_CLK24 respectively.
-    Required properties for network device_type:
-    - mac-address : list of bytes representing the ethernet address.
-    - phy-handle : The phandle for the PHY connected to this controller.
-    Recommended properties:
-    - phy-connection-type : a string naming the controller/PHY interface type,
-      i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id" (Internal
-      Delay), "rgmii-txid" (delay on TX only), "rgmii-rxid" (delay on RX only),
-      "tbi", or "rtbi".
-    Example:
-       ucc@2000 {
-               device_type = "network";
-               compatible = "ucc_geth";
-               cell-index = <1>;
-               reg = <2000 200>;
-               interrupts = <a0 0>;
-               interrupt-parent = <700>;
-               mac-address = [ 00 04 9f 00 23 23 ];
-               rx-clock = "none";
-               tx-clock = "clk9";
-               phy-handle = <212000>;
-               phy-connection-type = "gmii";
-               pio-handle = <140001>;
-       };
-    v) Parallel I/O Ports
-    This node configures Parallel I/O ports for CPUs with QE support.
-    The node should reside in the "soc" node of the tree.  For each
-    device that using parallel I/O ports, a child node should be created.
-    See the definition of the Pin configuration nodes below for more
-    information.
-    Required properties:
-    - device_type : should be "par_io".
-    - reg : offset to the register set and its length.
-    - num-ports : number of Parallel I/O ports
-    Example:
-       par_io@1400 {
-               reg = <1400 100>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-               device_type = "par_io";
-               num-ports = <7>;
-               ucc_pin@01 {
-                       ......
-               };
-    vi) Pin configuration nodes
-    Required properties:
-    - linux,phandle : phandle of this node; likely referenced by a QE
-      device.
-    - pio-map : array of pin configurations.  Each pin is defined by 6
-      integers.  The six numbers are respectively: port, pin, dir,
-      open_drain, assignment, has_irq.
-      - port : port number of the pin; 0-6 represent port A-G in UM.
-      - pin : pin number in the port.
-      - dir : direction of the pin, should encode as follows:
-       0 = The pin is disabled
-       1 = The pin is an output
-       2 = The pin is an input
-       3 = The pin is I/O
-      - open_drain : indicates the pin is normal or wired-OR:
-       0 = The pin is actively driven as an output
-       1 = The pin is an open-drain driver. As an output, the pin is
-           driven active-low, otherwise it is three-stated.
-      - assignment : function number of the pin according to the Pin Assignment
-        tables in User Manual.  Each pin can have up to 4 possible functions in
-        QE and two options for CPM.
-      - has_irq : indicates if the pin is used as source of external
-        interrupts.
-    Example:
-       ucc_pin@01 {
-               linux,phandle = <140001>;
-               pio-map = <
-               /* port  pin  dir  open_drain  assignment  has_irq */
-                       0  3  1  0  1  0        /* TxD0 */
-                       0  4  1  0  1  0        /* TxD1 */
-                       0  5  1  0  1  0        /* TxD2 */
-                       0  6  1  0  1  0        /* TxD3 */
-                       1  6  1  0  3  0        /* TxD4 */
-                       1  7  1  0  1  0        /* TxD5 */
-                       1  9  1  0  2  0        /* TxD6 */
-                       1  a  1  0  2  0        /* TxD7 */
-                       0  9  2  0  1  0        /* RxD0 */
-                       0  a  2  0  1  0        /* RxD1 */
-                       0  b  2  0  1  0        /* RxD2 */
-                       0  c  2  0  1  0        /* RxD3 */
-                       0  d  2  0  1  0        /* RxD4 */
-                       1  1  2  0  2  0        /* RxD5 */
-                       1  0  2  0  2  0        /* RxD6 */
-                       1  4  2  0  2  0        /* RxD7 */
-                       0  7  1  0  1  0        /* TX_EN */
-                       0  8  1  0  1  0        /* TX_ER */
-                       0  f  2  0  1  0        /* RX_DV */
-                       0  10 2  0  1  0        /* RX_ER */
-                       0  0  2  0  1  0        /* RX_CLK */
-                       2  9  1  0  3  0        /* GTX_CLK - CLK10 */
-                       2  8  2  0  1  0>;      /* GTX125 - CLK9 */
-       };
-    vii) Multi-User RAM (MURAM)
-    Required properties:
-    - compatible : should be "fsl,qe-muram", "fsl,cpm-muram".
-    - mode : the could be "host" or "slave".
-    - ranges : Should be defined as specified in 1) to describe the
-       translation of MURAM addresses.
-    - data-only : sub-node which defines the address area under MURAM
-       bus that can be allocated as data/parameter
-    Example:
-       muram@10000 {
-               compatible = "fsl,qe-muram", "fsl,cpm-muram";
-               ranges = <0 00010000 0000c000>;
-               data-only@0{
-                       compatible = "fsl,qe-muram-data",
-                                    "fsl,cpm-muram-data";
-                       reg = <0 c000>;
-               };
-       };
-    viii) Uploaded QE firmware
-        If a new firwmare has been uploaded to the QE (usually by the
-        boot loader), then a 'firmware' child node should be added to the QE
-        node.  This node provides information on the uploaded firmware that
-        device drivers may need.
-        Required properties:
-        - id: The string name of the firmware.  This is taken from the 'id'
-              member of the qe_firmware structure of the uploaded firmware.
-              Device drivers can search this string to determine if the
-              firmware they want is already present.
-        - extended-modes: The Extended Modes bitfield, taken from the
-                          firmware binary.  It is a 64-bit number represented
-                          as an array of two 32-bit numbers.
-        - virtual-traps: The virtual traps, taken from the firmware binary.
-                         It is an array of 8 32-bit numbers.
-        Example:
-               firmware {
-                       id = "Soft-UART";
-                       extended-modes = <0 0>;
-                       virtual-traps = <0 0 0 0 0 0 0 0>;
-               }
-    j) CFI or JEDEC memory-mapped NOR flash
+    c) CFI or JEDEC memory-mapped NOR flash
  
      Flash chips (Memory Technology Devices) are often used for solid state
      file systems on embedded devices.
                };
        };
  
-    k) Global Utilities Block
-    The global utilities block controls power management, I/O device
-    enabling, power-on-reset configuration monitoring, general-purpose
-    I/O signal configuration, alternate function selection for multiplexed
-    signals, and clock control.
-    Required properties:
-     - compatible : Should define the compatible device type for
-       global-utilities.
-     - reg : Offset and length of the register set for the device.
-   Recommended properties:
-     - fsl,has-rstcr : Indicates that the global utilities register set
-       contains a functioning "reset control register" (i.e. the board
-       is wired to reset upon setting the HRESET_REQ bit in this register).
-     Example:
-       global-utilities@e0000 {        /* global utilities block */
-               compatible = "fsl,mpc8548-guts";
-               reg = <e0000 1000>;
-               fsl,has-rstcr;
-       };
-    l) Freescale Communications Processor Module
-    NOTE: This is an interim binding, and will likely change slightly,
-    as more devices are supported.  The QE bindings especially are
-    incomplete.
-    i) Root CPM node
-    Properties:
-    - compatible : "fsl,cpm1", "fsl,cpm2", or "fsl,qe".
-    - reg : A 48-byte region beginning with CPCR.
-    Example:
-       cpm@119c0 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               #interrupt-cells = <2>;
-               compatible = "fsl,mpc8272-cpm", "fsl,cpm2";
-               reg = <119c0 30>;
-       }
-    ii) Properties common to mulitple CPM/QE devices
-    - fsl,cpm-command : This value is ORed with the opcode and command flag
-                        to specify the device on which a CPM command operates.
-    - fsl,cpm-brg : Indicates which baud rate generator the device
-                    is associated with.  If absent, an unused BRG
-                    should be dynamically allocated.  If zero, the
-                    device uses an external clock rather than a BRG.
-    - reg : Unless otherwise specified, the first resource represents the
-            scc/fcc/ucc registers, and the second represents the device's
-            parameter RAM region (if it has one).
-    iii) Serial
-    Currently defined compatibles:
-    - fsl,cpm1-smc-uart
-    - fsl,cpm2-smc-uart
-    - fsl,cpm1-scc-uart
-    - fsl,cpm2-scc-uart
-    - fsl,qe-uart
-    Example:
-       serial@11a00 {
-               device_type = "serial";
-               compatible = "fsl,mpc8272-scc-uart",
-                            "fsl,cpm2-scc-uart";
-               reg = <11a00 20 8000 100>;
-               interrupts = <28 8>;
-               interrupt-parent = <&PIC>;
-               fsl,cpm-brg = <1>;
-               fsl,cpm-command = <00800000>;
-       };
-    iii) Network
-    Currently defined compatibles:
-    - fsl,cpm1-scc-enet
-    - fsl,cpm2-scc-enet
-    - fsl,cpm1-fec-enet
-    - fsl,cpm2-fcc-enet (third resource is GFEMR)
-    - fsl,qe-enet
-    Example:
-       ethernet@11300 {
-               device_type = "network";
-               compatible = "fsl,mpc8272-fcc-enet",
-                            "fsl,cpm2-fcc-enet";
-               reg = <11300 20 8400 100 11390 1>;
-               local-mac-address = [ 00 00 00 00 00 00 ];
-               interrupts = <20 8>;
-               interrupt-parent = <&PIC>;
-               phy-handle = <&PHY0>;
-               fsl,cpm-command = <12000300>;
-       };
-    iv) MDIO
-    Currently defined compatibles:
-    fsl,pq1-fec-mdio (reg is same as first resource of FEC device)
-    fsl,cpm2-mdio-bitbang (reg is port C registers)
-    Properties for fsl,cpm2-mdio-bitbang:
-    fsl,mdio-pin : pin of port C controlling mdio data
-    fsl,mdc-pin : pin of port C controlling mdio clock
-    Example:
-       mdio@10d40 {
-               device_type = "mdio";
-               compatible = "fsl,mpc8272ads-mdio-bitbang",
-                            "fsl,mpc8272-mdio-bitbang",
-                            "fsl,cpm2-mdio-bitbang";
-               reg = <10d40 14>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-               fsl,mdio-pin = <12>;
-               fsl,mdc-pin = <13>;
-       };
-    v) Baud Rate Generators
-    Currently defined compatibles:
-    fsl,cpm-brg
-    fsl,cpm1-brg
-    fsl,cpm2-brg
-    Properties:
-    - reg : There may be an arbitrary number of reg resources; BRG
-      numbers are assigned to these in order.
-    - clock-frequency : Specifies the base frequency driving
-      the BRG.
-    Example:
-       brg@119f0 {
-               compatible = "fsl,mpc8272-brg",
-                            "fsl,cpm2-brg",
-                            "fsl,cpm-brg";
-               reg = <119f0 10 115f0 10>;
-               clock-frequency = <d#25000000>;
-       };
-    vi) Interrupt Controllers
-    Currently defined compatibles:
-    - fsl,cpm1-pic
-      - only one interrupt cell
-    - fsl,pq1-pic
-    - fsl,cpm2-pic
-      - second interrupt cell is level/sense:
-        - 2 is falling edge
-        - 8 is active low
-    Example:
-       interrupt-controller@10c00 {
-               #interrupt-cells = <2>;
-               interrupt-controller;
-               reg = <10c00 80>;
-               compatible = "mpc8272-pic", "fsl,cpm2-pic";
-       };
-    vii) USB (Universal Serial Bus Controller)
-    Properties:
-    - compatible : "fsl,cpm1-usb", "fsl,cpm2-usb", "fsl,qe-usb"
-    Example:
-       usb@11bc0 {
-               #address-cells = <1>;
-               #size-cells = <0>;
-               compatible = "fsl,cpm2-usb";
-               reg = <11b60 18 8b00 100>;
-               interrupts = <b 8>;
-               interrupt-parent = <&PIC>;
-               fsl,cpm-command = <2e600000>;
-       };
-    viii) Multi-User RAM (MURAM)
-    The multi-user/dual-ported RAM is expressed as a bus under the CPM node.
-    Ranges must be set up subject to the following restrictions:
-    - Children's reg nodes must be offsets from the start of all muram, even
-      if the user-data area does not begin at zero.
-    - If multiple range entries are used, the difference between the parent
-      address and the child address must be the same in all, so that a single
-      mapping can cover them all while maintaining the ability to determine
-      CPM-side offsets with pointer subtraction.  It is recommended that
-      multiple range entries not be used.
-    - A child address of zero must be translatable, even if no reg resources
-      contain it.
-    A child "data" node must exist, compatible with "fsl,cpm-muram-data", to
-    indicate the portion of muram that is usable by the OS for arbitrary
-    purposes.  The data node may have an arbitrary number of reg resources,
-    all of which contribute to the allocatable muram pool.
-    Example, based on mpc8272:
-       muram@0 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges = <0 0 10000>;
-               data@0 {
-                       compatible = "fsl,cpm-muram-data";
-                       reg = <0 2000 9800 800>;
-               };
-       };
-    m) Chipselect/Local Bus
-    Properties:
-    - name : Should be localbus
-    - #address-cells : Should be either two or three.  The first cell is the
-                       chipselect number, and the remaining cells are the
-                       offset into the chipselect.
-    - #size-cells : Either one or two, depending on how large each chipselect
-                    can be.
-    - ranges : Each range corresponds to a single chipselect, and cover
-               the entire access window as configured.
-    Example:
-       localbus@f0010100 {
-               compatible = "fsl,mpc8272-localbus",
-                            "fsl,pq2-localbus";
-               #address-cells = <2>;
-               #size-cells = <1>;
-               reg = <f0010100 40>;
-               ranges = <0 0 fe000000 02000000
-                         1 0 f4500000 00008000>;
-               flash@0,0 {
-                       compatible = "jedec-flash";
-                       reg = <0 0 2000000>;
-                       bank-width = <4>;
-                       device-width = <1>;
-               };
-               board-control@1,0 {
-                       reg = <1 0 20>;
-                       compatible = "fsl,mpc8272ads-bcsr";
-               };
-       };
-     n) 4xx/Axon EMAC ethernet nodes
+     d) 4xx/Axon EMAC ethernet nodes
  
      The EMAC ethernet controller in IBM and AMCC 4xx chips, and also
      the Axon bridge.  To operate this needs to interact with a ths
                           available.
                           For Axon: 0x0000012a
  
-    o) Xilinx IP cores
+    e) Xilinx IP cores
  
     The Xilinx EDK toolchain ships with a set of IP cores (devices) for use
     in Xilinx Spartan and Virtex FPGAs.  The devices cover the whole range
         - reg-offset : A value of 3 is required
         - reg-shift : A value of 2 is required
  
-     p) Freescale Synchronous Serial Interface
-        The SSI is a serial device that communicates with audio codecs.  It can
-        be programmed in AC97, I2S, left-justified, or right-justified modes.
-        Required properties:
-        - compatible     : compatible list, containing "fsl,ssi"
-        - cell-index     : the SSI, <0> = SSI1, <1> = SSI2, and so on
-        - reg            : offset and length of the register set for the device
-        - interrupts     : <a b> where a is the interrupt number and b is a
-                             field that represents an encoding of the sense and
-                           level information for the interrupt.  This should be
-                           encoded based on the information in section 2)
-                           depending on the type of interrupt controller you
-                           have.
-        - interrupt-parent : the phandle for the interrupt controller that
-                             services interrupts for this device.
-        - fsl,mode       : the operating mode for the SSI interface
-                           "i2s-slave" - I2S mode, SSI is clock slave
-                           "i2s-master" - I2S mode, SSI is clock master
-                           "lj-slave" - left-justified mode, SSI is clock slave
-                           "lj-master" - l.j. mode, SSI is clock master
-                           "rj-slave" - right-justified mode, SSI is clock slave
-                           "rj-master" - r.j., SSI is clock master
-                           "ac97-slave" - AC97 mode, SSI is clock slave
-                           "ac97-master" - AC97 mode, SSI is clock master
-        Optional properties:
-        - codec-handle   : phandle to a 'codec' node that defines an audio
-                           codec connected to this SSI.  This node is typically
-                           a child of an I2C or other control node.
-        Child 'codec' node required properties:
-        - compatible     : compatible list, contains the name of the codec
-        Child 'codec' node optional properties:
-        - clock-frequency  : The frequency of the input clock, which typically
-                             comes from an on-board dedicated oscillator.
-     * Freescale 83xx DMA Controller
-     Freescale PowerPC 83xx have on chip general purpose DMA controllers.
-     Required properties:
-     - compatible        : compatible list, contains 2 entries, first is
-                        "fsl,CHIP-dma", where CHIP is the processor
-                        (mpc8349, mpc8360, etc.) and the second is
-                        "fsl,elo-dma"
-     - reg               : <registers mapping for DMA general status reg>
-     - ranges          : Should be defined as specified in 1) to describe the
-                         DMA controller channels.
-     - cell-index        : controller index.  0 for controller @ 0x8100
-     - interrupts        : <interrupt mapping for DMA IRQ>
-     - interrupt-parent  : optional, if needed for interrupt mapping
-     - DMA channel nodes:
-           - compatible        : compatible list, contains 2 entries, first is
-                                "fsl,CHIP-dma-channel", where CHIP is the processor
-                                (mpc8349, mpc8350, etc.) and the second is
-                                "fsl,elo-dma-channel"
-           - reg               : <registers mapping for channel>
-           - cell-index        : dma channel index starts at 0.
-     Optional properties:
-           - interrupts        : <interrupt mapping for DMA channel IRQ>
-                                 (on 83xx this is expected to be identical to
-                                  the interrupts property of the parent node)
-           - interrupt-parent  : optional, if needed for interrupt mapping
-   Example:
-       dma@82a8 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "fsl,mpc8349-dma", "fsl,elo-dma";
-               reg = <82a8 4>;
-               ranges = <0 8100 1a4>;
-               interrupt-parent = <&ipic>;
-               interrupts = <47 8>;
-               cell-index = <0>;
-               dma-channel@0 {
-                       compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
-                       cell-index = <0>;
-                       reg = <0 80>;
-               };
-               dma-channel@80 {
-                       compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
-                       cell-index = <1>;
-                       reg = <80 80>;
-               };
-               dma-channel@100 {
-                       compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
-                       cell-index = <2>;
-                       reg = <100 80>;
-               };
-               dma-channel@180 {
-                       compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
-                       cell-index = <3>;
-                       reg = <180 80>;
-               };
-       };
-    * Freescale 85xx/86xx DMA Controller
-     Freescale PowerPC 85xx/86xx have on chip general purpose DMA controllers.
-     Required properties:
-     - compatible        : compatible list, contains 2 entries, first is
-                        "fsl,CHIP-dma", where CHIP is the processor
-                        (mpc8540, mpc8540, etc.) and the second is
-                        "fsl,eloplus-dma"
-     - reg               : <registers mapping for DMA general status reg>
-     - cell-index        : controller index.  0 for controller @ 0x21000,
-                                              1 for controller @ 0xc000
-     - ranges          : Should be defined as specified in 1) to describe the
-                         DMA controller channels.
-     - DMA channel nodes:
-           - compatible        : compatible list, contains 2 entries, first is
-                                "fsl,CHIP-dma-channel", where CHIP is the processor
-                                (mpc8540, mpc8560, etc.) and the second is
-                                "fsl,eloplus-dma-channel"
-           - cell-index        : dma channel index starts at 0.
-           - reg               : <registers mapping for channel>
-           - interrupts        : <interrupt mapping for DMA channel IRQ>
-           - interrupt-parent  : optional, if needed for interrupt mapping
-   Example:
-       dma@21300 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "fsl,mpc8540-dma", "fsl,eloplus-dma";
-               reg = <21300 4>;
-               ranges = <0 21100 200>;
-               cell-index = <0>;
-               dma-channel@0 {
-                       compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
-                       reg = <0 80>;
-                       cell-index = <0>;
-                       interrupt-parent = <&mpic>;
-                       interrupts = <14 2>;
-               };
-               dma-channel@80 {
-                       compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
-                       reg = <80 80>;
-                       cell-index = <1>;
-                       interrupt-parent = <&mpic>;
-                       interrupts = <15 2>;
-               };
-               dma-channel@100 {
-                       compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
-                       reg = <100 80>;
-                       cell-index = <2>;
-                       interrupt-parent = <&mpic>;
-                       interrupts = <16 2>;
-               };
-               dma-channel@180 {
-                       compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
-                       reg = <180 80>;
-                       cell-index = <3>;
-                       interrupt-parent = <&mpic>;
-                       interrupts = <17 2>;
-               };
-       };
-     * Freescale 8xxx/3.0 Gb/s SATA nodes
-     SATA nodes are defined to describe on-chip Serial ATA controllers.
-     Each SATA port should have its own node.
-     Required properties:
-     - compatible        : compatible list, contains 2 entries, first is
-                        "fsl,CHIP-sata", where CHIP is the processor
-                        (mpc8315, mpc8379, etc.) and the second is
-                        "fsl,pq-sata"
-     - interrupts        : <interrupt mapping for SATA IRQ>
-     - cell-index        : controller index.
-                               1 for controller @ 0x18000
-                               2 for controller @ 0x19000
-                               3 for controller @ 0x1a000
-                               4 for controller @ 0x1b000
-     Optional properties:
-     - interrupt-parent  : optional, if needed for interrupt mapping
-     - reg               : <registers mapping>
-    Example:
-       sata@18000 {
-               compatible = "fsl,mpc8379-sata", "fsl,pq-sata";
-               reg = <0x18000 0x1000>;
-               cell-index = <1>;
-               interrupts = <2c 8>;
-               interrupt-parent = < &ipic >;
-         };
-     q) USB EHCI controllers
+     f) USB EHCI controllers
  
      Required properties:
        - compatible : should be "usb-ehci".
                   big-endian;
           };
  
 +    r) Freescale Display Interface Unit
 +
 +    The Freescale DIU is a LCD controller, with proper hardware, it can also
 +    drive DVI monitors.
 +
 +    Required properties:
 +    - compatible : should be "fsl-diu".
 +    - reg : should contain at least address and length of the DIU register
 +      set.
 +    - Interrupts : one DIU interrupt should be describe here.
 +
 +    Example (MPC8610HPCD)
 +      display@2c000 {
 +              compatible = "fsl,diu";
 +              reg = <0x2c000 100>;
 +              interrupts = <72 2>;
 +              interrupt-parent = <&mpic>;
 +      };
 +
 +    s) Freescale on board FPGA
 +
 +    This is the memory-mapped registers for on board FPGA.
 +
 +    Required properities:
 +    - compatible : should be "fsl,fpga-pixis".
 +    - reg : should contain the address and the lenght of the FPPGA register
 +      set.
 +
 +    Example (MPC8610HPCD)
 +      board-control@e8000000 {
 +              compatible = "fsl,fpga-pixis";
 +              reg = <0xe8000000 32>;
 +      };
 +
 +   r) MDIO on GPIOs
 +
 +   Currently defined compatibles:
 +   - virtual,gpio-mdio
 +
 +   MDC and MDIO lines connected to GPIO controllers are listed in the
 +   gpios property as described in section VIII.1 in the following order:
 +
 +   MDC, MDIO.
 +
 +   Example:
 +
 +      mdio {
 +              compatible = "virtual,mdio-gpio";
 +              #address-cells = <1>;
 +              #size-cells = <0>;
 +              gpios = <&qe_pio_a 11
 +                       &qe_pio_c 6>;
 +      };
 +
  VII - Marvell Discovery mv64[345]6x System Controller chips
  ===========================================================
  
@@@ -3643,14 -2567,11 +2633,11 @@@ not necessary as they are usually the s
  
                pic@40000 {
                        linux,phandle = <40000>;
-                       clock-frequency = <0>;
                        interrupt-controller;
                        #address-cells = <0>;
                        reg = <40000 40000>;
-                       built-in;
                        compatible = "chrp,open-pic";
                        device_type = "open-pic";
-                         big-endian;
                };
  
                i2c@3000 {
diff --combined MAINTAINERS
index 9ba00869514b711234a44edb9461428a60abdd2e,93fd6b2efeee80c4948e0f33f02d8081a26c637c..f92707fee59e66348e02f792566a0c8f9a58ba04
@@@ -216,8 -216,8 +216,8 @@@ W: http://code.google.com/p/aceracp
  S:    Maintained
  
  ACPI
- P:    Len Brown
- M:    len.brown@intel.com
+ P:    Andi Kleen
+ M:    ak@linux.intel.com
  M:    lenb@kernel.org
  L:    linux-acpi@vger.kernel.org
  W:    http://www.lesswatts.org/projects/acpi/
@@@ -239,8 -239,8 +239,8 @@@ W: http://www.lesswatts.org/projects/ac
  S:    Supported
  
  ACPI FAN DRIVER
- P:    Len Brown
- M:    len.brown@intel.com
+ P:    Zhang Rui
+ M:    rui.zhang@intel.com
  L:    linux-acpi@vger.kernel.org
  W:    http://www.lesswatts.org/projects/acpi/
  S:    Supported
  ACPI PCI HOTPLUG DRIVER
  P:    Kristen Carlson Accardi
  M:    kristen.c.accardi@intel.com
- L:    pcihpd-discuss@lists.sourceforge.net
+ L:    linux-pci@vger.kernel.org
  S:    Supported
  
  ACPI THERMAL DRIVER
- P:    Len Brown
- M:    len.brown@intel.com
+ P:    Zhang Rui
+ M:    rui.zhang@intel.com
  L:    linux-acpi@vger.kernel.org
  W:    http://www.lesswatts.org/projects/acpi/
  S:    Supported
  
  ACPI VIDEO DRIVER
- P:    Rui Zhang
+ P:    Zhang Rui
  M:    rui.zhang@intel.com
  L:    linux-acpi@vger.kernel.org
  W:    http://www.lesswatts.org/projects/acpi/
@@@ -348,7 -348,9 +348,9 @@@ W: http://www.linux-usb.org/SpeedTouch
  S:    Maintained
  
  ALCHEMY AU1XX0 MMC DRIVER
- S:    Orphan
+ P:    Manuel Lauss
+ M:    manuel.lauss@gmail.com
+ S:    Maintained
  
  ALI1563 I2C DRIVER
  P:    Rudolf Marek
@@@ -376,6 -378,12 +378,12 @@@ L:       linux-geode@lists.infradead.org (mod
  W:    http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
  S:    Supported
  
+ AMD IOMMU (AMD-VI)
+ P:    Joerg Roedel
+ M:    joerg.roedel@amd.com
+ L:    iommu@lists.linux-foundation.org
+ S:    Supported
  AMS (Apple Motion Sensor) DRIVER
  P:    Stelian Pop
  M:    stelian@popies.net
@@@ -763,9 -771,10 +771,10 @@@ S:       Maintaine
  
  AUXILIARY DISPLAY DRIVERS
  P:    Miguel Ojeda Sandonis
- M:    maxextreme@gmail.com
+ M:    miguel.ojeda.sandonis@gmail.com
  L:    linux-kernel@vger.kernel.org
- W:    http://auxdisplay.googlepages.com/
+ W:    http://miguelojeda.es/auxdisplay.htm
+ W:    http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm
  S:    Maintained
  
  AVR32 ARCHITECTURE
@@@ -1055,16 -1064,18 +1064,18 @@@ S:   Supporte
  
  CFAG12864B LCD DRIVER
  P:    Miguel Ojeda Sandonis
- M:    maxextreme@gmail.com
+ M:    miguel.ojeda.sandonis@gmail.com
  L:    linux-kernel@vger.kernel.org
- W:    http://auxdisplay.googlepages.com/
+ W:    http://miguelojeda.es/auxdisplay.htm
+ W:    http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm
  S:    Maintained
  
  CFAG12864BFB LCD FRAMEBUFFER DRIVER
  P:    Miguel Ojeda Sandonis
- M:    maxextreme@gmail.com
+ M:    miguel.ojeda.sandonis@gmail.com
  L:    linux-kernel@vger.kernel.org
- W:    http://auxdisplay.googlepages.com/
+ W:    http://miguelojeda.es/auxdisplay.htm
+ W:    http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm
  S:    Maintained
  
  CFG80211 and NL80211
@@@ -1134,23 -1145,28 +1145,28 @@@ COMPACTPCI HOTPLUG COR
  P:    Scott Murray
  M:    scottm@somanetworks.com
  M:    scott@spiteful.org
- L:    pcihpd-discuss@lists.sourceforge.net
+ L:    linux-pci@vger.kernel.org
  S:    Supported
  
  COMPACTPCI HOTPLUG ZIATECH ZT5550 DRIVER
  P:    Scott Murray
  M:    scottm@somanetworks.com
  M:    scott@spiteful.org
- L:    pcihpd-discuss@lists.sourceforge.net
+ L:    linux-pci@vger.kernel.org
  S:    Supported
  
  COMPACTPCI HOTPLUG GENERIC DRIVER
  P:    Scott Murray
  M:    scottm@somanetworks.com
  M:    scott@spiteful.org
- L:    pcihpd-discuss@lists.sourceforge.net
+ L:    linux-pci@vger.kernel.org
  S:    Supported
  
+ COMPAL LAPTOP SUPPORT
+ P:    Cezary Jackiewicz
+ M:    cezary.jackiewicz@gmail.com
+ S:    Maintained
  COMPUTONE INTELLIPORT MULTIPORT CARD
  P:    Michael H. Warfield
  M:    mhw@wittsend.com
@@@ -1420,6 -1436,14 +1436,14 @@@ M:    kristen.c.accardi@intel.co
  L:    linux-acpi@vger.kernel.org
  S:    Supported
  
+ DOCUMENTATION (/Documentation directory)
+ P:     Michael Kerrisk
+ M:     mtk.manpages@gmail.com
+ P:     Randy Dunlap
+ M:     rdunlap@xenotime.net
+ L:     linux-doc@vger.kernel.org
+ S:     Maintained
  DOUBLETALK DRIVER
  P:    James R. Van Zandt
  M:    jrv@vanzandt.mv.com
@@@ -1626,13 -1650,13 +1650,13 @@@ S:   Maintaine
  
  EXT3 FILE SYSTEM
  P:    Stephen Tweedie, Andrew Morton
- M:    sct@redhat.com, akpm@linux-foundation.org, adilger@clusterfs.com
+ M:    sct@redhat.com, akpm@linux-foundation.org, adilger@sun.com
  L:    linux-ext4@vger.kernel.org
  S:    Maintained
  
  EXT4 FILE SYSTEM
  P:    Stephen Tweedie, Andrew Morton
- M:    sct@redhat.com, akpm@linux-foundation.org, adilger@clusterfs.com
+ M:    sct@redhat.com, akpm@linux-foundation.org, adilger@sun.com
  L:    linux-ext4@vger.kernel.org
  S:    Maintained
  
@@@ -1669,6 -1693,13 +1693,13 @@@ L:    linuxppc-embedded@ozlabs.or
  L:    linux-kernel@vger.kernel.org
  S:    Maintained
  
+ FREESCALE I2C CPM DRIVER
+ P:    Jochen Friedrich
+ M:    jochen@scram.de
+ L:    linuxppc-dev@ozlabs.org
+ L:    i2c@lm-sensors.org
+ S:    Maintained
  FREESCALE SOC FS_ENET DRIVER
  P:    Pantelis Antoniou
  M:    pantelis.antoniou@gmail.com
@@@ -1753,11 -1784,22 +1784,22 @@@ M:   hch@infradead.or
  W:    ftp://ftp.openlinux.org/pub/people/hch/vxfs
  S:    Maintained
  
+ FTRACE
+ P:    Steven Rostedt
+ M:    srostedt@redhat.com
+ S:    Maintained
  FUJITSU FR-V (FRV) PORT
  P:    David Howells
  M:    dhowells@redhat.com
  S:    Maintained
  
+ FUJITSU LAPTOP EXTRAS
+ P:    Jonathan Woithe
+ M:    jwoithe@physics.adelaide.edu.au
+ L:    linux-acpi@vger.kernel.org
+ S:    Maintained
  FUSE: FILESYSTEM IN USERSPACE
  P:    Miklos Szeredi
  M:    miklos@szeredi.hu
@@@ -2147,8 -2189,6 +2189,8 @@@ P:      Jesse Brandebur
  M:    jesse.brandeburg@intel.com
  P:    Bruce Allan
  M:    bruce.w.allan@intel.com
 +P:    PJ Waskiewicz
 +M:    peter.p.waskiewicz.jr@intel.com
  P:    John Ronciak
  M:    john.ronciak@intel.com
  L:    e1000-devel@lists.sourceforge.net
@@@ -2298,6 -2338,16 +2340,16 @@@ L:    linux-mtd@lists.infradead.or
  W:    http://www.linux-mtd.infradead.org/doc/jffs2.html
  S:    Maintained
  
+ UBI FILE SYSTEM (UBIFS)
+ P:    Artem Bityutskiy
+ M:    dedekind@infradead.org
+ P:    Adrian Hunter
+ M:    ext-adrian.hunter@nokia.com
+ L:    linux-mtd@lists.infradead.org
+ T:    git git://git.infradead.org/~dedekind/ubifs-2.6.git
+ W:    http://www.linux-mtd.infradead.org/doc/ubifs.html
+ S:    Maintained
  JFS FILESYSTEM
  P:    Dave Kleikamp
  M:    shaggy@austin.ibm.com
@@@ -2430,9 -2480,10 +2482,10 @@@ S:    Maintaine
  
  KS0108 LCD CONTROLLER DRIVER
  P:    Miguel Ojeda Sandonis
- M:    maxextreme@gmail.com
+ M:    miguel.ojeda.sandonis@gmail.com
  L:    linux-kernel@vger.kernel.org
- W:    http://auxdisplay.googlepages.com/
+ W:    http://miguelojeda.es/auxdisplay.htm
+ W:    http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm
  S:    Maintained
  
  LAPB module
@@@ -2476,9 -2527,11 +2529,11 @@@ M:    James.Bottomley@HansenPartnership.co
  W:    http://www.hansenpartnership.com/voyager
  S:    Maintained
  
- LINUX FOR POWERPC
+ LINUX FOR POWERPC (32-BIT AND 64-BIT)
  P:    Paul Mackerras
  M:    paulus@samba.org
+ P:    Benjamin Herrenschmidt
+ M:    benh@kernel.crashing.org
  W:    http://www.penguinppc.org/
  L:    linuxppc-dev@ozlabs.org
  T:    git kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc.git
@@@ -2491,13 -2544,11 +2546,11 @@@ W:   http://www.penguinppc.org
  L:    linuxppc-dev@ozlabs.org
  S:    Maintained
  
- LINUX FOR POWERPC EMBEDDED MPC52XX
+ LINUX FOR POWERPC EMBEDDED MPC5XXX
  P:    Sylvain Munaut
  M:    tnt@246tNt.com
  P:    Grant Likely
  M:    grant.likely@secretlab.ca
- W:    http://www.246tNt.com/mpc52xx/
- W:    http://www.penguinppc.org/
  L:    linuxppc-dev@ozlabs.org
  S:    Maintained
  
@@@ -2518,13 -2569,6 +2571,6 @@@ W:     http://wiki.secretlab.ca/index.php/L
  L:    linuxppc-dev@ozlabs.org
  S:    Maintained
  
- LINUX FOR POWERPC BOOT CODE
- P:    Tom Rini
- M:    trini@kernel.crashing.org
- W:    http://www.penguinppc.org/
- L:    linuxppc-dev@ozlabs.org
- S:    Maintained
  LINUX FOR POWERPC EMBEDDED PPC8XX
  P:    Vitaly Bordug
  M:    vitb@kernel.crashing.org
@@@ -2553,17 -2597,6 +2599,6 @@@ P:     Arnaldo Carvalho de Mel
  M:    acme@ghostprotocols.net
  S:    Maintained
  
- LINUX FOR 64BIT POWERPC
- P:    Paul Mackerras
- M:    paulus@samba.org
- M:    paulus@au.ibm.com
- P:    Anton Blanchard
- M:    anton@samba.org
- M:    anton@au.ibm.com
- W:    http://www.penguinppc.org/ppc64/
- L:    linuxppc-dev@ozlabs.org
- S:    Supported
  LINUX SECURITY MODULE (LSM) FRAMEWORK
  P:    Chris Wright
  M:    chrisw@sous-sol.org
@@@ -2682,8 -2715,8 +2717,8 @@@ S:      Supporte
  MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
  P:    Michael Kerrisk
  M:    mtk.manpages@gmail.com
- W:    ftp://ftp.kernel.org/pub/linux/docs/manpages
- S:    Maintained
+ W:     http://www.kernel.org/doc/man-pages
+ S:     Supported
  
  MARVELL LIBERTAS WIRELESS DRIVER
  P:    Dan Williams
@@@ -2692,10 -2725,12 +2727,10 @@@ L:   libertas-dev@lists.infradead.or
  S:    Maintained
  
  MARVELL MV643XX ETHERNET DRIVER
 -P:    Dale Farnsworth
 -M:    dale@farnsworth.org
 -P:    Manish Lachwani
 -M:    mlachwani@mvista.com
 +P:    Lennert Buytenhek
 +M:    buytenh@marvell.com
  L:    netdev@vger.kernel.org
 -S:    Odd Fixes for 2.4; Maintained for 2.6.
 +S:    Supported
  
  MATROX FRAMEBUFFER DRIVER
  P:    Petr Vandrovec
@@@ -2814,6 -2849,12 +2849,12 @@@ W:    https://tango.0pointer.de/mailman/li
  W:    http://0pointer.de/lennart/tchibo.html
  S:    Maintained
  
+ MULTIFUNCTION DEVICES (MFD)
+ P:    Samuel Ortiz
+ M:    sameo@openedhand.com
+ L:    linux-kernel@vger.kernel.org
+ S:    Supported
  MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
  P:    Pierre Ossman
  M:    drzeus-mmc@drzeus.cx
@@@ -3080,8 -3121,8 +3121,8 @@@ L:      linux-scsi@vger.kernel.or
  S:    Maintained
  
  OPROFILE
- P:    Philippe Elie
- M:    phil.el@wanadoo.fr
+ P:    Robert Richter
+ M:    robert.richter@amd.com
  L:    oprofile-list@lists.sf.net
  S:    Maintained
  
@@@ -3178,7 -3219,7 +3219,7 @@@ S:      Supporte
  PCIE HOTPLUG DRIVER
  P:    Kristen Carlson Accardi
  M:    kristen.c.accardi@intel.com
- L:    pcihpd-discuss@lists.sourceforge.net
+ L:    linux-pci@vger.kernel.org
  S:    Supported
  
  PCMCIA SUBSYSTEM
@@@ -3195,8 -3236,8 +3236,8 @@@ L:      netdev@vger.kernel.or
  S:    Maintained
  
  PER-TASK DELAY ACCOUNTING
- P:    Shailabh Nagar
- M:    nagar@watson.ibm.com
+ P:    Balbir Singh
+ M:    balbir@linux.vnet.ibm.com
  L:    linux-kernel@vger.kernel.org
  S:    Maintained
  
@@@ -3233,6 -3274,14 +3274,6 @@@ L:     linux-kernel@vger.kernel.or
  T:    git git.infradead.org/battery-2.6.git
  S:    Maintained
  
 -POWERPC 4xx EMAC DRIVER
 -P:    Eugene Surovegin
 -M:    ebs@ebshome.net
 -W:    http://kernel.ebshome.net/emac/
 -L:    linuxppc-dev@ozlabs.org
 -L:    netdev@vger.kernel.org
 -S:    Maintained
 -
  PNP SUPPORT
  P:    Adam Belay
  M:    ambx1@neo.rr.com
@@@ -3512,6 -3561,13 +3553,13 @@@ L:    linux-s390@vger.kernel.or
  W:    http://www.ibm.com/developerworks/linux/linux390/
  S:    Supported
  
+ S3C24XX SD/MMC Driver
+ P:    Ben Dooks
+ M:    ben-linux@fluff.org
+ L:    linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+ L:    linux-kernel@vger.kernel.org
+ S:    Supported
  SAA7146 VIDEO4LINUX-2 DRIVER
  P:    Michael Hunold
  M:    michael@mihu.de
@@@ -3584,6 -3640,12 +3632,12 @@@ P:    Jim Cromi
  M:    jim.cromie@gmail.com
  S:    Maintained
  
+ SDRICOH_CS MMC/SD HOST CONTROLLER INTERFACE DRIVER
+ P:    Sascha Sommer
+ M:    saschasommer@freenet.de
+ L:    sdricohcs-devel@lists.sourceforge.net (subscribers-only)
+ S:    Maintained
  SECURITY CONTACT
  P:    Security Officers
  M:    security@kernel.org
@@@ -3680,7 -3742,7 +3734,7 @@@ S:      Maintaine
  
  SLAB ALLOCATOR
  P:    Christoph Lameter
- M:    clameter@sgi.com
+ M:    cl@linux-foundation.org
  P:    Pekka Enberg
  M:    penberg@cs.helsinki.fi
  P:    Matt Mackall
@@@ -3803,7 -3865,7 +3857,7 @@@ S:      Maintaine
  SHPC HOTPLUG DRIVER
  P:    Kristen Carlson Accardi
  M:    kristen.c.accardi@intel.com
- L:    pcihpd-discuss@lists.sourceforge.net
+ L:    linux-pci@vger.kernel.org
  S:    Supported
  
  SECURE DIGITAL HOST CONTROLLER INTERFACE DRIVER
@@@ -3854,6 -3916,10 +3908,6 @@@ P:     Ion Badulesc
  M:    ionut@cs.columbia.edu
  S:    Maintained
  
 -STARMODE RADIO IP (STRIP) PROTOCOL DRIVER
 -W:    http://mosquitonet.Stanford.EDU/strip.html
 -S:    Unsupported ?
 -
  STRADIS MPEG-2 DECODER DRIVER
  P:    Nathan Laredo
  M:    laredo@gnu.org
@@@ -3886,8 -3952,8 +3940,8 @@@ M:      hch@infradead.or
  S:    Maintained
  
  TASKSTATS STATISTICS INTERFACE
- P:    Shailabh Nagar
- M:    nagar@watson.ibm.com
+ P:    Balbir Singh
+ M:    balbir@linux.vnet.ibm.com
  L:    linux-kernel@vger.kernel.org
  S:    Maintained
  
@@@ -3983,7 -4049,8 +4037,8 @@@ W:      http://www.buzzard.org.uk/toshiba
  S:    Maintained
  
  TPM DEVICE DRIVER
- P:    Kylene Hall
+ P:     Debora Velarde
+ P:     Rajiv Andrade
  M:    tpmdd-devel@lists.sourceforge.net
  W:    http://tpmdd.sourceforge.net
  P:    Marcel Selhorst
index cd2fb955040f0ab83854439a4d98740062a2d95e,1fcc9a898d81c8fefd4ceb852926221fb3261da8..8950e9546f4eb64a33fe4dd2b7c7698382b63e37
@@@ -30,8 -30,6 +30,6 @@@
   * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   * SOFTWARE.
-  *
-  * $Id: ipoib_multicast.c 1362 2004-12-18 15:56:29Z roland $
   */
  
  #include <linux/skbuff.h>
@@@ -188,6 -186,7 +186,7 @@@ static int ipoib_mcast_join_finish(stru
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ipoib_ah *ah;
        int ret;
+       int set_qkey = 0;
  
        mcast->mcmember = *mcmember;
  
                priv->qkey = be32_to_cpu(priv->broadcast->mcmember.qkey);
                spin_unlock_irq(&priv->lock);
                priv->tx_wr.wr.ud.remote_qkey = priv->qkey;
+               set_qkey = 1;
        }
  
        if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
                }
  
                ret = ipoib_mcast_attach(dev, be16_to_cpu(mcast->mcmember.mlid),
-                                        &mcast->mcmember.mgid);
+                                        &mcast->mcmember.mgid, set_qkey);
                if (ret < 0) {
                        ipoib_warn(priv, "couldn't attach QP to multicast group "
                                   IPOIB_GID_FMT "\n",
@@@ -575,8 -575,11 +575,11 @@@ void ipoib_mcast_join_task(struct work_
  
        priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu));
  
-       if (!ipoib_cm_admin_enabled(dev))
-               dev->mtu = min(priv->mcast_mtu, priv->admin_mtu);
+       if (!ipoib_cm_admin_enabled(dev)) {
+               rtnl_lock();
+               dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu));
+               rtnl_unlock();
+       }
  
        ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n");
  
@@@ -594,10 -597,6 +597,6 @@@ int ipoib_mcast_start_thread(struct net
                queue_delayed_work(ipoib_workqueue, &priv->mcast_task, 0);
        mutex_unlock(&mcast_mutex);
  
-       spin_lock_irq(&priv->lock);
-       set_bit(IPOIB_MCAST_STARTED, &priv->flags);
-       spin_unlock_irq(&priv->lock);
        return 0;
  }
  
@@@ -607,10 -606,6 +606,6 @@@ int ipoib_mcast_stop_thread(struct net_
  
        ipoib_dbg_mcast(priv, "stopping multicast thread\n");
  
-       spin_lock_irq(&priv->lock);
-       clear_bit(IPOIB_MCAST_STARTED, &priv->flags);
-       spin_unlock_irq(&priv->lock);
        mutex_lock(&mcast_mutex);
        clear_bit(IPOIB_MCAST_RUN, &priv->flags);
        cancel_delayed_work(&priv->mcast_task);
@@@ -635,10 -630,10 +630,10 @@@ static int ipoib_mcast_leave(struct net
                                IPOIB_GID_ARG(mcast->mcmember.mgid));
  
                /* Remove ourselves from the multicast group */
-               ret = ipoib_mcast_detach(dev, be16_to_cpu(mcast->mcmember.mlid),
-                                        &mcast->mcmember.mgid);
+               ret = ib_detach_mcast(priv->qp, &mcast->mcmember.mgid,
+                                     be16_to_cpu(mcast->mcmember.mlid));
                if (ret)
-                       ipoib_warn(priv, "ipoib_mcast_detach failed (result = %d)\n", ret);
+                       ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret);
        }
  
        return 0;
@@@ -774,7 -769,7 +769,7 @@@ void ipoib_mcast_restart_task(struct wo
        ipoib_mcast_stop_thread(dev, 0);
  
        local_irq_save(flags);
 -      netif_tx_lock(dev);
 +      netif_addr_lock(dev);
        spin_lock(&priv->lock);
  
        /*
        }
  
        spin_unlock(&priv->lock);
 -      netif_tx_unlock(dev);
 +      netif_addr_unlock(dev);
        local_irq_restore(flags);
  
        /* We have to cancel outside of the spinlock */
diff --combined drivers/net/Kconfig
index 9490cb1723308b0c2d4fd536d2c12ba82632fd28,2683ee32fc11358294ccc34fb66019c0f6fe258f..611e9fb18b678dbaa6e2a92218531ea9d9a37ec4
@@@ -26,6 -26,14 +26,6 @@@ menuconfig NETDEVICE
  # that for each of the symbols.
  if NETDEVICES
  
 -config NETDEVICES_MULTIQUEUE
 -      bool "Netdevice multiple hardware queue support"
 -      ---help---
 -        Say Y here if you want to allow the network stack to use multiple
 -        hardware TX queues on an ethernet device.
 -
 -        Most people will say N here.
 -
  config IFB
        tristate "Intermediate Functional Block support"
        depends on NET_CLS_ACT
@@@ -209,7 -217,7 +209,7 @@@ config MI
  
  config MACB
        tristate "Atmel MACB support"
-       depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 || ARCH_AT91CAP9
+       depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 || ARCH_AT91SAM9G20 || ARCH_AT91CAP9
        select PHYLIB
        help
          The Atmel MACB ethernet interface is found on many AT32 and AT91
@@@ -516,18 -524,6 +516,18 @@@ config STNI
  
          If unsure, say N.
  
 +config SH_ETH
 +      tristate "Renesas SuperH Ethernet support"
 +      depends on SUPERH && \
 +              (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712)
 +      select CRC32
 +      select MII
 +      select MDIO_BITBANG
 +      select PHYLIB
 +      help
 +        Renesas SuperH Ethernet device driver.
 +        This driver support SH7710 and SH7712.
 +
  config SUNLANCE
        tristate "Sun LANCE support"
        depends on SBUS
@@@ -930,23 -926,6 +930,23 @@@ config DM900
          To compile this driver as a module, choose M here.  The module
          will be called dm9000.
  
 +config DM9000_DEBUGLEVEL
 +      int "DM9000 maximum debug level"
 +      depends on DM9000
 +      default 4
 +      help
 +        The maximum level of debugging code compiled into the DM9000
 +        driver.
 +
 +config DM9000_FORCE_SIMPLE_PHY_POLL
 +      bool "Force simple NSR based PHY polling"
 +      depends on DM9000
 +      ---help---
 +        This configuration forces the DM9000 to use the NSR's LinkStatus
 +        bit to determine if the link is up or down instead of the more
 +        costly MII PHY reads. Note, this will not work if the chip is
 +        operating with an external PHY.
 +
  config ENC28J60
        tristate "ENC28J60 support"
        depends on EXPERIMENTAL && SPI && NET_ETHERNET
@@@ -964,11 -943,19 +964,11 @@@ config ENC28J60_WRITEVERIF
          Enable the verify after the buffer write useful for debugging purpose.
          If unsure, say N.
  
 -config DM9000_DEBUGLEVEL
 -      int "DM9000 maximum debug level"
 -      depends on DM9000
 -      default 4
 -      help
 -        The maximum level of debugging code compiled into the DM9000
 -        driver.
 -
  config SMC911X
        tristate "SMSC LAN911[5678] support"
        select CRC32
        select MII
 -      depends on ARCH_PXA || SH_MAGIC_PANEL_R2
 +      depends on ARCH_PXA || SUPERH
        help
          This is a driver for SMSC's LAN911x series of Ethernet chipsets
          including the new LAN9115, LAN9116, LAN9117, and LAN9118.
@@@ -1256,6 -1243,7 +1256,6 @@@ config IBMVET
          To compile this driver as a module, choose M here. The module will
          be called ibmveth.
  
 -source "drivers/net/ibm_emac/Kconfig"
  source "drivers/net/ibm_newemac/Kconfig"
  
  config NET_PCI
@@@ -1298,6 -1286,20 +1298,6 @@@ config AMD8111_ET
          To compile this driver as a module, choose M here. The module
          will be called amd8111e.
  
 -config AMD8111E_NAPI
 -      bool "Use RX polling (NAPI)"
 -      depends on AMD8111_ETH
 -      help
 -        NAPI is a new driver API designed to reduce CPU and interrupt load
 -        when the driver is receiving lots of packets from the card. It is
 -        still somewhat experimental and thus not yet enabled by default.
 -
 -        If your estimated Rx load is 10kpps or more, or if the card will be
 -        deployed on potentially unfriendly networks (e.g. in a firewall),
 -        then say Y here.
 -
 -        If in doubt, say N.
 -
  config ADAPTEC_STARFIRE
        tristate "Adaptec Starfire/DuraLAN support"
        depends on NET_PCI && PCI
          To compile this driver as a module, choose M here: the module
          will be called starfire.  This is recommended.
  
 -config ADAPTEC_STARFIRE_NAPI
 -      bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
 -      depends on ADAPTEC_STARFIRE && EXPERIMENTAL
 -      help
 -        NAPI is a new driver API designed to reduce CPU and interrupt load
 -        when the driver is receiving lots of packets from the card. It is
 -        still somewhat experimental and thus not yet enabled by default.
 -
 -        If your estimated Rx load is 10kpps or more, or if the card will be
 -        deployed on potentially unfriendly networks (e.g. in a firewall),
 -        then say Y here.
 -
 -        If in doubt, say N.
 -
  config AC3200
        tristate "Ansel Communications EISA 3200 support (EXPERIMENTAL)"
        depends on NET_PCI && (ISA || EISA) && EXPERIMENTAL
@@@ -1654,7 -1670,7 +1654,7 @@@ config SUNDANCE_MMI
  
  config TLAN
        tristate "TI ThunderLAN support"
 -      depends on NET_PCI && (PCI || EISA) && !64BIT
 +      depends on NET_PCI && (PCI || EISA)
        ---help---
          If you have a PCI Ethernet network card based on the ThunderLAN chip
          which is supported by this driver, say Y and read the
@@@ -1694,6 -1710,26 +1694,6 @@@ config VIA_RHINE_MMI
  
          If unsure, say Y.
  
 -config VIA_RHINE_NAPI
 -      bool "Use Rx Polling (NAPI)"
 -      depends on VIA_RHINE
 -      help
 -        NAPI is a new driver API designed to reduce CPU and interrupt load
 -        when the driver is receiving lots of packets from the card.
 -
 -        If your estimated Rx load is 10kpps or more, or if the card will be
 -        deployed on potentially unfriendly networks (e.g. in a firewall),
 -        then say Y here.
 -
 -config LAN_SAA9730
 -      bool "Philips SAA9730 Ethernet support"
 -      depends on NET_PCI && PCI && MIPS_ATLAS
 -      help
 -        The SAA9730 is a combined multimedia and peripheral controller used
 -        in thin clients, Internet access terminals, and diskless
 -        workstations.
 -        See <http://www.semiconductors.philips.com/pip/SAA9730_flyer_1>.
 -
  config SC92031
        tristate "Silan SC92031 PCI Fast Ethernet Adapter driver (EXPERIMENTAL)"
        depends on NET_PCI && PCI && EXPERIMENTAL
@@@ -1848,7 -1884,6 +1848,6 @@@ config NE_H830
          Say Y here if you want to use the NE2000 compatible
          controller on the Renesas H8/300 processor.
  
- source "drivers/net/fec_8xx/Kconfig"
  source "drivers/net/fs_enet/Kconfig"
  
  endif # NET_ETHERNET
@@@ -1978,6 -2013,9 +1977,6 @@@ config E1000
          To compile this driver as a module, choose M here. The module
          will be called e1000e.
  
 -config E1000E_ENABLED
 -      def_bool E1000E != n
 -
  config IP1000
        tristate "IP1000 Gigabit Ethernet support"
        depends on PCI && EXPERIMENTAL
@@@ -2009,15 -2047,6 +2008,15 @@@ config IG
           To compile this driver as a module, choose M here. The module
           will be called igb.
  
 +config IGB_LRO 
 +      bool "Use software LRO"
 +      depends on IGB && INET
 +      select INET_LRO
 +      ---help---
 +        Say Y here if you want to use large receive offload. 
 +
 +        If in doubt, say N.
 +
  source "drivers/net/ixp2000/Kconfig"
  
  config MYRI_SBUS
@@@ -2075,13 -2104,27 +2074,13 @@@ config R816
          To compile this driver as a module, choose M here: the module
          will be called r8169.  This is recommended.
  
 -config R8169_NAPI
 -      bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
 -      depends on R8169 && EXPERIMENTAL
 -      help
 -        NAPI is a new driver API designed to reduce CPU and interrupt load
 -        when the driver is receiving lots of packets from the card. It is
 -        still somewhat experimental and thus not yet enabled by default.
 -
 -        If your estimated Rx load is 10kpps or more, or if the card will be
 -        deployed on potentially unfriendly networks (e.g. in a firewall),
 -        then say Y here.
 -
 -        If in doubt, say N.
 -
  config R8169_VLAN
        bool "VLAN support"
        depends on R8169 && VLAN_8021Q
        ---help---
          Say Y here for the r8169 driver to support the functions required
          by the kernel 802.1Q code.
 -        
 +
          If in doubt, say Y.
  
  config SB1250_MAC
@@@ -2184,7 -2227,6 +2183,7 @@@ config VIA_VELOCIT
  config TIGON3
        tristate "Broadcom Tigon3 support"
        depends on PCI
 +      select PHYLIB
        help
          This driver supports Broadcom Tigon3 based gigabit Ethernet cards.
  
@@@ -2240,19 -2282,6 +2239,19 @@@ config GELIC_WIRELES
          the driver automatically distinguishes the models, you can
          safely enable this option even if you have a wireless-less model.
  
 +config GELIC_WIRELESS_OLD_PSK_INTERFACE
 +       bool "PS3 Wireless private PSK interface (OBSOLETE)"
 +       depends on GELIC_WIRELESS
 +       help
 +          This option retains the obsolete private interface to pass
 +          the PSK from user space programs to the driver.  The PSK
 +          stands for 'Pre Shared Key' and is used for WPA[2]-PSK
 +          (WPA-Personal) environment.
 +          If WPA[2]-PSK is used and you need to use old programs that
 +          support only this old interface, say Y.  Otherwise N.
 +
 +          If unsure, say N.
 +
  config GIANFAR
        tristate "Gianfar Ethernet"
        depends on FSL_SOC
          This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx,
          and MPC86xx family of chips, and the FEC on the 8540.
  
 -config GFAR_NAPI
 -      bool "Use Rx Polling (NAPI)"
 -      depends on GIANFAR
 -
  config UCC_GETH
        tristate "Freescale QE Gigabit Ethernet"
        depends on QUICC_ENGINE
          This driver supports the Gigabit Ethernet mode of the QUICC Engine,
          which is available on some Freescale SOCs.
  
 -config UGETH_NAPI
 -      bool "Use Rx Polling (NAPI)"
 -      depends on UCC_GETH
 -
  config UGETH_MAGIC_PACKET
        bool "Magic Packet detection support"
        depends on UCC_GETH
@@@ -2359,11 -2396,18 +2358,11 @@@ config CHELSIO_T1_1
            Enables support for Chelsio's gigabit Ethernet PCI cards.  If you
            are using only 10G cards say 'N' here.
  
 -config CHELSIO_T1_NAPI
 -      bool "Use Rx Polling (NAPI)"
 -      depends on CHELSIO_T1
 -      default y
 -      help
 -        NAPI is a driver API designed to reduce CPU and interrupt load
 -        when the driver is receiving lots of packets from the card.
 -
  config CHELSIO_T3
        tristate "Chelsio Communications T3 10Gb Ethernet support"
 -      depends on PCI
 +      depends on PCI && INET
        select FW_LOADER
 +      select INET_LRO
        help
          This driver supports Chelsio T3-based gigabit and 10Gb Ethernet
          adapters.
@@@ -2391,8 -2435,7 +2390,8 @@@ config EHE
  
  config IXGBE
        tristate "Intel(R) 10GbE PCI Express adapters support"
 -      depends on PCI
 +      depends on PCI && INET
 +      select INET_LRO
        ---help---
          This driver supports Intel(R) 10GbE PCI Express family of
          adapters.  For more information on how to identify your adapter, go
@@@ -2430,6 -2473,20 +2429,6 @@@ config IXG
          To compile this driver as a module, choose M here. The module
          will be called ixgb.
  
 -config IXGB_NAPI
 -      bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
 -      depends on IXGB && EXPERIMENTAL
 -      help
 -        NAPI is a new driver API designed to reduce CPU and interrupt load
 -        when the driver is receiving lots of packets from the card. It is
 -        still somewhat experimental and thus not yet enabled by default.
 -
 -        If your estimated Rx load is 10kpps or more, or if the card will be
 -        deployed on potentially unfriendly networks (e.g. in a firewall),
 -        then say Y here.
 -
 -        If in doubt, say N.
 -
  config S2IO
        tristate "S2IO 10Gbe XFrame NIC"
        depends on PCI
          More specific information on configuring the driver is in 
          <file:Documentation/networking/s2io.txt>.
  
 -config S2IO_NAPI
 -      bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
 -      depends on S2IO && EXPERIMENTAL
 -      help
 -        NAPI is a new driver API designed to reduce CPU and interrupt load
 -        when the driver is receiving lots of packets from the card. It is
 -        still somewhat experimental and thus not yet enabled by default.
 -
 -        If your estimated Rx load is 10kpps or more, or if the card will be
 -        deployed on potentially unfriendly networks (e.g. in a firewall),
 -        then say Y here.
 -
 -        If in doubt, say N.
 -
  config MYRI10GE
        tristate "Myricom Myri-10G Ethernet support"
        depends on PCI && INET
@@@ -2502,7 -2573,6 +2501,7 @@@ config BNX2
        tristate "Broadcom NetXtremeII 10Gb support"
        depends on PCI
        select ZLIB_INFLATE
 +      select LIBCRC32C
        help
          This driver supports Broadcom NetXtremeII 10 gigabit Ethernet cards.
          To compile this driver as a module, choose M here: the module
diff --combined drivers/net/Makefile
index 3292d0af59c32943955b67045e2e345c2f058cf3,9010e58da0f2ffeccddc157082d55f631e82aac3..4b17a9ab7861a10551e98758ca91599319eb03ea
@@@ -4,6 -4,7 +4,6 @@@
  
  obj-$(CONFIG_E1000) += e1000/
  obj-$(CONFIG_E1000E) += e1000e/
 -obj-$(CONFIG_IBM_EMAC) += ibm_emac/
  obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac/
  obj-$(CONFIG_IGB) += igb/
  obj-$(CONFIG_IXGBE) += ixgbe/
@@@ -66,7 -67,6 +66,7 @@@ obj-$(CONFIG_FEALNX) += fealnx.
  obj-$(CONFIG_TIGON3) += tg3.o
  obj-$(CONFIG_BNX2) += bnx2.o
  obj-$(CONFIG_BNX2X) += bnx2x.o
 +bnx2x-objs := bnx2x_main.o bnx2x_link.o
  spidernet-y += spider_net.o spider_net_ethtool.o
  obj-$(CONFIG_SPIDER_NET) += spidernet.o sungem_phy.o
  obj-$(CONFIG_GELIC_NET) += ps3_gelic.o
@@@ -80,7 -80,6 +80,7 @@@ obj-$(CONFIG_VIA_RHINE) += via-rhine.
  obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
  obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
  obj-$(CONFIG_RIONET) += rionet.o
 +obj-$(CONFIG_SH_ETH) += sh_eth.o
  
  #
  # end link order section
@@@ -106,11 -105,11 +106,11 @@@ ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y
  endif
  obj-$(CONFIG_68360_ENET) += 68360enet.o
  obj-$(CONFIG_WD80x3) += wd.o 8390.o
 -obj-$(CONFIG_EL2) += 3c503.o 8390.o
 -obj-$(CONFIG_NE2000) += ne.o 8390.o
 -obj-$(CONFIG_NE2_MCA) += ne2.o 8390.o
 -obj-$(CONFIG_HPLAN) += hp.o 8390.o
 -obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390.o
 +obj-$(CONFIG_EL2) += 3c503.o 8390p.o
 +obj-$(CONFIG_NE2000) += ne.o 8390p.o
 +obj-$(CONFIG_NE2_MCA) += ne2.o 8390p.o
 +obj-$(CONFIG_HPLAN) += hp.o 8390p.o
 +obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390p.o
  obj-$(CONFIG_ULTRA) += smc-ultra.o 8390.o
  obj-$(CONFIG_ULTRAMCA) += smc-mca.o 8390.o
  obj-$(CONFIG_ULTRA32) += smc-ultra32.o 8390.o
@@@ -166,6 -165,7 +166,6 @@@ obj-$(CONFIG_EEXPRESS_PRO) += eepro.
  obj-$(CONFIG_8139CP) += 8139cp.o
  obj-$(CONFIG_8139TOO) += 8139too.o
  obj-$(CONFIG_ZNET) += znet.o
 -obj-$(CONFIG_LAN_SAA9730) += saa9730.o
  obj-$(CONFIG_CPMAC) += cpmac.o
  obj-$(CONFIG_DEPCA) += depca.o
  obj-$(CONFIG_EWRK3) += ewrk3.o
@@@ -217,7 -217,6 +217,6 @@@ obj-$(CONFIG_SMC91X) += smc91x.
  obj-$(CONFIG_SMC911X) += smc911x.o
  obj-$(CONFIG_BFIN_MAC) += bfin_mac.o
  obj-$(CONFIG_DM9000) += dm9000.o
- obj-$(CONFIG_FEC_8XX) += fec_8xx/
  obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o
  pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o
  obj-$(CONFIG_MLX4_CORE) += mlx4/
@@@ -236,7 -235,6 +235,7 @@@ obj-$(CONFIG_USB_CATC)          += usb
  obj-$(CONFIG_USB_KAWETH)        += usb/
  obj-$(CONFIG_USB_PEGASUS)       += usb/
  obj-$(CONFIG_USB_RTL8150)       += usb/
 +obj-$(CONFIG_USB_HSO)         += usb/
  obj-$(CONFIG_USB_USBNET)        += usb/
  obj-$(CONFIG_USB_ZD1201)        += usb/
  
index d444f5881f56691ccf5e2e9276ad5f4694714791,8e8ebd788537c6dd65ba5cdc5a1b4e25eb8e080b..9ecf8a6dc97f2c5a0ac2d00886a51c2c67bed39d
@@@ -351,7 -351,6 +351,7 @@@ struct tp_params 
  
  struct qset_params {          /* SGE queue set parameters */
        unsigned int polling;   /* polling/interrupt service for rspq */
 +      unsigned int lro;       /* large receive offload */
        unsigned int coalesce_usecs;    /* irq coalescing timer */
        unsigned int rspq_size; /* # of entries in response queue */
        unsigned int fl_size;   /* # of entries in regular free list */
@@@ -687,8 -686,9 +687,9 @@@ int t3_seeprom_write(struct adapter *ad
  int t3_seeprom_wp(struct adapter *adapter, int enable);
  int t3_get_tp_version(struct adapter *adapter, u32 *vers);
  int t3_check_tpsram_version(struct adapter *adapter, int *must_load);
- int t3_check_tpsram(struct adapter *adapter, u8 *tp_ram, unsigned int size);
- int t3_set_proto_sram(struct adapter *adap, u8 *data);
+ int t3_check_tpsram(struct adapter *adapter, const u8 *tp_ram,
+                   unsigned int size);
+ int t3_set_proto_sram(struct adapter *adap, const u8 *data);
  int t3_read_flash(struct adapter *adapter, unsigned int addr,
                  unsigned int nwords, u32 *data, int byte_oriented);
  int t3_load_fw(struct adapter *adapter, const u8 * fw_data, unsigned int size);
index d38e6cc92668574393e1d850308a25051aeeeb64,ed0ecd9679cbff52c6875f443b9a5c4b1be92455..6ad92405d9a034268796aafb7ece1540aa37c6bc
@@@ -54,6 -54,7 +54,7 @@@ enum 
        RDMA_CQ_DISABLE         = 16,
        RDMA_CTRL_QP_SETUP      = 17,
        RDMA_GET_MEM            = 18,
+       RDMA_GET_MIB            = 19,
  
        GET_RX_PAGE_INFO        = 50,
  };
@@@ -110,7 -111,10 +111,7 @@@ struct ulp_iscsi_info 
        unsigned int llimit;
        unsigned int ulimit;
        unsigned int tagmask;
 -      unsigned int pgsz3;
 -      unsigned int pgsz2;
 -      unsigned int pgsz1;
 -      unsigned int pgsz0;
 +      u8 pgsz_factor[4];
        unsigned int max_rxsz;
        unsigned int max_txsz;
        struct pci_dev *pdev;
index c69f4c0187d93b499711854f88c9b2531f6b2d3c,cf26968737966ddff1b52d0052644954f234f42f..c5b3de1bb45625a688ee7d020e723545284f0947
@@@ -207,17 -207,6 +207,17 @@@ static int cxgb_ulp_iscsi_ctl(struct ad
                break;
        case ULP_ISCSI_SET_PARAMS:
                t3_write_reg(adapter, A_ULPRX_ISCSI_TAGMASK, uiip->tagmask);
 +              /* set MaxRxData and MaxCoalesceSize to 16224 */
 +              t3_write_reg(adapter, A_TP_PARA_REG2, 0x3f603f60);
 +              /* program the ddp page sizes */
 +              {
 +                      int i;
 +                      unsigned int val = 0;
 +                      for (i = 0; i < 4; i++)
 +                              val |= (uiip->pgsz_factor[i] & 0xF) << (8 * i);
 +                      if (val)
 +                              t3_write_reg(adapter, A_ULPRX_ISCSI_PSZ, val);
 +              }
                break;
        default:
                ret = -EOPNOTSUPP;
@@@ -314,6 -303,12 +314,12 @@@ static int cxgb_rdma_ctl(struct adapte
                spin_unlock_irq(&adapter->sge.reg_lock);
                break;
        }
+       case RDMA_GET_MIB: {
+               spin_lock(&adapter->stats_lock);
+               t3_tp_get_mib_stats(adapter, (struct tp_mib_stats *)data);
+               spin_unlock(&adapter->stats_lock);
+               break;
+       }
        default:
                ret = -EOPNOTSUPP;
        }
@@@ -392,6 -387,7 +398,7 @@@ static int cxgb_offload_ctl(struct t3cd
        case RDMA_CQ_DISABLE:
        case RDMA_CTRL_QP_SETUP:
        case RDMA_GET_MEM:
+       case RDMA_GET_MIB:
                if (!offload_running(adapter))
                        return -EAGAIN;
                return cxgb_rdma_ctl(adapter, req, data);
@@@ -1259,25 -1255,6 +1266,25 @@@ static inline void unregister_tdev(stru
        mutex_unlock(&cxgb3_db_lock);
  }
  
 +static inline int adap2type(struct adapter *adapter)
 +{
 +      int type = 0;
 +
 +      switch (adapter->params.rev) {
 +      case T3_REV_A:
 +              type = T3A;
 +              break;
 +      case T3_REV_B:
 +      case T3_REV_B2:
 +              type = T3B;
 +              break;
 +      case T3_REV_C:
 +              type = T3C;
 +              break;
 +      }
 +      return type;
 +}
 +
  void __devinit cxgb3_adapter_ofld(struct adapter *adapter)
  {
        struct t3cdev *tdev = &adapter->tdev;
        cxgb3_set_dummy_ops(tdev);
        tdev->send = t3_offload_tx;
        tdev->ctl = cxgb_offload_ctl;
 -      tdev->type = adapter->params.rev == 0 ? T3A : T3B;
 +      tdev->type = adap2type(adapter);
  
        register_tdev(tdev);
  }
index bdb81f5750adefee1b08069fb325a26ce96baf44,352574a3f056ae81f260e144f10211eabf5008e4..445763e5648eef9951e4858762fc9872daeeace2
@@@ -43,8 -43,7 +43,8 @@@
  #include <asm/uaccess.h>
  
  #ifdef CONFIG_PPC_CPM_NEW_BINDING
- #include <asm/of_platform.h>
 +#include <linux/of_gpio.h>
+ #include <linux/of_platform.h>
  #endif
  
  #include "fs_enet.h"
@@@ -738,7 -737,7 +738,7 @@@ static void generic_adjust_link(struc
                if (!fep->oldlink) {
                        new_state = 1;
                        fep->oldlink = 1;
 -                      netif_schedule(dev);
 +                      netif_tx_schedule_all(dev);
                        netif_carrier_on(dev);
                        netif_start_queue(dev);
                }
@@@ -1173,7 -1172,8 +1173,7 @@@ static int __devinit find_phy(struct de
                                struct fs_platform_info *fpi)
  {
        struct device_node *phynode, *mdionode;
 -      struct resource res;
 -      int ret = 0, len;
 +      int ret = 0, len, bus_id;
        const u32 *data;
  
        data  = of_get_property(np, "fixed-link", NULL);
        if (!phynode)
                return -EINVAL;
  
 -      mdionode = of_get_parent(phynode);
 -      if (!mdionode)
 +      data = of_get_property(phynode, "reg", &len);
 +      if (!data || len != 4) {
 +              ret = -EINVAL;
                goto out_put_phy;
 +      }
  
 -      ret = of_address_to_resource(mdionode, 0, &res);
 -      if (ret)
 -              goto out_put_mdio;
 +      mdionode = of_get_parent(phynode);
 +      if (!mdionode) {
 +              ret = -EINVAL;
 +              goto out_put_phy;
 +      }
  
 -      data = of_get_property(phynode, "reg", &len);
 -      if (!data || len != 4)
 -              goto out_put_mdio;
 +      bus_id = of_get_gpio(mdionode, 0);
 +      if (bus_id < 0) {
 +              struct resource res;
 +              ret = of_address_to_resource(mdionode, 0, &res);
 +              if (ret)
 +                      goto out_put_mdio;
 +              bus_id = res.start;
 +      }
  
 -      snprintf(fpi->bus_id, 16, "%x:%02x", res.start, *data);
 +      snprintf(fpi->bus_id, 16, "%x:%02x", bus_id, *data);
  
  out_put_mdio:
        of_node_put(mdionode);
index 9ca57d3655997a25f8bfbf671aa227131c7c0d2e,61af02b4c9d88b88365e1917d47193c23a61d475..2e720f26ca83981c30a4a07cef6d79bc87289d0d
@@@ -295,9 -295,7 +295,9 @@@ static void emac_rx_disable(struct emac
  static inline void emac_netif_stop(struct emac_instance *dev)
  {
        netif_tx_lock_bh(dev->ndev);
 +      netif_addr_lock(dev->ndev);
        dev->no_mcast = 1;
 +      netif_addr_unlock(dev->ndev);
        netif_tx_unlock_bh(dev->ndev);
        dev->ndev->trans_start = jiffies;       /* prevent tx timeout */
        mal_poll_disable(dev->mal, &dev->commac);
  static inline void emac_netif_start(struct emac_instance *dev)
  {
        netif_tx_lock_bh(dev->ndev);
 +      netif_addr_lock(dev->ndev);
        dev->no_mcast = 0;
        if (dev->mcast_pending && netif_running(dev->ndev))
                __emac_set_multicast_list(dev);
 +      netif_addr_unlock(dev->ndev);
        netif_tx_unlock_bh(dev->ndev);
  
        netif_wake_queue(dev->ndev);
@@@ -367,25 -363,31 +367,31 @@@ static int emac_reset(struct emac_insta
  
  static void emac_hash_mc(struct emac_instance *dev)
  {
-       struct emac_regs __iomem *p = dev->emacp;
-       u16 gaht[4] = { 0 };
+       const int regs = EMAC_XAHT_REGS(dev);
+       u32 *gaht_base = emac_gaht_base(dev);
+       u32 gaht_temp[regs];
        struct dev_mc_list *dmi;
+       int i;
  
        DBG(dev, "hash_mc %d" NL, dev->ndev->mc_count);
  
+       memset(gaht_temp, 0, sizeof (gaht_temp));
        for (dmi = dev->ndev->mc_list; dmi; dmi = dmi->next) {
-               int bit;
+               int slot, reg, mask;
                DBG2(dev, "mc %02x:%02x:%02x:%02x:%02x:%02x" NL,
                     dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2],
                     dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5]);
  
-               bit = 63 - (ether_crc(ETH_ALEN, dmi->dmi_addr) >> 26);
-               gaht[bit >> 4] |= 0x8000 >> (bit & 0x0f);
+               slot = EMAC_XAHT_CRC_TO_SLOT(dev, ether_crc(ETH_ALEN, dmi->dmi_addr));
+               reg = EMAC_XAHT_SLOT_TO_REG(dev, slot);
+               mask = EMAC_XAHT_SLOT_TO_MASK(dev, slot);
+               gaht_temp[reg] |= mask;
        }
-       out_be32(&p->gaht1, gaht[0]);
-       out_be32(&p->gaht2, gaht[1]);
-       out_be32(&p->gaht3, gaht[2]);
-       out_be32(&p->gaht4, gaht[3]);
+       for (i = 0; i < regs; i++)
+               out_be32(gaht_base + i, gaht_temp[i]);
  }
  
  static inline u32 emac_iff2rmr(struct net_device *ndev)
  
        if (ndev->flags & IFF_PROMISC)
                r |= EMAC_RMR_PME;
-       else if (ndev->flags & IFF_ALLMULTI || ndev->mc_count > 32)
+       else if (ndev->flags & IFF_ALLMULTI ||
+                        (ndev->mc_count > EMAC_XAHT_SLOTS(dev)))
                r |= EMAC_RMR_PMME;
        else if (ndev->mc_count > 0)
                r |= EMAC_RMR_MAE;
@@@ -546,7 -549,7 +553,7 @@@ static int emac_configure(struct emac_i
                        /* Put some arbitrary OUI, Manuf & Rev IDs so we can
                         * identify this GPCS PHY later.
                         */
-                       out_be32(&p->ipcr, 0xdeadbeef);
+                       out_be32(&p->u1.emac4.ipcr, 0xdeadbeef);
                } else
                        mr1 |= EMAC_MR1_MF_1000;
  
@@@ -2025,10 -2028,10 +2032,10 @@@ static int emac_get_regs_len(struct ema
  {
        if (emac_has_feature(dev, EMAC_FTR_EMAC4))
                return sizeof(struct emac_ethtool_regs_subhdr) +
-                       EMAC4_ETHTOOL_REGS_SIZE;
+                       EMAC4_ETHTOOL_REGS_SIZE(dev);
        else
                return sizeof(struct emac_ethtool_regs_subhdr) +
-                       EMAC_ETHTOOL_REGS_SIZE;
+                       EMAC_ETHTOOL_REGS_SIZE(dev);
  }
  
  static int emac_ethtool_get_regs_len(struct net_device *ndev)
@@@ -2055,12 -2058,12 +2062,12 @@@ static void *emac_dump_regs(struct emac
        hdr->index = dev->cell_index;
        if (emac_has_feature(dev, EMAC_FTR_EMAC4)) {
                hdr->version = EMAC4_ETHTOOL_REGS_VER;
-               memcpy_fromio(hdr + 1, dev->emacp, EMAC4_ETHTOOL_REGS_SIZE);
-               return ((void *)(hdr + 1) + EMAC4_ETHTOOL_REGS_SIZE);
+               memcpy_fromio(hdr + 1, dev->emacp, EMAC4_ETHTOOL_REGS_SIZE(dev));
+               return ((void *)(hdr + 1) + EMAC4_ETHTOOL_REGS_SIZE(dev));
        } else {
                hdr->version = EMAC_ETHTOOL_REGS_VER;
-               memcpy_fromio(hdr + 1, dev->emacp, EMAC_ETHTOOL_REGS_SIZE);
-               return ((void *)(hdr + 1) + EMAC_ETHTOOL_REGS_SIZE);
+               memcpy_fromio(hdr + 1, dev->emacp, EMAC_ETHTOOL_REGS_SIZE(dev));
+               return ((void *)(hdr + 1) + EMAC_ETHTOOL_REGS_SIZE(dev));
        }
  }
  
@@@ -2550,7 -2553,9 +2557,9 @@@ static int __devinit emac_init_config(s
        }
  
        /* Check EMAC version */
-       if (of_device_is_compatible(np, "ibm,emac4")) {
+       if (of_device_is_compatible(np, "ibm,emac4sync")) {
+               dev->features |= (EMAC_FTR_EMAC4 | EMAC_FTR_EMAC4SYNC);
+       } else if (of_device_is_compatible(np, "ibm,emac4")) {
                dev->features |= EMAC_FTR_EMAC4;
                if (of_device_is_compatible(np, "ibm,emac-440gx"))
                        dev->features |= EMAC_FTR_440GX_PHY_CLK_FIX;
        }
        memcpy(dev->ndev->dev_addr, p, 6);
  
+       /* IAHT and GAHT filter parameterization */
+       if (emac_has_feature(dev, EMAC_FTR_EMAC4SYNC)) {
+               dev->xaht_slots_shift = EMAC4SYNC_XAHT_SLOTS_SHIFT;
+               dev->xaht_width_shift = EMAC4SYNC_XAHT_WIDTH_SHIFT;
+       } else {
+               dev->xaht_slots_shift = EMAC4_XAHT_SLOTS_SHIFT;
+               dev->xaht_width_shift = EMAC4_XAHT_WIDTH_SHIFT;
+       }
        DBG(dev, "features     : 0x%08x / 0x%08x\n", dev->features, EMAC_FTRS_POSSIBLE);
        DBG(dev, "tx_fifo_size : %d (%d gige)\n", dev->tx_fifo_size, dev->tx_fifo_size_gige);
        DBG(dev, "rx_fifo_size : %d (%d gige)\n", dev->rx_fifo_size, dev->rx_fifo_size_gige);
@@@ -2682,7 -2696,8 +2700,8 @@@ static int __devinit emac_probe(struct 
                goto err_irq_unmap;
        }
        // TODO : request_mem_region
-       dev->emacp = ioremap(dev->rsrc_regs.start, sizeof(struct emac_regs));
+       dev->emacp = ioremap(dev->rsrc_regs.start,
+                            dev->rsrc_regs.end - dev->rsrc_regs.start + 1);
        if (dev->emacp == NULL) {
                printk(KERN_ERR "%s: Can't map device registers!\n",
                       np->full_name);
@@@ -2896,6 -2911,10 +2915,10 @@@ static struct of_device_id emac_match[
                .type           = "network",
                .compatible     = "ibm,emac4",
        },
+       {
+               .type           = "network",
+               .compatible     = "ibm,emac4sync",
+       },
        {},
  };
  
diff --combined drivers/net/macb.c
index 50688a52658eb359f8c12ebf56a8d64a9c3c46e6,0a5745a854c7bbbe562a5f4e7b88e464a8891b0d..0496d16f9de5f39a690597991c1bdcb4cc0eca9b
@@@ -80,12 -80,8 +80,12 @@@ static void __init macb_get_hwaddr(stru
        addr[4] = top & 0xff;
        addr[5] = (top >> 8) & 0xff;
  
 -      if (is_valid_ether_addr(addr))
 +      if (is_valid_ether_addr(addr)) {
                memcpy(bp->dev->dev_addr, addr, sizeof(addr));
 +      } else {
 +              dev_info(&bp->pdev->dev, "invalid hw address, using random\n");
 +              random_ether_addr(bp->dev->dev_addr);
 +      }
  }
  
  static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
@@@ -165,7 -161,7 +165,7 @@@ static void macb_handle_link_change(str
  
        if (phydev->link != bp->link) {
                if (phydev->link)
 -                      netif_schedule(dev);
 +                      netif_tx_schedule_all(dev);
                else {
                        bp->speed = 0;
                        bp->duplex = -1;
@@@ -1281,8 -1277,45 +1281,45 @@@ static int __exit macb_remove(struct pl
        return 0;
  }
  
+ #ifdef CONFIG_PM
+ static int macb_suspend(struct platform_device *pdev, pm_message_t state)
+ {
+       struct net_device *netdev = platform_get_drvdata(pdev);
+       struct macb *bp = netdev_priv(netdev);
+       netif_device_detach(netdev);
+ #ifndef CONFIG_ARCH_AT91
+       clk_disable(bp->hclk);
+ #endif
+       clk_disable(bp->pclk);
+       return 0;
+ }
+ static int macb_resume(struct platform_device *pdev)
+ {
+       struct net_device *netdev = platform_get_drvdata(pdev);
+       struct macb *bp = netdev_priv(netdev);
+       clk_enable(bp->pclk);
+ #ifndef CONFIG_ARCH_AT91
+       clk_enable(bp->hclk);
+ #endif
+       netif_device_attach(netdev);
+       return 0;
+ }
+ #else
+ #define macb_suspend  NULL
+ #define macb_resume   NULL
+ #endif
  static struct platform_driver macb_driver = {
        .remove         = __exit_p(macb_remove),
+       .suspend        = macb_suspend,
+       .resume         = macb_resume,
        .driver         = {
                .name           = "macb",
                .owner  = THIS_MODULE,
diff --combined drivers/net/macvlan.c
index 72745ce588c65464cabeeee4abea53a7dfdfe32c,860d75d81f822968144621a310a20ef3f969636d..efbc15567dd326b61887958f29f2c30f712f0304
@@@ -20,7 -20,7 +20,7 @@@
  #include <linux/errno.h>
  #include <linux/slab.h>
  #include <linux/string.h>
- #include <linux/list.h>
+ #include <linux/rculist.h>
  #include <linux/notifier.h>
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
@@@ -189,20 -189,12 +189,20 @@@ static int macvlan_open(struct net_devi
  
        err = dev_unicast_add(lowerdev, dev->dev_addr, ETH_ALEN);
        if (err < 0)
 -              return err;
 -      if (dev->flags & IFF_ALLMULTI)
 -              dev_set_allmulti(lowerdev, 1);
 +              goto out;
 +      if (dev->flags & IFF_ALLMULTI) {
 +              err = dev_set_allmulti(lowerdev, 1);
 +              if (err < 0)
 +                      goto del_unicast;
 +      }
  
        hlist_add_head_rcu(&vlan->hlist, &port->vlan_hash[dev->dev_addr[5]]);
        return 0;
 +
 +del_unicast:
 +      dev_unicast_delete(lowerdev, dev->dev_addr, ETH_ALEN);
 +out:
 +      return err;
  }
  
  static int macvlan_stop(struct net_device *dev)
@@@ -285,19 -277,6 +285,19 @@@ static struct lock_class_key macvlan_ne
  #define MACVLAN_STATE_MASK \
        ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))
  
 +static void macvlan_set_lockdep_class_one(struct net_device *dev,
 +                                        struct netdev_queue *txq,
 +                                        void *_unused)
 +{
 +      lockdep_set_class(&txq->_xmit_lock,
 +                        &macvlan_netdev_xmit_lock_key);
 +}
 +
 +static void macvlan_set_lockdep_class(struct net_device *dev)
 +{
 +      netdev_for_each_tx_queue(dev, macvlan_set_lockdep_class_one, NULL);
 +}
 +
  static int macvlan_init(struct net_device *dev)
  {
        struct macvlan_dev *vlan = netdev_priv(dev);
        dev->features           = lowerdev->features & MACVLAN_FEATURES;
        dev->iflink             = lowerdev->ifindex;
  
 -      lockdep_set_class(&dev->_xmit_lock, &macvlan_netdev_xmit_lock_key);
 +      macvlan_set_lockdep_class(dev);
 +
        return 0;
  }
  
index 9a68d2ea5f3eb10902e067cf5fc5f4585094b038,823bb6d35334acfcd3548b0a79f14a480b5f7779..b3981ed972bf7768b4d90520b8f2dc2fecf3b5f3
@@@ -49,7 -49,6 +49,7 @@@
  #include <linux/if_ether.h>
  #include <linux/if_vlan.h>
  #include <linux/inet_lro.h>
 +#include <linux/dca.h>
  #include <linux/ip.h>
  #include <linux/inet.h>
  #include <linux/in.h>
@@@ -186,18 -185,11 +186,18 @@@ struct myri10ge_slice_state 
        dma_addr_t fw_stats_bus;
        int watchdog_tx_done;
        int watchdog_tx_req;
 +#ifdef CONFIG_DCA
 +      int cached_dca_tag;
 +      int cpu;
 +      __be32 __iomem *dca_tag;
 +#endif
 +      char irq_desc[32];
  };
  
  struct myri10ge_priv {
 -      struct myri10ge_slice_state ss;
 +      struct myri10ge_slice_state *ss;
        int tx_boundary;        /* boundary transmits cannot cross */
 +      int num_slices;
        int running;            /* running?             */
        int csum_flag;          /* rx_csums?            */
        int small_bytes;
        dma_addr_t cmd_bus;
        struct pci_dev *pdev;
        int msi_enabled;
 +      int msix_enabled;
 +      struct msix_entry *msix_vectors;
 +#ifdef CONFIG_DCA
 +      int dca_enabled;
 +#endif
        u32 link_state;
        unsigned int rdma_tags_available;
        int intr_coal_delay;
  
  static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat";
  static char *myri10ge_fw_aligned = "myri10ge_eth_z8e.dat";
 +static char *myri10ge_fw_rss_unaligned = "myri10ge_rss_ethp_z8e.dat";
 +static char *myri10ge_fw_rss_aligned = "myri10ge_rss_eth_z8e.dat";
  
  static char *myri10ge_fw_name = NULL;
  module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR);
@@@ -336,18 -321,6 +336,18 @@@ static int myri10ge_wcfifo = 0
  module_param(myri10ge_wcfifo, int, S_IRUGO);
  MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled");
  
 +static int myri10ge_max_slices = 1;
 +module_param(myri10ge_max_slices, int, S_IRUGO);
 +MODULE_PARM_DESC(myri10ge_max_slices, "Max tx/rx queues");
 +
 +static int myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_PORT;
 +module_param(myri10ge_rss_hash, int, S_IRUGO);
 +MODULE_PARM_DESC(myri10ge_rss_hash, "Type of RSS hashing to do");
 +
 +static int myri10ge_dca = 1;
 +module_param(myri10ge_dca, int, S_IRUGO);
 +MODULE_PARM_DESC(myri10ge_dca, "Enable DCA if possible");
 +
  #define MYRI10GE_FW_OFFSET 1024*1024
  #define MYRI10GE_HIGHPART_TO_U32(X) \
  (sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0)
@@@ -556,6 -529,7 +556,7 @@@ static int myri10ge_load_hotplug_firmwa
        unsigned crc, reread_crc;
        const struct firmware *fw;
        struct device *dev = &mgp->pdev->dev;
+       unsigned char *fw_readback;
        struct mcp_gen_header *hdr;
        size_t hdr_offset;
        int status;
                mb();
                readb(mgp->sram);
        }
+       fw_readback = vmalloc(fw->size);
+       if (!fw_readback) {
+               status = -ENOMEM;
+               goto abort_with_fw;
+       }
        /* corruption checking is good for parity recovery and buggy chipset */
-       memcpy_fromio(fw->data, mgp->sram + MYRI10GE_FW_OFFSET, fw->size);
-       reread_crc = crc32(~0, fw->data, fw->size);
+       memcpy_fromio(fw_readback, mgp->sram + MYRI10GE_FW_OFFSET, fw->size);
+       reread_crc = crc32(~0, fw_readback, fw->size);
+       vfree(fw_readback);
        if (crc != reread_crc) {
                dev_err(dev, "CRC failed(fw-len=%u), got 0x%x (expect 0x%x)\n",
                        (unsigned)fw->size, reread_crc, crc);
@@@ -684,7 -664,7 +691,7 @@@ static int myri10ge_get_firmware_capabi
        return 0;
  }
  
 -static int myri10ge_load_firmware(struct myri10ge_priv *mgp)
 +static int myri10ge_load_firmware(struct myri10ge_priv *mgp, int adopt)
  {
        char __iomem *submit;
        __be32 buf[16] __attribute__ ((__aligned__(8)));
        size = 0;
        status = myri10ge_load_hotplug_firmware(mgp, &size);
        if (status) {
 +              if (!adopt)
 +                      return status;
                dev_warn(&mgp->pdev->dev, "hotplug firmware loading failed\n");
  
                /* Do not attempt to adopt firmware if there
@@@ -888,12 -866,8 +895,12 @@@ abort
  static int myri10ge_reset(struct myri10ge_priv *mgp)
  {
        struct myri10ge_cmd cmd;
 -      int status;
 +      struct myri10ge_slice_state *ss;
 +      int i, status;
        size_t bytes;
 +#ifdef CONFIG_DCA
 +      unsigned long dca_tag_off;
 +#endif
  
        /* try to send a reset command to the card to see if it
         * is alive */
        }
  
        (void)myri10ge_dma_test(mgp, MXGEFW_DMA_TEST);
 +      /*
 +       * Use non-ndis mcp_slot (eg, 4 bytes total,
 +       * no toeplitz hash value returned.  Older firmware will
 +       * not understand this command, but will use the correct
 +       * sized mcp_slot, so we ignore error returns
 +       */
 +      cmd.data0 = MXGEFW_RSS_MCP_SLOT_TYPE_MIN;
 +      (void)myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_RSS_MCP_SLOT_TYPE, &cmd, 0);
  
        /* Now exchange information about interrupts  */
  
 -      bytes = mgp->max_intr_slots * sizeof(*mgp->ss.rx_done.entry);
 -      memset(mgp->ss.rx_done.entry, 0, bytes);
 +      bytes = mgp->max_intr_slots * sizeof(*mgp->ss[0].rx_done.entry);
        cmd.data0 = (u32) bytes;
        status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_SIZE, &cmd, 0);
 -      cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->ss.rx_done.bus);
 -      cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->ss.rx_done.bus);
 -      status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_DMA, &cmd, 0);
 +
 +      /*
 +       * Even though we already know how many slices are supported
 +       * via myri10ge_probe_slices() MXGEFW_CMD_GET_MAX_RSS_QUEUES
 +       * has magic side effects, and must be called after a reset.
 +       * It must be called prior to calling any RSS related cmds,
 +       * including assigning an interrupt queue for anything but
 +       * slice 0.  It must also be called *after*
 +       * MXGEFW_CMD_SET_INTRQ_SIZE, since the intrq size is used by
 +       * the firmware to compute offsets.
 +       */
 +
 +      if (mgp->num_slices > 1) {
 +
 +              /* ask the maximum number of slices it supports */
 +              status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_RSS_QUEUES,
 +                                         &cmd, 0);
 +              if (status != 0) {
 +                      dev_err(&mgp->pdev->dev,
 +                              "failed to get number of slices\n");
 +              }
 +
 +              /*
 +               * MXGEFW_CMD_ENABLE_RSS_QUEUES must be called prior
 +               * to setting up the interrupt queue DMA
 +               */
 +
 +              cmd.data0 = mgp->num_slices;
 +              cmd.data1 = 1;  /* use MSI-X */
 +              status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES,
 +                                         &cmd, 0);
 +              if (status != 0) {
 +                      dev_err(&mgp->pdev->dev,
 +                              "failed to set number of slices\n");
 +
 +                      return status;
 +              }
 +      }
 +      for (i = 0; i < mgp->num_slices; i++) {
 +              ss = &mgp->ss[i];
 +              cmd.data0 = MYRI10GE_LOWPART_TO_U32(ss->rx_done.bus);
 +              cmd.data1 = MYRI10GE_HIGHPART_TO_U32(ss->rx_done.bus);
 +              cmd.data2 = i;
 +              status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_DMA,
 +                                          &cmd, 0);
 +      };
  
        status |=
            myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0);
 -      mgp->ss.irq_claim = (__iomem __be32 *) (mgp->sram + cmd.data0);
 +      for (i = 0; i < mgp->num_slices; i++) {
 +              ss = &mgp->ss[i];
 +              ss->irq_claim =
 +                  (__iomem __be32 *) (mgp->sram + cmd.data0 + 8 * i);
 +      }
        status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET,
                                    &cmd, 0);
        mgp->irq_deassert = (__iomem __be32 *) (mgp->sram + cmd.data0);
        }
        put_be32(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
  
 -      memset(mgp->ss.rx_done.entry, 0, bytes);
 +#ifdef CONFIG_DCA
 +      status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_DCA_OFFSET, &cmd, 0);
 +      dca_tag_off = cmd.data0;
 +      for (i = 0; i < mgp->num_slices; i++) {
 +              ss = &mgp->ss[i];
 +              if (status == 0) {
 +                      ss->dca_tag = (__iomem __be32 *)
 +                          (mgp->sram + dca_tag_off + 4 * i);
 +              } else {
 +                      ss->dca_tag = NULL;
 +              }
 +      }
 +#endif                                /* CONFIG_DCA */
  
        /* reset mcp/driver shared state back to 0 */
 -      mgp->ss.tx.req = 0;
 -      mgp->ss.tx.done = 0;
 -      mgp->ss.tx.pkt_start = 0;
 -      mgp->ss.tx.pkt_done = 0;
 -      mgp->ss.rx_big.cnt = 0;
 -      mgp->ss.rx_small.cnt = 0;
 -      mgp->ss.rx_done.idx = 0;
 -      mgp->ss.rx_done.cnt = 0;
 +
        mgp->link_changes = 0;
 +      for (i = 0; i < mgp->num_slices; i++) {
 +              ss = &mgp->ss[i];
 +
 +              memset(ss->rx_done.entry, 0, bytes);
 +              ss->tx.req = 0;
 +              ss->tx.done = 0;
 +              ss->tx.pkt_start = 0;
 +              ss->tx.pkt_done = 0;
 +              ss->rx_big.cnt = 0;
 +              ss->rx_small.cnt = 0;
 +              ss->rx_done.idx = 0;
 +              ss->rx_done.cnt = 0;
 +              ss->tx.wake_queue = 0;
 +              ss->tx.stop_queue = 0;
 +      }
 +
        status = myri10ge_update_mac_address(mgp, mgp->dev->dev_addr);
        myri10ge_change_pause(mgp, mgp->pause);
        myri10ge_set_multicast_list(mgp->dev);
        return status;
  }
  
 +#ifdef CONFIG_DCA
 +static void
 +myri10ge_write_dca(struct myri10ge_slice_state *ss, int cpu, int tag)
 +{
 +      ss->cpu = cpu;
 +      ss->cached_dca_tag = tag;
 +      put_be32(htonl(tag), ss->dca_tag);
 +}
 +
 +static inline void myri10ge_update_dca(struct myri10ge_slice_state *ss)
 +{
 +      int cpu = get_cpu();
 +      int tag;
 +
 +      if (cpu != ss->cpu) {
 +              tag = dca_get_tag(cpu);
 +              if (ss->cached_dca_tag != tag)
 +                      myri10ge_write_dca(ss, cpu, tag);
 +      }
 +      put_cpu();
 +}
 +
 +static void myri10ge_setup_dca(struct myri10ge_priv *mgp)
 +{
 +      int err, i;
 +      struct pci_dev *pdev = mgp->pdev;
 +
 +      if (mgp->ss[0].dca_tag == NULL || mgp->dca_enabled)
 +              return;
 +      if (!myri10ge_dca) {
 +              dev_err(&pdev->dev, "dca disabled by administrator\n");
 +              return;
 +      }
 +      err = dca_add_requester(&pdev->dev);
 +      if (err) {
 +              dev_err(&pdev->dev,
 +                      "dca_add_requester() failed, err=%d\n", err);
 +              return;
 +      }
 +      mgp->dca_enabled = 1;
 +      for (i = 0; i < mgp->num_slices; i++)
 +              myri10ge_write_dca(&mgp->ss[i], -1, 0);
 +}
 +
 +static void myri10ge_teardown_dca(struct myri10ge_priv *mgp)
 +{
 +      struct pci_dev *pdev = mgp->pdev;
 +      int err;
 +
 +      if (!mgp->dca_enabled)
 +              return;
 +      mgp->dca_enabled = 0;
 +      err = dca_remove_requester(&pdev->dev);
 +}
 +
 +static int myri10ge_notify_dca_device(struct device *dev, void *data)
 +{
 +      struct myri10ge_priv *mgp;
 +      unsigned long event;
 +
 +      mgp = dev_get_drvdata(dev);
 +      event = *(unsigned long *)data;
 +
 +      if (event == DCA_PROVIDER_ADD)
 +              myri10ge_setup_dca(mgp);
 +      else if (event == DCA_PROVIDER_REMOVE)
 +              myri10ge_teardown_dca(mgp);
 +      return 0;
 +}
 +#endif                                /* CONFIG_DCA */
 +
  static inline void
  myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst,
                    struct mcp_kreq_ether_recv *src)
@@@ -1274,10 -1102,9 +1281,10 @@@ myri10ge_rx_done(struct myri10ge_slice_
                rx_frags[0].size -= MXGEFW_PAD;
                len -= MXGEFW_PAD;
                lro_receive_frags(&ss->rx_done.lro_mgr, rx_frags,
 -                                len, len,
                                  /* opaque, will come back in get_frag_header */
 +                                len, len,
                                  (void *)(__force unsigned long)csum, csum);
 +
                return 1;
        }
  
@@@ -1416,7 -1243,7 +1423,7 @@@ myri10ge_clean_rx_done(struct myri10ge_
  
  static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
  {
 -      struct mcp_irq_data *stats = mgp->ss.fw_stats;
 +      struct mcp_irq_data *stats = mgp->ss[0].fw_stats;
  
        if (unlikely(stats->stats_updated)) {
                unsigned link_up = ntohl(stats->link_up);
@@@ -1463,11 -1290,6 +1470,11 @@@ static int myri10ge_poll(struct napi_st
        struct net_device *netdev = ss->mgp->dev;
        int work_done;
  
 +#ifdef CONFIG_DCA
 +      if (ss->mgp->dca_enabled)
 +              myri10ge_update_dca(ss);
 +#endif
 +
        /* process as many rx events as NAPI will allow */
        work_done = myri10ge_clean_rx_done(ss, budget);
  
@@@ -1487,13 -1309,6 +1494,13 @@@ static irqreturn_t myri10ge_intr(int ir
        u32 send_done_count;
        int i;
  
 +      /* an interrupt on a non-zero slice is implicitly valid
 +       * since MSI-X irqs are not shared */
 +      if (ss != mgp->ss) {
 +              netif_rx_schedule(ss->dev, &ss->napi);
 +              return (IRQ_HANDLED);
 +      }
 +
        /* make sure it is our IRQ, and that the DMA has finished */
        if (unlikely(!stats->valid))
                return (IRQ_NONE);
        if (stats->valid & 1)
                netif_rx_schedule(ss->dev, &ss->napi);
  
 -      if (!mgp->msi_enabled) {
 +      if (!mgp->msi_enabled && !mgp->msix_enabled) {
                put_be32(0, mgp->irq_deassert);
                if (!myri10ge_deassert_wait)
                        stats->valid = 0;
@@@ -1638,10 -1453,10 +1645,10 @@@ myri10ge_get_ringparam(struct net_devic
  {
        struct myri10ge_priv *mgp = netdev_priv(netdev);
  
 -      ring->rx_mini_max_pending = mgp->ss.rx_small.mask + 1;
 -      ring->rx_max_pending = mgp->ss.rx_big.mask + 1;
 +      ring->rx_mini_max_pending = mgp->ss[0].rx_small.mask + 1;
 +      ring->rx_max_pending = mgp->ss[0].rx_big.mask + 1;
        ring->rx_jumbo_max_pending = 0;
 -      ring->tx_max_pending = mgp->ss.rx_small.mask + 1;
 +      ring->tx_max_pending = mgp->ss[0].rx_small.mask + 1;
        ring->rx_mini_pending = ring->rx_mini_max_pending;
        ring->rx_pending = ring->rx_max_pending;
        ring->rx_jumbo_pending = ring->rx_jumbo_max_pending;
@@@ -1689,12 -1504,9 +1696,12 @@@ static const char myri10ge_gstrings_mai
        "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
        "tx_heartbeat_errors", "tx_window_errors",
        /* device-specific stats */
 -      "tx_boundary", "WC", "irq", "MSI",
 +      "tx_boundary", "WC", "irq", "MSI", "MSIX",
        "read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs",
        "serial_number", "watchdog_resets",
 +#ifdef CONFIG_DCA
 +      "dca_capable", "dca_enabled",
 +#endif
        "link_changes", "link_up", "dropped_link_overflow",
        "dropped_link_error_or_filtered",
        "dropped_pause", "dropped_bad_phy", "dropped_bad_crc32",
@@@ -1719,31 -1531,23 +1726,31 @@@ static const char myri10ge_gstrings_sli
  static void
  myri10ge_get_strings(struct net_device *netdev, u32 stringset, u8 * data)
  {
 +      struct myri10ge_priv *mgp = netdev_priv(netdev);
 +      int i;
 +
        switch (stringset) {
        case ETH_SS_STATS:
                memcpy(data, *myri10ge_gstrings_main_stats,
                       sizeof(myri10ge_gstrings_main_stats));
                data += sizeof(myri10ge_gstrings_main_stats);
 -              memcpy(data, *myri10ge_gstrings_slice_stats,
 -                     sizeof(myri10ge_gstrings_slice_stats));
 -              data += sizeof(myri10ge_gstrings_slice_stats);
 +              for (i = 0; i < mgp->num_slices; i++) {
 +                      memcpy(data, *myri10ge_gstrings_slice_stats,
 +                             sizeof(myri10ge_gstrings_slice_stats));
 +                      data += sizeof(myri10ge_gstrings_slice_stats);
 +              }
                break;
        }
  }
  
  static int myri10ge_get_sset_count(struct net_device *netdev, int sset)
  {
 +      struct myri10ge_priv *mgp = netdev_priv(netdev);
 +
        switch (sset) {
        case ETH_SS_STATS:
 -              return MYRI10GE_MAIN_STATS_LEN + MYRI10GE_SLICE_STATS_LEN;
 +              return MYRI10GE_MAIN_STATS_LEN +
 +                  mgp->num_slices * MYRI10GE_SLICE_STATS_LEN;
        default:
                return -EOPNOTSUPP;
        }
@@@ -1755,7 -1559,6 +1762,7 @@@ myri10ge_get_ethtool_stats(struct net_d
  {
        struct myri10ge_priv *mgp = netdev_priv(netdev);
        struct myri10ge_slice_state *ss;
 +      int slice;
        int i;
  
        for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++)
        data[i++] = (unsigned int)mgp->wc_enabled;
        data[i++] = (unsigned int)mgp->pdev->irq;
        data[i++] = (unsigned int)mgp->msi_enabled;
 +      data[i++] = (unsigned int)mgp->msix_enabled;
        data[i++] = (unsigned int)mgp->read_dma;
        data[i++] = (unsigned int)mgp->write_dma;
        data[i++] = (unsigned int)mgp->read_write_dma;
        data[i++] = (unsigned int)mgp->serial_number;
        data[i++] = (unsigned int)mgp->watchdog_resets;
 +#ifdef CONFIG_DCA
 +      data[i++] = (unsigned int)(mgp->ss[0].dca_tag != NULL);
 +      data[i++] = (unsigned int)(mgp->dca_enabled);
 +#endif
        data[i++] = (unsigned int)mgp->link_changes;
  
        /* firmware stats are useful only in the first slice */
 -      ss = &mgp->ss;
 +      ss = &mgp->ss[0];
        data[i++] = (unsigned int)ntohl(ss->fw_stats->link_up);
        data[i++] = (unsigned int)ntohl(ss->fw_stats->dropped_link_overflow);
        data[i++] =
        data[i++] = (unsigned int)ntohl(ss->fw_stats->dropped_no_small_buffer);
        data[i++] = (unsigned int)ntohl(ss->fw_stats->dropped_no_big_buffer);
  
 -      data[i++] = 0;
 -      data[i++] = (unsigned int)ss->tx.pkt_start;
 -      data[i++] = (unsigned int)ss->tx.pkt_done;
 -      data[i++] = (unsigned int)ss->tx.req;
 -      data[i++] = (unsigned int)ss->tx.done;
 -      data[i++] = (unsigned int)ss->rx_small.cnt;
 -      data[i++] = (unsigned int)ss->rx_big.cnt;
 -      data[i++] = (unsigned int)ss->tx.wake_queue;
 -      data[i++] = (unsigned int)ss->tx.stop_queue;
 -      data[i++] = (unsigned int)ss->tx.linearized;
 -      data[i++] = ss->rx_done.lro_mgr.stats.aggregated;
 -      data[i++] = ss->rx_done.lro_mgr.stats.flushed;
 -      if (ss->rx_done.lro_mgr.stats.flushed)
 -              data[i++] = ss->rx_done.lro_mgr.stats.aggregated /
 -                  ss->rx_done.lro_mgr.stats.flushed;
 -      else
 -              data[i++] = 0;
 -      data[i++] = ss->rx_done.lro_mgr.stats.no_desc;
 +      for (slice = 0; slice < mgp->num_slices; slice++) {
 +              ss = &mgp->ss[slice];
 +              data[i++] = slice;
 +              data[i++] = (unsigned int)ss->tx.pkt_start;
 +              data[i++] = (unsigned int)ss->tx.pkt_done;
 +              data[i++] = (unsigned int)ss->tx.req;
 +              data[i++] = (unsigned int)ss->tx.done;
 +              data[i++] = (unsigned int)ss->rx_small.cnt;
 +              data[i++] = (unsigned int)ss->rx_big.cnt;
 +              data[i++] = (unsigned int)ss->tx.wake_queue;
 +              data[i++] = (unsigned int)ss->tx.stop_queue;
 +              data[i++] = (unsigned int)ss->tx.linearized;
 +              data[i++] = ss->rx_done.lro_mgr.stats.aggregated;
 +              data[i++] = ss->rx_done.lro_mgr.stats.flushed;
 +              if (ss->rx_done.lro_mgr.stats.flushed)
 +                      data[i++] = ss->rx_done.lro_mgr.stats.aggregated /
 +                          ss->rx_done.lro_mgr.stats.flushed;
 +              else
 +                      data[i++] = 0;
 +              data[i++] = ss->rx_done.lro_mgr.stats.no_desc;
 +      }
  }
  
  static void myri10ge_set_msglevel(struct net_device *netdev, u32 value)
@@@ -1857,15 -1652,12 +1864,15 @@@ static int myri10ge_allocate_rings(stru
        struct net_device *dev = mgp->dev;
        int tx_ring_size, rx_ring_size;
        int tx_ring_entries, rx_ring_entries;
 -      int i, status;
 +      int i, slice, status;
        size_t bytes;
  
        /* get ring sizes */
 +      slice = ss - mgp->ss;
 +      cmd.data0 = slice;
        status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_RING_SIZE, &cmd, 0);
        tx_ring_size = cmd.data0;
 +      cmd.data0 = slice;
        status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd, 0);
        if (status != 0)
                return status;
                                mgp->small_bytes + MXGEFW_PAD, 0);
  
        if (ss->rx_small.fill_cnt < ss->rx_small.mask + 1) {
 -              printk(KERN_ERR "myri10ge: %s: alloced only %d small bufs\n",
 -                     dev->name, ss->rx_small.fill_cnt);
 +              printk(KERN_ERR
 +                     "myri10ge: %s:slice-%d: alloced only %d small bufs\n",
 +                     dev->name, slice, ss->rx_small.fill_cnt);
                goto abort_with_rx_small_ring;
        }
  
        myri10ge_alloc_rx_pages(mgp, &ss->rx_big, mgp->big_bytes, 0);
        if (ss->rx_big.fill_cnt < ss->rx_big.mask + 1) {
 -              printk(KERN_ERR "myri10ge: %s: alloced only %d big bufs\n",
 -                     dev->name, ss->rx_big.fill_cnt);
 +              printk(KERN_ERR
 +                     "myri10ge: %s:slice-%d: alloced only %d big bufs\n",
 +                     dev->name, slice, ss->rx_big.fill_cnt);
                goto abort_with_rx_big_ring;
        }
  
@@@ -1992,10 -1782,6 +1999,10 @@@ static void myri10ge_free_rings(struct 
        struct myri10ge_tx_buf *tx;
        int i, len, idx;
  
 +      /* If not allocated, skip it */
 +      if (ss->tx.req_list == NULL)
 +              return;
 +
        for (i = ss->rx_big.cnt; i < ss->rx_big.fill_cnt; i++) {
                idx = i & ss->rx_big.mask;
                if (i == ss->rx_big.fill_cnt - 1)
  static int myri10ge_request_irq(struct myri10ge_priv *mgp)
  {
        struct pci_dev *pdev = mgp->pdev;
 +      struct myri10ge_slice_state *ss;
 +      struct net_device *netdev = mgp->dev;
 +      int i;
        int status;
  
 +      mgp->msi_enabled = 0;
 +      mgp->msix_enabled = 0;
 +      status = 0;
        if (myri10ge_msi) {
 -              status = pci_enable_msi(pdev);
 -              if (status != 0)
 -                      dev_err(&pdev->dev,
 -                              "Error %d setting up MSI; falling back to xPIC\n",
 -                              status);
 -              else
 -                      mgp->msi_enabled = 1;
 -      } else {
 -              mgp->msi_enabled = 0;
 +              if (mgp->num_slices > 1) {
 +                      status =
 +                          pci_enable_msix(pdev, mgp->msix_vectors,
 +                                          mgp->num_slices);
 +                      if (status == 0) {
 +                              mgp->msix_enabled = 1;
 +                      } else {
 +                              dev_err(&pdev->dev,
 +                                      "Error %d setting up MSI-X\n", status);
 +                              return status;
 +                      }
 +              }
 +              if (mgp->msix_enabled == 0) {
 +                      status = pci_enable_msi(pdev);
 +                      if (status != 0) {
 +                              dev_err(&pdev->dev,
 +                                      "Error %d setting up MSI; falling back to xPIC\n",
 +                                      status);
 +                      } else {
 +                              mgp->msi_enabled = 1;
 +                      }
 +              }
        }
 -      status = request_irq(pdev->irq, myri10ge_intr, IRQF_SHARED,
 -                           mgp->dev->name, mgp);
 -      if (status != 0) {
 -              dev_err(&pdev->dev, "failed to allocate IRQ\n");
 -              if (mgp->msi_enabled)
 -                      pci_disable_msi(pdev);
 +      if (mgp->msix_enabled) {
 +              for (i = 0; i < mgp->num_slices; i++) {
 +                      ss = &mgp->ss[i];
 +                      snprintf(ss->irq_desc, sizeof(ss->irq_desc),
 +                               "%s:slice-%d", netdev->name, i);
 +                      status = request_irq(mgp->msix_vectors[i].vector,
 +                                           myri10ge_intr, 0, ss->irq_desc,
 +                                           ss);
 +                      if (status != 0) {
 +                              dev_err(&pdev->dev,
 +                                      "slice %d failed to allocate IRQ\n", i);
 +                              i--;
 +                              while (i >= 0) {
 +                                      free_irq(mgp->msix_vectors[i].vector,
 +                                               &mgp->ss[i]);
 +                                      i--;
 +                              }
 +                              pci_disable_msix(pdev);
 +                              return status;
 +                      }
 +              }
 +      } else {
 +              status = request_irq(pdev->irq, myri10ge_intr, IRQF_SHARED,
 +                                   mgp->dev->name, &mgp->ss[0]);
 +              if (status != 0) {
 +                      dev_err(&pdev->dev, "failed to allocate IRQ\n");
 +                      if (mgp->msi_enabled)
 +                              pci_disable_msi(pdev);
 +              }
        }
        return status;
  }
  static void myri10ge_free_irq(struct myri10ge_priv *mgp)
  {
        struct pci_dev *pdev = mgp->pdev;
 +      int i;
  
 -      free_irq(pdev->irq, mgp);
 +      if (mgp->msix_enabled) {
 +              for (i = 0; i < mgp->num_slices; i++)
 +                      free_irq(mgp->msix_vectors[i].vector, &mgp->ss[i]);
 +      } else {
 +              free_irq(pdev->irq, &mgp->ss[0]);
 +      }
        if (mgp->msi_enabled)
                pci_disable_msi(pdev);
 +      if (mgp->msix_enabled)
 +              pci_disable_msix(pdev);
  }
  
  static int
@@@ -2199,82 -1935,12 +2206,82 @@@ myri10ge_get_frag_header(struct skb_fra
        return 0;
  }
  
 +static int myri10ge_get_txrx(struct myri10ge_priv *mgp, int slice)
 +{
 +      struct myri10ge_cmd cmd;
 +      struct myri10ge_slice_state *ss;
 +      int status;
 +
 +      ss = &mgp->ss[slice];
 +      cmd.data0 = 0;          /* single slice for now */
 +      status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0);
 +      ss->tx.lanai = (struct mcp_kreq_ether_send __iomem *)
 +          (mgp->sram + cmd.data0);
 +
 +      cmd.data0 = slice;
 +      status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SMALL_RX_OFFSET,
 +                                  &cmd, 0);
 +      ss->rx_small.lanai = (struct mcp_kreq_ether_recv __iomem *)
 +          (mgp->sram + cmd.data0);
 +
 +      cmd.data0 = slice;
 +      status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_BIG_RX_OFFSET, &cmd, 0);
 +      ss->rx_big.lanai = (struct mcp_kreq_ether_recv __iomem *)
 +          (mgp->sram + cmd.data0);
 +
 +      if (myri10ge_wcfifo && mgp->wc_enabled) {
 +              ss->tx.wc_fifo = (u8 __iomem *)
 +                  mgp->sram + MXGEFW_ETH_SEND_4 + 64 * slice;
 +              ss->rx_small.wc_fifo = (u8 __iomem *)
 +                  mgp->sram + MXGEFW_ETH_RECV_SMALL + 64 * slice;
 +              ss->rx_big.wc_fifo = (u8 __iomem *)
 +                  mgp->sram + MXGEFW_ETH_RECV_BIG + 64 * slice;
 +      } else {
 +              ss->tx.wc_fifo = NULL;
 +              ss->rx_small.wc_fifo = NULL;
 +              ss->rx_big.wc_fifo = NULL;
 +      }
 +      return status;
 +
 +}
 +
 +static int myri10ge_set_stats(struct myri10ge_priv *mgp, int slice)
 +{
 +      struct myri10ge_cmd cmd;
 +      struct myri10ge_slice_state *ss;
 +      int status;
 +
 +      ss = &mgp->ss[slice];
 +      cmd.data0 = MYRI10GE_LOWPART_TO_U32(ss->fw_stats_bus);
 +      cmd.data1 = MYRI10GE_HIGHPART_TO_U32(ss->fw_stats_bus);
 +      cmd.data2 = sizeof(struct mcp_irq_data);
 +      status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA_V2, &cmd, 0);
 +      if (status == -ENOSYS) {
 +              dma_addr_t bus = ss->fw_stats_bus;
 +              if (slice != 0)
 +                      return -EINVAL;
 +              bus += offsetof(struct mcp_irq_data, send_done_count);
 +              cmd.data0 = MYRI10GE_LOWPART_TO_U32(bus);
 +              cmd.data1 = MYRI10GE_HIGHPART_TO_U32(bus);
 +              status = myri10ge_send_cmd(mgp,
 +                                         MXGEFW_CMD_SET_STATS_DMA_OBSOLETE,
 +                                         &cmd, 0);
 +              /* Firmware cannot support multicast without STATS_DMA_V2 */
 +              mgp->fw_multicast_support = 0;
 +      } else {
 +              mgp->fw_multicast_support = 1;
 +      }
 +      return 0;
 +}
 +
  static int myri10ge_open(struct net_device *dev)
  {
 +      struct myri10ge_slice_state *ss;
        struct myri10ge_priv *mgp = netdev_priv(dev);
        struct myri10ge_cmd cmd;
 +      int i, status, big_pow2, slice;
 +      u8 *itable;
        struct net_lro_mgr *lro_mgr;
 -      int status, big_pow2;
  
        if (mgp->running != MYRI10GE_ETH_STOPPED)
                return -EBUSY;
                goto abort_with_nothing;
        }
  
 +      if (mgp->num_slices > 1) {
 +              cmd.data0 = mgp->num_slices;
 +              cmd.data1 = 1;  /* use MSI-X */
 +              status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES,
 +                                         &cmd, 0);
 +              if (status != 0) {
 +                      printk(KERN_ERR
 +                             "myri10ge: %s: failed to set number of slices\n",
 +                             dev->name);
 +                      goto abort_with_nothing;
 +              }
 +              /* setup the indirection table */
 +              cmd.data0 = mgp->num_slices;
 +              status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_RSS_TABLE_SIZE,
 +                                         &cmd, 0);
 +
 +              status |= myri10ge_send_cmd(mgp,
 +                                          MXGEFW_CMD_GET_RSS_TABLE_OFFSET,
 +                                          &cmd, 0);
 +              if (status != 0) {
 +                      printk(KERN_ERR
 +                             "myri10ge: %s: failed to setup rss tables\n",
 +                             dev->name);
 +              }
 +
 +              /* just enable an identity mapping */
 +              itable = mgp->sram + cmd.data0;
 +              for (i = 0; i < mgp->num_slices; i++)
 +                      __raw_writeb(i, &itable[i]);
 +
 +              cmd.data0 = 1;
 +              cmd.data1 = myri10ge_rss_hash;
 +              status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_RSS_ENABLE,
 +                                         &cmd, 0);
 +              if (status != 0) {
 +                      printk(KERN_ERR
 +                             "myri10ge: %s: failed to enable slices\n",
 +                             dev->name);
 +                      goto abort_with_nothing;
 +              }
 +      }
 +
        status = myri10ge_request_irq(mgp);
        if (status != 0)
                goto abort_with_nothing;
        if (myri10ge_small_bytes > 0)
                mgp->small_bytes = myri10ge_small_bytes;
  
 -      /* get the lanai pointers to the send and receive rings */
 -
 -      status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0);
 -      mgp->ss.tx.lanai =
 -          (struct mcp_kreq_ether_send __iomem *)(mgp->sram + cmd.data0);
 -
 -      status |=
 -          myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SMALL_RX_OFFSET, &cmd, 0);
 -      mgp->ss.rx_small.lanai =
 -          (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0);
 -
 -      status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_BIG_RX_OFFSET, &cmd, 0);
 -      mgp->ss.rx_big.lanai =
 -          (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0);
 -
 -      if (status != 0) {
 -              printk(KERN_ERR
 -                     "myri10ge: %s: failed to get ring sizes or locations\n",
 -                     dev->name);
 -              mgp->running = MYRI10GE_ETH_STOPPED;
 -              goto abort_with_irq;
 -      }
 -
 -      if (myri10ge_wcfifo && mgp->wc_enabled) {
 -              mgp->ss.tx.wc_fifo = (u8 __iomem *) mgp->sram + MXGEFW_ETH_SEND_4;
 -              mgp->ss.rx_small.wc_fifo =
 -                  (u8 __iomem *) mgp->sram + MXGEFW_ETH_RECV_SMALL;
 -              mgp->ss.rx_big.wc_fifo =
 -                  (u8 __iomem *) mgp->sram + MXGEFW_ETH_RECV_BIG;
 -      } else {
 -              mgp->ss.tx.wc_fifo = NULL;
 -              mgp->ss.rx_small.wc_fifo = NULL;
 -              mgp->ss.rx_big.wc_fifo = NULL;
 -      }
 -
        /* Firmware needs the big buff size as a power of 2.  Lie and
         * tell him the buffer is larger, because we only use 1
         * buffer/pkt, and the mtu will prevent overruns.
                mgp->big_bytes = big_pow2;
        }
  
 -      status = myri10ge_allocate_rings(&mgp->ss);
 -      if (status != 0)
 -              goto abort_with_irq;
 +      /* setup the per-slice data structures */
 +      for (slice = 0; slice < mgp->num_slices; slice++) {
 +              ss = &mgp->ss[slice];
 +
 +              status = myri10ge_get_txrx(mgp, slice);
 +              if (status != 0) {
 +                      printk(KERN_ERR
 +                             "myri10ge: %s: failed to get ring sizes or locations\n",
 +                             dev->name);
 +                      goto abort_with_rings;
 +              }
 +              status = myri10ge_allocate_rings(ss);
 +              if (status != 0)
 +                      goto abort_with_rings;
 +              if (slice == 0)
 +                      status = myri10ge_set_stats(mgp, slice);
 +              if (status) {
 +                      printk(KERN_ERR
 +                             "myri10ge: %s: Couldn't set stats DMA\n",
 +                             dev->name);
 +                      goto abort_with_rings;
 +              }
 +
 +              lro_mgr = &ss->rx_done.lro_mgr;
 +              lro_mgr->dev = dev;
 +              lro_mgr->features = LRO_F_NAPI;
 +              lro_mgr->ip_summed = CHECKSUM_COMPLETE;
 +              lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY;
 +              lro_mgr->max_desc = MYRI10GE_MAX_LRO_DESCRIPTORS;
 +              lro_mgr->lro_arr = ss->rx_done.lro_desc;
 +              lro_mgr->get_frag_header = myri10ge_get_frag_header;
 +              lro_mgr->max_aggr = myri10ge_lro_max_pkts;
 +              if (lro_mgr->max_aggr > MAX_SKB_FRAGS)
 +                      lro_mgr->max_aggr = MAX_SKB_FRAGS;
 +
 +              /* must happen prior to any irq */
 +              napi_enable(&(ss)->napi);
 +      }
  
        /* now give firmware buffers sizes, and MTU */
        cmd.data0 = dev->mtu + ETH_HLEN + VLAN_HLEN;
                goto abort_with_rings;
        }
  
 -      cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->ss.fw_stats_bus);
 -      cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->ss.fw_stats_bus);
 -      cmd.data2 = sizeof(struct mcp_irq_data);
 -      status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA_V2, &cmd, 0);
 -      if (status == -ENOSYS) {
 -              dma_addr_t bus = mgp->ss.fw_stats_bus;
 -              bus += offsetof(struct mcp_irq_data, send_done_count);
 -              cmd.data0 = MYRI10GE_LOWPART_TO_U32(bus);
 -              cmd.data1 = MYRI10GE_HIGHPART_TO_U32(bus);
 -              status = myri10ge_send_cmd(mgp,
 -                                         MXGEFW_CMD_SET_STATS_DMA_OBSOLETE,
 -                                         &cmd, 0);
 -              /* Firmware cannot support multicast without STATS_DMA_V2 */
 -              mgp->fw_multicast_support = 0;
 -      } else {
 -              mgp->fw_multicast_support = 1;
 -      }
 -      if (status) {
 -              printk(KERN_ERR "myri10ge: %s: Couldn't set stats DMA\n",
 +      /*
 +       * Set Linux style TSO mode; this is needed only on newer
 +       *  firmware versions.  Older versions default to Linux
 +       *  style TSO
 +       */
 +      cmd.data0 = 0;
 +      status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_TSO_MODE, &cmd, 0);
 +      if (status && status != -ENOSYS) {
 +              printk(KERN_ERR "myri10ge: %s: Couldn't set TSO mode\n",
                       dev->name);
                goto abort_with_rings;
        }
        mgp->link_state = ~0U;
        mgp->rdma_tags_available = 15;
  
 -      lro_mgr = &mgp->ss.rx_done.lro_mgr;
 -      lro_mgr->dev = dev;
 -      lro_mgr->features = LRO_F_NAPI;
 -      lro_mgr->ip_summed = CHECKSUM_COMPLETE;
 -      lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY;
 -      lro_mgr->max_desc = MYRI10GE_MAX_LRO_DESCRIPTORS;
 -      lro_mgr->lro_arr = mgp->ss.rx_done.lro_desc;
 -      lro_mgr->get_frag_header = myri10ge_get_frag_header;
 -      lro_mgr->max_aggr = myri10ge_lro_max_pkts;
 -      lro_mgr->frag_align_pad = 2;
 -      if (lro_mgr->max_aggr > MAX_SKB_FRAGS)
 -              lro_mgr->max_aggr = MAX_SKB_FRAGS;
 -
 -      napi_enable(&mgp->ss.napi);     /* must happen prior to any irq */
 -
        status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd, 0);
        if (status) {
                printk(KERN_ERR "myri10ge: %s: Couldn't bring up link\n",
                goto abort_with_rings;
        }
  
 -      mgp->ss.tx.wake_queue = 0;
 -      mgp->ss.tx.stop_queue = 0;
        mgp->running = MYRI10GE_ETH_RUNNING;
        mgp->watchdog_timer.expires = jiffies + myri10ge_watchdog_timeout * HZ;
        add_timer(&mgp->watchdog_timer);
        return 0;
  
  abort_with_rings:
 -      myri10ge_free_rings(&mgp->ss);
 +      for (i = 0; i < mgp->num_slices; i++)
 +              myri10ge_free_rings(&mgp->ss[i]);
  
 -abort_with_irq:
        myri10ge_free_irq(mgp);
  
  abort_with_nothing:
@@@ -2464,19 -2115,16 +2471,19 @@@ static int myri10ge_close(struct net_de
        struct myri10ge_priv *mgp = netdev_priv(dev);
        struct myri10ge_cmd cmd;
        int status, old_down_cnt;
 +      int i;
  
        if (mgp->running != MYRI10GE_ETH_RUNNING)
                return 0;
  
 -      if (mgp->ss.tx.req_bytes == NULL)
 +      if (mgp->ss[0].tx.req_bytes == NULL)
                return 0;
  
        del_timer_sync(&mgp->watchdog_timer);
        mgp->running = MYRI10GE_ETH_STOPPING;
 -      napi_disable(&mgp->ss.napi);
 +      for (i = 0; i < mgp->num_slices; i++) {
 +              napi_disable(&mgp->ss[i].napi);
 +      }
        netif_carrier_off(dev);
        netif_stop_queue(dev);
        old_down_cnt = mgp->down_cnt;
  
        netif_tx_disable(dev);
        myri10ge_free_irq(mgp);
 -      myri10ge_free_rings(&mgp->ss);
 +      for (i = 0; i < mgp->num_slices; i++)
 +              myri10ge_free_rings(&mgp->ss[i]);
  
        mgp->running = MYRI10GE_ETH_STOPPED;
        return 0;
@@@ -2614,7 -2261,7 +2621,7 @@@ static int myri10ge_xmit(struct sk_buf
        u8 flags, odd_flag;
  
        /* always transmit through slot 0 */
 -      ss = &mgp->ss;
 +      ss = mgp->ss;
        tx = &ss->tx;
  again:
        req = tx->req_list;
@@@ -2919,21 -2566,7 +2926,21 @@@ drop
  static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
  {
        struct myri10ge_priv *mgp = netdev_priv(dev);
 -      return &mgp->stats;
 +      struct myri10ge_slice_netstats *slice_stats;
 +      struct net_device_stats *stats = &mgp->stats;
 +      int i;
 +
 +      memset(stats, 0, sizeof(*stats));
 +      for (i = 0; i < mgp->num_slices; i++) {
 +              slice_stats = &mgp->ss[i].stats;
 +              stats->rx_packets += slice_stats->rx_packets;
 +              stats->tx_packets += slice_stats->tx_packets;
 +              stats->rx_bytes += slice_stats->rx_bytes;
 +              stats->tx_bytes += slice_stats->tx_bytes;
 +              stats->rx_dropped += slice_stats->rx_dropped;
 +              stats->tx_dropped += slice_stats->tx_dropped;
 +      }
 +      return stats;
  }
  
  static void myri10ge_set_multicast_list(struct net_device *dev)
@@@ -3144,10 -2777,10 +3151,10 @@@ static void myri10ge_enable_ecrc(struc
   *
   * If the driver can neither enable ECRC nor verify that it has
   * already been enabled, then it must use a firmware image which works
 - * around unaligned completion packets (myri10ge_ethp_z8e.dat), and it
 + * around unaligned completion packets (myri10ge_rss_ethp_z8e.dat), and it
   * should also ensure that it never gives the device a Read-DMA which is
   * larger than 2KB by setting the tx_boundary to 2KB.  If ECRC is
 - * enabled, then the driver should use the aligned (myri10ge_eth_z8e.dat)
 + * enabled, then the driver should use the aligned (myri10ge_rss_eth_z8e.dat)
   * firmware image, and set tx_boundary to 4KB.
   */
  
@@@ -3176,7 -2809,7 +3183,7 @@@ static void myri10ge_firmware_probe(str
         * completions) in order to see if it works on this host.
         */
        mgp->fw_name = myri10ge_fw_aligned;
 -      status = myri10ge_load_firmware(mgp);
 +      status = myri10ge_load_firmware(mgp, 1);
        if (status != 0) {
                goto abort;
        }
@@@ -3357,7 -2990,6 +3364,7 @@@ static void myri10ge_watchdog(struct wo
        struct myri10ge_tx_buf *tx;
        u32 reboot;
        int status;
 +      int i;
        u16 cmd, vendor;
  
        mgp->watchdog_resets++;
  
                printk(KERN_ERR "myri10ge: %s: device timeout, resetting\n",
                       mgp->dev->name);
 -              tx = &mgp->ss.tx;
 -              printk(KERN_INFO "myri10ge: %s: %d %d %d %d %d\n",
 -                     mgp->dev->name, tx->req, tx->done,
 -                     tx->pkt_start, tx->pkt_done,
 -                     (int)ntohl(mgp->ss.fw_stats->send_done_count));
 -              msleep(2000);
 -              printk(KERN_INFO "myri10ge: %s: %d %d %d %d %d\n",
 -                     mgp->dev->name, tx->req, tx->done,
 -                     tx->pkt_start, tx->pkt_done,
 -                     (int)ntohl(mgp->ss.fw_stats->send_done_count));
 +              for (i = 0; i < mgp->num_slices; i++) {
 +                      tx = &mgp->ss[i].tx;
 +                      printk(KERN_INFO
 +                             "myri10ge: %s: (%d): %d %d %d %d %d\n",
 +                             mgp->dev->name, i, tx->req, tx->done,
 +                             tx->pkt_start, tx->pkt_done,
 +                             (int)ntohl(mgp->ss[i].fw_stats->
 +                                        send_done_count));
 +                      msleep(2000);
 +                      printk(KERN_INFO
 +                             "myri10ge: %s: (%d): %d %d %d %d %d\n",
 +                             mgp->dev->name, i, tx->req, tx->done,
 +                             tx->pkt_start, tx->pkt_done,
 +                             (int)ntohl(mgp->ss[i].fw_stats->
 +                                        send_done_count));
 +              }
        }
        rtnl_lock();
        myri10ge_close(mgp->dev);
 -      status = myri10ge_load_firmware(mgp);
 +      status = myri10ge_load_firmware(mgp, 1);
        if (status != 0)
                printk(KERN_ERR "myri10ge: %s: failed to load firmware\n",
                       mgp->dev->name);
@@@ -3444,241 -3070,47 +3451,241 @@@ static void myri10ge_watchdog_timer(uns
  {
        struct myri10ge_priv *mgp;
        struct myri10ge_slice_state *ss;
 +      int i, reset_needed;
        u32 rx_pause_cnt;
  
        mgp = (struct myri10ge_priv *)arg;
  
 -      rx_pause_cnt = ntohl(mgp->ss.fw_stats->dropped_pause);
 +      rx_pause_cnt = ntohl(mgp->ss[0].fw_stats->dropped_pause);
 +      for (i = 0, reset_needed = 0;
 +           i < mgp->num_slices && reset_needed == 0; ++i) {
 +
 +              ss = &mgp->ss[i];
 +              if (ss->rx_small.watchdog_needed) {
 +                      myri10ge_alloc_rx_pages(mgp, &ss->rx_small,
 +                                              mgp->small_bytes + MXGEFW_PAD,
 +                                              1);
 +                      if (ss->rx_small.fill_cnt - ss->rx_small.cnt >=
 +                          myri10ge_fill_thresh)
 +                              ss->rx_small.watchdog_needed = 0;
 +              }
 +              if (ss->rx_big.watchdog_needed) {
 +                      myri10ge_alloc_rx_pages(mgp, &ss->rx_big,
 +                                              mgp->big_bytes, 1);
 +                      if (ss->rx_big.fill_cnt - ss->rx_big.cnt >=
 +                          myri10ge_fill_thresh)
 +                              ss->rx_big.watchdog_needed = 0;
 +              }
  
 -      ss = &mgp->ss;
 -      if (ss->rx_small.watchdog_needed) {
 -              myri10ge_alloc_rx_pages(mgp, &ss->rx_small,
 -                                      mgp->small_bytes + MXGEFW_PAD, 1);
 -              if (ss->rx_small.fill_cnt - ss->rx_small.cnt >=
 -                  myri10ge_fill_thresh)
 -                      ss->rx_small.watchdog_needed = 0;
 -      }
 -      if (ss->rx_big.watchdog_needed) {
 -              myri10ge_alloc_rx_pages(mgp, &ss->rx_big, mgp->big_bytes, 1);
 -              if (ss->rx_big.fill_cnt - ss->rx_big.cnt >=
 -                  myri10ge_fill_thresh)
 -                      ss->rx_big.watchdog_needed = 0;
 -      }
 -
 -      if (ss->tx.req != ss->tx.done &&
 -          ss->tx.done == ss->watchdog_tx_done &&
 -          ss->watchdog_tx_req != ss->watchdog_tx_done) {
 -              /* nic seems like it might be stuck.. */
 -              if (rx_pause_cnt != mgp->watchdog_pause) {
 -                      if (net_ratelimit())
 -                              printk(KERN_WARNING "myri10ge %s:"
 -                                     "TX paused, check link partner\n",
 -                                     mgp->dev->name);
 -              } else {
 -                      schedule_work(&mgp->watchdog_work);
 -                      return;
 +              if (ss->tx.req != ss->tx.done &&
 +                  ss->tx.done == ss->watchdog_tx_done &&
 +                  ss->watchdog_tx_req != ss->watchdog_tx_done) {
 +                      /* nic seems like it might be stuck.. */
 +                      if (rx_pause_cnt != mgp->watchdog_pause) {
 +                              if (net_ratelimit())
 +                                      printk(KERN_WARNING "myri10ge %s:"
 +                                             "TX paused, check link partner\n",
 +                                             mgp->dev->name);
 +                      } else {
 +                              reset_needed = 1;
 +                      }
                }
 +              ss->watchdog_tx_done = ss->tx.done;
 +              ss->watchdog_tx_req = ss->tx.req;
        }
 -      /* rearm timer */
 -      mod_timer(&mgp->watchdog_timer,
 -                jiffies + myri10ge_watchdog_timeout * HZ);
 -      ss->watchdog_tx_done = ss->tx.done;
 -      ss->watchdog_tx_req = ss->tx.req;
        mgp->watchdog_pause = rx_pause_cnt;
 +
 +      if (reset_needed) {
 +              schedule_work(&mgp->watchdog_work);
 +      } else {
 +              /* rearm timer */
 +              mod_timer(&mgp->watchdog_timer,
 +                        jiffies + myri10ge_watchdog_timeout * HZ);
 +      }
 +}
 +
 +static void myri10ge_free_slices(struct myri10ge_priv *mgp)
 +{
 +      struct myri10ge_slice_state *ss;
 +      struct pci_dev *pdev = mgp->pdev;
 +      size_t bytes;
 +      int i;
 +
 +      if (mgp->ss == NULL)
 +              return;
 +
 +      for (i = 0; i < mgp->num_slices; i++) {
 +              ss = &mgp->ss[i];
 +              if (ss->rx_done.entry != NULL) {
 +                      bytes = mgp->max_intr_slots *
 +                          sizeof(*ss->rx_done.entry);
 +                      dma_free_coherent(&pdev->dev, bytes,
 +                                        ss->rx_done.entry, ss->rx_done.bus);
 +                      ss->rx_done.entry = NULL;
 +              }
 +              if (ss->fw_stats != NULL) {
 +                      bytes = sizeof(*ss->fw_stats);
 +                      dma_free_coherent(&pdev->dev, bytes,
 +                                        ss->fw_stats, ss->fw_stats_bus);
 +                      ss->fw_stats = NULL;
 +              }
 +      }
 +      kfree(mgp->ss);
 +      mgp->ss = NULL;
 +}
 +
 +static int myri10ge_alloc_slices(struct myri10ge_priv *mgp)
 +{
 +      struct myri10ge_slice_state *ss;
 +      struct pci_dev *pdev = mgp->pdev;
 +      size_t bytes;
 +      int i;
 +
 +      bytes = sizeof(*mgp->ss) * mgp->num_slices;
 +      mgp->ss = kzalloc(bytes, GFP_KERNEL);
 +      if (mgp->ss == NULL) {
 +              return -ENOMEM;
 +      }
 +
 +      for (i = 0; i < mgp->num_slices; i++) {
 +              ss = &mgp->ss[i];
 +              bytes = mgp->max_intr_slots * sizeof(*ss->rx_done.entry);
 +              ss->rx_done.entry = dma_alloc_coherent(&pdev->dev, bytes,
 +                                                     &ss->rx_done.bus,
 +                                                     GFP_KERNEL);
 +              if (ss->rx_done.entry == NULL)
 +                      goto abort;
 +              memset(ss->rx_done.entry, 0, bytes);
 +              bytes = sizeof(*ss->fw_stats);
 +              ss->fw_stats = dma_alloc_coherent(&pdev->dev, bytes,
 +                                                &ss->fw_stats_bus,
 +                                                GFP_KERNEL);
 +              if (ss->fw_stats == NULL)
 +                      goto abort;
 +              ss->mgp = mgp;
 +              ss->dev = mgp->dev;
 +              netif_napi_add(ss->dev, &ss->napi, myri10ge_poll,
 +                             myri10ge_napi_weight);
 +      }
 +      return 0;
 +abort:
 +      myri10ge_free_slices(mgp);
 +      return -ENOMEM;
 +}
 +
 +/*
 + * This function determines the number of slices supported.
 + * The number slices is the minumum of the number of CPUS,
 + * the number of MSI-X irqs supported, the number of slices
 + * supported by the firmware
 + */
 +static void myri10ge_probe_slices(struct myri10ge_priv *mgp)
 +{
 +      struct myri10ge_cmd cmd;
 +      struct pci_dev *pdev = mgp->pdev;
 +      char *old_fw;
 +      int i, status, ncpus, msix_cap;
 +
 +      mgp->num_slices = 1;
 +      msix_cap = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
 +      ncpus = num_online_cpus();
 +
 +      if (myri10ge_max_slices == 1 || msix_cap == 0 ||
 +          (myri10ge_max_slices == -1 && ncpus < 2))
 +              return;
 +
 +      /* try to load the slice aware rss firmware */
 +      old_fw = mgp->fw_name;
 +      if (old_fw == myri10ge_fw_aligned)
 +              mgp->fw_name = myri10ge_fw_rss_aligned;
 +      else
 +              mgp->fw_name = myri10ge_fw_rss_unaligned;
 +      status = myri10ge_load_firmware(mgp, 0);
 +      if (status != 0) {
 +              dev_info(&pdev->dev, "Rss firmware not found\n");
 +              return;
 +      }
 +
 +      /* hit the board with a reset to ensure it is alive */
 +      memset(&cmd, 0, sizeof(cmd));
 +      status = myri10ge_send_cmd(mgp, MXGEFW_CMD_RESET, &cmd, 0);
 +      if (status != 0) {
 +              dev_err(&mgp->pdev->dev, "failed reset\n");
 +              goto abort_with_fw;
 +              return;
 +      }
 +
 +      mgp->max_intr_slots = cmd.data0 / sizeof(struct mcp_slot);
 +
 +      /* tell it the size of the interrupt queues */
 +      cmd.data0 = mgp->max_intr_slots * sizeof(struct mcp_slot);
 +      status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_SIZE, &cmd, 0);
 +      if (status != 0) {
 +              dev_err(&mgp->pdev->dev, "failed MXGEFW_CMD_SET_INTRQ_SIZE\n");
 +              goto abort_with_fw;
 +      }
 +
 +      /* ask the maximum number of slices it supports */
 +      status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_RSS_QUEUES, &cmd, 0);
 +      if (status != 0)
 +              goto abort_with_fw;
 +      else
 +              mgp->num_slices = cmd.data0;
 +
 +      /* Only allow multiple slices if MSI-X is usable */
 +      if (!myri10ge_msi) {
 +              goto abort_with_fw;
 +      }
 +
 +      /* if the admin did not specify a limit to how many
 +       * slices we should use, cap it automatically to the
 +       * number of CPUs currently online */
 +      if (myri10ge_max_slices == -1)
 +              myri10ge_max_slices = ncpus;
 +
 +      if (mgp->num_slices > myri10ge_max_slices)
 +              mgp->num_slices = myri10ge_max_slices;
 +
 +      /* Now try to allocate as many MSI-X vectors as we have
 +       * slices. We give up on MSI-X if we can only get a single
 +       * vector. */
 +
 +      mgp->msix_vectors = kzalloc(mgp->num_slices *
 +                                  sizeof(*mgp->msix_vectors), GFP_KERNEL);
 +      if (mgp->msix_vectors == NULL)
 +              goto disable_msix;
 +      for (i = 0; i < mgp->num_slices; i++) {
 +              mgp->msix_vectors[i].entry = i;
 +      }
 +
 +      while (mgp->num_slices > 1) {
 +              /* make sure it is a power of two */
 +              while (!is_power_of_2(mgp->num_slices))
 +                      mgp->num_slices--;
 +              if (mgp->num_slices == 1)
 +                      goto disable_msix;
 +              status = pci_enable_msix(pdev, mgp->msix_vectors,
 +                                       mgp->num_slices);
 +              if (status == 0) {
 +                      pci_disable_msix(pdev);
 +                      return;
 +              }
 +              if (status > 0)
 +                      mgp->num_slices = status;
 +              else
 +                      goto disable_msix;
 +      }
 +
 +disable_msix:
 +      if (mgp->msix_vectors != NULL) {
 +              kfree(mgp->msix_vectors);
 +              mgp->msix_vectors = NULL;
 +      }
 +
 +abort_with_fw:
 +      mgp->num_slices = 1;
 +      mgp->fw_name = old_fw;
 +      myri10ge_load_firmware(mgp, 0);
  }
  
  static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct net_device *netdev;
        struct myri10ge_priv *mgp;
        struct device *dev = &pdev->dev;
 -      size_t bytes;
        int i;
        int status = -ENXIO;
        int dac_enabled;
  
        mgp = netdev_priv(netdev);
        mgp->dev = netdev;
 -      netif_napi_add(netdev, &mgp->ss.napi, myri10ge_poll, myri10ge_napi_weight);
        mgp->pdev = pdev;
        mgp->csum_flag = MXGEFW_FLAGS_CKSUM;
        mgp->pause = myri10ge_flow_control;
        if (mgp->cmd == NULL)
                goto abort_with_netdev;
  
 -      mgp->ss.fw_stats = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->ss.fw_stats),
 -                                         &mgp->ss.fw_stats_bus, GFP_KERNEL);
 -      if (mgp->ss.fw_stats == NULL)
 -              goto abort_with_cmd;
 -
        mgp->board_span = pci_resource_len(pdev, 0);
        mgp->iomem_base = pci_resource_start(pdev, 0);
        mgp->mtrr = -1;
        for (i = 0; i < ETH_ALEN; i++)
                netdev->dev_addr[i] = mgp->mac_addr[i];
  
 -      /* allocate rx done ring */
 -      bytes = mgp->max_intr_slots * sizeof(*mgp->ss.rx_done.entry);
 -      mgp->ss.rx_done.entry = dma_alloc_coherent(&pdev->dev, bytes,
 -                                              &mgp->ss.rx_done.bus, GFP_KERNEL);
 -      if (mgp->ss.rx_done.entry == NULL)
 -              goto abort_with_ioremap;
 -      memset(mgp->ss.rx_done.entry, 0, bytes);
 -
        myri10ge_select_firmware(mgp);
  
 -      status = myri10ge_load_firmware(mgp);
 +      status = myri10ge_load_firmware(mgp, 1);
        if (status != 0) {
                dev_err(&pdev->dev, "failed to load firmware\n");
 -              goto abort_with_rx_done;
 +              goto abort_with_ioremap;
 +      }
 +      myri10ge_probe_slices(mgp);
 +      status = myri10ge_alloc_slices(mgp);
 +      if (status != 0) {
 +              dev_err(&pdev->dev, "failed to alloc slice state\n");
 +              goto abort_with_firmware;
        }
  
        status = myri10ge_reset(mgp);
        if (status != 0) {
                dev_err(&pdev->dev, "failed reset\n");
 -              goto abort_with_firmware;
 +              goto abort_with_slices;
        }
 -
 +#ifdef CONFIG_DCA
 +      myri10ge_setup_dca(mgp);
 +#endif
        pci_set_drvdata(pdev, mgp);
        if ((myri10ge_initial_mtu + ETH_HLEN) > MYRI10GE_MAX_ETHER_MTU)
                myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;
                dev_err(&pdev->dev, "register_netdev failed: %d\n", status);
                goto abort_with_state;
        }
 -      dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, WC %s\n",
 -               (mgp->msi_enabled ? "MSI" : "xPIC"),
 -               netdev->irq, mgp->tx_boundary, mgp->fw_name,
 -               (mgp->wc_enabled ? "Enabled" : "Disabled"));
 +      if (mgp->msix_enabled)
 +              dev_info(dev, "%d MSI-X IRQs, tx bndry %d, fw %s, WC %s\n",
 +                       mgp->num_slices, mgp->tx_boundary, mgp->fw_name,
 +                       (mgp->wc_enabled ? "Enabled" : "Disabled"));
 +      else
 +              dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, WC %s\n",
 +                       mgp->msi_enabled ? "MSI" : "xPIC",
 +                       netdev->irq, mgp->tx_boundary, mgp->fw_name,
 +                       (mgp->wc_enabled ? "Enabled" : "Disabled"));
  
        return 0;
  
  abort_with_state:
        pci_restore_state(pdev);
  
 +abort_with_slices:
 +      myri10ge_free_slices(mgp);
 +
  abort_with_firmware:
        myri10ge_dummy_rdma(mgp, 0);
  
 -abort_with_rx_done:
 -      bytes = mgp->max_intr_slots * sizeof(*mgp->ss.rx_done.entry);
 -      dma_free_coherent(&pdev->dev, bytes,
 -                        mgp->ss.rx_done.entry, mgp->ss.rx_done.bus);
 -
  abort_with_ioremap:
        iounmap(mgp->sram);
  
@@@ -3874,6 -3310,10 +3881,6 @@@ abort_with_wc
        if (mgp->mtrr >= 0)
                mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span);
  #endif
 -      dma_free_coherent(&pdev->dev, sizeof(*mgp->ss.fw_stats),
 -                        mgp->ss.fw_stats, mgp->ss.fw_stats_bus);
 -
 -abort_with_cmd:
        dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd),
                          mgp->cmd, mgp->cmd_bus);
  
@@@ -3894,6 -3334,7 +3901,6 @@@ static void myri10ge_remove(struct pci_
  {
        struct myri10ge_priv *mgp;
        struct net_device *netdev;
 -      size_t bytes;
  
        mgp = pci_get_drvdata(pdev);
        if (mgp == NULL)
        netdev = mgp->dev;
        unregister_netdev(netdev);
  
 +#ifdef CONFIG_DCA
 +      myri10ge_teardown_dca(mgp);
 +#endif
        myri10ge_dummy_rdma(mgp, 0);
  
        /* avoid a memory leak */
        pci_restore_state(pdev);
  
 -      bytes = mgp->max_intr_slots * sizeof(*mgp->ss.rx_done.entry);
 -      dma_free_coherent(&pdev->dev, bytes,
 -                        mgp->ss.rx_done.entry, mgp->ss.rx_done.bus);
 -
        iounmap(mgp->sram);
  
  #ifdef CONFIG_MTRR
        if (mgp->mtrr >= 0)
                mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span);
  #endif
 -      dma_free_coherent(&pdev->dev, sizeof(*mgp->ss.fw_stats),
 -                        mgp->ss.fw_stats, mgp->ss.fw_stats_bus);
 -
 +      myri10ge_free_slices(mgp);
 +      if (mgp->msix_vectors != NULL)
 +              kfree(mgp->msix_vectors);
        dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd),
                          mgp->cmd, mgp->cmd_bus);
  
@@@ -3948,42 -3390,10 +3955,42 @@@ static struct pci_driver myri10ge_drive
  #endif
  };
  
 +#ifdef CONFIG_DCA
 +static int
 +myri10ge_notify_dca(struct notifier_block *nb, unsigned long event, void *p)
 +{
 +      int err = driver_for_each_device(&myri10ge_driver.driver,
 +                                       NULL, &event,
 +                                       myri10ge_notify_dca_device);
 +
 +      if (err)
 +              return NOTIFY_BAD;
 +      return NOTIFY_DONE;
 +}
 +
 +static struct notifier_block myri10ge_dca_notifier = {
 +      .notifier_call = myri10ge_notify_dca,
 +      .next = NULL,
 +      .priority = 0,
 +};
 +#endif                                /* CONFIG_DCA */
 +
  static __init int myri10ge_init_module(void)
  {
        printk(KERN_INFO "%s: Version %s\n", myri10ge_driver.name,
               MYRI10GE_VERSION_STR);
 +
 +      if (myri10ge_rss_hash > MXGEFW_RSS_HASH_TYPE_SRC_PORT ||
 +          myri10ge_rss_hash < MXGEFW_RSS_HASH_TYPE_IPV4) {
 +              printk(KERN_ERR
 +                     "%s: Illegal rssh hash type %d, defaulting to source port\n",
 +                     myri10ge_driver.name, myri10ge_rss_hash);
 +              myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_PORT;
 +      }
 +#ifdef CONFIG_DCA
 +      dca_register_notify(&myri10ge_dca_notifier);
 +#endif
 +
        return pci_register_driver(&myri10ge_driver);
  }
  
@@@ -3991,9 -3401,6 +3998,9 @@@ module_init(myri10ge_init_module)
  
  static __exit void myri10ge_cleanup_module(void)
  {
 +#ifdef CONFIG_DCA
 +      dca_unregister_notify(&myri10ge_dca_notifier);
 +#endif
        pci_unregister_driver(&myri10ge_driver);
  }
  
index c926bf0b190efd6d9abe3cba36a477102731f4f8,83625fdff3dd810944aa8cbd60165a32b1a3f937..6b1d7a8edf1554aeff5680fd4f467f2444dce498
@@@ -39,6 -39,7 +39,7 @@@
  #include <linux/if_arp.h>
  #include <linux/ip.h>
  #include <linux/tcp.h>
+ #include <linux/smp_lock.h>
  #include <linux/spinlock.h>
  #include <linux/rwsem.h>
  #include <linux/stddef.h>
@@@ -353,6 -354,7 +354,7 @@@ static const int npindex_to_ethertype[N
   */
  static int ppp_open(struct inode *inode, struct file *file)
  {
+       cycle_kernel_lock();
        /*
         * This could (should?) be enforced by the permissions on /dev/ppp.
         */
        return 0;
  }
  
 -static int ppp_release(struct inode *inode, struct file *file)
 +static int ppp_release(struct inode *unused, struct file *file)
  {
        struct ppp_file *pf = file->private_data;
        struct ppp *ppp;
@@@ -545,7 -547,8 +547,7 @@@ static int get_filter(void __user *arg
  }
  #endif /* CONFIG_PPP_FILTER */
  
 -static int ppp_ioctl(struct inode *inode, struct file *file,
 -                   unsigned int cmd, unsigned long arg)
 +static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
        struct ppp_file *pf = file->private_data;
        struct ppp *ppp;
                 * this fd and reopening /dev/ppp.
                 */
                err = -EINVAL;
 +              lock_kernel();
                if (pf->kind == INTERFACE) {
                        ppp = PF_TO_PPP(pf);
                        if (file == ppp->owner)
                                ppp_shutdown_interface(ppp);
                }
                if (atomic_read(&file->f_count) <= 2) {
 -                      ppp_release(inode, file);
 +                      ppp_release(NULL, file);
                        err = 0;
                } else
                        printk(KERN_DEBUG "PPPIOCDETACH file->f_count=%d\n",
                               atomic_read(&file->f_count));
 +              unlock_kernel();
                return err;
        }
  
        if (pf->kind == CHANNEL) {
 -              struct channel *pch = PF_TO_CHANNEL(pf);
 +              struct channel *pch;
                struct ppp_channel *chan;
  
 +              lock_kernel();
 +              pch = PF_TO_CHANNEL(pf);
 +
                switch (cmd) {
                case PPPIOCCONNECT:
                        if (get_user(unit, p))
                                err = chan->ops->ioctl(chan, cmd, arg);
                        up_read(&pch->chan_sem);
                }
 +              unlock_kernel();
                return err;
        }
  
                return -EINVAL;
        }
  
 +      lock_kernel();
        ppp = PF_TO_PPP(pf);
        switch (cmd) {
        case PPPIOCSMRU:
        default:
                err = -ENOTTY;
        }
 -
 +      unlock_kernel();
        return err;
  }
  
@@@ -785,7 -781,6 +787,7 @@@ static int ppp_unattached_ioctl(struct 
        struct channel *chan;
        int __user *p = (int __user *)arg;
  
 +      lock_kernel();
        switch (cmd) {
        case PPPIOCNEWUNIT:
                /* Create a new ppp unit */
        default:
                err = -ENOTTY;
        }
 +      unlock_kernel();
        return err;
  }
  
@@@ -843,7 -837,7 +845,7 @@@ static const struct file_operations ppp
        .read           = ppp_read,
        .write          = ppp_write,
        .poll           = ppp_poll,
 -      .ioctl          = ppp_ioctl,
 +      .unlocked_ioctl = ppp_ioctl,
        .open           = ppp_open,
        .release        = ppp_release
  };
diff --combined drivers/net/tun.c
index 901551c8ca0ea1c34457a47f89f1c42f856d84c2,eba1271b9735cec24b5a9b986b9958ee95337332..a82b32b401319c0749eac671849e2e2792edca1b
  /*
   *  Changes:
   *
 - *  Brian Braunstein <linuxkernel@bristyle.com> 2007/03/23
 - *    Fixed hw address handling.  Now net_device.dev_addr is kept consistent
 - *    with tun.dev_addr when the address is set by this module.
 - *
   *  Mike Kershaw <dragorn@kismetwireless.net> 2005/08/14
   *    Add TUNSETLINK ioctl to set the link encapsulation
   *
   *  Mark Smith <markzzzsmith@yahoo.com.au>
 - *   Use random_ether_addr() for tap MAC address.
 + *    Use random_ether_addr() for tap MAC address.
   *
   *  Harald Roelle <harald.roelle@ifi.lmu.de>  2004/04/20
   *    Fixes in packet dropping, queue length setting and queue wakeup.
@@@ -44,6 -48,7 +44,7 @@@
  #include <linux/kernel.h>
  #include <linux/major.h>
  #include <linux/slab.h>
+ #include <linux/smp_lock.h>
  #include <linux/poll.h>
  #include <linux/fcntl.h>
  #include <linux/init.h>
@@@ -59,7 -64,6 +60,7 @@@
  #include <linux/if_tun.h>
  #include <linux/crc32.h>
  #include <linux/nsproxy.h>
 +#include <linux/virtio_net.h>
  #include <net/net_namespace.h>
  #include <net/netns/generic.h>
  
@@@ -79,16 -83,9 +80,16 @@@ static int debug
  #define DBG1( a... )
  #endif
  
 +#define FLT_EXACT_COUNT 8
 +struct tap_filter {
 +      unsigned int    count;    /* Number of addrs. Zero means disabled */
 +      u32             mask[2];  /* Mask of the hashed addrs */
 +      unsigned char   addr[FLT_EXACT_COUNT][ETH_ALEN];
 +};
 +
  struct tun_struct {
        struct list_head        list;
 -      unsigned long           flags;
 +      unsigned int            flags;
        int                     attached;
        uid_t                   owner;
        gid_t                   group;
        struct sk_buff_head     readq;
  
        struct net_device       *dev;
 +      struct fasync_struct    *fasync;
  
 -      struct fasync_struct    *fasync;
 -
 -      unsigned long if_flags;
 -      u8 dev_addr[ETH_ALEN];
 -      u32 chr_filter[2];
 -      u32 net_filter[2];
 +      struct tap_filter       txflt;
  
  #ifdef TUN_DEBUG
        int debug;
  #endif
  };
  
 +/* TAP filterting */
 +static void addr_hash_set(u32 *mask, const u8 *addr)
 +{
 +      int n = ether_crc(ETH_ALEN, addr) >> 26;
 +      mask[n >> 5] |= (1 << (n & 31));
 +}
 +
 +static unsigned int addr_hash_test(const u32 *mask, const u8 *addr)
 +{
 +      int n = ether_crc(ETH_ALEN, addr) >> 26;
 +      return mask[n >> 5] & (1 << (n & 31));
 +}
 +
 +static int update_filter(struct tap_filter *filter, void __user *arg)
 +{
 +      struct { u8 u[ETH_ALEN]; } *addr;
 +      struct tun_filter uf;
 +      int err, alen, n, nexact;
 +
 +      if (copy_from_user(&uf, arg, sizeof(uf)))
 +              return -EFAULT;
 +
 +      if (!uf.count) {
 +              /* Disabled */
 +              filter->count = 0;
 +              return 0;
 +      }
 +
 +      alen = ETH_ALEN * uf.count;
 +      addr = kmalloc(alen, GFP_KERNEL);
 +      if (!addr)
 +              return -ENOMEM;
 +
 +      if (copy_from_user(addr, arg + sizeof(uf), alen)) {
 +              err = -EFAULT;
 +              goto done;
 +      }
 +
 +      /* The filter is updated without holding any locks. Which is
 +       * perfectly safe. We disable it first and in the worst
 +       * case we'll accept a few undesired packets. */
 +      filter->count = 0;
 +      wmb();
 +
 +      /* Use first set of addresses as an exact filter */
 +      for (n = 0; n < uf.count && n < FLT_EXACT_COUNT; n++)
 +              memcpy(filter->addr[n], addr[n].u, ETH_ALEN);
 +
 +      nexact = n;
 +
 +      /* The rest is hashed */
 +      memset(filter->mask, 0, sizeof(filter->mask));
 +      for (; n < uf.count; n++)
 +              addr_hash_set(filter->mask, addr[n].u);
 +
 +      /* For ALLMULTI just set the mask to all ones.
 +       * This overrides the mask populated above. */
 +      if ((uf.flags & TUN_FLT_ALLMULTI))
 +              memset(filter->mask, ~0, sizeof(filter->mask));
 +
 +      /* Now enable the filter */
 +      wmb();
 +      filter->count = nexact;
 +
 +      /* Return the number of exact filters */
 +      err = nexact;
 +
 +done:
 +      kfree(addr);
 +      return err;
 +}
 +
 +/* Returns: 0 - drop, !=0 - accept */
 +static int run_filter(struct tap_filter *filter, const struct sk_buff *skb)
 +{
 +      /* Cannot use eth_hdr(skb) here because skb_mac_hdr() is incorrect
 +       * at this point. */
 +      struct ethhdr *eh = (struct ethhdr *) skb->data;
 +      int i;
 +
 +      /* Exact match */
 +      for (i = 0; i < filter->count; i++)
 +              if (!compare_ether_addr(eh->h_dest, filter->addr[i]))
 +                      return 1;
 +
 +      /* Inexact match (multicast only) */
 +      if (is_multicast_ether_addr(eh->h_dest))
 +              return addr_hash_test(filter->mask, eh->h_dest);
 +
 +      return 0;
 +}
 +
 +/*
 + * Checks whether the packet is accepted or not.
 + * Returns: 0 - drop, !=0 - accept
 + */
 +static int check_filter(struct tap_filter *filter, const struct sk_buff *skb)
 +{
 +      if (!filter->count)
 +              return 1;
 +
 +      return run_filter(filter, skb);
 +}
 +
  /* Network device part of the driver */
  
  static unsigned int tun_net_id;
@@@ -244,12 -141,7 +245,12 @@@ static int tun_net_xmit(struct sk_buff 
        if (!tun->attached)
                goto drop;
  
 -      /* Packet dropping */
 +      /* Drop if the filter does not like it.
 +       * This is a noop if the filter is disabled.
 +       * Filter can be enabled only for the TAP devices. */
 +      if (!check_filter(&tun->txflt, skb))
 +              goto drop;
 +
        if (skb_queue_len(&tun->readq) >= dev->tx_queue_len) {
                if (!(tun->flags & TUN_ONE_QUEUE)) {
                        /* Normal queueing mode. */
                }
        }
  
 -      /* Queue packet */
 +      /* Enqueue packet */
        skb_queue_tail(&tun->readq, skb);
        dev->trans_start = jiffies;
  
@@@ -282,14 -174,41 +283,14 @@@ drop
        return 0;
  }
  
 -/** Add the specified Ethernet address to this multicast filter. */
 -static void
 -add_multi(u32* filter, const u8* addr)
 +static void tun_net_mclist(struct net_device *dev)
  {
 -      int bit_nr = ether_crc(ETH_ALEN, addr) >> 26;
 -      filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
 -}
 -
 -/** Remove the specified Ethernet addres from this multicast filter. */
 -static void
 -del_multi(u32* filter, const u8* addr)
 -{
 -      int bit_nr = ether_crc(ETH_ALEN, addr) >> 26;
 -      filter[bit_nr >> 5] &= ~(1 << (bit_nr & 31));
 -}
 -
 -/** Update the list of multicast groups to which the network device belongs.
 - * This list is used to filter packets being sent from the character device to
 - * the network device. */
 -static void
 -tun_net_mclist(struct net_device *dev)
 -{
 -      struct tun_struct *tun = netdev_priv(dev);
 -      const struct dev_mc_list *mclist;
 -      int i;
 -      DECLARE_MAC_BUF(mac);
 -      DBG(KERN_DEBUG "%s: tun_net_mclist: mc_count %d\n",
 -                      dev->name, dev->mc_count);
 -      memset(tun->chr_filter, 0, sizeof tun->chr_filter);
 -      for (i = 0, mclist = dev->mc_list; i < dev->mc_count && mclist != NULL;
 -                      i++, mclist = mclist->next) {
 -              add_multi(tun->net_filter, mclist->dmi_addr);
 -              DBG(KERN_DEBUG "%s: tun_net_mclist: %s\n",
 -                  dev->name, print_mac(mac, mclist->dmi_addr));
 -      }
 +      /*
 +       * This callback is supposed to deal with mc filter in
 +       * _rx_ path and has nothing to do with the _tx_ path.
 +       * In rx path we always accept everything userspace gives us.
 +       */
 +      return;
  }
  
  #define MIN_MTU 68
@@@ -325,11 -244,13 +326,11 @@@ static void tun_net_init(struct net_dev
  
        case TUN_TAP_DEV:
                /* Ethernet TAP Device */
 -              dev->set_multicast_list = tun_net_mclist;
 -
                ether_setup(dev);
 -              dev->change_mtu = tun_net_change_mtu;
 +              dev->change_mtu         = tun_net_change_mtu;
 +              dev->set_multicast_list = tun_net_mclist;
  
 -              /* random address already created for us by tun_set_iff, use it */
 -              memcpy(dev->dev_addr, tun->dev_addr, min(sizeof(tun->dev_addr), sizeof(dev->dev_addr)) );
 +              random_ether_addr(dev->dev_addr);
  
                dev->tx_queue_len = TUN_READQ_SIZE;  /* We prefer our own queue length */
                break;
@@@ -363,7 -284,6 +364,7 @@@ static __inline__ ssize_t tun_get_user(
        struct tun_pi pi = { 0, __constant_htons(ETH_P_IP) };
        struct sk_buff *skb;
        size_t len = count, align = 0;
 +      struct virtio_net_hdr gso = { 0 };
  
        if (!(tun->flags & TUN_NO_PI)) {
                if ((len -= sizeof(pi)) > count)
                        return -EFAULT;
        }
  
 +      if (tun->flags & TUN_VNET_HDR) {
 +              if ((len -= sizeof(gso)) > count)
 +                      return -EINVAL;
 +
 +              if (memcpy_fromiovec((void *)&gso, iv, sizeof(gso)))
 +                      return -EFAULT;
 +
 +              if (gso.hdr_len > len)
 +                      return -EINVAL;
 +      }
 +
        if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) {
                align = NET_IP_ALIGN;
                if (unlikely(len < ETH_HLEN))
                return -EFAULT;
        }
  
 +      if (gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
 +              if (!skb_partial_csum_set(skb, gso.csum_start,
 +                                        gso.csum_offset)) {
 +                      tun->dev->stats.rx_frame_errors++;
 +                      kfree_skb(skb);
 +                      return -EINVAL;
 +              }
 +      } else if (tun->flags & TUN_NOCHECKSUM)
 +              skb->ip_summed = CHECKSUM_UNNECESSARY;
 +
        switch (tun->flags & TUN_TYPE_MASK) {
        case TUN_TUN_DEV:
                if (tun->flags & TUN_NO_PI) {
                break;
        };
  
 -      if (tun->flags & TUN_NOCHECKSUM)
 -              skb->ip_summed = CHECKSUM_UNNECESSARY;
 +      if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
 +              pr_debug("GSO!\n");
 +              switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
 +              case VIRTIO_NET_HDR_GSO_TCPV4:
 +                      skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
 +                      break;
 +              case VIRTIO_NET_HDR_GSO_TCPV6:
 +                      skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
 +                      break;
 +              default:
 +                      tun->dev->stats.rx_frame_errors++;
 +                      kfree_skb(skb);
 +                      return -EINVAL;
 +              }
 +
 +              if (gso.gso_type & VIRTIO_NET_HDR_GSO_ECN)
 +                      skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
 +
 +              skb_shinfo(skb)->gso_size = gso.gso_size;
 +              if (skb_shinfo(skb)->gso_size == 0) {
 +                      tun->dev->stats.rx_frame_errors++;
 +                      kfree_skb(skb);
 +                      return -EINVAL;
 +              }
 +
 +              /* Header must be checked, and gso_segs computed. */
 +              skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
 +              skb_shinfo(skb)->gso_segs = 0;
 +      }
  
        netif_rx_ni(skb);
        tun->dev->last_rx = jiffies;
@@@ -513,39 -385,6 +514,39 @@@ static __inline__ ssize_t tun_put_user(
                total += sizeof(pi);
        }
  
 +      if (tun->flags & TUN_VNET_HDR) {
 +              struct virtio_net_hdr gso = { 0 }; /* no info leak */
 +              if ((len -= sizeof(gso)) < 0)
 +                      return -EINVAL;
 +
 +              if (skb_is_gso(skb)) {
 +                      struct skb_shared_info *sinfo = skb_shinfo(skb);
 +
 +                      /* This is a hint as to how much should be linear. */
 +                      gso.hdr_len = skb_headlen(skb);
 +                      gso.gso_size = sinfo->gso_size;
 +                      if (sinfo->gso_type & SKB_GSO_TCPV4)
 +                              gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
 +                      else if (sinfo->gso_type & SKB_GSO_TCPV6)
 +                              gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
 +                      else
 +                              BUG();
 +                      if (sinfo->gso_type & SKB_GSO_TCP_ECN)
 +                              gso.gso_type |= VIRTIO_NET_HDR_GSO_ECN;
 +              } else
 +                      gso.gso_type = VIRTIO_NET_HDR_GSO_NONE;
 +
 +              if (skb->ip_summed == CHECKSUM_PARTIAL) {
 +                      gso.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
 +                      gso.csum_start = skb->csum_start - skb_headroom(skb);
 +                      gso.csum_offset = skb->csum_offset;
 +              } /* else everything is zero */
 +
 +              if (unlikely(memcpy_toiovec(iv, (void *)&gso, sizeof(gso))))
 +                      return -EFAULT;
 +              total += sizeof(gso);
 +      }
 +
        len = min_t(int, skb->len, len);
  
        skb_copy_datagram_iovec(skb, 0, iv, len);
@@@ -565,6 -404,7 +566,6 @@@ static ssize_t tun_chr_aio_read(struct 
        DECLARE_WAITQUEUE(wait, current);
        struct sk_buff *skb;
        ssize_t len, ret = 0;
 -      DECLARE_MAC_BUF(mac);
  
        if (!tun)
                return -EBADFD;
  
        add_wait_queue(&tun->read_wait, &wait);
        while (len) {
 -              const u8 ones[ ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 -              u8 addr[ ETH_ALEN];
 -              int bit_nr;
 -
                current->state = TASK_INTERRUPTIBLE;
  
                /* Read frames from the queue */
                }
                netif_wake_queue(tun->dev);
  
 -              /** Decide whether to accept this packet. This code is designed to
 -               * behave identically to an Ethernet interface. Accept the packet if
 -               * - we are promiscuous.
 -               * - the packet is addressed to us.
 -               * - the packet is broadcast.
 -               * - the packet is multicast and
 -               *   - we are multicast promiscous.
 -               *   - we belong to the multicast group.
 -               */
 -              skb_copy_from_linear_data(skb, addr, min_t(size_t, sizeof addr,
 -                                                                 skb->len));
 -              bit_nr = ether_crc(sizeof addr, addr) >> 26;
 -              if ((tun->if_flags & IFF_PROMISC) ||
 -                              memcmp(addr, tun->dev_addr, sizeof addr) == 0 ||
 -                              memcmp(addr, ones, sizeof addr) == 0 ||
 -                              (((addr[0] == 1 && addr[1] == 0 && addr[2] == 0x5e) ||
 -                                (addr[0] == 0x33 && addr[1] == 0x33)) &&
 -                               ((tun->if_flags & IFF_ALLMULTI) ||
 -                                (tun->chr_filter[bit_nr >> 5] & (1 << (bit_nr & 31)))))) {
 -                      DBG(KERN_DEBUG "%s: tun_chr_readv: accepted: %s\n",
 -                                      tun->dev->name, print_mac(mac, addr));
 -                      ret = tun_put_user(tun, skb, (struct iovec *) iv, len);
 -                      kfree_skb(skb);
 -                      break;
 -              } else {
 -                      DBG(KERN_DEBUG "%s: tun_chr_readv: rejected: %s\n",
 -                                      tun->dev->name, print_mac(mac, addr));
 -                      kfree_skb(skb);
 -                      continue;
 -              }
 +              ret = tun_put_user(tun, skb, (struct iovec *) iv, len);
 +              kfree_skb(skb);
 +              break;
        }
  
        current->state = TASK_RUNNING;
@@@ -694,7 -565,12 +695,7 @@@ static int tun_set_iff(struct net *net
                tun = netdev_priv(dev);
                tun->dev = dev;
                tun->flags = flags;
 -              /* Be promiscuous by default to maintain previous behaviour. */
 -              tun->if_flags = IFF_PROMISC;
 -              /* Generate random Ethernet address. */
 -              *(__be16 *)tun->dev_addr = htons(0x00FF);
 -              get_random_bytes(tun->dev_addr + sizeof(u16), 4);
 -              memset(tun->chr_filter, 0, sizeof tun->chr_filter);
 +              tun->txflt.count = 0;
  
                tun_net_init(dev);
  
        else
                tun->flags &= ~TUN_ONE_QUEUE;
  
 +      if (ifr->ifr_flags & IFF_VNET_HDR)
 +              tun->flags |= TUN_VNET_HDR;
 +      else
 +              tun->flags &= ~TUN_VNET_HDR;
 +
        file->private_data = tun;
        tun->attached = 1;
        get_net(dev_net(tun->dev));
        return err;
  }
  
 +/* This is like a cut-down ethtool ops, except done via tun fd so no
 + * privs required. */
 +static int set_offload(struct net_device *dev, unsigned long arg)
 +{
 +      unsigned int old_features, features;
 +
 +      old_features = dev->features;
 +      /* Unset features, set them as we chew on the arg. */
 +      features = (old_features & ~(NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST
 +                                  |NETIF_F_TSO_ECN|NETIF_F_TSO|NETIF_F_TSO6));
 +
 +      if (arg & TUN_F_CSUM) {
 +              features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
 +              arg &= ~TUN_F_CSUM;
 +
 +              if (arg & (TUN_F_TSO4|TUN_F_TSO6)) {
 +                      if (arg & TUN_F_TSO_ECN) {
 +                              features |= NETIF_F_TSO_ECN;
 +                              arg &= ~TUN_F_TSO_ECN;
 +                      }
 +                      if (arg & TUN_F_TSO4)
 +                              features |= NETIF_F_TSO;
 +                      if (arg & TUN_F_TSO6)
 +                              features |= NETIF_F_TSO6;
 +                      arg &= ~(TUN_F_TSO4|TUN_F_TSO6);
 +              }
 +      }
 +
 +      /* This gives the user a way to test for new features in future by
 +       * trying to set them. */
 +      if (arg)
 +              return -EINVAL;
 +
 +      dev->features = features;
 +      if (old_features != dev->features)
 +              netdev_features_change(dev);
 +
 +      return 0;
 +}
 +
  static int tun_chr_ioctl(struct inode *inode, struct file *file,
                         unsigned int cmd, unsigned long arg)
  {
        struct tun_struct *tun = file->private_data;
        void __user* argp = (void __user*)arg;
        struct ifreq ifr;
 +      int ret;
        DECLARE_MAC_BUF(mac);
  
        if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89)
                return 0;
        }
  
 +      if (cmd == TUNGETFEATURES) {
 +              /* Currently this just means: "what IFF flags are valid?".
 +               * This is needed because we never checked for invalid flags on
 +               * TUNSETIFF. */
 +              return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE |
 +                              IFF_VNET_HDR,
 +                              (unsigned int __user*)argp);
 +      }
 +
        if (!tun)
                return -EBADFD;
  
                break;
  
        case TUNSETLINK:
 -      {
 -              int ret;
 -
                /* Only allow setting the type when the interface is down */
                rtnl_lock();
                if (tun->dev->flags & IFF_UP) {
                }
                rtnl_unlock();
                return ret;
 -      }
  
  #ifdef TUN_DEBUG
        case TUNSETDEBUG:
                tun->debug = arg;
                break;
  #endif
 +      case TUNSETOFFLOAD:
 +              rtnl_lock();
 +              ret = set_offload(tun->dev, arg);
 +              rtnl_unlock();
 +              return ret;
  
 -      case SIOCGIFFLAGS:
 -              ifr.ifr_flags = tun->if_flags;
 -              if (copy_to_user( argp, &ifr, sizeof ifr))
 -                      return -EFAULT;
 -              return 0;
 -
 -      case SIOCSIFFLAGS:
 -              /** Set the character device's interface flags. Currently only
 -               * IFF_PROMISC and IFF_ALLMULTI are used. */
 -              tun->if_flags = ifr.ifr_flags;
 -              DBG(KERN_INFO "%s: interface flags 0x%lx\n",
 -                              tun->dev->name, tun->if_flags);
 -              return 0;
 +      case TUNSETTXFILTER:
 +              /* Can be set only for TAPs */
 +              if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
 +                      return -EINVAL;
 +              rtnl_lock();
 +              ret = update_filter(&tun->txflt, (void *) __user arg);
 +              rtnl_unlock();
 +              return ret;
  
        case SIOCGIFHWADDR:
 -              /* Note: the actual net device's address may be different */
 -              memcpy(ifr.ifr_hwaddr.sa_data, tun->dev_addr,
 -                              min(sizeof ifr.ifr_hwaddr.sa_data, sizeof tun->dev_addr));
 -              if (copy_to_user( argp, &ifr, sizeof ifr))
 +              /* Get hw addres */
 +              memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN);
 +              ifr.ifr_hwaddr.sa_family = tun->dev->type;
 +              if (copy_to_user(argp, &ifr, sizeof ifr))
                        return -EFAULT;
                return 0;
  
        case SIOCSIFHWADDR:
 -      {
 -              /* try to set the actual net device's hw address */
 -              int ret;
 +              /* Set hw address */
 +              DBG(KERN_DEBUG "%s: set hw address: %s\n",
 +                      tun->dev->name, print_mac(mac, ifr.ifr_hwaddr.sa_data));
  
                rtnl_lock();
                ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr);
                rtnl_unlock();
 -
 -              if (ret == 0) {
 -                      /** Set the character device's hardware address. This is used when
 -                       * filtering packets being sent from the network device to the character
 -                       * device. */
 -                      memcpy(tun->dev_addr, ifr.ifr_hwaddr.sa_data,
 -                                      min(sizeof ifr.ifr_hwaddr.sa_data, sizeof tun->dev_addr));
 -                      DBG(KERN_DEBUG "%s: set hardware address: %x:%x:%x:%x:%x:%x\n",
 -                                      tun->dev->name,
 -                                      tun->dev_addr[0], tun->dev_addr[1], tun->dev_addr[2],
 -                                      tun->dev_addr[3], tun->dev_addr[4], tun->dev_addr[5]);
 -              }
 -
 -              return  ret;
 -      }
 -
 -      case SIOCADDMULTI:
 -              /** Add the specified group to the character device's multicast filter
 -               * list. */
 -              rtnl_lock();
 -              netif_tx_lock_bh(tun->dev);
 -              add_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
 -              netif_tx_unlock_bh(tun->dev);
 -              rtnl_unlock();
 -
 -              DBG(KERN_DEBUG "%s: add multi: %s\n",
 -                  tun->dev->name, print_mac(mac, ifr.ifr_hwaddr.sa_data));
 -              return 0;
 -
 -      case SIOCDELMULTI:
 -              /** Remove the specified group from the character device's multicast
 -               * filter list. */
 -              rtnl_lock();
 -              netif_tx_lock_bh(tun->dev);
 -              del_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
 -              netif_tx_unlock_bh(tun->dev);
 -              rtnl_unlock();
 -
 -              DBG(KERN_DEBUG "%s: del multi: %s\n",
 -                  tun->dev->name, print_mac(mac, ifr.ifr_hwaddr.sa_data));
 -              return 0;
 +              return ret;
  
        default:
                return -EINVAL;
@@@ -938,22 -803,26 +939,26 @@@ static int tun_chr_fasync(int fd, struc
  
        DBG(KERN_INFO "%s: tun_chr_fasync %d\n", tun->dev->name, on);
  
+       lock_kernel();
        if ((ret = fasync_helper(fd, file, on, &tun->fasync)) < 0)
-               return ret;
+               goto out;
  
        if (on) {
                ret = __f_setown(file, task_pid(current), PIDTYPE_PID, 0);
                if (ret)
-                       return ret;
+                       goto out;
                tun->flags |= TUN_FASYNC;
        } else
                tun->flags &= ~TUN_FASYNC;
-       return 0;
+       ret = 0;
+ out:
+       unlock_kernel();
+       return ret;
  }
  
  static int tun_chr_open(struct inode *inode, struct file * file)
  {
+       cycle_kernel_lock();
        DBG1(KERN_INFO "tunX: tun_chr_open\n");
        file->private_data = NULL;
        return 0;
diff --combined drivers/net/ucc_geth.c
index c1b55bc7eab759e7e093e45c7a1ce49e4e5e381c,402e81020fb8fd583a1a201f63161bd0418b7b16..756ba10b79d64cdf8489719db70bd3b012df87ef
@@@ -28,8 -28,8 +28,8 @@@
  #include <linux/mii.h>
  #include <linux/phy.h>
  #include <linux/workqueue.h>
+ #include <linux/of_platform.h>
  
- #include <asm/of_platform.h>
  #include <asm/uaccess.h>
  #include <asm/irq.h>
  #include <asm/io.h>
@@@ -1588,7 -1588,7 +1588,7 @@@ static void adjust_link(struct net_devi
                if (!ugeth->oldlink) {
                        new_state = 1;
                        ugeth->oldlink = 1;
 -                      netif_schedule(dev);
 +                      netif_tx_schedule_all(dev);
                }
        } else if (ugeth->oldlink) {
                        new_state = 1;
@@@ -3372,7 -3372,7 +3372,7 @@@ static void ucc_geth_timeout(struct net
                ucc_geth_startup(ugeth);
        }
  
 -      netif_schedule(dev);
 +      netif_tx_schedule_all(dev);
  }
  
  /* This is called by the kernel when a frame is ready for transmission. */
@@@ -3500,7 -3500,11 +3500,7 @@@ static int ucc_geth_rx(struct ucc_geth_
  
                        dev->stats.rx_bytes += length;
                        /* Send the packet up the stack */
 -#ifdef CONFIG_UGETH_NAPI
                        netif_receive_skb(skb);
 -#else
 -                      netif_rx(skb);
 -#endif                                /* CONFIG_UGETH_NAPI */
                }
  
                ugeth->dev->last_rx = jiffies;
@@@ -3576,6 -3580,7 +3576,6 @@@ static int ucc_geth_tx(struct net_devic
        return 0;
  }
  
 -#ifdef CONFIG_UGETH_NAPI
  static int ucc_geth_poll(struct napi_struct *napi, int budget)
  {
        struct ucc_geth_private *ugeth = container_of(napi, struct ucc_geth_private, napi);
  
        return howmany;
  }
 -#endif                                /* CONFIG_UGETH_NAPI */
  
  static irqreturn_t ucc_geth_irq_handler(int irq, void *info)
  {
        struct ucc_geth_info *ug_info;
        register u32 ucce;
        register u32 uccm;
 -#ifndef CONFIG_UGETH_NAPI
 -      register u32 rx_mask;
 -#endif
        register u32 tx_mask;
        u8 i;
  
  
        /* check for receive events that require processing */
        if (ucce & UCCE_RX_EVENTS) {
 -#ifdef CONFIG_UGETH_NAPI
                if (netif_rx_schedule_prep(dev, &ugeth->napi)) {
                        uccm &= ~UCCE_RX_EVENTS;
                        out_be32(uccf->p_uccm, uccm);
                        __netif_rx_schedule(dev, &ugeth->napi);
                }
 -#else
 -              rx_mask = UCCE_RXBF_SINGLE_MASK;
 -              for (i = 0; i < ug_info->numQueuesRx; i++) {
 -                      if (ucce & rx_mask)
 -                              ucc_geth_rx(ugeth, i, (int)ugeth->ug_info->bdRingLenRx[i]);
 -                      ucce &= ~rx_mask;
 -                      rx_mask <<= 1;
 -              }
 -#endif /* CONFIG_UGETH_NAPI */
        }
  
        /* Tx event processing */
@@@ -3701,8 -3720,9 +3701,8 @@@ static int ucc_geth_open(struct net_dev
                return err;
        }
  
 -#ifdef CONFIG_UGETH_NAPI
        napi_enable(&ugeth->napi);
 -#endif
 +
        err = ucc_geth_startup(ugeth);
        if (err) {
                if (netif_msg_ifup(ugeth))
        return err;
  
  out_err:
 -#ifdef CONFIG_UGETH_NAPI
        napi_disable(&ugeth->napi);
 -#endif
 +
        return err;
  }
  
@@@ -3775,7 -3796,9 +3775,7 @@@ static int ucc_geth_close(struct net_de
  
        ugeth_vdbg("%s: IN", __FUNCTION__);
  
 -#ifdef CONFIG_UGETH_NAPI
        napi_disable(&ugeth->napi);
 -#endif
  
        ucc_geth_stop(ugeth);
  
@@@ -4027,7 -4050,9 +4027,7 @@@ static int ucc_geth_probe(struct of_dev
        dev->hard_start_xmit = ucc_geth_start_xmit;
        dev->tx_timeout = ucc_geth_timeout;
        dev->watchdog_timeo = TX_TIMEOUT;
 -#ifdef CONFIG_UGETH_NAPI
        netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, UCC_GETH_DEV_WEIGHT);
 -#endif                                /* CONFIG_UGETH_NAPI */
  #ifdef CONFIG_NET_POLL_CONTROLLER
        dev->poll_controller = ucc_netpoll;
  #endif
index 28b6ff3eaa3764467d877c802d5529ad72ca7fce,d1acef7e0b1461579c585f2a74984400b61d845f..bd35bb0a14803d0daa4b9691d86426d6968299f2
@@@ -433,6 -433,7 +433,6 @@@ struct atmel_private 
        struct net_device *dev;
        struct device *sys_dev;
        struct iw_statistics wstats;
 -      struct net_device_stats stats;  // device stats
        spinlock_t irqlock, timerlock;  // spinlocks
        enum { BUS_TYPE_PCCARD, BUS_TYPE_PCI } bus_type;
        enum {
@@@ -559,7 -560,7 +559,7 @@@ static const struct 
  static void build_wpa_mib(struct atmel_private *priv);
  static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
  static void atmel_copy_to_card(struct net_device *dev, u16 dest,
-                              unsigned char *src, u16 len);
+                              const unsigned char *src, u16 len);
  static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest,
                               u16 src, u16 len);
  static void atmel_set_gcr(struct net_device *dev, u16 mask);
@@@ -693,9 -694,9 +693,9 @@@ static void tx_done_irq(struct atmel_pr
  
                if (type == TX_PACKET_TYPE_DATA) {
                        if (status == TX_STATUS_SUCCESS)
 -                              priv->stats.tx_packets++;
 +                              priv->dev->stats.tx_packets++;
                        else
 -                              priv->stats.tx_errors++;
 +                              priv->dev->stats.tx_errors++;
                        netif_wake_queue(priv->dev);
                }
        }
@@@ -791,13 -792,13 +791,13 @@@ static int start_tx(struct sk_buff *skb
  
        if (priv->card && priv->present_callback &&
            !(*priv->present_callback)(priv->card)) {
 -              priv->stats.tx_errors++;
 +              dev->stats.tx_errors++;
                dev_kfree_skb(skb);
                return 0;
        }
  
        if (priv->station_state != STATION_STATE_READY) {
 -              priv->stats.tx_errors++;
 +              dev->stats.tx_errors++;
                dev_kfree_skb(skb);
                return 0;
        }
           initial + 18 (+30-12) */
  
        if (!(buff = find_tx_buff(priv, len + 18))) {
 -              priv->stats.tx_dropped++;
 +              dev->stats.tx_dropped++;
                spin_unlock_irqrestore(&priv->irqlock, flags);
                spin_unlock_bh(&priv->timerlock);
                netif_stop_queue(dev);
        /* low bit of first byte of destination tells us if broadcast */
        tx_update_descriptor(priv, *(skb->data) & 0x01, len + 18, buff, TX_PACKET_TYPE_DATA);
        dev->trans_start = jiffies;
 -      priv->stats.tx_bytes += len;
 +      dev->stats.tx_bytes += len;
  
        spin_unlock_irqrestore(&priv->irqlock, flags);
        spin_unlock_bh(&priv->timerlock);
@@@ -894,7 -895,7 +894,7 @@@ static void fast_rx_path(struct atmel_p
        }
  
        if (!(skb = dev_alloc_skb(msdu_size + 14))) {
 -              priv->stats.rx_dropped++;
 +              priv->dev->stats.rx_dropped++;
                return;
        }
  
                crc = crc32_le(crc, skbp + 12, msdu_size);
                atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + 30 + msdu_size, 4);
                if ((crc ^ 0xffffffff) != netcrc) {
 -                      priv->stats.rx_crc_errors++;
 +                      priv->dev->stats.rx_crc_errors++;
                        dev_kfree_skb(skb);
                        return;
                }
        skb->protocol = eth_type_trans(skb, priv->dev);
        skb->ip_summed = CHECKSUM_NONE;
        netif_rx(skb);
 -      priv->stats.rx_bytes += 12 + msdu_size;
 -      priv->stats.rx_packets++;
 +      priv->dev->stats.rx_bytes += 12 + msdu_size;
 +      priv->dev->stats.rx_packets++;
  }
  
  /* Test to see if the packet in card memory at packet_loc has a valid CRC
@@@ -990,7 -991,7 +990,7 @@@ static void frag_rx_path(struct atmel_p
                        crc = crc32_le(crc, &priv->rx_buf[12], msdu_size);
                        atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4);
                        if ((crc ^ 0xffffffff) != netcrc) {
 -                              priv->stats.rx_crc_errors++;
 +                              priv->dev->stats.rx_crc_errors++;
                                memset(priv->frag_source, 0xff, 6);
                        }
                }
                                       msdu_size);
                        atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4);
                        if ((crc ^ 0xffffffff) != netcrc) {
 -                              priv->stats.rx_crc_errors++;
 +                              priv->dev->stats.rx_crc_errors++;
                                memset(priv->frag_source, 0xff, 6);
                                more_frags = 1; /* don't send broken assembly */
                        }
                if (!more_frags) { /* last one */
                        memset(priv->frag_source, 0xff, 6);
                        if (!(skb = dev_alloc_skb(priv->frag_len + 14))) {
 -                              priv->stats.rx_dropped++;
 +                              priv->dev->stats.rx_dropped++;
                        } else {
                                skb_reserve(skb, 2);
                                memcpy(skb_put(skb, priv->frag_len + 12),
                                skb->protocol = eth_type_trans(skb, priv->dev);
                                skb->ip_summed = CHECKSUM_NONE;
                                netif_rx(skb);
 -                              priv->stats.rx_bytes += priv->frag_len + 12;
 -                              priv->stats.rx_packets++;
 +                              priv->dev->stats.rx_bytes += priv->frag_len + 12;
 +                              priv->dev->stats.rx_packets++;
                        }
                }
        } else
@@@ -1056,7 -1057,7 +1056,7 @@@ static void rx_done_irq(struct atmel_pr
                        if (status == 0xc1) /* determined by experiment */
                                priv->wstats.discard.nwid++;
                        else
 -                              priv->stats.rx_errors++;
 +                              priv->dev->stats.rx_errors++;
                        goto next;
                }
  
                rx_packet_loc = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_POS_OFFSET, priv->rx_desc_head));
  
                if (msdu_size < 30) {
 -                      priv->stats.rx_errors++;
 +                      priv->dev->stats.rx_errors++;
                        goto next;
                }
  
                                msdu_size -= 4;
                                crc = crc32_le(crc, (unsigned char *)&priv->rx_buf, msdu_size);
                                if ((crc ^ 0xffffffff) != (*((u32 *)&priv->rx_buf[msdu_size]))) {
 -                                      priv->stats.rx_crc_errors++;
 +                                      priv->dev->stats.rx_crc_errors++;
                                        goto next;
                                }
                        }
@@@ -1249,6 -1250,12 +1249,6 @@@ static irqreturn_t service_interrupt(in
        }
  }
  
 -static struct net_device_stats *atmel_get_stats(struct net_device *dev)
 -{
 -      struct atmel_private *priv = netdev_priv(dev);
 -      return &priv->stats;
 -}
 -
  static struct iw_statistics *atmel_get_wireless_stats(struct net_device *dev)
  {
        struct atmel_private *priv = netdev_priv(dev);
@@@ -1511,6 -1518,8 +1511,6 @@@ struct net_device *init_atmel_card(unsi
                priv->crc_ok_cnt = priv->crc_ko_cnt = 0;
        } else
                priv->probe_crc = 0;
 -      memset(&priv->stats, 0, sizeof(priv->stats));
 -      memset(&priv->wstats, 0, sizeof(priv->wstats));
        priv->last_qual = jiffies;
        priv->last_beacon_timestamp = 0;
        memset(priv->frag_source, 0xff, sizeof(priv->frag_source));
        dev->change_mtu = atmel_change_mtu;
        dev->set_mac_address = atmel_set_mac_address;
        dev->hard_start_xmit = start_tx;
 -      dev->get_stats = atmel_get_stats;
        dev->wireless_handlers = (struct iw_handler_def *)&atmel_handler_def;
        dev->do_ioctl = atmel_ioctl;
        dev->irq = irq;
@@@ -2310,40 -2320,30 +2310,40 @@@ static int atmel_get_scan(struct net_de
                iwe.cmd = SIOCGIWAP;
                iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
                memcpy(iwe.u.ap_addr.sa_data, priv->BSSinfo[i].BSSID, 6);
 -              current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_ADDR_LEN);
 +              current_ev = iwe_stream_add_event(info, current_ev,
 +                                                extra + IW_SCAN_MAX_DATA,
 +                                                &iwe, IW_EV_ADDR_LEN);
  
                iwe.u.data.length =  priv->BSSinfo[i].SSIDsize;
                if (iwe.u.data.length > 32)
                        iwe.u.data.length = 32;
                iwe.cmd = SIOCGIWESSID;
                iwe.u.data.flags = 1;
 -              current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, priv->BSSinfo[i].SSID);
 +              current_ev = iwe_stream_add_point(info, current_ev,
 +                                                extra + IW_SCAN_MAX_DATA,
 +                                                &iwe, priv->BSSinfo[i].SSID);
  
                iwe.cmd = SIOCGIWMODE;
                iwe.u.mode = priv->BSSinfo[i].BSStype;
 -              current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_UINT_LEN);
 +              current_ev = iwe_stream_add_event(info, current_ev,
 +                                                extra + IW_SCAN_MAX_DATA,
 +                                                &iwe, IW_EV_UINT_LEN);
  
                iwe.cmd = SIOCGIWFREQ;
                iwe.u.freq.m = priv->BSSinfo[i].channel;
                iwe.u.freq.e = 0;
 -              current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_FREQ_LEN);
 +              current_ev = iwe_stream_add_event(info, current_ev,
 +                                                extra + IW_SCAN_MAX_DATA,
 +                                                &iwe, IW_EV_FREQ_LEN);
  
                /* Add quality statistics */
                iwe.cmd = IWEVQUAL;
                iwe.u.qual.level = priv->BSSinfo[i].RSSI;
                iwe.u.qual.qual  = iwe.u.qual.level;
                /* iwe.u.qual.noise  = SOMETHING */
 -              current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA , &iwe, IW_EV_QUAL_LEN);
 +              current_ev = iwe_stream_add_event(info, current_ev,
 +                                                extra + IW_SCAN_MAX_DATA,
 +                                                &iwe, IW_EV_QUAL_LEN);
  
  
                iwe.cmd = SIOCGIWENCODE;
                else
                        iwe.u.data.flags = IW_ENCODE_DISABLED;
                iwe.u.data.length = 0;
 -              current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, NULL);
 +              current_ev = iwe_stream_add_point(info, current_ev,
 +                                                extra + IW_SCAN_MAX_DATA,
 +                                                &iwe, NULL);
        }
  
        /* Length of data */
@@@ -3855,7 -3853,7 +3855,7 @@@ static int reset_atmel_card(struct net_
        if (priv->card_type == CARD_TYPE_EEPROM) {
                /* copy in firmware if needed */
                const struct firmware *fw_entry = NULL;
-               unsigned char *fw;
+               const unsigned char *fw;
                int len = priv->firmware_length;
                if (!(fw = priv->firmware)) {
                        if (priv->firmware_type == ATMEL_FW_TYPE_NONE) {
@@@ -4122,7 -4120,7 +4122,7 @@@ static void atmel_writeAR(struct net_de
  }
  
  static void atmel_copy_to_card(struct net_device *dev, u16 dest,
-                              unsigned char *src, u16 len)
+                              const unsigned char *src, u16 len)
  {
        int i;
        atmel_writeAR(dev, dest);
index cc70d53fadd35b8fdec0b05b788d6756ad17563b,d075b448da94b899fe3dd8d40f4cec1bdd13dddf..04d7a251e3f0c75a9c0084ca6cd401f7bbd980d0
@@@ -122,7 -122,7 +122,7 @@@ static inline void if_cs_write16(struc
  static inline void if_cs_write16_rep(
        struct if_cs_card *card,
        uint reg,
-       void *buf,
+       const void *buf,
        unsigned long count)
  {
        if (debug_output)
@@@ -148,149 -148,76 +148,149 @@@ static int if_cs_poll_while_fw_download
  {
        int i;
  
 -      for (i = 0; i < 1000; i++) {
 +      for (i = 0; i < 100000; i++) {
                u8 val = if_cs_read8(card, addr);
                if (val == reg)
                        return i;
 -              udelay(500);
 +              udelay(5);
        }
        return -ETIME;
  }
  
  
  
 -/* Host control registers and their bit definitions */
 -
 -#define IF_CS_H_STATUS                        0x00000000
 -#define IF_CS_H_STATUS_TX_OVER                0x0001
 -#define IF_CS_H_STATUS_RX_OVER                0x0002
 -#define IF_CS_H_STATUS_DNLD_OVER      0x0004
 -
 -#define IF_CS_H_INT_CAUSE             0x00000002
 -#define IF_CS_H_IC_TX_OVER            0x0001
 -#define IF_CS_H_IC_RX_OVER            0x0002
 -#define IF_CS_H_IC_DNLD_OVER          0x0004
 -#define IF_CS_H_IC_POWER_DOWN         0x0008
 -#define IF_CS_H_IC_HOST_EVENT         0x0010
 -#define IF_CS_H_IC_MASK                       0x001f
 -
 -#define IF_CS_H_INT_MASK              0x00000004
 -#define       IF_CS_H_IM_MASK                 0x001f
 -
 -#define IF_CS_H_WRITE_LEN             0x00000014
 -
 -#define IF_CS_H_WRITE                 0x00000016
 +/*
 + * First the bitmasks for the host/card interrupt/status registers:
 + */
 +#define IF_CS_BIT_TX                  0x0001
 +#define IF_CS_BIT_RX                  0x0002
 +#define IF_CS_BIT_COMMAND             0x0004
 +#define IF_CS_BIT_RESP                        0x0008
 +#define IF_CS_BIT_EVENT                       0x0010
 +#define       IF_CS_BIT_MASK                  0x001f
  
 -#define IF_CS_H_CMD_LEN                       0x00000018
  
 -#define IF_CS_H_CMD                   0x0000001A
  
 -#define IF_CS_C_READ_LEN              0x00000024
 +/*
 + * It's not really clear to me what the host status register is for. It
 + * needs to be set almost in union with "host int cause". The following
 + * bits from above are used:
 + *
 + *   IF_CS_BIT_TX         driver downloaded a data packet
 + *   IF_CS_BIT_RX         driver got a data packet
 + *   IF_CS_BIT_COMMAND    driver downloaded a command
 + *   IF_CS_BIT_RESP       not used (has some meaning with powerdown)
 + *   IF_CS_BIT_EVENT      driver read a host event
 + */
 +#define IF_CS_HOST_STATUS             0x00000000
  
 -#define IF_CS_H_READ                  0x00000010
 +/*
 + * With the host int cause register can the host (that is, Linux) cause
 + * an interrupt in the firmware, to tell the firmware about those events:
 + *
 + *   IF_CS_BIT_TX         a data packet has been downloaded
 + *   IF_CS_BIT_RX         a received data packet has retrieved
 + *   IF_CS_BIT_COMMAND    a firmware block or a command has been downloaded
 + *   IF_CS_BIT_RESP       not used (has some meaning with powerdown)
 + *   IF_CS_BIT_EVENT      a host event (link lost etc) has been retrieved
 + */
 +#define IF_CS_HOST_INT_CAUSE          0x00000002
  
 -/* Card control registers and their bit definitions */
 +/*
 + * The host int mask register is used to enable/disable interrupt.  However,
 + * I have the suspicion that disabled interrupts are lost.
 + */
 +#define IF_CS_HOST_INT_MASK           0x00000004
  
 -#define IF_CS_C_STATUS                        0x00000020
 -#define IF_CS_C_S_TX_DNLD_RDY         0x0001
 -#define IF_CS_C_S_RX_UPLD_RDY         0x0002
 -#define IF_CS_C_S_CMD_DNLD_RDY                0x0004
 -#define IF_CS_C_S_CMD_UPLD_RDY                0x0008
 -#define IF_CS_C_S_CARDEVENT           0x0010
 -#define IF_CS_C_S_MASK                        0x001f
 -#define IF_CS_C_S_STATUS_MASK         0x7f00
 +/*
 + * Used to send or receive data packets:
 + */
 +#define IF_CS_WRITE                   0x00000016
 +#define IF_CS_WRITE_LEN                       0x00000014
 +#define IF_CS_READ                    0x00000010
 +#define IF_CS_READ_LEN                        0x00000024
  
 -#define IF_CS_C_INT_CAUSE             0x00000022
 -#define       IF_CS_C_IC_MASK                 0x001f
 +/*
 + * Used to send commands (and to send firmware block) and to
 + * receive command responses:
 + */
 +#define IF_CS_CMD                     0x0000001A
 +#define IF_CS_CMD_LEN                 0x00000018
 +#define IF_CS_RESP                    0x00000012
 +#define IF_CS_RESP_LEN                        0x00000030
  
 -#define IF_CS_C_SQ_READ_LOW           0x00000028
 -#define IF_CS_C_SQ_HELPER_OK          0x10
 +/*
 + * The card status registers shows what the card/firmware actually
 + * accepts:
 + *
 + *   IF_CS_BIT_TX        you may send a data packet
 + *   IF_CS_BIT_RX        you may retrieve a data packet
 + *   IF_CS_BIT_COMMAND   you may send a command
 + *   IF_CS_BIT_RESP      you may retrieve a command response
 + *   IF_CS_BIT_EVENT     the card has a event for use (link lost, snr low etc)
 + *
 + * When reading this register several times, you will get back the same
 + * results --- with one exception: the IF_CS_BIT_EVENT clear itself
 + * automatically.
 + *
 + * Not that we don't rely on BIT_RX,_BIT_RESP or BIT_EVENT because
 + * we handle this via the card int cause register.
 + */
 +#define IF_CS_CARD_STATUS             0x00000020
 +#define IF_CS_CARD_STATUS_MASK                0x7f00
  
 -#define IF_CS_C_CMD_LEN                       0x00000030
 +/*
 + * The card int cause register is used by the card/firmware to notify us
 + * about the following events:
 + *
 + *   IF_CS_BIT_TX        a data packet has successfully been sentx
 + *   IF_CS_BIT_RX        a data packet has been received and can be retrieved
 + *   IF_CS_BIT_COMMAND   not used
 + *   IF_CS_BIT_RESP      the firmware has a command response for us
 + *   IF_CS_BIT_EVENT     the card has a event for use (link lost, snr low etc)
 + */
 +#define IF_CS_CARD_INT_CAUSE          0x00000022
  
 -#define IF_CS_C_CMD                   0x00000012
 +/*
 + * This is used to for handshaking with the card's bootloader/helper image
 + * to synchronize downloading of firmware blocks.
 + */
 +#define IF_CS_SQ_READ_LOW             0x00000028
 +#define IF_CS_SQ_HELPER_OK            0x10
  
 +/*
 + * The scratch register tells us ...
 + *
 + * IF_CS_SCRATCH_BOOT_OK     the bootloader runs
 + * IF_CS_SCRATCH_HELPER_OK   the helper firmware already runs
 + */
  #define IF_CS_SCRATCH                 0x0000003F
 +#define IF_CS_SCRATCH_BOOT_OK         0x00
 +#define IF_CS_SCRATCH_HELPER_OK               0x5a
  
 +/*
 + * Used to detect ancient chips:
 + */
 +#define IF_CS_PRODUCT_ID              0x0000001C
 +#define IF_CS_CF8385_B1_REV           0x12
  
  
  /********************************************************************/
 -/* I/O                                                              */
 +/* I/O and interrupt handling                                       */
  /********************************************************************/
  
 +static inline void if_cs_enable_ints(struct if_cs_card *card)
 +{
 +      lbs_deb_enter(LBS_DEB_CS);
 +      if_cs_write16(card, IF_CS_HOST_INT_MASK, 0);
 +}
 +
 +static inline void if_cs_disable_ints(struct if_cs_card *card)
 +{
 +      lbs_deb_enter(LBS_DEB_CS);
 +      if_cs_write16(card, IF_CS_HOST_INT_MASK, IF_CS_BIT_MASK);
 +}
 +
  /*
   * Called from if_cs_host_to_card to send a command to the hardware
   */
@@@ -301,12 -228,11 +301,12 @@@ static int if_cs_send_cmd(struct lbs_pr
        int loops = 0;
  
        lbs_deb_enter(LBS_DEB_CS);
 +      if_cs_disable_ints(card);
  
        /* Is hardware ready? */
        while (1) {
 -              u16 val = if_cs_read16(card, IF_CS_C_STATUS);
 -              if (val & IF_CS_C_S_CMD_DNLD_RDY)
 +              u16 status = if_cs_read16(card, IF_CS_CARD_STATUS);
 +              if (status & IF_CS_BIT_COMMAND)
                        break;
                if (++loops > 100) {
                        lbs_pr_err("card not ready for commands\n");
                mdelay(1);
        }
  
 -      if_cs_write16(card, IF_CS_H_CMD_LEN, nb);
 +      if_cs_write16(card, IF_CS_CMD_LEN, nb);
  
 -      if_cs_write16_rep(card, IF_CS_H_CMD, buf, nb / 2);
 +      if_cs_write16_rep(card, IF_CS_CMD, buf, nb / 2);
        /* Are we supposed to transfer an odd amount of bytes? */
        if (nb & 1)
 -              if_cs_write8(card, IF_CS_H_CMD, buf[nb-1]);
 +              if_cs_write8(card, IF_CS_CMD, buf[nb-1]);
  
        /* "Assert the download over interrupt command in the Host
         * status register" */
 -      if_cs_write16(card, IF_CS_H_STATUS, IF_CS_H_STATUS_DNLD_OVER);
 +      if_cs_write16(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND);
  
        /* "Assert the download over interrupt command in the Card
         * interrupt case register" */
 -      if_cs_write16(card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_DNLD_OVER);
 +      if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND);
        ret = 0;
  
  done:
 +      if_cs_enable_ints(card);
        lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
        return ret;
  }
  
 -
  /*
   * Called from if_cs_host_to_card to send a data to the hardware
   */
  static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb)
  {
        struct if_cs_card *card = (struct if_cs_card *)priv->card;
 +      u16 status;
  
        lbs_deb_enter(LBS_DEB_CS);
 +      if_cs_disable_ints(card);
  
 -      if_cs_write16(card, IF_CS_H_WRITE_LEN, nb);
 +      status = if_cs_read16(card, IF_CS_CARD_STATUS);
 +      BUG_ON((status & IF_CS_BIT_TX) == 0);
 +
 +      if_cs_write16(card, IF_CS_WRITE_LEN, nb);
  
        /* write even number of bytes, then odd byte if necessary */
 -      if_cs_write16_rep(card, IF_CS_H_WRITE, buf, nb / 2);
 +      if_cs_write16_rep(card, IF_CS_WRITE, buf, nb / 2);
        if (nb & 1)
 -              if_cs_write8(card, IF_CS_H_WRITE, buf[nb-1]);
 +              if_cs_write8(card, IF_CS_WRITE, buf[nb-1]);
  
 -      if_cs_write16(card, IF_CS_H_STATUS, IF_CS_H_STATUS_TX_OVER);
 -      if_cs_write16(card, IF_CS_H_INT_CAUSE, IF_CS_H_STATUS_TX_OVER);
 +      if_cs_write16(card, IF_CS_HOST_STATUS, IF_CS_BIT_TX);
 +      if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_TX);
 +      if_cs_enable_ints(card);
  
        lbs_deb_leave(LBS_DEB_CS);
  }
  
 -
  /*
   * Get the command result out of the card.
   */
@@@ -372,28 -293,27 +372,28 @@@ static int if_cs_receive_cmdres(struct 
  {
        unsigned long flags;
        int ret = -1;
 -      u16 val;
 +      u16 status;
  
        lbs_deb_enter(LBS_DEB_CS);
  
        /* is hardware ready? */
 -      val = if_cs_read16(priv->card, IF_CS_C_STATUS);
 -      if ((val & IF_CS_C_S_CMD_UPLD_RDY) == 0) {
 -              lbs_pr_err("card not ready for CMD\n");
 +      status = if_cs_read16(priv->card, IF_CS_CARD_STATUS);
 +      if ((status & IF_CS_BIT_RESP) == 0) {
 +              lbs_pr_err("no cmd response in card\n");
 +              *len = 0;
                goto out;
        }
  
 -      *len = if_cs_read16(priv->card, IF_CS_C_CMD_LEN);
 +      *len = if_cs_read16(priv->card, IF_CS_RESP_LEN);
        if ((*len == 0) || (*len > LBS_CMD_BUFFER_SIZE)) {
                lbs_pr_err("card cmd buffer has invalid # of bytes (%d)\n", *len);
                goto out;
        }
  
        /* read even number of bytes, then odd byte if necessary */
 -      if_cs_read16_rep(priv->card, IF_CS_C_CMD, data, *len/sizeof(u16));
 +      if_cs_read16_rep(priv->card, IF_CS_RESP, data, *len/sizeof(u16));
        if (*len & 1)
 -              data[*len-1] = if_cs_read8(priv->card, IF_CS_C_CMD);
 +              data[*len-1] = if_cs_read8(priv->card, IF_CS_RESP);
  
        /* This is a workaround for a firmware that reports too much
         * bytes */
@@@ -410,6 -330,7 +410,6 @@@ out
        return ret;
  }
  
 -
  static struct sk_buff *if_cs_receive_data(struct lbs_private *priv)
  {
        struct sk_buff *skb = NULL;
  
        lbs_deb_enter(LBS_DEB_CS);
  
 -      len = if_cs_read16(priv->card, IF_CS_C_READ_LEN);
 +      len = if_cs_read16(priv->card, IF_CS_READ_LEN);
        if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
                lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len);
                priv->stats.rx_dropped++;
        data = skb->data;
  
        /* read even number of bytes, then odd byte if necessary */
 -      if_cs_read16_rep(priv->card, IF_CS_H_READ, data, len/sizeof(u16));
 +      if_cs_read16_rep(priv->card, IF_CS_READ, data, len/sizeof(u16));
        if (len & 1)
 -              data[len-1] = if_cs_read8(priv->card, IF_CS_H_READ);
 +              data[len-1] = if_cs_read8(priv->card, IF_CS_READ);
  
  dat_err:
 -      if_cs_write16(priv->card, IF_CS_H_STATUS, IF_CS_H_STATUS_RX_OVER);
 -      if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_RX_OVER);
 +      if_cs_write16(priv->card, IF_CS_HOST_STATUS, IF_CS_BIT_RX);
 +      if_cs_write16(priv->card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_RX);
  
  out:
        lbs_deb_leave_args(LBS_DEB_CS, "ret %p", skb);
        return skb;
  }
  
 -
 -
 -/********************************************************************/
 -/* Interrupts                                                       */
 -/********************************************************************/
 -
 -static inline void if_cs_enable_ints(struct if_cs_card *card)
 -{
 -      lbs_deb_enter(LBS_DEB_CS);
 -      if_cs_write16(card, IF_CS_H_INT_MASK, 0);
 -}
 -
 -static inline void if_cs_disable_ints(struct if_cs_card *card)
 -{
 -      lbs_deb_enter(LBS_DEB_CS);
 -      if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK);
 -}
 -
 -
  static irqreturn_t if_cs_interrupt(int irq, void *data)
  {
        struct if_cs_card *card = data;
  
        lbs_deb_enter(LBS_DEB_CS);
  
 -      cause = if_cs_read16(card, IF_CS_C_INT_CAUSE);
 -      if_cs_write16(card, IF_CS_C_INT_CAUSE, cause & IF_CS_C_IC_MASK);
 -
 +      /* Ask card interrupt cause register if there is something for us */
 +      cause = if_cs_read16(card, IF_CS_CARD_INT_CAUSE);
        lbs_deb_cs("cause 0x%04x\n", cause);
 +
        if (cause == 0) {
                /* Not for us */
                return IRQ_NONE;
                return IRQ_HANDLED;
        }
  
 -      /* TODO: I'm not sure what the best ordering is */
 -
 -      cause = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK;
 -
 -      if (cause & IF_CS_C_S_RX_UPLD_RDY) {
 +      if (cause & IF_CS_BIT_RX) {
                struct sk_buff *skb;
                lbs_deb_cs("rx packet\n");
                skb = if_cs_receive_data(priv);
                        lbs_process_rxed_packet(priv, skb);
        }
  
 -      if (cause & IF_CS_H_IC_TX_OVER) {
 -              lbs_deb_cs("tx over\n");
 +      if (cause & IF_CS_BIT_TX) {
 +              lbs_deb_cs("tx done\n");
                lbs_host_to_card_done(priv);
        }
  
 -      if (cause & IF_CS_C_S_CMD_UPLD_RDY) {
 +      if (cause & IF_CS_BIT_RESP) {
                unsigned long flags;
                u8 i;
  
 -              lbs_deb_cs("cmd upload ready\n");
 +              lbs_deb_cs("cmd resp\n");
                spin_lock_irqsave(&priv->driver_lock, flags);
                i = (priv->resp_idx == 0) ? 1 : 0;
                spin_unlock_irqrestore(&priv->driver_lock, flags);
                spin_unlock_irqrestore(&priv->driver_lock, flags);
        }
  
 -      if (cause & IF_CS_H_IC_HOST_EVENT) {
 -              u16 event = if_cs_read16(priv->card, IF_CS_C_STATUS)
 -                      & IF_CS_C_S_STATUS_MASK;
 -              if_cs_write16(priv->card, IF_CS_H_INT_CAUSE,
 -                      IF_CS_H_IC_HOST_EVENT);
 -              lbs_deb_cs("eventcause 0x%04x\n", event);
 -              lbs_queue_event(priv, event >> 8 & 0xff);
 +      if (cause & IF_CS_BIT_EVENT) {
 +              u16 status = if_cs_read16(priv->card, IF_CS_CARD_STATUS);
 +              if_cs_write16(priv->card, IF_CS_HOST_INT_CAUSE,
 +                      IF_CS_BIT_EVENT);
 +              lbs_queue_event(priv, (status & IF_CS_CARD_STATUS_MASK) >> 8);
        }
  
 +      /* Clear interrupt cause */
 +      if_cs_write16(card, IF_CS_CARD_INT_CAUSE, cause & IF_CS_BIT_MASK);
 +
 +      lbs_deb_leave(LBS_DEB_CS);
        return IRQ_HANDLED;
  }
  
@@@ -540,11 -482,11 +540,11 @@@ static int if_cs_prog_helper(struct if_
        /* "If the value is 0x5a, the firmware is already
         * downloaded successfully"
         */
 -      if (scratch == 0x5a)
 +      if (scratch == IF_CS_SCRATCH_HELPER_OK)
                goto done;
  
        /* "If the value is != 00, it is invalid value of register */
 -      if (scratch != 0x00) {
 +      if (scratch != IF_CS_SCRATCH_BOOT_OK) {
                ret = -ENODEV;
                goto done;
        }
  
                /* "write the number of bytes to be sent to the I/O Command
                 * write length register" */
 -              if_cs_write16(card, IF_CS_H_CMD_LEN, count);
 +              if_cs_write16(card, IF_CS_CMD_LEN, count);
  
                /* "write this to I/O Command port register as 16 bit writes */
                if (count)
 -                      if_cs_write16_rep(card, IF_CS_H_CMD,
 +                      if_cs_write16_rep(card, IF_CS_CMD,
                                &fw->data[sent],
                                count >> 1);
  
                /* "Assert the download over interrupt command in the Host
                 * status register" */
 -              if_cs_write8(card, IF_CS_H_STATUS, IF_CS_H_STATUS_DNLD_OVER);
 +              if_cs_write8(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND);
  
                /* "Assert the download over interrupt command in the Card
                 * interrupt case register" */
 -              if_cs_write16(card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_DNLD_OVER);
 +              if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND);
  
                /* "The host polls the Card Status register ... for 50 ms before
                   declaring a failure */
 -              ret = if_cs_poll_while_fw_download(card, IF_CS_C_STATUS,
 -                      IF_CS_C_S_CMD_DNLD_RDY);
 +              ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS,
 +                      IF_CS_BIT_COMMAND);
                if (ret < 0) {
                        lbs_pr_err("can't download helper at 0x%x, ret %d\n",
                                sent, ret);
@@@ -633,15 -575,14 +633,15 @@@ static int if_cs_prog_real(struct if_cs
        }
        lbs_deb_cs("fw size %td\n", fw->size);
  
 -      ret = if_cs_poll_while_fw_download(card, IF_CS_C_SQ_READ_LOW, IF_CS_C_SQ_HELPER_OK);
 +      ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW,
 +              IF_CS_SQ_HELPER_OK);
        if (ret < 0) {
                lbs_pr_err("helper firmware doesn't answer\n");
                goto err_release;
        }
  
        for (sent = 0; sent < fw->size; sent += len) {
 -              len = if_cs_read16(card, IF_CS_C_SQ_READ_LOW);
 +              len = if_cs_read16(card, IF_CS_SQ_READ_LOW);
                if (len & 1) {
                        retry++;
                        lbs_pr_info("odd, need to retry this firmware block\n");
                }
  
  
 -              if_cs_write16(card, IF_CS_H_CMD_LEN, len);
 +              if_cs_write16(card, IF_CS_CMD_LEN, len);
  
 -              if_cs_write16_rep(card, IF_CS_H_CMD,
 +              if_cs_write16_rep(card, IF_CS_CMD,
                        &fw->data[sent],
                        (len+1) >> 1);
 -              if_cs_write8(card, IF_CS_H_STATUS, IF_CS_H_STATUS_DNLD_OVER);
 -              if_cs_write16(card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_DNLD_OVER);
 +              if_cs_write8(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND);
 +              if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND);
  
 -              ret = if_cs_poll_while_fw_download(card, IF_CS_C_STATUS,
 -                      IF_CS_C_S_CMD_DNLD_RDY);
 +              ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS,
 +                      IF_CS_BIT_COMMAND);
                if (ret < 0) {
                        lbs_pr_err("can't download firmware at 0x%x\n", sent);
                        goto err_release;
@@@ -865,12 -806,6 +865,12 @@@ static int if_cs_probe(struct pcmcia_de
               p_dev->irq.AssignedIRQ, p_dev->io.BasePort1,
               p_dev->io.BasePort1 + p_dev->io.NumPorts1 - 1);
  
 +      /* Check if we have a current silicon */
 +      if (if_cs_read8(card, IF_CS_PRODUCT_ID) < IF_CS_CF8385_B1_REV) {
 +              lbs_pr_err("old chips like 8385 rev B1 aren't supported\n");
 +              ret = -ENODEV;
 +              goto out2;
 +      }
  
        /* Load the firmware early, before calling into libertas.ko */
        ret = if_cs_prog_helper(card);
  
        /* Clear any interrupt cause that happend while sending
         * firmware/initializing card */
 -      if_cs_write16(card, IF_CS_C_INT_CAUSE, IF_CS_C_IC_MASK);
 +      if_cs_write16(card, IF_CS_CARD_INT_CAUSE, IF_CS_BIT_MASK);
        if_cs_enable_ints(card);
  
        /* And finally bring the card up */
index a8b4abce5bfab14b0f74c2b218d79e836c2f3611,4dcd4092e0f02856e94187f98f27714aa318c05e..632c291404ab5ccbbe7a7a862f24ab600aca8fa8
@@@ -7,10 -7,6 +7,10 @@@
  #include <linux/netdevice.h>
  #include <linux/usb.h>
  
 +#ifdef CONFIG_OLPC
 +#include <asm/olpc.h>
 +#endif
 +
  #define DRV_NAME "usb8xxx"
  
  #include "host.h"
@@@ -150,14 -146,6 +150,14 @@@ static void if_usb_fw_timeo(unsigned lo
        wake_up(&cardp->fw_wq);
  }
  
 +#ifdef CONFIG_OLPC
 +static void if_usb_reset_olpc_card(struct lbs_private *priv)
 +{
 +      printk(KERN_CRIT "Resetting OLPC wireless via EC...\n");
 +      olpc_ec_cmd(0x25, NULL, 0, NULL, 0);
 +}
 +#endif
 +
  /**
   *  @brief sets the configuration values
   *  @param ifnum      interface number
@@@ -243,11 -231,6 +243,11 @@@ static int if_usb_probe(struct usb_inte
        cardp->priv->fw_ready = 1;
  
        priv->hw_host_to_card = if_usb_host_to_card;
 +#ifdef CONFIG_OLPC
 +      if (machine_is_olpc())
 +              priv->reset_card = if_usb_reset_olpc_card;
 +#endif
 +
        cardp->boot2_version = udev->descriptor.bcdDevice;
  
        if_usb_submit_rx_urb(cardp);
@@@ -310,7 -293,7 +310,7 @@@ static void if_usb_disconnect(struct us
  static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
  {
        struct fwdata *fwdata = cardp->ep_out_buf;
-       uint8_t *firmware = cardp->fw->data;
+       const uint8_t *firmware = cardp->fw->data;
  
        /* If we got a CRC failure on the last block, back
           up and retry it */
@@@ -381,11 -364,6 +381,11 @@@ static int if_usb_reset_device(struct i
        ret = usb_reset_device(cardp->udev);
        msleep(100);
  
 +#ifdef CONFIG_OLPC
 +      if (ret && machine_is_olpc())
 +              if_usb_reset_olpc_card(NULL);
 +#endif
 +
        lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
  
        return ret;
@@@ -768,7 -746,7 +768,7 @@@ static int if_usb_issue_boot_command(st
   *         len               image length
   *  @return     0 or -1
   */
- static int check_fwfile_format(uint8_t *data, uint32_t totlen)
+ static int check_fwfile_format(const uint8_t *data, uint32_t totlen)
  {
        uint32_t bincmd, exit;
        uint32_t blksize, offset, len;
index 9fab0df18c3cd032215483717ec6f152f6e8d613,a74e1a5c56fd90acfbb4b929fd4696216aee1508..07b03b3c7ef1655407debfd19664c5ff47a5e86f
@@@ -44,7 -44,7 +44,7 @@@
  /*
   * Module information.
   */
 -#define DRV_VERSION   "2.1.4"
 +#define DRV_VERSION   "2.1.8"
  #define DRV_PROJECT   "http://rt2x00.serialmonkey.com"
  
  /*
  #define SHORT_DIFS            ( SHORT_PIFS + SHORT_SLOT_TIME )
  #define EIFS                  ( SIFS + (8 * (IEEE80211_HEADER + ACK_SIZE)) )
  
 -/*
 - * IEEE802.11 header defines
 - */
 -static inline int is_rts_frame(u16 fc)
 -{
 -      return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
 -              ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS));
 -}
 -
 -static inline int is_cts_frame(u16 fc)
 -{
 -      return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
 -              ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_CTS));
 -}
 -
 -static inline int is_probe_resp(u16 fc)
 -{
 -      return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
 -              ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP));
 -}
 -
 -static inline int is_beacon(u16 fc)
 -{
 -      return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
 -              ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON));
 -}
 -
  /*
   * Chipset identification
   * The chipset on the device is composed of a RT and RF chip.
@@@ -364,8 -391,6 +364,8 @@@ struct rt2x00_intf 
  #define DELAYED_UPDATE_BEACON         0x00000001
  #define DELAYED_CONFIG_ERP            0x00000002
  #define DELAYED_LED_ASSOC             0x00000004
 +
 +      u16 seqno;
  };
  
  static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
   * @supported_rates: Rate types which are supported (CCK, OFDM).
   * @num_channels: Number of supported channels. This is used as array size
   *    for @tx_power_a, @tx_power_bg and @channels.
 - * channels: Device/chipset specific channel values (See &struct rf_channel).
 + * @channels: Device/chipset specific channel values (See &struct rf_channel).
   * @tx_power_a: TX power values for all 5.2GHz channels (may be NULL).
   * @tx_power_bg: TX power values for all 2.4GHz channels (may be NULL).
   * @tx_power_default: Default TX power value to use when either
@@@ -436,7 -461,6 +436,7 @@@ struct rt2x00lib_conf 
   */
  struct rt2x00lib_erp {
        int short_preamble;
 +      int cts_protection;
  
        int ack_timeout;
        int ack_consume_time;
@@@ -487,8 -511,8 +487,8 @@@ struct rt2x00lib_ops 
         */
        int (*probe_hw) (struct rt2x00_dev *rt2x00dev);
        char *(*get_firmware_name) (struct rt2x00_dev *rt2x00dev);
-       u16 (*get_firmware_crc) (void *data, const size_t len);
-       int (*load_firmware) (struct rt2x00_dev *rt2x00dev, void *data,
+       u16 (*get_firmware_crc) (const void *data, const size_t len);
+       int (*load_firmware) (struct rt2x00_dev *rt2x00dev, const void *data,
                              const size_t len);
  
        /*
         */
        void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev,
                               struct sk_buff *skb,
 -                             struct txentry_desc *txdesc,
 -                             struct ieee80211_tx_control *control);
 -      int (*write_tx_data) (struct rt2x00_dev *rt2x00dev,
 -                            struct data_queue *queue, struct sk_buff *skb,
 -                            struct ieee80211_tx_control *control);
 +                             struct txentry_desc *txdesc);
 +      int (*write_tx_data) (struct queue_entry *entry);
 +      void (*write_beacon) (struct queue_entry *entry);
        int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev,
                                struct sk_buff *skb);
        void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev,
 -                             const unsigned int queue);
 +                             const enum data_queue_qid queue);
  
        /*
         * RX control handlers
@@@ -571,7 -597,6 +571,7 @@@ struct rt2x00_ops 
        const unsigned int max_ap_intf;
        const unsigned int eeprom_size;
        const unsigned int rf_size;
 +      const unsigned int tx_queues;
        const struct data_queue_desc *rx;
        const struct data_queue_desc *tx;
        const struct data_queue_desc *bcn;
@@@ -601,11 -626,11 +601,11 @@@ enum rt2x00_flags 
        /*
         * Driver features
         */
 -      DRIVER_SUPPORT_MIXED_INTERFACES,
        DRIVER_REQUIRE_FIRMWARE,
        DRIVER_REQUIRE_BEACON_GUARD,
        DRIVER_REQUIRE_ATIM_QUEUE,
        DRIVER_REQUIRE_SCHEDULED,
 +      DRIVER_REQUIRE_DMA,
  
        /*
         * Driver configuration
@@@ -630,7 -655,11 +630,7 @@@ struct rt2x00_dev 
         * When accessing this variable, the rt2x00dev_{pci,usb}
         * macro's should be used for correct typecasting.
         */
 -      void *dev;
 -#define rt2x00dev_pci(__dev)  ( (struct pci_dev *)(__dev)->dev )
 -#define rt2x00dev_usb(__dev)  ( (struct usb_interface *)(__dev)->dev )
 -#define rt2x00dev_usb_dev(__dev)\
 -      ( (struct usb_device *)interface_to_usbdev(rt2x00dev_usb(__dev)) )
 +      struct device *dev;
  
        /*
         * Callback functions.
  #define RFKILL_STATE_ALLOCATED                1
  #define RFKILL_STATE_REGISTERED               2
        struct rfkill *rfkill;
 -      struct input_polled_dev *poll_dev;
 +      struct delayed_work rfkill_work;
  #endif /* CONFIG_RT2X00_LIB_RFKILL */
  
        /*
  
        /*
         * Scheduled work.
 +       * NOTE: intf_work will use ieee80211_iterate_active_interfaces()
 +       * which means it cannot be placed on the hw->workqueue
 +       * due to RTNL locking requirements.
         */
 -      struct workqueue_struct *workqueue;
        struct work_struct intf_work;
        struct work_struct filter_work;
  
         * The Beacon array also contains the Atim queue
         * if that is supported by the device.
         */
 -      int data_queues;
 +      unsigned int data_queues;
        struct data_queue *rx;
        struct data_queue *tx;
        struct data_queue *bcn;
@@@ -907,41 -934,55 +907,41 @@@ static inline u16 get_duration_res(cons
  }
  
  /**
 - * rt2x00queue_get_queue - Convert mac80211 queue index to rt2x00 queue
 + * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes.
   * @rt2x00dev: Pointer to &struct rt2x00_dev.
 - * @queue: mac80211/rt2x00 queue index
 - *    (see &enum ieee80211_tx_queue and &enum rt2x00_bcn_queue).
 + * @skb: The skb to map.
 + */
 +void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
 +
 +/**
 + * rt2x00queue_get_queue - Convert queue index to queue pointer
 + * @rt2x00dev: Pointer to &struct rt2x00_dev.
 + * @queue: rt2x00 queue index (see &enum data_queue_qid).
   */
  struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
 -                                       const unsigned int queue);
 +                                       const enum data_queue_qid queue);
  
  /**
   * rt2x00queue_get_entry - Get queue entry where the given index points to.
 - * @rt2x00dev: Pointer to &struct rt2x00_dev.
 + * @queue: Pointer to &struct data_queue from where we obtain the entry.
   * @index: Index identifier for obtaining the correct index.
   */
  struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
                                          enum queue_index index);
  
 -/**
 - * rt2x00queue_index_inc - Index incrementation function
 - * @queue: Queue (&struct data_queue) to perform the action on.
 - * @action: Index type (&enum queue_index) to perform the action on.
 - *
 - * This function will increase the requested index on the queue,
 - * it will grab the appropriate locks and handle queue overflow events by
 - * resetting the index to the start of the queue.
 - */
 -void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index);
 -
 -
  /*
   * Interrupt context handlers.
   */
  void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
  void rt2x00lib_txdone(struct queue_entry *entry,
                      struct txdone_entry_desc *txdesc);
 -void rt2x00lib_rxdone(struct queue_entry *entry,
 -                    struct rxdone_entry_desc *rxdesc);
 -
 -/*
 - * TX descriptor initializer
 - */
 -void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 -                           struct sk_buff *skb,
 -                           struct ieee80211_tx_control *control);
 +void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
 +                    struct queue_entry *entry);
  
  /*
   * mac80211 handlers.
   */
 -int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
 -               struct ieee80211_tx_control *control);
 +int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
  int rt2x00mac_start(struct ieee80211_hw *hw);
  void rt2x00mac_stop(struct ieee80211_hw *hw);
  int rt2x00mac_add_interface(struct ieee80211_hw *hw,
@@@ -964,7 -1005,7 +964,7 @@@ void rt2x00mac_bss_info_changed(struct 
                                struct ieee80211_vif *vif,
                                struct ieee80211_bss_conf *bss_conf,
                                u32 changes);
 -int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue,
 +int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
                      const struct ieee80211_tx_queue_params *params);
  
  /*
index 50c6df4f81db639ce67847e2bd2484d4362d1d8e,b41967ecbf6dfb8ff671b5be39d676d2da654ff7..80bf97c03e2d159395f46d9933db3be0275948c8
@@@ -82,31 -82,49 +82,31 @@@ static inline void rt2x00pci_register_w
  static inline void
  rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
                              const unsigned long offset,
-                             void *value, const u16 length)
+                             const void *value, const u16 length)
  {
        memcpy_toio(rt2x00dev->csr.base + offset, value, length);
  }
  
 -/*
 - * TX data handlers.
 - */
 -int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
 -                          struct data_queue *queue, struct sk_buff *skb,
 -                          struct ieee80211_tx_control *control);
 -
  /**
 - * struct queue_entry_priv_pci_rx: Per RX entry PCI specific information
 + * rt2x00pci_write_tx_data - Initialize data for TX operation
 + * @entry: The entry where the frame is located
   *
 - * @desc: Pointer to device descriptor.
 - * @data: Pointer to device's entry memory.
 - * @dma: DMA pointer to &data.
 + * This function will initialize the DMA and skb descriptor
 + * to prepare the entry for the actual TX operation.
   */
 -struct queue_entry_priv_pci_rx {
 -      __le32 *desc;
 -      dma_addr_t desc_dma;
 -
 -      void *data;
 -      dma_addr_t data_dma;
 -};
 +int rt2x00pci_write_tx_data(struct queue_entry *entry);
  
  /**
 - * struct queue_entry_priv_pci_tx: Per TX entry PCI specific information
 + * struct queue_entry_priv_pci: Per entry PCI specific information
   *
   * @desc: Pointer to device descriptor
 + * @desc_dma: DMA pointer to &desc.
   * @data: Pointer to device's entry memory.
 - * @dma: DMA pointer to &data.
 - * @control: mac80211 control structure used to transmit data.
 + * @data_dma: DMA pointer to &data.
   */
 -struct queue_entry_priv_pci_tx {
 +struct queue_entry_priv_pci {
        __le32 *desc;
        dma_addr_t desc_dma;
 -
 -      void *data;
 -      dma_addr_t data_dma;
 -
 -      struct ieee80211_tx_control control;
  };
  
  /**
   */
  void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
  
 -/**
 - * rt2x00pci_txdone - Handle TX done events
 - * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
 - * @entry: Entry which has completed the transmission of a frame.
 - * @desc: TX done descriptor
 - */
 -void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry,
 -                    struct txdone_entry_desc *desc);
 -
  /*
   * Device initialization handlers.
   */
index 70ef7bf434ab44dee46e031999a19e1f7041e311,580f90b63de7a2aae5c5254f82f1227832c044aa..f7c1f92c1448ac6aa7b61b9403054bb64b7593b7
@@@ -330,17 -330,6 +330,17 @@@ static int rt61pci_blink_set(struct led
  
        return 0;
  }
 +
 +static void rt61pci_init_led(struct rt2x00_dev *rt2x00dev,
 +                           struct rt2x00_led *led,
 +                           enum led_type type)
 +{
 +      led->rt2x00dev = rt2x00dev;
 +      led->type = type;
 +      led->led_dev.brightness_set = rt61pci_brightness_set;
 +      led->led_dev.blink_set = rt61pci_blink_set;
 +      led->flags = LED_INITIALIZED;
 +}
  #endif /* CONFIG_RT61PCI_LEDS */
  
  /*
@@@ -926,7 -915,7 +926,7 @@@ static char *rt61pci_get_firmware_name(
        return fw_name;
  }
  
- static u16 rt61pci_get_firmware_crc(void *data, const size_t len)
+ static u16 rt61pci_get_firmware_crc(const void *data, const size_t len)
  {
        u16 crc;
  
        return crc;
  }
  
- static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
+ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data,
                                 const size_t len)
  {
        int i;
  static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
                                 struct queue_entry *entry)
  {
 -      struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
 +      struct queue_entry_priv_pci *entry_priv = entry->priv_data;
 +      struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
        u32 word;
  
 -      rt2x00_desc_read(priv_rx->desc, 5, &word);
 +      rt2x00_desc_read(entry_priv->desc, 5, &word);
        rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
 -                         priv_rx->data_dma);
 -      rt2x00_desc_write(priv_rx->desc, 5, word);
 +                         skbdesc->skb_dma);
 +      rt2x00_desc_write(entry_priv->desc, 5, word);
  
 -      rt2x00_desc_read(priv_rx->desc, 0, &word);
 +      rt2x00_desc_read(entry_priv->desc, 0, &word);
        rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
 -      rt2x00_desc_write(priv_rx->desc, 0, word);
 +      rt2x00_desc_write(entry_priv->desc, 0, word);
  }
  
  static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev,
                                 struct queue_entry *entry)
  {
 -      struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
 +      struct queue_entry_priv_pci *entry_priv = entry->priv_data;
        u32 word;
  
 -      rt2x00_desc_read(priv_tx->desc, 1, &word);
 -      rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
 -      rt2x00_desc_write(priv_tx->desc, 1, word);
 -
 -      rt2x00_desc_read(priv_tx->desc, 5, &word);
 -      rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid);
 -      rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, entry->entry_idx);
 -      rt2x00_desc_write(priv_tx->desc, 5, word);
 -
 -      rt2x00_desc_read(priv_tx->desc, 6, &word);
 -      rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
 -                         priv_tx->data_dma);
 -      rt2x00_desc_write(priv_tx->desc, 6, word);
 -
 -      rt2x00_desc_read(priv_tx->desc, 0, &word);
 +      rt2x00_desc_read(entry_priv->desc, 0, &word);
        rt2x00_set_field32(&word, TXD_W0_VALID, 0);
        rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
 -      rt2x00_desc_write(priv_tx->desc, 0, word);
 +      rt2x00_desc_write(entry_priv->desc, 0, word);
  }
  
  static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
  {
 -      struct queue_entry_priv_pci_rx *priv_rx;
 -      struct queue_entry_priv_pci_tx *priv_tx;
 +      struct queue_entry_priv_pci *entry_priv;
        u32 reg;
  
        /*
                           rt2x00dev->tx[0].desc_size / 4);
        rt2x00pci_register_write(rt2x00dev, TX_RING_CSR1, reg);
  
 -      priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
 +      entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, &reg);
        rt2x00_set_field32(&reg, AC0_BASE_CSR_RING_REGISTER,
 -                         priv_tx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg);
  
 -      priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
 +      entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, &reg);
        rt2x00_set_field32(&reg, AC1_BASE_CSR_RING_REGISTER,
 -                         priv_tx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg);
  
 -      priv_tx = rt2x00dev->tx[2].entries[0].priv_data;
 +      entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, &reg);
        rt2x00_set_field32(&reg, AC2_BASE_CSR_RING_REGISTER,
 -                         priv_tx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg);
  
 -      priv_tx = rt2x00dev->tx[3].entries[0].priv_data;
 +      entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, &reg);
        rt2x00_set_field32(&reg, AC3_BASE_CSR_RING_REGISTER,
 -                         priv_tx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg);
  
        rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, &reg);
        rt2x00_set_field32(&reg, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4);
        rt2x00pci_register_write(rt2x00dev, RX_RING_CSR, reg);
  
 -      priv_rx = rt2x00dev->rx->entries[0].priv_data;
 +      entry_priv = rt2x00dev->rx->entries[0].priv_data;
        rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, &reg);
        rt2x00_set_field32(&reg, RX_BASE_CSR_RING_REGISTER,
 -                         priv_rx->desc_dma);
 +                         entry_priv->desc_dma);
        rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg);
  
        rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, &reg);
@@@ -1291,32 -1294,25 +1291,32 @@@ static int rt61pci_init_registers(struc
        return 0;
  }
  
 -static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev)
 +static int rt61pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
  {
        unsigned int i;
 -      u16 eeprom;
 -      u8 reg_id;
        u8 value;
  
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
                rt61pci_bbp_read(rt2x00dev, 0, &value);
                if ((value != 0xff) && (value != 0x00))
 -                      goto continue_csr_init;
 -              NOTICE(rt2x00dev, "Waiting for BBP register.\n");
 +                      return 0;
                udelay(REGISTER_BUSY_DELAY);
        }
  
        ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
        return -EACCES;
 +}
 +
 +static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev)
 +{
 +      unsigned int i;
 +      u16 eeprom;
 +      u8 reg_id;
 +      u8 value;
 +
 +      if (unlikely(rt61pci_wait_bbp_ready(rt2x00dev)))
 +              return -EACCES;
  
 -continue_csr_init:
        rt61pci_bbp_write(rt2x00dev, 3, 0x00);
        rt61pci_bbp_write(rt2x00dev, 15, 0x30);
        rt61pci_bbp_write(rt2x00dev, 21, 0xc8);
@@@ -1365,8 -1361,7 +1365,8 @@@ static void rt61pci_toggle_rx(struct rt
  
        rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
        rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX,
 -                         state == STATE_RADIO_RX_OFF);
 +                         (state == STATE_RADIO_RX_OFF) ||
 +                         (state == STATE_RADIO_RX_OFF_LINK));
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
  }
  
@@@ -1418,10 -1413,17 +1418,10 @@@ static int rt61pci_enable_radio(struct 
        /*
         * Initialize all registers.
         */
 -      if (rt61pci_init_queues(rt2x00dev) ||
 -          rt61pci_init_registers(rt2x00dev) ||
 -          rt61pci_init_bbp(rt2x00dev)) {
 -              ERROR(rt2x00dev, "Register initialization failed.\n");
 +      if (unlikely(rt61pci_init_queues(rt2x00dev) ||
 +                   rt61pci_init_registers(rt2x00dev) ||
 +                   rt61pci_init_bbp(rt2x00dev)))
                return -EIO;
 -      }
 -
 -      /*
 -       * Enable interrupts.
 -       */
 -      rt61pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON);
  
        /*
         * Enable RX.
@@@ -1453,6 -1455,11 +1453,6 @@@ static void rt61pci_disable_radio(struc
        rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, 1);
        rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, 1);
        rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
 -
 -      /*
 -       * Disable interrupts.
 -       */
 -      rt61pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_OFF);
  }
  
  static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
        u32 reg;
        unsigned int i;
        char put_to_sleep;
 -      char current_state;
  
        put_to_sleep = (state != STATE_AWAKE);
  
         */
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
                rt2x00pci_register_read(rt2x00dev, MAC_CSR12, &reg);
 -              current_state =
 -                  rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
 -              if (current_state == !put_to_sleep)
 +              state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
 +              if (state == !put_to_sleep)
                        return 0;
                msleep(10);
        }
  
 -      NOTICE(rt2x00dev, "Device failed to enter state %d, "
 -             "current device state %d.\n", !put_to_sleep, current_state);
 -
        return -EBUSY;
  }
  
@@@ -1498,13 -1510,11 +1498,13 @@@ static int rt61pci_set_device_state(str
                break;
        case STATE_RADIO_RX_ON:
        case STATE_RADIO_RX_ON_LINK:
 -              rt61pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
 -              break;
        case STATE_RADIO_RX_OFF:
        case STATE_RADIO_RX_OFF_LINK:
 -              rt61pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
 +              rt61pci_toggle_rx(rt2x00dev, state);
 +              break;
 +      case STATE_RADIO_IRQ_ON:
 +      case STATE_RADIO_IRQ_OFF:
 +              rt61pci_toggle_irq(rt2x00dev, state);
                break;
        case STATE_DEEP_SLEEP:
        case STATE_SLEEP:
                break;
        }
  
 +      if (unlikely(retval))
 +              ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
 +                    state, retval);
 +
        return retval;
  }
  
   */
  static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
                                    struct sk_buff *skb,
 -                                  struct txentry_desc *txdesc,
 -                                  struct ieee80211_tx_control *control)
 +                                  struct txentry_desc *txdesc)
  {
        struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
        __le32 *txd = skbdesc->desc;
        rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
        rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
        rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1);
 +      rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
        rt2x00_desc_write(txd, 1, word);
  
        rt2x00_desc_read(txd, 2, &word);
        rt2x00_desc_write(txd, 2, word);
  
        rt2x00_desc_read(txd, 5, &word);
 +      rt2x00_set_field32(&word, TXD_W5_PID_TYPE, skbdesc->entry->queue->qid);
 +      rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE,
 +                         skbdesc->entry->entry_idx);
        rt2x00_set_field32(&word, TXD_W5_TX_POWER,
                           TXPOWER_TO_DEV(rt2x00dev->tx_power));
        rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
        rt2x00_desc_write(txd, 5, word);
  
 +      rt2x00_desc_read(txd, 6, &word);
 +      rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
 +                         skbdesc->skb_dma);
 +      rt2x00_desc_write(txd, 6, word);
 +
        if (skbdesc->desc_len > TXINFO_SIZE) {
                rt2x00_desc_read(txd, 11, &word);
 -              rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skbdesc->data_len);
 +              rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skb->len);
                rt2x00_desc_write(txd, 11, word);
        }
  
                           test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
        rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
 -                         !!(control->flags &
 -                            IEEE80211_TXCTL_LONG_RETRY_LIMIT));
 +                         test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
 -      rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
 +      rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len);
        rt2x00_set_field32(&word, TXD_W0_BURST,
                           test_bit(ENTRY_TXD_BURST, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
  /*
   * TX data initialization
   */
 +static void rt61pci_write_beacon(struct queue_entry *entry)
 +{
 +      struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 +      struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
 +      unsigned int beacon_base;
 +      u32 reg;
 +
 +      /*
 +       * Disable beaconing while we are reloading the beacon data,
 +       * otherwise we might be sending out invalid data.
 +       */
 +      rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
 +      rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
 +      rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
 +      rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
 +      rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
 +
 +      /*
 +       * Write entire beacon with descriptor to register.
 +       */
 +      beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
 +      rt2x00pci_register_multiwrite(rt2x00dev,
 +                                    beacon_base,
 +                                    skbdesc->desc, skbdesc->desc_len);
 +      rt2x00pci_register_multiwrite(rt2x00dev,
 +                                    beacon_base + skbdesc->desc_len,
 +                                    entry->skb->data, entry->skb->len);
 +
 +      /*
 +       * Clean up beacon skb.
 +       */
 +      dev_kfree_skb_any(entry->skb);
 +      entry->skb = NULL;
 +}
 +
  static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
 -                                const unsigned int queue)
 +                                const enum data_queue_qid queue)
  {
        u32 reg;
  
 -      if (queue == RT2X00_BCN_QUEUE_BEACON) {
 +      if (queue == QID_BEACON) {
                /*
                 * For Wi-Fi faily generated beacons between participating
                 * stations. Set TBTT phase adaptive adjustment step to 8us.
        }
  
        rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
 -      rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0,
 -                         (queue == IEEE80211_TX_QUEUE_DATA0));
 -      rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1,
 -                         (queue == IEEE80211_TX_QUEUE_DATA1));
 -      rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2,
 -                         (queue == IEEE80211_TX_QUEUE_DATA2));
 -      rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3,
 -                         (queue == IEEE80211_TX_QUEUE_DATA3));
 +      rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0, (queue == QID_AC_BE));
 +      rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, (queue == QID_AC_BK));
 +      rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2, (queue == QID_AC_VI));
 +      rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3, (queue == QID_AC_VO));
        rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
  }
  
@@@ -1712,13 -1680,14 +1712,13 @@@ static int rt61pci_agc_to_rssi(struct r
  static void rt61pci_fill_rxdone(struct queue_entry *entry,
                                struct rxdone_entry_desc *rxdesc)
  {
 -      struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
 +      struct queue_entry_priv_pci *entry_priv = entry->priv_data;
        u32 word0;
        u32 word1;
  
 -      rt2x00_desc_read(priv_rx->desc, 0, &word0);
 -      rt2x00_desc_read(priv_rx->desc, 1, &word1);
 +      rt2x00_desc_read(entry_priv->desc, 0, &word0);
 +      rt2x00_desc_read(entry_priv->desc, 1, &word1);
  
 -      rxdesc->flags = 0;
        if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
                rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
  
        rxdesc->rssi = rt61pci_agc_to_rssi(entry->queue->rt2x00dev, word1);
        rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
  
 -      rxdesc->dev_flags = 0;
        if (rt2x00_get_field32(word0, RXD_W0_OFDM))
                rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
        if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
@@@ -1746,7 -1716,7 +1746,7 @@@ static void rt61pci_txdone(struct rt2x0
        struct data_queue *queue;
        struct queue_entry *entry;
        struct queue_entry *entry_done;
 -      struct queue_entry_priv_pci_tx *priv_tx;
 +      struct queue_entry_priv_pci *entry_priv;
        struct txdone_entry_desc txdesc;
        u32 word;
        u32 reg;
                        continue;
  
                entry = &queue->entries[index];
 -              priv_tx = entry->priv_data;
 -              rt2x00_desc_read(priv_tx->desc, 0, &word);
 +              entry_priv = entry->priv_data;
 +              rt2x00_desc_read(entry_priv->desc, 0, &word);
  
                if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
                    !rt2x00_get_field32(word, TXD_W0_VALID))
                                "TX status report missed for entry %d\n",
                                entry_done->entry_idx);
  
 -                      txdesc.status = TX_FAIL_OTHER;
 +                      txdesc.flags = 0;
 +                      __set_bit(TXDONE_UNKNOWN, &txdesc.flags);
                        txdesc.retry = 0;
  
 -                      rt2x00pci_txdone(rt2x00dev, entry_done, &txdesc);
 +                      rt2x00lib_txdone(entry_done, &txdesc);
                        entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
                }
  
                /*
                 * Obtain the status about this packet.
                 */
 -              txdesc.status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
 +              txdesc.flags = 0;
 +              switch (rt2x00_get_field32(reg, STA_CSR4_TX_RESULT)) {
 +              case 0: /* Success, maybe with retry */
 +                      __set_bit(TXDONE_SUCCESS, &txdesc.flags);
 +                      break;
 +              case 6: /* Failure, excessive retries */
 +                      __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
 +                      /* Don't break, this is a failed frame! */
 +              default: /* Failure */
 +                      __set_bit(TXDONE_FAILURE, &txdesc.flags);
 +              }
                txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
  
 -              rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
 +              rt2x00lib_txdone(entry, &txdesc);
        }
  }
  
@@@ -2017,7 -1976,7 +2017,7 @@@ static int rt61pci_init_eeprom(struct r
         * To determine the RT chip we have to read the
         * PCI header of the device.
         */
 -      pci_read_config_word(rt2x00dev_pci(rt2x00dev),
 +      pci_read_config_word(to_pci_dev(rt2x00dev->dev),
                             PCI_CONFIG_HEADER_DEVICE, &device);
        value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
        rt2x00pci_register_read(rt2x00dev, MAC_CSR0, &reg);
        rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
        value = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
  
 -      rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
 -      rt2x00dev->led_radio.type = LED_TYPE_RADIO;
 -      rt2x00dev->led_radio.led_dev.brightness_set =
 -          rt61pci_brightness_set;
 -      rt2x00dev->led_radio.led_dev.blink_set =
 -          rt61pci_blink_set;
 -      rt2x00dev->led_radio.flags = LED_INITIALIZED;
 -
 -      rt2x00dev->led_assoc.rt2x00dev = rt2x00dev;
 -      rt2x00dev->led_assoc.type = LED_TYPE_ASSOC;
 -      rt2x00dev->led_assoc.led_dev.brightness_set =
 -          rt61pci_brightness_set;
 -      rt2x00dev->led_assoc.led_dev.blink_set =
 -          rt61pci_blink_set;
 -      rt2x00dev->led_assoc.flags = LED_INITIALIZED;
 -
 -      if (value == LED_MODE_SIGNAL_STRENGTH) {
 -              rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
 -              rt2x00dev->led_qual.type = LED_TYPE_QUALITY;
 -              rt2x00dev->led_qual.led_dev.brightness_set =
 -                  rt61pci_brightness_set;
 -              rt2x00dev->led_qual.led_dev.blink_set =
 -                  rt61pci_blink_set;
 -              rt2x00dev->led_qual.flags = LED_INITIALIZED;
 -      }
 +      rt61pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
 +      rt61pci_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
 +      if (value == LED_MODE_SIGNAL_STRENGTH)
 +              rt61pci_init_led(rt2x00dev, &rt2x00dev->led_qual,
 +                               LED_TYPE_QUALITY);
  
        rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
        rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
@@@ -2279,11 -2258,13 +2279,11 @@@ static void rt61pci_probe_hw_mode(struc
         */
        rt2x00dev->hw->flags =
            IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
 -          IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
 +          IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 +          IEEE80211_HW_SIGNAL_DBM;
        rt2x00dev->hw->extra_tx_headroom = 0;
 -      rt2x00dev->hw->max_signal = MAX_SIGNAL;
 -      rt2x00dev->hw->max_rssi = MAX_RX_SSI;
 -      rt2x00dev->hw->queues = 4;
  
 -      SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
 +      SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
        SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
                                rt2x00_eeprom_addr(rt2x00dev,
                                                   EEPROM_MAC_ADDR_0));
@@@ -2346,10 -2327,9 +2346,10 @@@ static int rt61pci_probe_hw(struct rt2x
        rt61pci_probe_hw_mode(rt2x00dev);
  
        /*
 -       * This device requires firmware.
 +       * This device requires firmware and DMA mapped skbs.
         */
        __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
 +      __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
  
        /*
         * Set the rssi offset.
@@@ -2390,6 -2370,67 +2390,6 @@@ static u64 rt61pci_get_tsf(struct ieee8
        return tsf;
  }
  
 -static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
 -                        struct ieee80211_tx_control *control)
 -{
 -      struct rt2x00_dev *rt2x00dev = hw->priv;
 -      struct rt2x00_intf *intf = vif_to_intf(control->vif);
 -      struct queue_entry_priv_pci_tx *priv_tx;
 -      struct skb_frame_desc *skbdesc;
 -      unsigned int beacon_base;
 -      u32 reg;
 -
 -      if (unlikely(!intf->beacon))
 -              return -ENOBUFS;
 -
 -      priv_tx = intf->beacon->priv_data;
 -      memset(priv_tx->desc, 0, intf->beacon->queue->desc_size);
 -
 -      /*
 -       * Fill in skb descriptor
 -       */
 -      skbdesc = get_skb_frame_desc(skb);
 -      memset(skbdesc, 0, sizeof(*skbdesc));
 -      skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
 -      skbdesc->data = skb->data;
 -      skbdesc->data_len = skb->len;
 -      skbdesc->desc = priv_tx->desc;
 -      skbdesc->desc_len = intf->beacon->queue->desc_size;
 -      skbdesc->entry = intf->beacon;
 -
 -      /*
 -       * Disable beaconing while we are reloading the beacon data,
 -       * otherwise we might be sending out invalid data.
 -       */
 -      rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
 -      rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
 -      rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
 -      rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
 -      rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
 -
 -      /*
 -       * mac80211 doesn't provide the control->queue variable
 -       * for beacons. Set our own queue identification so
 -       * it can be used during descriptor initialization.
 -       */
 -      control->queue = RT2X00_BCN_QUEUE_BEACON;
 -      rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
 -
 -      /*
 -       * Write entire beacon with descriptor to register,
 -       * and kick the beacon generator.
 -       */
 -      beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
 -      rt2x00pci_register_multiwrite(rt2x00dev, beacon_base,
 -                                    skbdesc->desc, skbdesc->desc_len);
 -      rt2x00pci_register_multiwrite(rt2x00dev,
 -                                    beacon_base + skbdesc->desc_len,
 -                                    skbdesc->data, skbdesc->data_len);
 -      rt61pci_kick_tx_queue(rt2x00dev, control->queue);
 -
 -      return 0;
 -}
 -
  static const struct ieee80211_ops rt61pci_mac80211_ops = {
        .tx                     = rt2x00mac_tx,
        .start                  = rt2x00mac_start,
        .conf_tx                = rt2x00mac_conf_tx,
        .get_tx_stats           = rt2x00mac_get_tx_stats,
        .get_tsf                = rt61pci_get_tsf,
 -      .beacon_update          = rt61pci_beacon_update,
  };
  
  static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
        .link_tuner             = rt61pci_link_tuner,
        .write_tx_desc          = rt61pci_write_tx_desc,
        .write_tx_data          = rt2x00pci_write_tx_data,
 +      .write_beacon           = rt61pci_write_beacon,
        .kick_tx_queue          = rt61pci_kick_tx_queue,
        .fill_rxdone            = rt61pci_fill_rxdone,
        .config_filter          = rt61pci_config_filter,
@@@ -2437,21 -2478,21 +2437,21 @@@ static const struct data_queue_desc rt6
        .entry_num              = RX_ENTRIES,
        .data_size              = DATA_FRAME_SIZE,
        .desc_size              = RXD_DESC_SIZE,
 -      .priv_size              = sizeof(struct queue_entry_priv_pci_rx),
 +      .priv_size              = sizeof(struct queue_entry_priv_pci),
  };
  
  static const struct data_queue_desc rt61pci_queue_tx = {
        .entry_num              = TX_ENTRIES,
        .data_size              = DATA_FRAME_SIZE,
        .desc_size              = TXD_DESC_SIZE,
 -      .priv_size              = sizeof(struct queue_entry_priv_pci_tx),
 +      .priv_size              = sizeof(struct queue_entry_priv_pci),
  };
  
  static const struct data_queue_desc rt61pci_queue_bcn = {
        .entry_num              = 4 * BEACON_ENTRIES,
        .data_size              = 0, /* No DMA required for beacons */
        .desc_size              = TXINFO_SIZE,
 -      .priv_size              = sizeof(struct queue_entry_priv_pci_tx),
 +      .priv_size              = sizeof(struct queue_entry_priv_pci),
  };
  
  static const struct rt2x00_ops rt61pci_ops = {
        .max_ap_intf    = 4,
        .eeprom_size    = EEPROM_SIZE,
        .rf_size        = RF_SIZE,
 +      .tx_queues      = NUM_TX_QUEUES,
        .rx             = &rt61pci_queue_rx,
        .tx             = &rt61pci_queue_tx,
        .bcn            = &rt61pci_queue_bcn,
index 34c6ff27afc4d5dbc0bcd8a009f3aeab331eb237,6a62d6bb96fefabae159d585a9590b90a328443a..d383735ab8f2dec53431bf3aa079a3490fa2c782
@@@ -74,10 -74,10 +74,10 @@@ static inline void rt73usb_register_mul
                                              const unsigned int offset,
                                              void *value, const u32 length)
  {
 -      int timeout = REGISTER_TIMEOUT * (length / sizeof(u32));
        rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
                                      USB_VENDOR_REQUEST_IN, offset,
 -                                    value, length, timeout);
 +                                    value, length,
 +                                    REGISTER_TIMEOUT32(length));
  }
  
  static inline void rt73usb_register_write(struct rt2x00_dev *rt2x00dev,
@@@ -102,10 -102,10 +102,10 @@@ static inline void rt73usb_register_mul
                                               const unsigned int offset,
                                               void *value, const u32 length)
  {
 -      int timeout = REGISTER_TIMEOUT * (length / sizeof(u32));
        rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
                                      USB_VENDOR_REQUEST_OUT, offset,
 -                                    value, length, timeout);
 +                                    value, length,
 +                                    REGISTER_TIMEOUT32(length));
  }
  
  static u32 rt73usb_bbp_check(struct rt2x00_dev *rt2x00dev)
@@@ -341,17 -341,6 +341,17 @@@ static int rt73usb_blink_set(struct led
  
        return 0;
  }
 +
 +static void rt73usb_init_led(struct rt2x00_dev *rt2x00dev,
 +                           struct rt2x00_led *led,
 +                           enum led_type type)
 +{
 +      led->rt2x00dev = rt2x00dev;
 +      led->type = type;
 +      led->led_dev.brightness_set = rt73usb_brightness_set;
 +      led->led_dev.blink_set = rt73usb_blink_set;
 +      led->flags = LED_INITIALIZED;
 +}
  #endif /* CONFIG_RT73USB_LEDS */
  
  /*
@@@ -867,7 -856,7 +867,7 @@@ static char *rt73usb_get_firmware_name(
        return FIRMWARE_RT2571;
  }
  
- static u16 rt73usb_get_firmware_crc(void *data, const size_t len)
+ static u16 rt73usb_get_firmware_crc(const void *data, const size_t len)
  {
        u16 crc;
  
        return crc;
  }
  
- static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
+ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data,
                                 const size_t len)
  {
        unsigned int i;
        int status;
        u32 reg;
-       char *ptr = data;
+       const char *ptr = data;
        char *cache;
        int buflen;
 -      int timeout;
  
        /*
         * Wait for stable hardware.
  
        for (i = 0; i < len; i += CSR_CACHE_SIZE_FIRMWARE) {
                buflen = min_t(int, len - i, CSR_CACHE_SIZE_FIRMWARE);
 -              timeout = REGISTER_TIMEOUT * (buflen / sizeof(u32));
  
                memcpy(cache, ptr, buflen);
  
                rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
                                         USB_VENDOR_REQUEST_OUT,
                                         FIRMWARE_IMAGE_BASE + i, 0,
 -                                       cache, buflen, timeout);
 +                                       cache, buflen,
 +                                       REGISTER_TIMEOUT32(buflen));
  
                ptr += buflen;
        }
@@@ -1110,32 -1100,25 +1110,32 @@@ static int rt73usb_init_registers(struc
        return 0;
  }
  
 -static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev)
 +static int rt73usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
  {
        unsigned int i;
 -      u16 eeprom;
 -      u8 reg_id;
        u8 value;
  
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
                rt73usb_bbp_read(rt2x00dev, 0, &value);
                if ((value != 0xff) && (value != 0x00))
 -                      goto continue_csr_init;
 -              NOTICE(rt2x00dev, "Waiting for BBP register.\n");
 +                      return 0;
                udelay(REGISTER_BUSY_DELAY);
        }
  
        ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
        return -EACCES;
 +}
 +
 +static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev)
 +{
 +      unsigned int i;
 +      u16 eeprom;
 +      u8 reg_id;
 +      u8 value;
 +
 +      if (unlikely(rt73usb_wait_bbp_ready(rt2x00dev)))
 +              return -EACCES;
  
 -continue_csr_init:
        rt73usb_bbp_write(rt2x00dev, 3, 0x80);
        rt73usb_bbp_write(rt2x00dev, 15, 0x30);
        rt73usb_bbp_write(rt2x00dev, 21, 0xc8);
@@@ -1185,8 -1168,7 +1185,8 @@@ static void rt73usb_toggle_rx(struct rt
  
        rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
        rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX,
 -                         state == STATE_RADIO_RX_OFF);
 +                         (state == STATE_RADIO_RX_OFF) ||
 +                         (state == STATE_RADIO_RX_OFF_LINK));
        rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
  }
  
@@@ -1195,9 -1177,11 +1195,9 @@@ static int rt73usb_enable_radio(struct 
        /*
         * Initialize all registers.
         */
 -      if (rt73usb_init_registers(rt2x00dev) ||
 -          rt73usb_init_bbp(rt2x00dev)) {
 -              ERROR(rt2x00dev, "Register initialization failed.\n");
 +      if (unlikely(rt73usb_init_registers(rt2x00dev) ||
 +                   rt73usb_init_bbp(rt2x00dev)))
                return -EIO;
 -      }
  
        return 0;
  }
@@@ -1219,6 -1203,7 +1219,6 @@@ static int rt73usb_set_state(struct rt2
        u32 reg;
        unsigned int i;
        char put_to_sleep;
 -      char current_state;
  
        put_to_sleep = (state != STATE_AWAKE);
  
         */
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
                rt73usb_register_read(rt2x00dev, MAC_CSR12, &reg);
 -              current_state =
 -                  rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
 -              if (current_state == !put_to_sleep)
 +              state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
 +              if (state == !put_to_sleep)
                        return 0;
                msleep(10);
        }
  
 -      NOTICE(rt2x00dev, "Device failed to enter state %d, "
 -             "current device state %d.\n", !put_to_sleep, current_state);
 -
        return -EBUSY;
  }
  
@@@ -1257,13 -1246,11 +1257,13 @@@ static int rt73usb_set_device_state(str
                break;
        case STATE_RADIO_RX_ON:
        case STATE_RADIO_RX_ON_LINK:
 -              rt73usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
 -              break;
        case STATE_RADIO_RX_OFF:
        case STATE_RADIO_RX_OFF_LINK:
 -              rt73usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
 +              rt73usb_toggle_rx(rt2x00dev, state);
 +              break;
 +      case STATE_RADIO_IRQ_ON:
 +      case STATE_RADIO_IRQ_OFF:
 +              /* No support, but no error either */
                break;
        case STATE_DEEP_SLEEP:
        case STATE_SLEEP:
                break;
        }
  
 +      if (unlikely(retval))
 +              ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
 +                    state, retval);
 +
        return retval;
  }
  
   */
  static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
                                    struct sk_buff *skb,
 -                                  struct txentry_desc *txdesc,
 -                                  struct ieee80211_tx_control *control)
 +                                  struct txentry_desc *txdesc)
  {
        struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
        __le32 *txd = skbdesc->desc;
                           test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
        rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
 -                         !!(control->flags &
 -                            IEEE80211_TXCTL_LONG_RETRY_LIMIT));
 +                         test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
 -      rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
 +      rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT,
 +                         skb->len - skbdesc->desc_len);
        rt2x00_set_field32(&word, TXD_W0_BURST2,
                           test_bit(ENTRY_TXD_BURST, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
        rt2x00_desc_write(txd, 0, word);
  }
  
 +/*
 + * TX data initialization
 + */
 +static void rt73usb_write_beacon(struct queue_entry *entry)
 +{
 +      struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 +      struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
 +      unsigned int beacon_base;
 +      u32 reg;
 +
 +      /*
 +       * Add the descriptor in front of the skb.
 +       */
 +      skb_push(entry->skb, entry->queue->desc_size);
 +      memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len);
 +      skbdesc->desc = entry->skb->data;
 +
 +      /*
 +       * Disable beaconing while we are reloading the beacon data,
 +       * otherwise we might be sending out invalid data.
 +       */
 +      rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
 +      rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
 +      rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
 +      rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
 +      rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
 +
 +      /*
 +       * Write entire beacon with descriptor to register.
 +       */
 +      beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
 +      rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
 +                               USB_VENDOR_REQUEST_OUT, beacon_base, 0,
 +                               entry->skb->data, entry->skb->len,
 +                               REGISTER_TIMEOUT32(entry->skb->len));
 +
 +      /*
 +       * Clean up the beacon skb.
 +       */
 +      dev_kfree_skb(entry->skb);
 +      entry->skb = NULL;
 +}
 +
  static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
                                   struct sk_buff *skb)
  {
        return length;
  }
  
 -/*
 - * TX data initialization
 - */
  static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
 -                                const unsigned int queue)
 +                                const enum data_queue_qid queue)
  {
        u32 reg;
  
 -      if (queue != RT2X00_BCN_QUEUE_BEACON)
 +      if (queue != QID_BEACON) {
 +              rt2x00usb_kick_tx_queue(rt2x00dev, queue);
                return;
 +      }
  
        /*
         * For Wi-Fi faily generated beacons between participating stations.
@@@ -1479,22 -1421,25 +1479,22 @@@ static void rt73usb_fill_rxdone(struct 
  {
        struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
        __le32 *rxd = (__le32 *)entry->skb->data;
 -      unsigned int offset = entry->queue->desc_size + 2;
        u32 word0;
        u32 word1;
  
        /*
 -       * Copy descriptor to the available headroom inside the skbuffer.
 +       * Copy descriptor to the skbdesc->desc buffer, making it safe from moving of
 +       * frame data in rt2x00usb.
         */
 -      skb_push(entry->skb, offset);
 -      memcpy(entry->skb->data, rxd, entry->queue->desc_size);
 -      rxd = (__le32 *)entry->skb->data;
 +      memcpy(skbdesc->desc, rxd, skbdesc->desc_len);
 +      rxd = (__le32 *)skbdesc->desc;
  
        /*
 -       * The descriptor is now aligned to 4 bytes and thus it is
 -       * now safe to read it on all architectures.
 +       * It is now safe to read the descriptor on all architectures.
         */
        rt2x00_desc_read(rxd, 0, &word0);
        rt2x00_desc_read(rxd, 1, &word1);
  
 -      rxdesc->flags = 0;
        if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
                rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
  
        rxdesc->rssi = rt73usb_agc_to_rssi(entry->queue->rt2x00dev, word1);
        rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
  
 -      rxdesc->dev_flags = 0;
        if (rt2x00_get_field32(word0, RXD_W0_OFDM))
                rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
        if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
                rxdesc->dev_flags |= RXDONE_MY_BSS;
  
        /*
 -       * Adjust the skb memory window to the frame boundaries.
 +       * Set skb pointers, and update frame information.
         */
 -      skb_pull(entry->skb, offset + entry->queue->desc_size);
 +      skb_pull(entry->skb, entry->queue->desc_size);
        skb_trim(entry->skb, rxdesc->size);
 -
 -      /*
 -       * Set descriptor and data pointer.
 -       */
 -      skbdesc->data = entry->skb->data;
 -      skbdesc->data_len = rxdesc->size;
 -      skbdesc->desc = rxd;
 -      skbdesc->desc_len = entry->queue->desc_size;
  }
  
  /*
@@@ -1690,11 -1644,31 +1690,11 @@@ static int rt73usb_init_eeprom(struct r
  #ifdef CONFIG_RT73USB_LEDS
        rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
  
 -      rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
 -      rt2x00dev->led_radio.type = LED_TYPE_RADIO;
 -      rt2x00dev->led_radio.led_dev.brightness_set =
 -          rt73usb_brightness_set;
 -      rt2x00dev->led_radio.led_dev.blink_set =
 -          rt73usb_blink_set;
 -      rt2x00dev->led_radio.flags = LED_INITIALIZED;
 -
 -      rt2x00dev->led_assoc.rt2x00dev = rt2x00dev;
 -      rt2x00dev->led_assoc.type = LED_TYPE_ASSOC;
 -      rt2x00dev->led_assoc.led_dev.brightness_set =
 -          rt73usb_brightness_set;
 -      rt2x00dev->led_assoc.led_dev.blink_set =
 -          rt73usb_blink_set;
 -      rt2x00dev->led_assoc.flags = LED_INITIALIZED;
 -
 -      if (value == LED_MODE_SIGNAL_STRENGTH) {
 -              rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
 -              rt2x00dev->led_qual.type = LED_TYPE_QUALITY;
 -              rt2x00dev->led_qual.led_dev.brightness_set =
 -                  rt73usb_brightness_set;
 -              rt2x00dev->led_qual.led_dev.blink_set =
 -                  rt73usb_blink_set;
 -              rt2x00dev->led_qual.flags = LED_INITIALIZED;
 -      }
 +      rt73usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
 +      rt73usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
 +      if (value == LED_MODE_SIGNAL_STRENGTH)
 +              rt73usb_init_led(rt2x00dev, &rt2x00dev->led_qual,
 +                               LED_TYPE_QUALITY);
  
        rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
        rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
@@@ -1872,11 -1846,13 +1872,11 @@@ static void rt73usb_probe_hw_mode(struc
         */
        rt2x00dev->hw->flags =
            IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
 -          IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
 +          IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 +          IEEE80211_HW_SIGNAL_DBM;
        rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
 -      rt2x00dev->hw->max_signal = MAX_SIGNAL;
 -      rt2x00dev->hw->max_rssi = MAX_RX_SSI;
 -      rt2x00dev->hw->queues = 4;
  
 -      SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
 +      SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
        SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
                                rt2x00_eeprom_addr(rt2x00dev,
                                                   EEPROM_MAC_ADDR_0));
@@@ -1998,6 -1974,69 +1998,6 @@@ static u64 rt73usb_get_tsf(struct ieee8
  #define rt73usb_get_tsf       NULL
  #endif
  
 -static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
 -                               struct ieee80211_tx_control *control)
 -{
 -      struct rt2x00_dev *rt2x00dev = hw->priv;
 -      struct rt2x00_intf *intf = vif_to_intf(control->vif);
 -      struct skb_frame_desc *skbdesc;
 -      unsigned int beacon_base;
 -      unsigned int timeout;
 -      u32 reg;
 -
 -      if (unlikely(!intf->beacon))
 -              return -ENOBUFS;
 -
 -      /*
 -       * Add the descriptor in front of the skb.
 -       */
 -      skb_push(skb, intf->beacon->queue->desc_size);
 -      memset(skb->data, 0, intf->beacon->queue->desc_size);
 -
 -      /*
 -       * Fill in skb descriptor
 -       */
 -      skbdesc = get_skb_frame_desc(skb);
 -      memset(skbdesc, 0, sizeof(*skbdesc));
 -      skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
 -      skbdesc->data = skb->data + intf->beacon->queue->desc_size;
 -      skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
 -      skbdesc->desc = skb->data;
 -      skbdesc->desc_len = intf->beacon->queue->desc_size;
 -      skbdesc->entry = intf->beacon;
 -
 -      /*
 -       * Disable beaconing while we are reloading the beacon data,
 -       * otherwise we might be sending out invalid data.
 -       */
 -      rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
 -      rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
 -      rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
 -      rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
 -      rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
 -
 -      /*
 -       * mac80211 doesn't provide the control->queue variable
 -       * for beacons. Set our own queue identification so
 -       * it can be used during descriptor initialization.
 -       */
 -      control->queue = RT2X00_BCN_QUEUE_BEACON;
 -      rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
 -
 -      /*
 -       * Write entire beacon with descriptor to register,
 -       * and kick the beacon generator.
 -       */
 -      beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
 -      timeout = REGISTER_TIMEOUT * (skb->len / sizeof(u32));
 -      rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
 -                               USB_VENDOR_REQUEST_OUT, beacon_base, 0,
 -                               skb->data, skb->len, timeout);
 -      rt73usb_kick_tx_queue(rt2x00dev, control->queue);
 -
 -      return 0;
 -}
 -
  static const struct ieee80211_ops rt73usb_mac80211_ops = {
        .tx                     = rt2x00mac_tx,
        .start                  = rt2x00mac_start,
        .conf_tx                = rt2x00mac_conf_tx,
        .get_tx_stats           = rt2x00mac_get_tx_stats,
        .get_tsf                = rt73usb_get_tsf,
 -      .beacon_update          = rt73usb_beacon_update,
  };
  
  static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
        .link_tuner             = rt73usb_link_tuner,
        .write_tx_desc          = rt73usb_write_tx_desc,
        .write_tx_data          = rt2x00usb_write_tx_data,
 +      .write_beacon           = rt73usb_write_beacon,
        .get_tx_data_len        = rt73usb_get_tx_data_len,
        .kick_tx_queue          = rt73usb_kick_tx_queue,
        .fill_rxdone            = rt73usb_fill_rxdone,
@@@ -2044,21 -2083,21 +2044,21 @@@ static const struct data_queue_desc rt7
        .entry_num              = RX_ENTRIES,
        .data_size              = DATA_FRAME_SIZE,
        .desc_size              = RXD_DESC_SIZE,
 -      .priv_size              = sizeof(struct queue_entry_priv_usb_rx),
 +      .priv_size              = sizeof(struct queue_entry_priv_usb),
  };
  
  static const struct data_queue_desc rt73usb_queue_tx = {
        .entry_num              = TX_ENTRIES,
        .data_size              = DATA_FRAME_SIZE,
        .desc_size              = TXD_DESC_SIZE,
 -      .priv_size              = sizeof(struct queue_entry_priv_usb_tx),
 +      .priv_size              = sizeof(struct queue_entry_priv_usb),
  };
  
  static const struct data_queue_desc rt73usb_queue_bcn = {
        .entry_num              = 4 * BEACON_ENTRIES,
        .data_size              = MGMT_FRAME_SIZE,
        .desc_size              = TXINFO_SIZE,
 -      .priv_size              = sizeof(struct queue_entry_priv_usb_tx),
 +      .priv_size              = sizeof(struct queue_entry_priv_usb),
  };
  
  static const struct rt2x00_ops rt73usb_ops = {
        .max_ap_intf    = 4,
        .eeprom_size    = EEPROM_SIZE,
        .rf_size        = RF_SIZE,
 +      .tx_queues      = NUM_TX_QUEUES,
        .rx             = &rt73usb_queue_rx,
        .tx             = &rt73usb_queue_tx,
        .bcn            = &rt73usb_queue_bcn,
index 07e4d1f732078d28f96d9fd49c5f7732bdf814db,78baa0f7926d10ba1412cf570db79deaa695ce61..b16ec6e5f0e3913115fe6a40b15ae9a9e0bde4ca
@@@ -49,7 -49,7 +49,7 @@@ MODULE_DEVICE_TABLE(usb, zd1201_table)
  static int zd1201_fw_upload(struct usb_device *dev, int apfw)
  {
        const struct firmware *fw_entry;
-       char *data;
+       const char *data;
        unsigned long len;
        int err;
        unsigned char ret;
@@@ -1152,36 -1152,32 +1152,36 @@@ static int zd1201_get_scan(struct net_d
                iwe.cmd = SIOCGIWAP;
                iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
                memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6);
 -              cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN);
 +              cev = iwe_stream_add_event(info, cev, end_buf,
 +                                         &iwe, IW_EV_ADDR_LEN);
  
                iwe.cmd = SIOCGIWESSID;
                iwe.u.data.length = zd->rxdata[i+16];
                iwe.u.data.flags = 1;
 -              cev = iwe_stream_add_point(cev, end_buf, &iwe, zd->rxdata+i+18);
 +              cev = iwe_stream_add_point(info, cev, end_buf,
 +                                         &iwe, zd->rxdata+i+18);
  
                iwe.cmd = SIOCGIWMODE;
                if (zd->rxdata[i+14]&0x01)
                        iwe.u.mode = IW_MODE_MASTER;
                else
                        iwe.u.mode = IW_MODE_ADHOC;
 -              cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN);
 +              cev = iwe_stream_add_event(info, cev, end_buf,
 +                                         &iwe, IW_EV_UINT_LEN);
                
                iwe.cmd = SIOCGIWFREQ;
                iwe.u.freq.m = zd->rxdata[i+0];
                iwe.u.freq.e = 0;
 -              cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN);
 +              cev = iwe_stream_add_event(info, cev, end_buf,
 +                                         &iwe, IW_EV_FREQ_LEN);
                
                iwe.cmd = SIOCGIWRATE;
                iwe.u.bitrate.fixed = 0;
                iwe.u.bitrate.disabled = 0;
                for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) {
                        iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000;
 -                      cev=iwe_stream_add_event(cev, end_buf, &iwe,
 -                          IW_EV_PARAM_LEN);
 +                      cev = iwe_stream_add_event(info, cev, end_buf,
 +                                                 &iwe, IW_EV_PARAM_LEN);
                }
                
                iwe.cmd = SIOCGIWENCODE;
                        iwe.u.data.flags = IW_ENCODE_ENABLED;
                else
                        iwe.u.data.flags = IW_ENCODE_DISABLED;
 -              cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL);
 +              cev = iwe_stream_add_point(info, cev, end_buf, &iwe, NULL);
                
                iwe.cmd = IWEVQUAL;
                iwe.u.qual.qual = zd->rxdata[i+4];
                iwe.u.qual.noise= zd->rxdata[i+2]/10-100;
                iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100;
                iwe.u.qual.updated = 7;
 -              cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN);
 +              cev = iwe_stream_add_event(info, cev, end_buf,
 +                                         &iwe, IW_EV_QUAL_LEN);
        }
  
        if (!enabled_save)
index 85be40abdda944f0a82b7c9800756f8e9a5c3af5,22f64aa6dd1fc9e7699c457c0c4c5b2d06c25118..b29afef5c7fb35afbc012d3ef9337130e5443543
@@@ -944,15 -944,8 +944,8 @@@ static int qeth_l3_deregister_addr_entr
        else
                rc = qeth_l3_send_setdelip(card, addr, IPA_CMD_DELIP,
                                        addr->del_flags);
-       if (rc) {
+       if (rc)
                QETH_DBF_TEXT(TRACE, 2, "failed");
-               /* TODO: re-activate this warning as soon as we have a
-                * clean mirco code
-               qeth_ipaddr_to_string(addr->proto, (u8 *)&addr->u, buf);
-               PRINT_WARN("Could not deregister IP address %s (rc=%x)\n",
-                          buf, rc);
-               */
-       }
  
        return rc;
  }
@@@ -2020,7 -2013,7 +2013,7 @@@ static int qeth_l3_verify_vlan_dev(stru
                }
        }
  
 -      if (rc && !(netdev_priv(vlan_dev_info(dev)->real_dev) == (void *)card))
 +      if (rc && !(netdev_priv(vlan_dev_real_dev(dev)) == (void *)card))
                return 0;
  
        return rc;
@@@ -2056,7 -2049,7 +2049,7 @@@ static struct qeth_card *qeth_l3_get_ca
        if (rc == QETH_REAL_CARD)
                card = netdev_priv(dev);
        else if (rc == QETH_VLAN_CARD)
 -              card = netdev_priv(vlan_dev_info(dev)->real_dev);
 +              card = netdev_priv(vlan_dev_real_dev(dev));
        if (card && card->options.layer2)
                card = NULL;
        QETH_DBF_TEXT_(TRACE, 4, "%d", rc);
@@@ -2946,8 -2939,7 +2939,7 @@@ static int qeth_l3_setup_netdev(struct 
  }
  
  static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev,
-               unsigned int status, unsigned int qdio_err,
-               unsigned int siga_err, unsigned int queue, int first_element,
+               unsigned int qdio_err, unsigned int queue, int first_element,
                int count, unsigned long card_ptr)
  {
        struct net_device *net_dev;
                card->perf_stats.inbound_cnt++;
                card->perf_stats.inbound_start_time = qeth_get_micros();
        }
-       if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
-               if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
-                       QETH_DBF_TEXT(TRACE, 1, "qdinchk");
-                       QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
-                       QETH_DBF_TEXT_(TRACE, 1, "%04X%04X",
-                                       first_element, count);
-                       QETH_DBF_TEXT_(TRACE, 1, "%04X%04X", queue, status);
-                       qeth_schedule_recovery(card);
-                       return;
-               }
+       if (qdio_err & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) {
+               QETH_DBF_TEXT(TRACE, 1, "qdinchk");
+               QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
+               QETH_DBF_TEXT_(TRACE, 1, "%04X%04X",
+                               first_element, count);
+               QETH_DBF_TEXT_(TRACE, 1, "%04X", queue);
+               qeth_schedule_recovery(card);
+               return;
        }
        for (i = first_element; i < (first_element + count); ++i) {
                index = i % QDIO_MAX_BUFFERS_PER_Q;
                buffer = &card->qdio.in_q->bufs[index];
-               if (!((status & QDIO_STATUS_LOOK_FOR_ERROR) &&
+               if (!(qdio_err &&
                      qeth_check_qdio_errors(buffer->buffer,
-                                            qdio_err, siga_err, "qinerr")))
+                                            qdio_err, "qinerr")))
                        qeth_l3_process_inbound_buffer(card, buffer, index);
                /* clear buffer and give back to hardware */
                qeth_put_buffer_pool_entry(card, buffer->pool_entry);
diff --combined fs/compat_ioctl.c
index 05ec7eef8690601e332c3517baf11002159485b4,c54eaab71a19a9707493ee298bfdff93c0c8ff26..ddefb8851a98deb77aa82780eca4e272f7d2ddaa
@@@ -58,6 -58,7 +58,6 @@@
  #include <linux/syscalls.h>
  #include <linux/i2c.h>
  #include <linux/i2c-dev.h>
 -#include <linux/wireless.h>
  #include <linux/atalk.h>
  #include <linux/loop.h>
  
  #include <linux/capi.h>
  #include <linux/gigaset_dev.h>
  
+ #ifdef CONFIG_BLOCK
  #include <scsi/scsi.h>
  #include <scsi/scsi_ioctl.h>
  #include <scsi/sg.h>
+ #endif
  
  #include <asm/uaccess.h>
  #include <linux/ethtool.h>
@@@ -1756,6 -1759,64 +1758,6 @@@ static int do_i2c_smbus_ioctl(unsigned 
        return sys_ioctl(fd, cmd, (unsigned long)tdata);
  }
  
 -struct compat_iw_point {
 -      compat_caddr_t pointer;
 -      __u16 length;
 -      __u16 flags;
 -};
 -
 -static int do_wireless_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 -{
 -      struct iwreq __user *iwr;
 -      struct iwreq __user *iwr_u;
 -      struct iw_point __user *iwp;
 -      struct compat_iw_point __user *iwp_u;
 -      compat_caddr_t pointer_u;
 -      void __user *pointer;
 -      __u16 length, flags;
 -      int ret;
 -
 -      iwr_u = compat_ptr(arg);
 -      iwp_u = (struct compat_iw_point __user *) &iwr_u->u.data;
 -      iwr = compat_alloc_user_space(sizeof(*iwr));
 -      if (iwr == NULL)
 -              return -ENOMEM;
 -
 -      iwp = &iwr->u.data;
 -
 -      if (!access_ok(VERIFY_WRITE, iwr, sizeof(*iwr)))
 -              return -EFAULT;
 -
 -      if (__copy_in_user(&iwr->ifr_ifrn.ifrn_name[0],
 -                         &iwr_u->ifr_ifrn.ifrn_name[0],
 -                         sizeof(iwr->ifr_ifrn.ifrn_name)))
 -              return -EFAULT;
 -
 -      if (__get_user(pointer_u, &iwp_u->pointer) ||
 -          __get_user(length, &iwp_u->length) ||
 -          __get_user(flags, &iwp_u->flags))
 -              return -EFAULT;
 -
 -      if (__put_user(compat_ptr(pointer_u), &iwp->pointer) ||
 -          __put_user(length, &iwp->length) ||
 -          __put_user(flags, &iwp->flags))
 -              return -EFAULT;
 -
 -      ret = sys_ioctl(fd, cmd, (unsigned long) iwr);
 -
 -      if (__get_user(pointer, &iwp->pointer) ||
 -          __get_user(length, &iwp->length) ||
 -          __get_user(flags, &iwp->flags))
 -              return -EFAULT;
 -
 -      if (__put_user(ptr_to_compat(pointer), &iwp_u->pointer) ||
 -          __put_user(length, &iwp_u->length) ||
 -          __put_user(flags, &iwp_u->flags))
 -              return -EFAULT;
 -
 -      return ret;
 -}
 -
  /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
   * for some operations; this forces use of the newer bridge-utils that
   * use compatiable ioctls
@@@ -1965,6 -2026,7 +1967,7 @@@ COMPATIBLE_IOCTL(GIO_UNISCRNMAP
  COMPATIBLE_IOCTL(PIO_UNISCRNMAP)
  COMPATIBLE_IOCTL(PIO_FONTRESET)
  COMPATIBLE_IOCTL(PIO_UNIMAPCLR)
+ #ifdef CONFIG_BLOCK
  /* Big S */
  COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN)
  COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK)
@@@ -1974,6 -2036,7 +1977,7 @@@ COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUM
  COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND)
  COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST)
  COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI)
+ #endif
  /* Big T */
  COMPATIBLE_IOCTL(TUNSETNOCSUM)
  COMPATIBLE_IOCTL(TUNSETDEBUG)
@@@ -2044,6 -2107,7 +2048,7 @@@ COMPATIBLE_IOCTL(SIOCGIFVLAN
  COMPATIBLE_IOCTL(SIOCSIFVLAN)
  COMPATIBLE_IOCTL(SIOCBRADDBR)
  COMPATIBLE_IOCTL(SIOCBRDELBR)
+ #ifdef CONFIG_BLOCK
  /* SG stuff */
  COMPATIBLE_IOCTL(SG_SET_TIMEOUT)
  COMPATIBLE_IOCTL(SG_GET_TIMEOUT)
@@@ -2068,6 -2132,7 +2073,7 @@@ COMPATIBLE_IOCTL(SG_SCSI_RESET
  COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE)
  COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN)
  COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN)
+ #endif
  /* PPP stuff */
  COMPATIBLE_IOCTL(PPPIOCGFLAGS)
  COMPATIBLE_IOCTL(PPPIOCSFLAGS)
@@@ -2436,6 -2501,36 +2442,6 @@@ COMPATIBLE_IOCTL(I2C_TENBIT
  COMPATIBLE_IOCTL(I2C_PEC)
  COMPATIBLE_IOCTL(I2C_RETRIES)
  COMPATIBLE_IOCTL(I2C_TIMEOUT)
 -/* wireless */
 -COMPATIBLE_IOCTL(SIOCSIWCOMMIT)
 -COMPATIBLE_IOCTL(SIOCGIWNAME)
 -COMPATIBLE_IOCTL(SIOCSIWNWID)
 -COMPATIBLE_IOCTL(SIOCGIWNWID)
 -COMPATIBLE_IOCTL(SIOCSIWFREQ)
 -COMPATIBLE_IOCTL(SIOCGIWFREQ)
 -COMPATIBLE_IOCTL(SIOCSIWMODE)
 -COMPATIBLE_IOCTL(SIOCGIWMODE)
 -COMPATIBLE_IOCTL(SIOCSIWSENS)
 -COMPATIBLE_IOCTL(SIOCGIWSENS)
 -COMPATIBLE_IOCTL(SIOCSIWRANGE)
 -COMPATIBLE_IOCTL(SIOCSIWPRIV)
 -COMPATIBLE_IOCTL(SIOCSIWSTATS)
 -COMPATIBLE_IOCTL(SIOCSIWAP)
 -COMPATIBLE_IOCTL(SIOCGIWAP)
 -COMPATIBLE_IOCTL(SIOCSIWRATE)
 -COMPATIBLE_IOCTL(SIOCGIWRATE)
 -COMPATIBLE_IOCTL(SIOCSIWRTS)
 -COMPATIBLE_IOCTL(SIOCGIWRTS)
 -COMPATIBLE_IOCTL(SIOCSIWFRAG)
 -COMPATIBLE_IOCTL(SIOCGIWFRAG)
 -COMPATIBLE_IOCTL(SIOCSIWTXPOW)
 -COMPATIBLE_IOCTL(SIOCGIWTXPOW)
 -COMPATIBLE_IOCTL(SIOCSIWRETRY)
 -COMPATIBLE_IOCTL(SIOCGIWRETRY)
 -COMPATIBLE_IOCTL(SIOCSIWPOWER)
 -COMPATIBLE_IOCTL(SIOCGIWPOWER)
 -COMPATIBLE_IOCTL(SIOCSIWAUTH)
 -COMPATIBLE_IOCTL(SIOCGIWAUTH)
  /* hiddev */
  COMPATIBLE_IOCTL(HIDIOCGVERSION)
  COMPATIBLE_IOCTL(HIDIOCAPPLICATION)
@@@ -2666,7 -2761,29 +2672,7 @@@ COMPATIBLE_IOCTL(USBDEVFS_IOCTL32
  HANDLE_IOCTL(I2C_FUNCS, w_long)
  HANDLE_IOCTL(I2C_RDWR, do_i2c_rdwr_ioctl)
  HANDLE_IOCTL(I2C_SMBUS, do_i2c_smbus_ioctl)
 -/* wireless */
 -HANDLE_IOCTL(SIOCGIWRANGE, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCGIWPRIV, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCGIWSTATS, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCSIWSPY, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCGIWSPY, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCSIWTHRSPY, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCGIWTHRSPY, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCSIWMLME, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCGIWAPLIST, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCSIWSCAN, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCGIWSCAN, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCSIWESSID, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCGIWESSID, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCSIWNICKN, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCGIWNICKN, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCSIWENCODE, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCGIWENCODE, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCSIWGENIE, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCGIWGENIE, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCSIWENCODEEXT, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCGIWENCODEEXT, do_wireless_ioctl)
 -HANDLE_IOCTL(SIOCSIWPMKSA, do_wireless_ioctl)
 +/* bridge */
  HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl)
  HANDLE_IOCTL(SIOCGIFBR, old_bridge_ioctl)
  /* Not implemented in the native kernel */
diff --combined include/linux/pci_ids.h
index e74b14acf8e08cee7a3b80c864e84e3b286a294a,6be6a7943d8b9a02bc466fb6500e09b38b8df3c0..d8507eb394cf6f50e4c622b53d13e0c417b6467c
  #define PCI_DEVICE_ID_MARVELL_GT64260 0x6430
  #define PCI_DEVICE_ID_MARVELL_MV64360 0x6460
  #define PCI_DEVICE_ID_MARVELL_MV64460 0x6480
+ #define PCI_DEVICE_ID_MARVELL_CAFE_SD 0x4101
  
  #define PCI_VENDOR_ID_V3              0x11b0
  #define PCI_DEVICE_ID_V3_V960         0x0001
  #define PCI_DEVICE_ID_NX2_5708                0x164c
  #define PCI_DEVICE_ID_TIGON3_5702FE   0x164d
  #define PCI_DEVICE_ID_NX2_57710               0x164e
 +#define PCI_DEVICE_ID_NX2_57711               0x164f
 +#define PCI_DEVICE_ID_NX2_57711E      0x1650
  #define PCI_DEVICE_ID_TIGON3_5705     0x1653
  #define PCI_DEVICE_ID_TIGON3_5705_2   0x1654
  #define PCI_DEVICE_ID_TIGON3_5720     0x1658
  #define PCI_DEVICE_ID_TIGON3_5787M    0x1693
  #define PCI_DEVICE_ID_TIGON3_5782     0x1696
  #define PCI_DEVICE_ID_TIGON3_5784     0x1698
 +#define PCI_DEVICE_ID_TIGON3_5785     0x1699
  #define PCI_DEVICE_ID_TIGON3_5786     0x169a
  #define PCI_DEVICE_ID_TIGON3_5787     0x169b
  #define PCI_DEVICE_ID_TIGON3_5788     0x169c
  #define PCI_DEVICE_ID_MPC8544         0x0033
  #define PCI_DEVICE_ID_MPC8572E                0x0040
  #define PCI_DEVICE_ID_MPC8572         0x0041
+ #define PCI_DEVICE_ID_MPC8536E                0x0050
+ #define PCI_DEVICE_ID_MPC8536         0x0051
  #define PCI_DEVICE_ID_MPC8641         0x7010
  #define PCI_DEVICE_ID_MPC8641D                0x7011
  #define PCI_DEVICE_ID_MPC8610         0x7018
  #define PCI_DEVICE_ID_JMICRON_JMB366  0x2366
  #define PCI_DEVICE_ID_JMICRON_JMB368  0x2368
  #define PCI_DEVICE_ID_JMICRON_JMB38X_SD       0x2381
+ #define PCI_DEVICE_ID_JMICRON_JMB38X_MMC 0x2382
  #define PCI_DEVICE_ID_JMICRON_JMB38X_MS       0x2383
  
  #define PCI_VENDOR_ID_KORENIX         0x1982
diff --combined lib/textsearch.c
index b451fcc9354c0f1811ae268d62d2bc1990197ad8,a3e500ad51d7d23b207b11f94a6b8922a3d2b37f..4b7c6075256f60e02cbf144029f00142e7411fa4
   * USAGE
   *
   *   Before a search can be performed, a configuration must be created
 - *   by calling textsearch_prepare() specyfing the searching algorithm and
 - *   the pattern to look for. The returned configuration may then be used
 - *   for an arbitary amount of times and even in parallel as long as a
 - *   separate struct ts_state variable is provided to every instance.
 + *   by calling textsearch_prepare() specifying the searching algorithm,
 + *   the pattern to look for and flags. As a flag, you can set TS_IGNORECASE
 + *   to perform case insensitive matching. But it might slow down
 + *   performance of algorithm, so you should use it at own your risk.
 + *   The returned configuration may then be used for an arbitary
 + *   amount of times and even in parallel as long as a separate struct
 + *   ts_state variable is provided to every instance.
   *
   *   The actual search is performed by either calling textsearch_find_-
   *   continuous() for linear data or by providing an own get_next_block()
@@@ -92,6 -89,7 +92,6 @@@
   *       panic("Oh my god, dancing chickens at %d\n", pos);
   *
   *   textsearch_destroy(conf);
 - *
   * ==========================================================================
   */
  
@@@ -99,6 -97,7 +99,7 @@@
  #include <linux/types.h>
  #include <linux/string.h>
  #include <linux/init.h>
+ #include <linux/rculist.h>
  #include <linux/rcupdate.h>
  #include <linux/err.h>
  #include <linux/textsearch.h>
@@@ -281,7 -280,7 +282,7 @@@ struct ts_config *textsearch_prepare(co
        if (ops == NULL)
                goto errout;
  
 -      conf = ops->init(pattern, len, gfp_mask);
 +      conf = ops->init(pattern, len, gfp_mask, flags);
        if (IS_ERR(conf)) {
                err = PTR_ERR(conf);
                goto errout;
diff --combined net/8021q/vlan.c
index 9f04cab92f95f393e0ee202dfa74fcb74d358cbb,08f14f6c5fd6f6368c325123fb2d88c00384f343..b661f47bf10a0320889f22e7e1fcf7f3496b6baa
   *            2 of the License, or (at your option) any later version.
   */
  
 -#include <asm/uaccess.h> /* for copy_from_user */
  #include <linux/capability.h>
  #include <linux/module.h>
  #include <linux/netdevice.h>
  #include <linux/skbuff.h>
 -#include <net/datalink.h>
 -#include <linux/mm.h>
 -#include <linux/in.h>
  #include <linux/init.h>
+ #include <linux/rculist.h>
+ #include <net/p8022.h>
+ #include <net/arp.h>
  #include <linux/rtnetlink.h>
  #include <linux/notifier.h>
 +#include <net/rtnetlink.h>
  #include <net/net_namespace.h>
  #include <net/netns/generic.h>
 +#include <asm/uaccess.h>
  
  #include <linux/if_vlan.h>
  #include "vlan.h"
@@@ -79,12 -84,13 +82,12 @@@ static struct vlan_group *__vlan_find_g
   *
   * Must be invoked with RCU read lock (no preempt)
   */
 -struct net_device *__find_vlan_dev(struct net_device *real_dev,
 -                                 unsigned short VID)
 +struct net_device *__find_vlan_dev(struct net_device *real_dev, u16 vlan_id)
  {
        struct vlan_group *grp = __vlan_find_group(real_dev);
  
        if (grp)
 -              return vlan_group_get_device(grp, VID);
 +              return vlan_group_get_device(grp, vlan_id);
  
        return NULL;
  }
@@@ -112,14 -118,14 +115,14 @@@ static struct vlan_group *vlan_group_al
        return grp;
  }
  
 -static int vlan_group_prealloc_vid(struct vlan_group *vg, int vid)
 +static int vlan_group_prealloc_vid(struct vlan_group *vg, u16 vlan_id)
  {
        struct net_device **array;
        unsigned int size;
  
        ASSERT_RTNL();
  
 -      array = vg->vlan_devices_arrays[vid / VLAN_GROUP_ARRAY_PART_LEN];
 +      array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN];
        if (array != NULL)
                return 0;
  
        if (array == NULL)
                return -ENOBUFS;
  
 -      vg->vlan_devices_arrays[vid / VLAN_GROUP_ARRAY_PART_LEN] = array;
 +      vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN] = array;
        return 0;
  }
  
@@@ -142,7 -148,7 +145,7 @@@ void unregister_vlan_dev(struct net_dev
        struct vlan_dev_info *vlan = vlan_dev_info(dev);
        struct net_device *real_dev = vlan->real_dev;
        struct vlan_group *grp;
 -      unsigned short vlan_id = vlan->vlan_id;
 +      u16 vlan_id = vlan->vlan_id;
  
        ASSERT_RTNL();
  
  
        synchronize_net();
  
 +      unregister_netdevice(dev);
 +
        /* If the group is now empty, kill off the group. */
        if (grp->nr_vlans == 0) {
 +              vlan_gvrp_uninit_applicant(real_dev);
 +
                if (real_dev->features & NETIF_F_HW_VLAN_RX)
                        real_dev->vlan_rx_register(real_dev, NULL);
  
  
        /* Get rid of the vlan's reference to real_dev */
        dev_put(real_dev);
 -
 -      unregister_netdevice(dev);
  }
  
  static void vlan_transfer_operstate(const struct net_device *dev,
        }
  }
  
 -int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id)
 +int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id)
  {
        char *name = real_dev->name;
  
@@@ -237,7 -241,7 +240,7 @@@ int register_vlan_dev(struct net_devic
  {
        struct vlan_dev_info *vlan = vlan_dev_info(dev);
        struct net_device *real_dev = vlan->real_dev;
 -      unsigned short vlan_id = vlan->vlan_id;
 +      u16 vlan_id = vlan->vlan_id;
        struct vlan_group *grp, *ngrp = NULL;
        int err;
  
                ngrp = grp = vlan_group_alloc(real_dev);
                if (!grp)
                        return -ENOBUFS;
 +              err = vlan_gvrp_init_applicant(real_dev);
 +              if (err < 0)
 +                      goto out_free_group;
        }
  
        err = vlan_group_prealloc_vid(grp, vlan_id);
        if (err < 0)
 -              goto out_free_group;
 +              goto out_uninit_applicant;
  
        err = register_netdevice(dev);
        if (err < 0)
 -              goto out_free_group;
 +              goto out_uninit_applicant;
  
        /* Account for reference in struct vlan_dev_info */
        dev_hold(real_dev);
  
        return 0;
  
 +out_uninit_applicant:
 +      if (ngrp)
 +              vlan_gvrp_uninit_applicant(real_dev);
  out_free_group:
        if (ngrp)
                vlan_group_free(ngrp);
  /*  Attach a VLAN device to a mac address (ie Ethernet Card).
   *  Returns 0 if the device was created or a negative error code otherwise.
   */
 -static int register_vlan_device(struct net_device *real_dev,
 -                              unsigned short VLAN_ID)
 +static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
  {
        struct net_device *new_dev;
        struct net *net = dev_net(real_dev);
        char name[IFNAMSIZ];
        int err;
  
 -      if (VLAN_ID >= VLAN_VID_MASK)
 +      if (vlan_id >= VLAN_VID_MASK)
                return -ERANGE;
  
 -      err = vlan_check_real_dev(real_dev, VLAN_ID);
 +      err = vlan_check_real_dev(real_dev, vlan_id);
        if (err < 0)
                return err;
  
        switch (vn->name_type) {
        case VLAN_NAME_TYPE_RAW_PLUS_VID:
                /* name will look like:  eth1.0005 */
 -              snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, VLAN_ID);
 +              snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, vlan_id);
                break;
        case VLAN_NAME_TYPE_PLUS_VID_NO_PAD:
                /* Put our vlan.VID in the name.
                 * Name will look like:  vlan5
                 */
 -              snprintf(name, IFNAMSIZ, "vlan%i", VLAN_ID);
 +              snprintf(name, IFNAMSIZ, "vlan%i", vlan_id);
                break;
        case VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD:
                /* Put our vlan.VID in the name.
                 * Name will look like:  eth0.5
                 */
 -              snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, VLAN_ID);
 +              snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, vlan_id);
                break;
        case VLAN_NAME_TYPE_PLUS_VID:
                /* Put our vlan.VID in the name.
                 * Name will look like:  vlan0005
                 */
        default:
 -              snprintf(name, IFNAMSIZ, "vlan%.4i", VLAN_ID);
 +              snprintf(name, IFNAMSIZ, "vlan%.4i", vlan_id);
        }
  
        new_dev = alloc_netdev(sizeof(struct vlan_dev_info), name,
         */
        new_dev->mtu = real_dev->mtu;
  
 -      vlan_dev_info(new_dev)->vlan_id = VLAN_ID; /* 1 through VLAN_VID_MASK */
 +      vlan_dev_info(new_dev)->vlan_id = vlan_id;
        vlan_dev_info(new_dev)->real_dev = real_dev;
        vlan_dev_info(new_dev)->dent = NULL;
        vlan_dev_info(new_dev)->flags = VLAN_FLAG_REORDER_HDR;
@@@ -537,6 -536,7 +540,6 @@@ static struct notifier_block vlan_notif
  static int vlan_ioctl_handler(struct net *net, void __user *arg)
  {
        int err;
 -      unsigned short vid = 0;
        struct vlan_ioctl_args args;
        struct net_device *dev = NULL;
  
                        goto out;
  
                err = -EINVAL;
 -              if (args.cmd != ADD_VLAN_CMD &&
 -                  !(dev->priv_flags & IFF_802_1Q_VLAN))
 +              if (args.cmd != ADD_VLAN_CMD && !is_vlan_dev(dev))
                        goto out;
        }
  
                err = -EPERM;
                if (!capable(CAP_NET_ADMIN))
                        break;
 -              err = vlan_dev_set_vlan_flag(dev,
 -                                           args.u.flag,
 -                                           args.vlan_qos);
 +              err = vlan_dev_change_flags(dev,
 +                                          args.vlan_qos ? args.u.flag : 0,
 +                                          args.u.flag);
                break;
  
        case SET_VLAN_NAME_TYPE_CMD:
  
        case GET_VLAN_VID_CMD:
                err = 0;
 -              vlan_dev_get_vid(dev, &vid);
 -              args.u.VID = vid;
 +              args.u.VID = vlan_dev_vlan_id(dev);
                if (copy_to_user(arg, &args,
                                 sizeof(struct vlan_ioctl_args)))
                      err = -EFAULT;
@@@ -712,20 -714,14 +715,20 @@@ static int __init vlan_proto_init(void
        if (err < 0)
                goto err2;
  
 -      err = vlan_netlink_init();
 +      err = vlan_gvrp_init();
        if (err < 0)
                goto err3;
  
 +      err = vlan_netlink_init();
 +      if (err < 0)
 +              goto err4;
 +
        dev_add_pack(&vlan_packet_type);
        vlan_ioctl_set(vlan_ioctl_handler);
        return 0;
  
 +err4:
 +      vlan_gvrp_uninit();
  err3:
        unregister_netdevice_notifier(&vlan_notifier_block);
  err2:
@@@ -750,9 -746,8 +753,9 @@@ static void __exit vlan_cleanup_module(
                BUG_ON(!hlist_empty(&vlan_group_hash[i]));
  
        unregister_pernet_gen_device(vlan_net_id, &vlan_net_ops);
 -
        synchronize_net();
 +
 +      vlan_gvrp_uninit();
  }
  
  module_init(vlan_proto_init);
diff --combined net/bridge/br_fdb.c
index 4de74cdd091db459c38307d65c7eecfd5649fc9f,142060f020540ab283597d2a8ae582cb50ed3f39..a48f5efdb6bfa9b44fb0149136c169857a6e0931
@@@ -5,6 -5,8 +5,6 @@@
   *    Authors:
   *    Lennert Buytenhek               <buytenh@gnu.org>
   *
 - *    $Id: br_fdb.c,v 1.6 2002/01/17 00:57:07 davem Exp $
 - *
   *    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
@@@ -13,6 -15,7 +13,7 @@@
  
  #include <linux/kernel.h>
  #include <linux/init.h>
+ #include <linux/rculist.h>
  #include <linux/spinlock.h>
  #include <linux/times.h>
  #include <linux/netdevice.h>
diff --combined net/bridge/br_stp.c
index 284d1b2fa1ff70c56c6ad931951b46f760bd6168,9e96ffcd29a34f7bd80191fb22326a6eb49d8f11..921bbe5cb94a9690028cb2e2677b0508f4c31519
@@@ -5,12 -5,15 +5,13 @@@
   *    Authors:
   *    Lennert Buytenhek               <buytenh@gnu.org>
   *
 - *    $Id: br_stp.c,v 1.4 2000/06/19 10:13:35 davem Exp $
 - *
   *    This program is free software; you can redistribute it and/or
   *    modify it under the terms of the GNU General Public License
   *    as published by the Free Software Foundation; either version
   *    2 of the License, or (at your option) any later version.
   */
  #include <linux/kernel.h>
+ #include <linux/rculist.h>
  
  #include "br_private.h"
  #include "br_private_stp.h"
diff --combined net/core/dev.c
index 32a13772c1cb250d87e493710b655c968c720474,821cb1628e5ee98acf431ba67feeb7158fdbe1ce..e54acde839dac1ecefc360ddb5aa0f9dc12134ff
@@@ -90,7 -90,6 +90,7 @@@
  #include <linux/if_ether.h>
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
 +#include <linux/ethtool.h>
  #include <linux/notifier.h>
  #include <linux/skbuff.h>
  #include <net/net_namespace.h>
  #include <linux/ctype.h>
  #include <linux/if_arp.h>
  #include <linux/if_vlan.h>
 +#include <linux/ip.h>
 +#include <linux/ipv6.h>
 +#include <linux/in.h>
  
  #include "net-sysfs.h"
  
@@@ -261,7 -257,7 +261,7 @@@ DEFINE_PER_CPU(struct softnet_data, sof
  
  #ifdef CONFIG_DEBUG_LOCK_ALLOC
  /*
 - * register_netdevice() inits dev->_xmit_lock and sets lockdep class
 + * register_netdevice() inits txq->_xmit_lock and sets lockdep class
   * according to dev->type
   */
  static const unsigned short netdev_lock_type[] =
@@@ -965,12 -961,6 +965,12 @@@ void netdev_state_change(struct net_dev
        }
  }
  
 +void netdev_bonding_change(struct net_device *dev)
 +{
 +      call_netdevice_notifiers(NETDEV_BONDING_FAILOVER, dev);
 +}
 +EXPORT_SYMBOL(netdev_bonding_change);
 +
  /**
   *    dev_load        - load a network module
   *    @net: the applicable net namespace
@@@ -1127,29 -1117,6 +1127,29 @@@ int dev_close(struct net_device *dev
  }
  
  
 +/**
 + *    dev_disable_lro - disable Large Receive Offload on a device
 + *    @dev: device
 + *
 + *    Disable Large Receive Offload (LRO) on a net device.  Must be
 + *    called under RTNL.  This is needed if received packets may be
 + *    forwarded to another interface.
 + */
 +void dev_disable_lro(struct net_device *dev)
 +{
 +      if (dev->ethtool_ops && dev->ethtool_ops->get_flags &&
 +          dev->ethtool_ops->set_flags) {
 +              u32 flags = dev->ethtool_ops->get_flags(dev);
 +              if (flags & ETH_FLAG_LRO) {
 +                      flags &= ~ETH_FLAG_LRO;
 +                      dev->ethtool_ops->set_flags(dev, flags);
 +              }
 +      }
 +      WARN_ON(dev->features & NETIF_F_LRO);
 +}
 +EXPORT_SYMBOL(dev_disable_lro);
 +
 +
  static int dev_boot_phase = 1;
  
  /*
@@@ -1323,18 -1290,16 +1323,18 @@@ static void dev_queue_xmit_nit(struct s
  }
  
  
 -void __netif_schedule(struct net_device *dev)
 +void __netif_schedule(struct Qdisc *q)
  {
 -      if (!test_and_set_bit(__LINK_STATE_SCHED, &dev->state)) {
 -              unsigned long flags;
 +      BUG_ON(q == &noop_qdisc);
 +
 +      if (!test_and_set_bit(__QDISC_STATE_SCHED, &q->state)) {
                struct softnet_data *sd;
 +              unsigned long flags;
  
                local_irq_save(flags);
                sd = &__get_cpu_var(softnet_data);
 -              dev->next_sched = sd->output_queue;
 -              sd->output_queue = dev;
 +              q->next_sched = sd->output_queue;
 +              sd->output_queue = q;
                raise_softirq_irqoff(NET_TX_SOFTIRQ);
                local_irq_restore(flags);
        }
@@@ -1601,8 -1566,7 +1601,8 @@@ static int dev_gso_segment(struct sk_bu
        return 0;
  }
  
 -int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 +int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 +                      struct netdev_queue *txq)
  {
        if (likely(!skb->next)) {
                if (!list_empty(&ptype_all))
@@@ -1631,7 -1595,9 +1631,7 @@@ gso
                        skb->next = nskb;
                        return rc;
                }
 -              if (unlikely((netif_queue_stopped(dev) ||
 -                           netif_subqueue_stopped(dev, skb)) &&
 -                           skb->next))
 +              if (unlikely(netif_tx_queue_stopped(txq) && skb->next))
                        return NETDEV_TX_BUSY;
        } while (skb->next);
  
@@@ -1668,71 -1634,9 +1668,71 @@@ out_kfree_skb
   *          --BLG
   */
  
 +static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb)
 +{
 +      u32 *addr, *ports, hash, ihl;
 +      u8 ip_proto;
 +      int alen;
 +
 +      switch (skb->protocol) {
 +      case __constant_htons(ETH_P_IP):
 +              ip_proto = ip_hdr(skb)->protocol;
 +              addr = &ip_hdr(skb)->saddr;
 +              ihl = ip_hdr(skb)->ihl;
 +              alen = 2;
 +              break;
 +      case __constant_htons(ETH_P_IPV6):
 +              ip_proto = ipv6_hdr(skb)->nexthdr;
 +              addr = &ipv6_hdr(skb)->saddr.s6_addr32[0];
 +              ihl = (40 >> 2);
 +              alen = 8;
 +              break;
 +      default:
 +              return 0;
 +      }
 +
 +      ports = (u32 *) (skb_network_header(skb) + (ihl * 4));
 +
 +      hash = 0;
 +      while (alen--)
 +              hash ^= *addr++;
 +
 +      switch (ip_proto) {
 +      case IPPROTO_TCP:
 +      case IPPROTO_UDP:
 +      case IPPROTO_DCCP:
 +      case IPPROTO_ESP:
 +      case IPPROTO_AH:
 +      case IPPROTO_SCTP:
 +      case IPPROTO_UDPLITE:
 +              hash ^= *ports;
 +              break;
 +
 +      default:
 +              break;
 +      }
 +
 +      return hash % dev->real_num_tx_queues;
 +}
 +
 +static struct netdev_queue *dev_pick_tx(struct net_device *dev,
 +                                      struct sk_buff *skb)
 +{
 +      u16 queue_index = 0;
 +
 +      if (dev->select_queue)
 +              queue_index = dev->select_queue(dev, skb);
 +      else if (dev->real_num_tx_queues > 1)
 +              queue_index = simple_tx_hash(dev, skb);
 +
 +      skb_set_queue_mapping(skb, queue_index);
 +      return netdev_get_tx_queue(dev, queue_index);
 +}
 +
  int dev_queue_xmit(struct sk_buff *skb)
  {
        struct net_device *dev = skb->dev;
 +      struct netdev_queue *txq;
        struct Qdisc *q;
        int rc = -ENOMEM;
  
        }
  
  gso:
 -      spin_lock_prefetch(&dev->queue_lock);
 -
        /* Disable soft irqs for various locks below. Also
         * stops preemption for RCU.
         */
        rcu_read_lock_bh();
  
 -      /* Updates of qdisc are serialized by queue_lock.
 -       * The struct Qdisc which is pointed to by qdisc is now a
 -       * rcu structure - it may be accessed without acquiring
 -       * a lock (but the structure may be stale.) The freeing of the
 -       * qdisc will be deferred until it's known that there are no
 -       * more references to it.
 -       *
 -       * If the qdisc has an enqueue function, we still need to
 -       * hold the queue_lock before calling it, since queue_lock
 -       * also serializes access to the device queue.
 -       */
 +      txq = dev_pick_tx(dev, skb);
 +      q = rcu_dereference(txq->qdisc);
  
 -      q = rcu_dereference(dev->qdisc);
  #ifdef CONFIG_NET_CLS_ACT
        skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS);
  #endif
        if (q->enqueue) {
 -              /* Grab device queue */
 -              spin_lock(&dev->queue_lock);
 -              q = dev->qdisc;
 -              if (q->enqueue) {
 -                      /* reset queue_mapping to zero */
 -                      skb_set_queue_mapping(skb, 0);
 -                      rc = q->enqueue(skb, q);
 -                      qdisc_run(dev);
 -                      spin_unlock(&dev->queue_lock);
 -
 -                      rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc;
 -                      goto out;
 -              }
 -              spin_unlock(&dev->queue_lock);
 +              spinlock_t *root_lock = qdisc_root_lock(q);
 +
 +              spin_lock(root_lock);
 +
 +              rc = q->enqueue(skb, q);
 +              qdisc_run(q);
 +
 +              spin_unlock(root_lock);
 +
 +              rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc;
 +              goto out;
        }
  
        /* The device has no queue. Common case for software devices:
        if (dev->flags & IFF_UP) {
                int cpu = smp_processor_id(); /* ok because BHs are off */
  
 -              if (dev->xmit_lock_owner != cpu) {
 +              if (txq->xmit_lock_owner != cpu) {
  
 -                      HARD_TX_LOCK(dev, cpu);
 +                      HARD_TX_LOCK(dev, txq, cpu);
  
 -                      if (!netif_queue_stopped(dev) &&
 -                          !netif_subqueue_stopped(dev, skb)) {
 +                      if (!netif_tx_queue_stopped(txq)) {
                                rc = 0;
 -                              if (!dev_hard_start_xmit(skb, dev)) {
 -                                      HARD_TX_UNLOCK(dev);
 +                              if (!dev_hard_start_xmit(skb, dev, txq)) {
 +                                      HARD_TX_UNLOCK(dev, txq);
                                        goto out;
                                }
                        }
 -                      HARD_TX_UNLOCK(dev);
 +                      HARD_TX_UNLOCK(dev, txq);
                        if (net_ratelimit())
                                printk(KERN_CRIT "Virtual device %s asks to "
                                       "queue packet!\n", dev->name);
@@@ -1960,7 -1880,7 +1960,7 @@@ static void net_tx_action(struct softir
        }
  
        if (sd->output_queue) {
 -              struct net_device *head;
 +              struct Qdisc *head;
  
                local_irq_disable();
                head = sd->output_queue;
                local_irq_enable();
  
                while (head) {
 -                      struct net_device *dev = head;
 +                      struct Qdisc *q = head;
 +                      spinlock_t *root_lock;
 +
                        head = head->next_sched;
  
                        smp_mb__before_clear_bit();
 -                      clear_bit(__LINK_STATE_SCHED, &dev->state);
 +                      clear_bit(__QDISC_STATE_SCHED, &q->state);
  
 -                      if (spin_trylock(&dev->queue_lock)) {
 -                              qdisc_run(dev);
 -                              spin_unlock(&dev->queue_lock);
 +                      root_lock = qdisc_root_lock(q);
 +                      if (spin_trylock(root_lock)) {
 +                              qdisc_run(q);
 +                              spin_unlock(root_lock);
                        } else {
 -                              netif_schedule(dev);
 +                              __netif_schedule(q);
                        }
                }
        }
@@@ -2062,11 -1979,10 +2062,11 @@@ static inline struct sk_buff *handle_ma
   */
  static int ing_filter(struct sk_buff *skb)
  {
 -      struct Qdisc *q;
        struct net_device *dev = skb->dev;
 -      int result = TC_ACT_OK;
        u32 ttl = G_TC_RTTL(skb->tc_verd);
 +      struct netdev_queue *rxq;
 +      int result = TC_ACT_OK;
 +      struct Qdisc *q;
  
        if (MAX_RED_LOOP < ttl++) {
                printk(KERN_WARNING
        skb->tc_verd = SET_TC_RTTL(skb->tc_verd, ttl);
        skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_INGRESS);
  
 -      spin_lock(&dev->ingress_lock);
 -      if ((q = dev->qdisc_ingress) != NULL)
 +      rxq = &dev->rx_queue;
 +
 +      q = rxq->qdisc;
 +      if (q) {
 +              spin_lock(qdisc_lock(q));
                result = q->enqueue(skb, q);
 -      spin_unlock(&dev->ingress_lock);
 +              spin_unlock(qdisc_lock(q));
 +      }
  
        return result;
  }
@@@ -2094,7 -2006,7 +2094,7 @@@ static inline struct sk_buff *handle_in
                                         struct packet_type **pt_prev,
                                         int *ret, struct net_device *orig_dev)
  {
 -      if (!skb->dev->qdisc_ingress)
 +      if (!skb->dev->rx_queue.qdisc)
                goto out;
  
        if (*pt_prev) {
  }
  #endif
  
 +/*
 + *    netif_nit_deliver - deliver received packets to network taps
 + *    @skb: buffer
 + *
 + *    This function is used to deliver incoming packets to network
 + *    taps. It should be used when the normal netif_receive_skb path
 + *    is bypassed, for example because of VLAN acceleration.
 + */
 +void netif_nit_deliver(struct sk_buff *skb)
 +{
 +      struct packet_type *ptype;
 +
 +      if (list_empty(&ptype_all))
 +              return;
 +
 +      skb_reset_network_header(skb);
 +      skb_reset_transport_header(skb);
 +      skb->mac_len = skb->network_header - skb->mac_header;
 +
 +      rcu_read_lock();
 +      list_for_each_entry_rcu(ptype, &ptype_all, list) {
 +              if (!ptype->dev || ptype->dev == skb->dev)
 +                      deliver_skb(skb, ptype, skb->dev);
 +      }
 +      rcu_read_unlock();
 +}
 +
  /**
   *    netif_receive_skb - process receive buffer from network
   *    @skb: buffer to process
@@@ -2884,29 -2769,16 +2884,29 @@@ int netdev_set_master(struct net_devic
        return 0;
  }
  
 -static void __dev_set_promiscuity(struct net_device *dev, int inc)
 +static int __dev_set_promiscuity(struct net_device *dev, int inc)
  {
        unsigned short old_flags = dev->flags;
  
        ASSERT_RTNL();
  
 -      if ((dev->promiscuity += inc) == 0)
 -              dev->flags &= ~IFF_PROMISC;
 -      else
 -              dev->flags |= IFF_PROMISC;
 +      dev->flags |= IFF_PROMISC;
 +      dev->promiscuity += inc;
 +      if (dev->promiscuity == 0) {
 +              /*
 +               * Avoid overflow.
 +               * If inc causes overflow, untouch promisc and return error.
 +               */
 +              if (inc < 0)
 +                      dev->flags &= ~IFF_PROMISC;
 +              else {
 +                      dev->promiscuity -= inc;
 +                      printk(KERN_WARNING "%s: promiscuity touches roof, "
 +                              "set promiscuity failed, promiscuity feature "
 +                              "of device might be broken.\n", dev->name);
 +                      return -EOVERFLOW;
 +              }
 +      }
        if (dev->flags != old_flags) {
                printk(KERN_INFO "device %s %s promiscuous mode\n",
                       dev->name, (dev->flags & IFF_PROMISC) ? "entered" :
                if (dev->change_rx_flags)
                        dev->change_rx_flags(dev, IFF_PROMISC);
        }
 +      return 0;
  }
  
  /**
   *    remains above zero the interface remains promiscuous. Once it hits zero
   *    the device reverts back to normal filtering operation. A negative inc
   *    value is used to drop promiscuity on the device.
 + *    Return 0 if successful or a negative errno code on error.
   */
 -void dev_set_promiscuity(struct net_device *dev, int inc)
 +int dev_set_promiscuity(struct net_device *dev, int inc)
  {
        unsigned short old_flags = dev->flags;
 +      int err;
  
 -      __dev_set_promiscuity(dev, inc);
 +      err = __dev_set_promiscuity(dev, inc);
 +      if (err < 0)
 +              return err;
        if (dev->flags != old_flags)
                dev_set_rx_mode(dev);
 +      return err;
  }
  
  /**
   *    to all interfaces. Once it hits zero the device reverts back to normal
   *    filtering operation. A negative @inc value is used to drop the counter
   *    when releasing a resource needing all multicasts.
 + *    Return 0 if successful or a negative errno code on error.
   */
  
 -void dev_set_allmulti(struct net_device *dev, int inc)
 +int dev_set_allmulti(struct net_device *dev, int inc)
  {
        unsigned short old_flags = dev->flags;
  
        ASSERT_RTNL();
  
        dev->flags |= IFF_ALLMULTI;
 -      if ((dev->allmulti += inc) == 0)
 -              dev->flags &= ~IFF_ALLMULTI;
 +      dev->allmulti += inc;
 +      if (dev->allmulti == 0) {
 +              /*
 +               * Avoid overflow.
 +               * If inc causes overflow, untouch allmulti and return error.
 +               */
 +              if (inc < 0)
 +                      dev->flags &= ~IFF_ALLMULTI;
 +              else {
 +                      dev->allmulti -= inc;
 +                      printk(KERN_WARNING "%s: allmulti touches roof, "
 +                              "set allmulti failed, allmulti feature of "
 +                              "device might be broken.\n", dev->name);
 +                      return -EOVERFLOW;
 +              }
 +      }
        if (dev->flags ^ old_flags) {
                if (dev->change_rx_flags)
                        dev->change_rx_flags(dev, IFF_ALLMULTI);
                dev_set_rx_mode(dev);
        }
 +      return 0;
  }
  
  /*
@@@ -3031,9 -2881,9 +3031,9 @@@ void __dev_set_rx_mode(struct net_devic
  
  void dev_set_rx_mode(struct net_device *dev)
  {
 -      netif_tx_lock_bh(dev);
 +      netif_addr_lock_bh(dev);
        __dev_set_rx_mode(dev);
 -      netif_tx_unlock_bh(dev);
 +      netif_addr_unlock_bh(dev);
  }
  
  int __dev_addr_delete(struct dev_addr_list **list, int *count,
@@@ -3111,11 -2961,11 +3111,11 @@@ int dev_unicast_delete(struct net_devic
  
        ASSERT_RTNL();
  
 -      netif_tx_lock_bh(dev);
 +      netif_addr_lock_bh(dev);
        err = __dev_addr_delete(&dev->uc_list, &dev->uc_count, addr, alen, 0);
        if (!err)
                __dev_set_rx_mode(dev);
 -      netif_tx_unlock_bh(dev);
 +      netif_addr_unlock_bh(dev);
        return err;
  }
  EXPORT_SYMBOL(dev_unicast_delete);
@@@ -3137,11 -2987,11 +3137,11 @@@ int dev_unicast_add(struct net_device *
  
        ASSERT_RTNL();
  
 -      netif_tx_lock_bh(dev);
 +      netif_addr_lock_bh(dev);
        err = __dev_addr_add(&dev->uc_list, &dev->uc_count, addr, alen, 0);
        if (!err)
                __dev_set_rx_mode(dev);
 -      netif_tx_unlock_bh(dev);
 +      netif_addr_unlock_bh(dev);
        return err;
  }
  EXPORT_SYMBOL(dev_unicast_add);
@@@ -3208,12 -3058,12 +3208,12 @@@ int dev_unicast_sync(struct net_device 
  {
        int err = 0;
  
 -      netif_tx_lock_bh(to);
 +      netif_addr_lock_bh(to);
        err = __dev_addr_sync(&to->uc_list, &to->uc_count,
                              &from->uc_list, &from->uc_count);
        if (!err)
                __dev_set_rx_mode(to);
 -      netif_tx_unlock_bh(to);
 +      netif_addr_unlock_bh(to);
        return err;
  }
  EXPORT_SYMBOL(dev_unicast_sync);
   */
  void dev_unicast_unsync(struct net_device *to, struct net_device *from)
  {
 -      netif_tx_lock_bh(from);
 -      netif_tx_lock_bh(to);
 +      netif_addr_lock_bh(from);
 +      netif_addr_lock(to);
  
        __dev_addr_unsync(&to->uc_list, &to->uc_count,
                          &from->uc_list, &from->uc_count);
        __dev_set_rx_mode(to);
  
 -      netif_tx_unlock_bh(to);
 -      netif_tx_unlock_bh(from);
 +      netif_addr_unlock(to);
 +      netif_addr_unlock_bh(from);
  }
  EXPORT_SYMBOL(dev_unicast_unsync);
  
@@@ -3257,7 -3107,7 +3257,7 @@@ static void __dev_addr_discard(struct d
  
  static void dev_addr_discard(struct net_device *dev)
  {
 -      netif_tx_lock_bh(dev);
 +      netif_addr_lock_bh(dev);
  
        __dev_addr_discard(&dev->uc_list);
        dev->uc_count = 0;
        __dev_addr_discard(&dev->mc_list);
        dev->mc_count = 0;
  
 -      netif_tx_unlock_bh(dev);
 +      netif_addr_unlock_bh(dev);
  }
  
  unsigned dev_get_flags(const struct net_device *dev)
@@@ -3838,21 -3688,6 +3838,21 @@@ static void rollback_registered(struct 
        dev_put(dev);
  }
  
 +static void __netdev_init_queue_locks_one(struct net_device *dev,
 +                                        struct netdev_queue *dev_queue,
 +                                        void *_unused)
 +{
 +      spin_lock_init(&dev_queue->_xmit_lock);
 +      netdev_set_lockdep_class(&dev_queue->_xmit_lock, dev->type);
 +      dev_queue->xmit_lock_owner = -1;
 +}
 +
 +static void netdev_init_queue_locks(struct net_device *dev)
 +{
 +      netdev_for_each_tx_queue(dev, __netdev_init_queue_locks_one, NULL);
 +      __netdev_init_queue_locks_one(dev, &dev->rx_queue, NULL);
 +}
 +
  /**
   *    register_netdevice      - register a network device
   *    @dev: device to register
@@@ -3887,10 -3722,11 +3887,10 @@@ int register_netdevice(struct net_devic
        BUG_ON(!dev_net(dev));
        net = dev_net(dev);
  
 -      spin_lock_init(&dev->queue_lock);
 -      spin_lock_init(&dev->_xmit_lock);
 -      netdev_set_lockdep_class(&dev->_xmit_lock, dev->type);
 -      dev->xmit_lock_owner = -1;
 -      spin_lock_init(&dev->ingress_lock);
 +      spin_lock_init(&dev->addr_list_lock);
 +      spin_lock_init(&dev->qdisc_list_lock);
 +      INIT_LIST_HEAD(&dev->qdisc_list);
 +      netdev_init_queue_locks(dev);
  
        dev->iflink = -1;
  
@@@ -4171,19 -4007,6 +4171,19 @@@ static struct net_device_stats *interna
        return &dev->stats;
  }
  
 +static void netdev_init_one_queue(struct net_device *dev,
 +                                struct netdev_queue *queue,
 +                                void *_unused)
 +{
 +      queue->dev = dev;
 +}
 +
 +static void netdev_init_queues(struct net_device *dev)
 +{
 +      netdev_init_one_queue(dev, &dev->rx_queue, NULL);
 +      netdev_for_each_tx_queue(dev, netdev_init_one_queue, NULL);
 +}
 +
  /**
   *    alloc_netdev_mq - allocate network device
   *    @sizeof_priv:   size of private data to allocate space for
  struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
                void (*setup)(struct net_device *), unsigned int queue_count)
  {
 -      void *p;
 +      struct netdev_queue *tx;
        struct net_device *dev;
        int alloc_size;
 +      void *p;
  
        BUG_ON(strlen(name) >= sizeof(dev->name));
  
 -      alloc_size = sizeof(struct net_device) +
 -                   sizeof(struct net_device_subqueue) * (queue_count - 1);
 +      alloc_size = sizeof(struct net_device);
        if (sizeof_priv) {
                /* ensure 32-byte alignment of private area */
                alloc_size = (alloc_size + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST;
                return NULL;
        }
  
 +      tx = kzalloc(sizeof(struct netdev_queue) * queue_count, GFP_KERNEL);
 +      if (!tx) {
 +              printk(KERN_ERR "alloc_netdev: Unable to allocate "
 +                     "tx qdiscs.\n");
 +              kfree(p);
 +              return NULL;
 +      }
 +
        dev = (struct net_device *)
                (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
        dev->padded = (char *)dev - (char *)p;
        dev_net_set(dev, &init_net);
  
 +      dev->_tx = tx;
 +      dev->num_tx_queues = queue_count;
 +      dev->real_num_tx_queues = queue_count;
 +
        if (sizeof_priv) {
                dev->priv = ((char *)dev +
 -                           ((sizeof(struct net_device) +
 -                             (sizeof(struct net_device_subqueue) *
 -                              (queue_count - 1)) + NETDEV_ALIGN_CONST)
 +                           ((sizeof(struct net_device) + NETDEV_ALIGN_CONST)
                              & ~NETDEV_ALIGN_CONST));
        }
  
 -      dev->egress_subqueue_count = queue_count;
        dev->gso_max_size = GSO_MAX_SIZE;
  
 +      netdev_init_queues(dev);
 +
        dev->get_stats = internal_stats;
        netpoll_netdev_init(dev);
        setup(dev);
@@@ -4267,8 -4079,6 +4267,8 @@@ void free_netdev(struct net_device *dev
  {
        release_net(dev_net(dev));
  
 +      kfree(dev->_tx);
 +
        /*  Compatibility with error handling in drivers */
        if (dev->reg_state == NETREG_UNINITIALIZED) {
                kfree((char *)dev - dev->padded);
@@@ -4450,7 -4260,7 +4450,7 @@@ static int dev_cpu_callback(struct noti
                            void *ocpu)
  {
        struct sk_buff **list_skb;
 -      struct net_device **list_net;
 +      struct Qdisc **list_net;
        struct sk_buff *skb;
        unsigned int cpu, oldcpu = (unsigned long)ocpu;
        struct softnet_data *sd, *oldsd;
@@@ -4775,8 -4585,8 +4775,8 @@@ static int __init net_dev_init(void
  
        dev_boot_phase = 0;
  
-       open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
-       open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL);
+       open_softirq(NET_TX_SOFTIRQ, net_tx_action);
+       open_softirq(NET_RX_SOFTIRQ, net_rx_action);
  
        hotcpu_notifier(dev_cpu_callback, 0);
        dst_init();
index f6e54fa97f47286ad43e247909b15a4b22339db9,e84a70dd346b7e48a350502699238286d6cf2f21..6d8ae03c14f5b8e3dc12af9906a14e1b0ae3b666
@@@ -479,6 -479,7 +479,7 @@@ dev_irnet_open(struct inode *      inode
    ap = kzalloc(sizeof(*ap), GFP_KERNEL);
    DABORT(ap == NULL, -ENOMEM, FS_ERROR, "Can't allocate struct irnet...\n");
  
+   lock_kernel();
    /* initialize the irnet structure */
    ap->file = file;
  
      {
        DERROR(FS_ERROR, "Can't setup IrDA link...\n");
        kfree(ap);
+       unlock_kernel();
        return err;
      }
  
    file->private_data = ap;
  
    DEXIT(FS_TRACE, " - ap=0x%p\n", ap);
+   unlock_kernel();
    return 0;
  }
  
@@@ -628,8 -631,8 +631,8 @@@ dev_irnet_poll(struct file *       file
   * This is the way pppd configure us and control us while the PPP
   * instance is active.
   */
 -static int
 -dev_irnet_ioctl(struct inode *        inode,
 +static long
 +dev_irnet_ioctl(
                struct file *   file,
                unsigned int    cmd,
                unsigned long   arg)
        {
          DEBUG(FS_INFO, "Entering PPP discipline.\n");
          /* PPP channel setup (ap->chan in configued in dev_irnet_open())*/
 +        lock_kernel();
          err = ppp_register_channel(&ap->chan);
          if(err == 0)
            {
            }
          else
            DERROR(FS_ERROR, "Can't setup PPP channel...\n");
 +          unlock_kernel();
        }
        else
        {
          /* In theory, should be N_TTY */
          DEBUG(FS_INFO, "Exiting PPP discipline.\n");
          /* Disconnect from the generic PPP layer */
 +        lock_kernel();
          if(ap->ppp_open)
            {
              ap->ppp_open = 0;
          else
            DERROR(FS_ERROR, "Channel not registered !\n");
          err = 0;
 +        unlock_kernel();
        }
        break;
  
        /* Query PPP channel and unit number */
      case PPPIOCGCHAN:
 -      if(!ap->ppp_open)
 -      break;
 -      if(put_user(ppp_channel_index(&ap->chan), (int __user *)argp))
 -      break;
 -      DEBUG(FS_INFO, "Query channel.\n");
 -      err = 0;
 +      if(ap->ppp_open && !put_user(ppp_channel_index(&ap->chan),
 +                                              (int __user *)argp))
 +      err = 0;
        break;
      case PPPIOCGUNIT:
 -      if(!ap->ppp_open)
 -      break;
 -      if(put_user(ppp_unit_number(&ap->chan), (int __user *)argp))
 -      break;
 -      DEBUG(FS_INFO, "Query unit number.\n");
 +      lock_kernel();
 +      if(ap->ppp_open && !put_user(ppp_unit_number(&ap->chan),
 +                                              (int __user *)argp))
        err = 0;
        break;
  
        DEBUG(FS_INFO, "Standard PPP ioctl.\n");
        if(!capable(CAP_NET_ADMIN))
        err = -EPERM;
 -      else
 +      else {
 +      lock_kernel();
        err = ppp_irnet_ioctl(&ap->chan, cmd, arg);
 +      unlock_kernel();
 +      }
        break;
  
        /* TTY IOCTLs : Pretend that we are a tty, to keep pppd happy */
        /* Get termios */
      case TCGETS:
        DEBUG(FS_INFO, "Get termios.\n");
 +      lock_kernel();
  #ifndef TCGETS2
 -      if(kernel_termios_to_user_termios((struct termios __user *)argp, &ap->termios))
 -      break;
 +      if(!kernel_termios_to_user_termios((struct termios __user *)argp, &ap->termios))
 +      err = 0;
  #else
        if(kernel_termios_to_user_termios_1((struct termios __user *)argp, &ap->termios))
 -      break;
 +      err = 0;
  #endif
 -      err = 0;
 +      unlock_kernel();
        break;
        /* Set termios */
      case TCSETSF:
        DEBUG(FS_INFO, "Set termios.\n");
 +      lock_kernel();
  #ifndef TCGETS2
 -      if(user_termios_to_kernel_termios(&ap->termios, (struct termios __user *)argp))
 -      break;
 +      if(!user_termios_to_kernel_termios(&ap->termios, (struct termios __user *)argp))
 +      err = 0;
  #else
 -      if(user_termios_to_kernel_termios_1(&ap->termios, (struct termios __user *)argp))
 -      break;
 +      if(!user_termios_to_kernel_termios_1(&ap->termios, (struct termios __user *)argp))
 +      err = 0;
  #endif
 -      err = 0;
 +      unlock_kernel();
        break;
  
        /* Set DTR/RTS */
         * We should also worry that we don't accept junk here and that
         * we get rid of our own buffers */
  #ifdef FLUSH_TO_PPP
 +      lock_kernel();
        ppp_output_wakeup(&ap->chan);
 +      unlock_kernel();
  #endif /* FLUSH_TO_PPP */
        err = 0;
        break;
  
      default:
        DERROR(FS_ERROR, "Unsupported ioctl (0x%X)\n", cmd);
 -      err = -ENOIOCTLCMD;
 +      err = -ENOTTY;
      }
  
    DEXIT(FS_TRACE, " - err = 0x%X\n", err);
diff --combined net/iucv/af_iucv.c
index 58e4aee3e6961d2c37273faa830d3590a344be3b,bda71015885cd2fdbfb4a0135eb82445854d9e08..29f7baa251107b03751619f1aae1318d170fe2d1
@@@ -644,7 -644,6 +644,7 @@@ static int iucv_sock_sendmsg(struct kio
                }
  
                txmsg.class = 0;
 +              memcpy(&txmsg.class, skb->data, skb->len >= 4 ? 4 : skb->len);
                txmsg.tag = iucv->send_tag++;
                memcpy(skb->cb, &txmsg.tag, 4);
                skb_queue_tail(&iucv->send_skb_q, skb);
@@@ -1136,8 -1135,7 +1136,7 @@@ static void iucv_callback_txdone(struc
                if (this)
                        kfree_skb(this);
        }
-       if (!this)
-               printk(KERN_ERR "AF_IUCV msg tag %u not found\n", msg->tag);
+       BUG_ON(!this);
  
        if (sk->sk_state == IUCV_CLOSING) {
                if (skb_queue_empty(&iucv_sk(sk)->send_skb_q)) {
@@@ -1197,7 -1195,7 +1196,7 @@@ static int __init afiucv_init(void
        }
        cpcmd("QUERY USERID", iucv_userid, sizeof(iucv_userid), &err);
        if (unlikely(err)) {
-               printk(KERN_ERR "AF_IUCV needs the VM userid\n");
+               WARN_ON(err);
                err = -EPROTONOSUPPORT;
                goto out;
        }
        err = sock_register(&iucv_sock_family_ops);
        if (err)
                goto out_proto;
-       printk(KERN_INFO "AF_IUCV lowlevel driver initialized\n");
        return 0;
  
  out_proto:
@@@ -1227,8 -1224,6 +1225,6 @@@ static void __exit afiucv_exit(void
        sock_unregister(PF_IUCV);
        proto_unregister(&iucv_proto);
        iucv_unregister(&af_iucv_handler, 0);
-       printk(KERN_INFO "AF_IUCV lowlevel driver unloaded\n");
  }
  
  module_init(afiucv_init);
diff --combined net/iucv/iucv.c
index d8e0635aace0198e9267436e3a86f83977e6f3ad,cc34ac769a3c9d3eb19bf6c1f52828d6e961725d..a598c73848401a215216a6f76ee3d5f0836f520e
@@@ -474,14 -474,14 +474,14 @@@ static void iucv_setmask_mp(void
  {
        int cpu;
  
 -      preempt_disable();
 +      get_online_cpus();
        for_each_online_cpu(cpu)
                /* Enable all cpus with a declared buffer. */
                if (cpu_isset(cpu, iucv_buffer_cpumask) &&
                    !cpu_isset(cpu, iucv_irq_cpumask))
                        smp_call_function_single(cpu, iucv_allow_cpu,
-                                                NULL, 0, 1);
+                                                NULL, 1);
 -      preempt_enable();
 +      put_online_cpus();
  }
  
  /**
@@@ -498,7 -498,7 +498,7 @@@ static void iucv_setmask_up(void
        cpumask = iucv_irq_cpumask;
        cpu_clear(first_cpu(iucv_irq_cpumask), cpumask);
        for_each_cpu_mask(cpu, cpumask)
-               smp_call_function_single(cpu, iucv_block_cpu, NULL, 0, 1);
+               smp_call_function_single(cpu, iucv_block_cpu, NULL, 1);
  }
  
  /**
@@@ -521,17 -521,16 +521,22 @@@ static int iucv_enable(void
                goto out;
        /* Declare per cpu buffers. */
        rc = -EIO;
 -      preempt_disable();
 +      get_online_cpus();
        for_each_online_cpu(cpu)
++<<<<<<< HEAD:net/iucv/iucv.c
 +              smp_call_function_single(cpu, iucv_declare_cpu, NULL, 0, 1);
++=======
+               smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1);
+       preempt_enable();
++>>>>>>> 5b664cb235e97afbf34db9c4d77f08ebd725335e:net/iucv/iucv.c
        if (cpus_empty(iucv_buffer_cpumask))
                /* No cpu could declare an iucv buffer. */
                goto out_path;
 +      put_online_cpus();
        return 0;
  
  out_path:
 +      put_online_cpus();
        kfree(iucv_path_table);
  out:
        return rc;
   */
  static void iucv_disable(void)
  {
++<<<<<<< HEAD:net/iucv/iucv.c
 +      get_online_cpus();
 +      on_each_cpu(iucv_retrieve_cpu, NULL, 0, 1);
 +      put_online_cpus();
++=======
+       on_each_cpu(iucv_retrieve_cpu, NULL, 1);
++>>>>>>> 5b664cb235e97afbf34db9c4d77f08ebd725335e:net/iucv/iucv.c
        kfree(iucv_path_table);
  }
  
@@@ -567,11 -564,8 +576,11 @@@ static int __cpuinit iucv_cpu_notify(st
                        return NOTIFY_BAD;
                iucv_param[cpu] = kmalloc_node(sizeof(union iucv_param),
                                     GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
 -              if (!iucv_param[cpu])
 +              if (!iucv_param[cpu]) {
 +                      kfree(iucv_irq_data[cpu]);
 +                      iucv_irq_data[cpu] = NULL;
                        return NOTIFY_BAD;
 +              }
                break;
        case CPU_UP_CANCELED:
        case CPU_UP_CANCELED_FROZEN:
        case CPU_ONLINE_FROZEN:
        case CPU_DOWN_FAILED:
        case CPU_DOWN_FAILED_FROZEN:
-               smp_call_function_single(cpu, iucv_declare_cpu, NULL, 0, 1);
+               smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1);
                break;
        case CPU_DOWN_PREPARE:
        case CPU_DOWN_PREPARE_FROZEN:
                if (cpus_empty(cpumask))
                        /* Can't offline last IUCV enabled cpu. */
                        return NOTIFY_BAD;
-               smp_call_function_single(cpu, iucv_retrieve_cpu, NULL, 0, 1);
+               smp_call_function_single(cpu, iucv_retrieve_cpu, NULL, 1);
                if (cpus_empty(iucv_irq_cpumask))
                        smp_call_function_single(first_cpu(iucv_buffer_cpumask),
-                                                iucv_allow_cpu, NULL, 0, 1);
+                                                iucv_allow_cpu, NULL, 1);
                break;
        }
        return NOTIFY_OK;
  }
  
 -static struct notifier_block __cpuinitdata iucv_cpu_notifier = {
 +static struct notifier_block __refdata iucv_cpu_notifier = {
        .notifier_call = iucv_cpu_notify,
  };
  
@@@ -658,7 -652,7 +667,7 @@@ static void iucv_cleanup_queue(void
         * pending interrupts force them to the work queue by calling
         * an empty function on all cpus.
         */
-       smp_call_function(__iucv_cleanup_queue, NULL, 0, 1);
+       smp_call_function(__iucv_cleanup_queue, NULL, 1);
        spin_lock_irq(&iucv_queue_lock);
        list_for_each_entry_safe(p, n, &iucv_task_queue, list) {
                /* Remove stale work items from the task queue. */
@@@ -1565,16 -1559,11 +1574,11 @@@ static void iucv_external_interrupt(u1
  
        p = iucv_irq_data[smp_processor_id()];
        if (p->ippathid >= iucv_max_pathid) {
-               printk(KERN_WARNING "iucv_do_int: Got interrupt with "
-                      "pathid %d > max_connections (%ld)\n",
-                      p->ippathid, iucv_max_pathid - 1);
+               WARN_ON(p->ippathid >= iucv_max_pathid);
                iucv_sever_pathid(p->ippathid, iucv_error_no_listener);
                return;
        }
-       if (p->iptype  < 0x01 || p->iptype > 0x09) {
-               printk(KERN_ERR "iucv_do_int: unknown iucv interrupt\n");
-               return;
-       }
+       BUG_ON(p->iptype  < 0x01 || p->iptype > 0x09);
        work = kmalloc(sizeof(struct iucv_irq_list), GFP_ATOMIC);
        if (!work) {
                printk(KERN_WARNING "iucv_external_interrupt: out of memory\n");
index dd233393f6952203c2408e5d904e490d784a940f,077bcd22879922f872cdb8cc63e6c2888de791f0..95a7967731f942ae68ea70126ff59fd81cc7b435
@@@ -4,7 -4,7 +4,7 @@@
   * (C) 2001 by Jay Schulist <jschlst@samba.org>
   * (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
   * (C) 2003 by Patrick Mchardy <kaber@trash.net>
 - * (C) 2005-2007 by Pablo Neira Ayuso <pablo@netfilter.org>
 + * (C) 2005-2008 by Pablo Neira Ayuso <pablo@netfilter.org>
   *
   * Initial connection tracking via netlink development funded and
   * generally made possible by Network Robots, Inc. (www.networkrobots.com)
@@@ -18,6 -18,7 +18,7 @@@
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/kernel.h>
+ #include <linux/rculist.h>
  #include <linux/types.h>
  #include <linux/timer.h>
  #include <linux/skbuff.h>
@@@ -475,14 -476,14 +476,14 @@@ static int ctnetlink_conntrack_event(st
        if (ctnetlink_dump_id(skb, ct) < 0)
                goto nla_put_failure;
  
 +      if (ctnetlink_dump_status(skb, ct) < 0)
 +              goto nla_put_failure;
 +
        if (events & IPCT_DESTROY) {
                if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
                    ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
                        goto nla_put_failure;
        } else {
 -              if (ctnetlink_dump_status(skb, ct) < 0)
 -                      goto nla_put_failure;
 -
                if (ctnetlink_dump_timeout(skb, ct) < 0)
                        goto nla_put_failure;
  
@@@ -812,8 -813,9 +813,8 @@@ ctnetlink_del_conntrack(struct sock *ct
                        return -ENOENT;
                }
        }
 -      if (del_timer(&ct->timeout))
 -              ct->timeout.function((unsigned long)ct);
  
 +      nf_ct_kill(ct);
        nf_ct_put(ct);
  
        return 0;
@@@ -890,19 -892,20 +891,19 @@@ ctnetlink_change_status(struct nf_conn 
  
        if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
                /* unchangeable */
 -              return -EINVAL;
 +              return -EBUSY;
  
        if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
                /* SEEN_REPLY bit can only be set */
 -              return -EINVAL;
 -
 +              return -EBUSY;
  
        if (d & IPS_ASSURED && !(status & IPS_ASSURED))
                /* ASSURED bit can only be set */
 -              return -EINVAL;
 +              return -EBUSY;
  
        if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) {
  #ifndef CONFIG_NF_NAT_NEEDED
 -              return -EINVAL;
 +              return -EOPNOTSUPP;
  #else
                struct nf_nat_range range;
  
@@@ -943,7 -946,7 +944,7 @@@ ctnetlink_change_helper(struct nf_conn 
  
        /* don't change helper of sibling connections */
        if (ct->master)
 -              return -EINVAL;
 +              return -EBUSY;
  
        err = ctnetlink_parse_help(cda[CTA_HELP], &helpname);
        if (err < 0)
  
        helper = __nf_conntrack_helper_find_byname(helpname);
        if (helper == NULL)
 -              return -EINVAL;
 +              return -EOPNOTSUPP;
  
        if (help) {
                if (help->helper == helper)
@@@ -1128,7 -1131,7 +1129,7 @@@ ctnetlink_create_conntrack(struct nlatt
        struct nf_conn_help *help;
        struct nf_conntrack_helper *helper;
  
 -      ct = nf_conntrack_alloc(otuple, rtuple);
 +      ct = nf_conntrack_alloc(otuple, rtuple, GFP_KERNEL);
        if (ct == NULL || IS_ERR(ct))
                return -ENOMEM;
  
@@@ -1256,12 -1259,12 +1257,12 @@@ ctnetlink_new_conntrack(struct sock *ct
        if (!(nlh->nlmsg_flags & NLM_F_EXCL)) {
                /* we only allow nat config for new conntracks */
                if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) {
 -                      err = -EINVAL;
 +                      err = -EOPNOTSUPP;
                        goto out_unlock;
                }
                /* can't link an existing conntrack to a master */
                if (cda[CTA_TUPLE_MASTER]) {
 -                      err = -EINVAL;
 +                      err = -EOPNOTSUPP;
                        goto out_unlock;
                }
                err = ctnetlink_change_conntrack(nf_ct_tuplehash_to_ctrack(h),
@@@ -1606,7 -1609,7 +1607,7 @@@ ctnetlink_del_expect(struct sock *ctnl
                h = __nf_conntrack_helper_find_byname(name);
                if (!h) {
                        spin_unlock_bh(&nf_conntrack_lock);
 -                      return -EINVAL;
 +                      return -EOPNOTSUPP;
                }
                for (i = 0; i < nf_ct_expect_hsize; i++) {
                        hlist_for_each_entry_safe(exp, n, next,
index 019d4b4478c98cdc1469e253d023832bfb336929,834a83199bdf5ec07d778b6346191fd2fb7ccf22..853a4142cea105bba2706a96094e7a8e2793d84e
@@@ -33,6 -33,8 +33,6 @@@
   *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 - *
 - * $Id$
   */
  
  
@@@ -61,22 -63,11 +61,11 @@@ static const struct rpc_credops gss_nul
  # define RPCDBG_FACILITY      RPCDBG_AUTH
  #endif
  
- #define NFS_NGROUPS   16
- #define GSS_CRED_SLACK                1024            /* XXX: unused */
+ #define GSS_CRED_SLACK                1024
  /* length of a krb5 verifier (48), plus data added before arguments when
   * using integrity (two 4-byte integers): */
  #define GSS_VERF_SLACK                100
  
- /* XXX this define must match the gssd define
- * as it is passed to gssd to signal the use of
- * machine creds should be part of the shared rpc interface */
- #define CA_RUN_AS_MACHINE  0x00000200
- /* dump the buffer in `emacs-hexl' style */
- #define isprint(c)      ((c > 0x1f) && (c < 0x7f))
  struct gss_auth {
        struct kref kref;
        struct rpc_auth rpc_auth;
@@@ -144,7 -135,7 +133,7 @@@ simple_get_netobj(const void *p, const 
        q = (const void *)((const char *)p + len);
        if (unlikely(q > end || q < p))
                return ERR_PTR(-EFAULT);
-       dest->data = kmemdup(p, len, GFP_KERNEL);
+       dest->data = kmemdup(p, len, GFP_NOFS);
        if (unlikely(dest->data == NULL))
                return ERR_PTR(-ENOMEM);
        dest->len = len;
@@@ -169,7 -160,7 +158,7 @@@ gss_alloc_context(void
  {
        struct gss_cl_ctx *ctx;
  
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       ctx = kzalloc(sizeof(*ctx), GFP_NOFS);
        if (ctx != NULL) {
                ctx->gc_proc = RPC_GSS_PROC_DATA;
                ctx->gc_seq = 1;        /* NetApp 6.4R1 doesn't accept seq. no. 0 */
@@@ -270,7 -261,7 +259,7 @@@ __gss_find_upcall(struct rpc_inode *rpc
        return NULL;
  }
  
- /* Try to add a upcall to the pipefs queue.
+ /* Try to add an upcall to the pipefs queue.
   * If an upcall owned by our uid already exists, then we return a reference
   * to that upcall instead of adding the new upcall.
   */
@@@ -339,7 -330,7 +328,7 @@@ gss_alloc_msg(struct gss_auth *gss_auth
  {
        struct gss_upcall_msg *gss_msg;
  
-       gss_msg = kzalloc(sizeof(*gss_msg), GFP_KERNEL);
+       gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS);
        if (gss_msg != NULL) {
                INIT_LIST_HEAD(&gss_msg->list);
                rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
@@@ -491,7 -482,6 +480,6 @@@ gss_pipe_downcall(struct file *filp, co
  {
        const void *p, *end;
        void *buf;
-       struct rpc_clnt *clnt;
        struct gss_upcall_msg *gss_msg;
        struct inode *inode = filp->f_path.dentry->d_inode;
        struct gss_cl_ctx *ctx;
        if (mlen > MSG_BUF_MAXSIZE)
                goto out;
        err = -ENOMEM;
-       buf = kmalloc(mlen, GFP_KERNEL);
+       buf = kmalloc(mlen, GFP_NOFS);
        if (!buf)
                goto out;
  
-       clnt = RPC_I(inode)->private;
        err = -EFAULT;
        if (copy_from_user(buf, src, mlen))
                goto err;
@@@ -804,7 -793,7 +791,7 @@@ gss_create_cred(struct rpc_auth *auth, 
        dprintk("RPC:       gss_create_cred for uid %d, flavor %d\n",
                acred->uid, auth->au_flavor);
  
-       if (!(cred = kzalloc(sizeof(*cred), GFP_KERNEL)))
+       if (!(cred = kzalloc(sizeof(*cred), GFP_NOFS)))
                goto out_err;
  
        rpcauth_init_cred(&cred->gc_base, acred, auth, &gss_credops);