Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 21 May 2010 04:04:44 +0000 (21:04 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 21 May 2010 04:04:44 +0000 (21:04 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1674 commits)
  qlcnic: adding co maintainer
  ixgbe: add support for active DA cables
  ixgbe: dcb, do not tag tc_prio_control frames
  ixgbe: fix ixgbe_tx_is_paused logic
  ixgbe: always enable vlan strip/insert when DCB is enabled
  ixgbe: remove some redundant code in setting FCoE FIP filter
  ixgbe: fix wrong offset to fc_frame_header in ixgbe_fcoe_ddp
  ixgbe: fix header len when unsplit packet overflows to data buffer
  ipv6: Never schedule DAD timer on dead address
  ipv6: Use POSTDAD state
  ipv6: Use state_lock to protect ifa state
  ipv6: Replace inet6_ifaddr->dead with state
  cxgb4: notify upper drivers if the device is already up when they load
  cxgb4: keep interrupts available when the ports are brought down
  cxgb4: fix initial addition of MAC address
  cnic: Return SPQ credit to bnx2x after ring setup and shutdown.
  cnic: Convert cnic_local_flags to atomic ops.
  can: Fix SJA1000 command register writes on SMP systems
  bridge: fix build for CONFIG_SYSFS disabled
  ARCNET: Limit com20020 PCI ID matches for SOHARD cards
  ...

Fix up various conflicts with pcmcia tree drivers/net/
{pcmcia/3c589_cs.c, wireless/orinoco/orinoco_cs.c and
wireless/orinoco/spectrum_cs.c} and feature removal
(Documentation/feature-removal-schedule.txt).

Also fix a non-content conflict due to pm_qos_requirement getting
renamed in the PM tree (now pm_qos_request) in net/mac80211/scan.c

34 files changed:
1  2 
Documentation/feature-removal-schedule.txt
MAINTAINERS
arch/arm/mach-pxa/zeus.c
drivers/infiniband/hw/nes/nes_nic.c
drivers/net/e1000e/netdev.c
drivers/net/igbvf/netdev.c
drivers/net/pcmcia/3c574_cs.c
drivers/net/pcmcia/3c589_cs.c
drivers/net/pcmcia/axnet_cs.c
drivers/net/pcmcia/fmvj18x_cs.c
drivers/net/pcmcia/ibmtr_cs.c
drivers/net/pcmcia/nmclan_cs.c
drivers/net/pcmcia/smc91c92_cs.c
drivers/net/pcmcia/xirc2ps_cs.c
drivers/net/ps3_gelic_wireless.c
drivers/net/smsc911x.c
drivers/net/wireless/ipw2x00/ipw2100.c
drivers/net/wireless/orinoco/orinoco_cs.c
drivers/net/wireless/orinoco/spectrum_cs.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/wl3501_cs.c
drivers/s390/net/qeth_core_main.c
drivers/ssb/main.c
drivers/staging/wavelan/wavelan_cs.c
include/linux/fs.h
include/linux/netdevice.h
kernel/sysctl.c
net/ipv4/ipmr.c
net/mac80211/mlme.c
net/mac80211/scan.c
net/sunrpc/clnt.c
net/sunrpc/svcsock.c
net/sunrpc/xprt.c
net/sunrpc/xprtsock.c

@@@ -241,16 -241,6 +241,6 @@@ Who:      Thomas Gleixner <tglx@linutronix.d
  
  ---------------------------
  
- What (Why):
-       - xt_recent: the old ipt_recent proc dir
-         (superseded by /proc/net/xt_recent)
- When: January 2009 or Linux 2.7.0, whichever comes first
- Why:  Superseded by newer revisions or modules
- Who:  Jan Engelhardt <jengelh@computergmbh.de>
- ---------------------------
  What: GPIO autorequest on gpio_direction_{input,output}() in gpiolib
  When: February 2010
  Why:  All callers should use explicit gpio_request()/gpio_free().
@@@ -520,6 -510,47 +510,24 @@@ Who:     Hans de Goede <hdegoede@redhat.com
  
  ----------------------------
  
 -What: corgikbd, spitzkbd, tosakbd driver
 -When: 2.6.35
 -Files:        drivers/input/keyboard/{corgi,spitz,tosa}kbd.c
 -Why:  We now have a generic GPIO based matrix keyboard driver that
 -      are fully capable of handling all the keys on these devices.
 -      The original drivers manipulate the GPIO registers directly
 -      and so are difficult to maintain.
 -Who:  Eric Miao <eric.y.miao@gmail.com>
 -
 -----------------------------
 -
 -What: corgi_ssp and corgi_ts driver
 -When: 2.6.35
 -Files:        arch/arm/mach-pxa/corgi_ssp.c, drivers/input/touchscreen/corgi_ts.c
 -Why:  The corgi touchscreen is now deprecated in favour of the generic
 -      ads7846.c driver. The noise reduction technique used in corgi_ts.c,
 -      that's to wait till vsync before ADC sampling, is also integrated into
 -      ads7846 driver now. Provided that the original driver is not generic
 -      and is difficult to maintain, it will be removed later.
 -Who:  Eric Miao <eric.y.miao@gmail.com>
 -
 -----------------------------
 -
+ What: sysfs-class-rfkill state file
+ When: Feb 2014
+ Files:        net/rfkill/core.c
+ Why:  Documented as obsolete since Feb 2010. This file is limited to 3
+       states while the rfkill drivers can have 4 states.
+ Who:  anybody or Florian Mickler <florian@mickler.org>
+ ----------------------------
+ What:         sysfs-class-rfkill claim file
+ When: Feb 2012
+ Files:        net/rfkill/core.c
+ Why:  It is not possible to claim an rfkill driver since 2007. This is
+       Documented as obsolete since Feb 2010.
+ Who:  anybody or Florian Mickler <florian@mickler.org>
+ ----------------------------
  What: capifs
  When: February 2011
  Files:        drivers/isdn/capi/capifs.*
@@@ -541,16 -572,6 +549,16 @@@ Who:     Avi Kivity <avi@redhat.com
  
  ----------------------------
  
 +What: xtime, wall_to_monotonic
 +When: 2.6.36+
 +Files:        kernel/time/timekeeping.c include/linux/time.h
 +Why:  Cleaning up timekeeping internal values. Please use
 +      existing timekeeping accessor functions to access
 +      the equivalent functionality.
 +Who:  John Stultz <johnstul@us.ibm.com>
 +
 +----------------------------
 +
  What: KVM kernel-allocated memory slots
  When: July 2010
  Why:  Since 2.6.25, kvm supports user-allocated memory slots, which are
@@@ -579,6 -600,35 +587,35 @@@ Who:     Len Brown <len.brown@intel.com
  
  ----------------------------
  
+ What: iwlwifi 50XX module parameters
+ When: 2.6.40
+ Why:  The "..50" modules parameters were used to configure 5000 series and
+       up devices; different set of module parameters also available for 4965
+       with same functionalities. Consolidate both set into single place
+       in drivers/net/wireless/iwlwifi/iwl-agn.c
+ Who:  Wey-Yi Guy <wey-yi.w.guy@intel.com>
+ ----------------------------
+ What: iwl4965 alias support
+ When: 2.6.40
+ Why:  Internal alias support has been present in module-init-tools for some
+       time, the MODULE_ALIAS("iwl4965") boilerplate aliases can be removed
+       with no impact.
+ Who:  Wey-Yi Guy <wey-yi.w.guy@intel.com>
+ ---------------------------
+ What: xt_NOTRACK
+ Files:        net/netfilter/xt_NOTRACK.c
+ When: April 2011
+ Why:  Superseded by xt_CT
+ Who:  Netfilter developer team <netfilter-devel@vger.kernel.org>
+ ---------------------------
  What: video4linux /dev/vtx teletext API support
  When: 2.6.35
  Files:        drivers/media/video/saa5246a.c drivers/media/video/saa5249.c
@@@ -599,13 -649,3 +636,13 @@@ Why:     The vtx device nodes have been sup
        provided by the vtx API, then that functionality should be build
        around the sliced VBI API instead.
  Who:  Hans Verkuil <hverkuil@xs4all.nl>
 +
 +----------------------------
 +
 +What: IRQF_DISABLED
 +When: 2.6.36
 +Why:  The flag is a NOOP as we run interrupt handlers with interrupts disabled
 +Who:  Thomas Gleixner <tglx@linutronix.de>
 +
 +----------------------------
 +
diff --combined MAINTAINERS
@@@ -586,12 -586,6 +586,12 @@@ F:       drivers/mtd/nand/bcm_umi_bch.
  F:    drivers/mtd/nand/bcm_umi_hamming.c
  F:    drivers/mtd/nand/nand_bcm_umi.h
  
 +ARM/CAVIUM NETWORKS CNS3XXX MACHINE SUPPORT
 +M:    Anton Vorontsov <avorontsov@mvista.com>
 +S:    Maintained
 +F:    arch/arm/mach-cns3xxx/
 +T:    git git://git.infradead.org/users/cbou/linux-cns3xxx.git
 +
  ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE
  M:    Hartley Sweeten <hsweeten@visionengravers.com>
  M:    Ryan Mallon <ryan@bluewatersys.com>
@@@ -781,10 -775,11 +781,10 @@@ M:      Philipp Zabel <philipp.zabel@gmail.c
  S:    Maintained
  
  ARM/Marvell Loki/Kirkwood/MV78xx0/Orion SOC support
 -M:    Lennert Buytenhek <buytenh@marvell.com>
 -M:    Nicolas Pitre <nico@marvell.com>
 +M:    Lennert Buytenhek <kernel@wantstofly.org>
 +M:    Nicolas Pitre <nico@fluxnic.net>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 -T:    git git://git.marvell.com/orion
 -S:    Maintained
 +S:    Odd Fixes
  F:    arch/arm/mach-loki/
  F:    arch/arm/mach-kirkwood/
  F:    arch/arm/mach-mv78xx0/
@@@ -819,7 -814,6 +819,7 @@@ ARM/QUALCOMM MSM MACHINE SUPPOR
  M:    David Brown <davidb@codeaurora.org>
  M:    Daniel Walker <dwalker@codeaurora.org>
  M:    Bryan Huntsman <bryanh@codeaurora.org>
 +L:    linux-arm-msm@vger.kernel.org
  F:    arch/arm/mach-msm/
  F:    drivers/video/msm/
  F:    drivers/mmc/host/msm_sdcc.c
@@@ -1000,20 -994,6 +1000,20 @@@ W:     http://www.arm.linux.org.uk
  S:    Maintained
  F:    arch/arm/vfp/
  
 +ARM/VOIPAC PXA270 SUPPORT
 +M:    Marek Vasut <marek.vasut@gmail.com>
 +L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 +S:    Maintained
 +F:    arch/arm/mach-pxa/vpac270.c
 +F:    arch/arm/mach-pxa/include/mach-pxa/vpac270.h
 +
 +ARM/ZIPIT Z2 SUPPORT
 +M:    Marek Vasut <marek.vasut@gmail.com>
 +L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 +S:    Maintained
 +F:    arch/arm/mach-pxa/z2.c
 +F:    arch/arm/mach-pxa/include/mach-pxa/z2.h
 +
  ASC7621 HARDWARE MONITOR DRIVER
  M:    George Joseph <george.joseph@fairview5.com>
  L:    lm-sensors@lm-sensors.org
@@@ -1521,9 -1501,10 +1521,10 @@@ M:    Andy Whitcroft <apw@canonical.com
  S:    Supported
  F:    scripts/checkpatch.pl
  
- CISCO 10G ETHERNET DRIVER
+ CISCO VIC ETHERNET NIC DRIVER
  M:    Scott Feldman <scofeldm@cisco.com>
- M:    Joe Eykholt <jeykholt@cisco.com>
+ M:    Vasanthy Kolluri <vkolluri@cisco.com>
+ M:    Roopa Prabhu <roprabhu@cisco.com>
  S:    Supported
  F:    drivers/net/enic/
  
@@@ -1749,20 -1730,6 +1750,20 @@@ W:    http://www.openfabrics.or
  S:    Supported
  F:    drivers/infiniband/hw/cxgb3/
  
 +CXGB4 ETHERNET DRIVER (CXGB4)
 +M:    Dimitris Michailidis <dm@chelsio.com>
 +L:    netdev@vger.kernel.org
 +W:    http://www.chelsio.com
 +S:    Supported
 +F:    drivers/net/cxgb4/
 +
 +CXGB4 IWARP RNIC DRIVER (IW_CXGB4)
 +M:    Steve Wise <swise@chelsio.com>
 +L:    linux-rdma@vger.kernel.org
 +W:    http://www.openfabrics.org
 +S:    Supported
 +F:    drivers/infiniband/hw/cxgb4/
 +
  CYBERPRO FB DRIVER
  M:    Russell King <linux@arm.linux.org.uk>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@@ -2701,12 -2668,16 +2702,12 @@@ F:   Documentation/timers/hpet.tx
  F:    drivers/char/hpet.c
  F:    include/linux/hpet.h
  
 -HPET: i386
 -M:    "Venkatesh Pallipadi (Venki)" <venkatesh.pallipadi@intel.com>
 +HPET: x86
 +M:    "Venkatesh Pallipadi (Venki)" <venki@google.com>
  S:    Maintained
  F:    arch/x86/kernel/hpet.c
  F:    arch/x86/include/asm/hpet.h
  
 -HPET: x86_64
 -M:    Vojtech Pavlik <vojtech@suse.cz>
 -S:    Maintained
 -
  HPET: ACPI
  M:    Bob Picco <bob.picco@hp.com>
  S:    Maintained
@@@ -2747,7 -2718,6 +2748,7 @@@ M:      "Ben Dooks (embedded platforms)" <be
  L:    linux-i2c@vger.kernel.org
  W:    http://i2c.wiki.kernel.org/
  T:    quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/
 +T:    git git://git.fluff.org/bjdooks/linux.git
  S:    Maintained
  F:    Documentation/i2c/
  F:    drivers/i2c/
@@@ -3044,10 -3014,9 +3045,9 @@@ F:     net/ipv4/netfilter/ipt_MASQUERADE.
  IP1000A 10/100/1000 GIGABIT ETHERNET DRIVER
  M:    Francois Romieu <romieu@fr.zoreil.com>
  M:    Sorbica Shieh <sorbica@icplus.com.tw>
- M:    Jesse Huang <jesse@icplus.com.tw>
  L:    netdev@vger.kernel.org
  S:    Maintained
- F:    drivers/net/ipg.c
+ F:    drivers/net/ipg.*
  
  IPATH DRIVER
  M:    Ralph Campbell <infinipath@qlogic.com>
@@@ -3666,8 -3635,7 +3666,8 @@@ F:      drivers/net/wireless/mwl8k.
  
  MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
  M:    Nicolas Pitre <nico@fluxnic.net>
 -S:    Maintained
 +S:    Odd Fixes
 +F: drivers/mmc/host/mvsdio.*
  
  MARVELL YUKON / SYSKONNECT DRIVER
  M:    Mirko Lindner <mlindner@syskonnect.de>
@@@ -3895,7 -3863,6 +3895,6 @@@ M:      Ramkrishna Vepa <ram.vepa@neterion.c
  M:    Rastapur Santosh <santosh.rastapur@neterion.com>
  M:    Sivakumar Subramani <sivakumar.subramani@neterion.com>
  M:    Sreenivasa Honnur <sreenivasa.honnur@neterion.com>
- M:    Anil Murthy <anil.murthy@neterion.com>
  L:    netdev@vger.kernel.org
  W:    http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous
  W:    http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous
@@@ -4000,6 -3967,7 +3999,7 @@@ F:      net/rfkill
  F:    net/wireless/
  F:    include/net/ieee80211*
  F:    include/linux/wireless.h
+ F:    include/linux/iw_handler.h
  F:    drivers/net/wireless/
  
  NETWORKING DRIVERS
@@@ -4631,6 -4599,7 +4631,7 @@@ F:      drivers/net/qla3xxx.
  
  QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
  M:    Amit Kumar Salecha <amit.salecha@qlogic.com>
+ M:    Anirban Chakraborty <anirban.chakraborty@qlogic.com>
  M:    linux-driver@qlogic.com
  L:    netdev@vger.kernel.org
  S:    Supported
@@@ -5165,7 -5134,7 +5166,7 @@@ F:      mm/sl?b.
  
  SMC91x ETHERNET DRIVER
  M:    Nicolas Pitre <nico@fluxnic.net>
 -S:    Maintained
 +S:    Odd Fixes
  F:    drivers/net/smc91x.*
  
  SMSC47B397 HARDWARE MONITOR DRIVER
@@@ -5296,46 -5265,6 +5297,46 @@@ F:    drivers/serial/sunsu.
  F:    drivers/serial/sunzilog.c
  F:    drivers/serial/sunzilog.h
  
 +SPEAR PLATFORM SUPPORT
 +M:    Viresh Kumar <viresh.kumar@st.com>
 +W:    http://www.st.com/spear
 +S:    Maintained
 +F:    arch/arm/plat-spear/
 +
 +SPEAR3XX MACHINE SUPPORT
 +M:    Viresh Kumar <viresh.kumar@st.com>
 +W:    http://www.st.com/spear
 +S:    Maintained
 +F:    arch/arm/mach-spear3xx/
 +
 +SPEAR6XX MACHINE SUPPORT
 +M:    Rajeev Kumar <rajeev-dlh.kumar@st.com>
 +W:    http://www.st.com/spear
 +S:    Maintained
 +F:    arch/arm/mach-spear6xx/
 +
 +SPEAR CLOCK FRAMEWORK SUPPORT
 +M:    Viresh Kumar <viresh.kumar@st.com>
 +W:    http://www.st.com/spear
 +S:    Maintained
 +F:    arch/arm/mach-spear*/clock.c
 +F:    arch/arm/mach-spear*/include/mach/clkdev.h
 +F:    arch/arm/plat-spear/clock.c
 +F:    arch/arm/plat-spear/include/plat/clock.h and clkdev.h
 +
 +SPEAR PAD MULTIPLEXING SUPPORT
 +M:    Viresh Kumar <viresh.kumar@st.com>
 +W:    http://www.st.com/spear
 +S:    Maintained
 +F:    arch/arm/plat-spear/include/plat/padmux.h
 +F:    arch/arm/plat-spear/padmux.c
 +F:    arch/arm/mach-spear*/spear*xx.c
 +F:    arch/arm/mach-spear*/include/mach/generic.h
 +F:    arch/arm/mach-spear3xx/spear3*0.c
 +F:    arch/arm/mach-spear3xx/spear3*0_evb.c
 +F:    arch/arm/mach-spear6xx/spear600.c
 +F:    arch/arm/mach-spear6xx/spear600_evb.c
 +
  SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
  M:    Roger Wolff <R.E.Wolff@BitWizard.nl>
  S:    Supported
@@@ -5964,7 -5893,7 +5965,7 @@@ M:      Laurent Pinchart <laurent.pinchart@s
  L:    linux-uvc-devel@lists.berlios.de (subscribers-only)
  L:    linux-media@vger.kernel.org
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
 -W:    http://linux-uvc.berlios.de
 +W:    http://www.ideasonboard.org/uvc/
  S:    Maintained
  F:    drivers/media/video/uvc/
  
diff --combined arch/arm/mach-pxa/zeus.c
@@@ -414,15 -414,13 +414,13 @@@ static int zeus_mcp2515_transceiver_ena
  
  static struct mcp251x_platform_data zeus_mcp2515_pdata = {
        .oscillator_frequency   = 16*1000*1000,
-       .model                  = CAN_MCP251X_MCP2515,
        .board_specific_setup   = zeus_mcp2515_setup,
-       .transceiver_enable     = zeus_mcp2515_transceiver_enable,
        .power_enable           = zeus_mcp2515_transceiver_enable,
  };
  
  static struct spi_board_info zeus_spi_board_info[] = {
        [0] = {
-               .modalias       = "mcp251x",
+               .modalias       = "mcp2515",
                .platform_data  = &zeus_mcp2515_pdata,
                .irq            = gpio_to_irq(ZEUS_CAN_GPIO),
                .max_speed_hz   = 1*1000*1000,
@@@ -644,7 -642,7 +642,7 @@@ static struct pxafb_mach_info zeus_fb_i
  
  static struct pxamci_platform_data zeus_mci_platform_data = {
        .ocr_mask               = MMC_VDD_32_33|MMC_VDD_33_34,
 -      .detect_delay           = HZ/4,
 +      .detect_delay_ms        = 250,
        .gpio_card_detect       = ZEUS_MMC_CD_GPIO,
        .gpio_card_ro           = ZEUS_MMC_WP_GPIO,
        .gpio_card_ro_invert    = 1,
@@@ -877,7 -877,7 +877,7 @@@ static void nes_netdev_set_multicast_li
        if (!mc_all_on) {
                char *addrs;
                int i;
-               struct dev_mc_list *mcaddr;
+               struct netdev_hw_addr *ha;
  
                addrs = kmalloc(ETH_ALEN * mc_count, GFP_ATOMIC);
                if (!addrs) {
                        goto unlock;
                }
                i = 0;
-               netdev_for_each_mc_addr(mcaddr, netdev)
-                       memcpy(get_addr(addrs, i++),
-                              mcaddr->dmi_addr, ETH_ALEN);
+               netdev_for_each_mc_addr(ha, netdev)
+                       memcpy(get_addr(addrs, i++), ha->addr, ETH_ALEN);
  
                perfect_filter_register_address = NES_IDX_PERFECT_FILTER_LOW +
                                                pft_entries_preallocated * 0x8;
@@@ -1461,14 -1460,11 +1460,14 @@@ static int nes_netdev_get_settings(stru
                        et_cmd->transceiver = XCVR_INTERNAL;
                        et_cmd->phy_address = mac_index;
                } else {
 +                      unsigned long flags;
                        et_cmd->supported   = SUPPORTED_1000baseT_Full
                                            | SUPPORTED_Autoneg;
                        et_cmd->advertising = ADVERTISED_1000baseT_Full
                                            | ADVERTISED_Autoneg;
 +                      spin_lock_irqsave(&nesadapter->phy_lock, flags);
                        nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
 +                      spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
                        if (phy_data & 0x1000)
                                et_cmd->autoneg = AUTONEG_ENABLE;
                        else
@@@ -1506,15 -1502,12 +1505,15 @@@ static int nes_netdev_set_settings(stru
        struct nes_vnic *nesvnic = netdev_priv(netdev);
        struct nes_device *nesdev = nesvnic->nesdev;
        struct nes_adapter *nesadapter = nesdev->nesadapter;
  
        if ((nesadapter->OneG_Mode) &&
            (nesadapter->phy_type[nesdev->mac_index] != NES_PHY_TYPE_PUMA_1G)) {
 -              nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[nesdev->mac_index],
 -                              &phy_data);
 +              unsigned long flags;
 +              u16 phy_data;
 +              u8 phy_index = nesadapter->phy_index[nesdev->mac_index];
 +
 +              spin_lock_irqsave(&nesadapter->phy_lock, flags);
 +              nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
                if (et_cmd->autoneg) {
                        /* Turn on Full duplex, Autoneg, and restart autonegotiation */
                        phy_data |= 0x1300;
                        /* Turn off autoneg */
                        phy_data &= ~0x1000;
                }
 -              nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[nesdev->mac_index],
 -                              phy_data);
 +              nes_write_1G_phy_reg(nesdev, 0, phy_index, phy_data);
 +              spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
        }
  
        return 0;
@@@ -26,6 -26,8 +26,8 @@@
  
  *******************************************************************************/
  
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  #include <linux/module.h>
  #include <linux/types.h>
  #include <linux/init.h>
  #include <linux/cpu.h>
  #include <linux/smp.h>
  #include <linux/pm_qos_params.h>
+ #include <linux/pm_runtime.h>
  #include <linux/aer.h>
  
  #include "e1000.h"
  
- #define DRV_VERSION "1.0.2-k2"
+ #define DRV_VERSION "1.0.2-k4"
  char e1000e_driver_name[] = "e1000e";
  const char e1000e_driver_version[] = DRV_VERSION;
  
@@@ -66,6 -69,361 +69,361 @@@ static const struct e1000_info *e1000_i
        [board_pchlan]          = &e1000_pch_info,
  };
  
+ struct e1000_reg_info {
+       u32 ofs;
+       char *name;
+ };
+ #define E1000_RDFH    0x02410 /* Rx Data FIFO Head - RW */
+ #define E1000_RDFT    0x02418 /* Rx Data FIFO Tail - RW */
+ #define E1000_RDFHS   0x02420 /* Rx Data FIFO Head Saved - RW */
+ #define E1000_RDFTS   0x02428 /* Rx Data FIFO Tail Saved - RW */
+ #define E1000_RDFPC   0x02430 /* Rx Data FIFO Packet Count - RW */
+ #define E1000_TDFH    0x03410 /* Tx Data FIFO Head - RW */
+ #define E1000_TDFT    0x03418 /* Tx Data FIFO Tail - RW */
+ #define E1000_TDFHS   0x03420 /* Tx Data FIFO Head Saved - RW */
+ #define E1000_TDFTS   0x03428 /* Tx Data FIFO Tail Saved - RW */
+ #define E1000_TDFPC   0x03430 /* Tx Data FIFO Packet Count - RW */
+ static const struct e1000_reg_info e1000_reg_info_tbl[] = {
+       /* General Registers */
+       {E1000_CTRL, "CTRL"},
+       {E1000_STATUS, "STATUS"},
+       {E1000_CTRL_EXT, "CTRL_EXT"},
+       /* Interrupt Registers */
+       {E1000_ICR, "ICR"},
+       /* RX Registers */
+       {E1000_RCTL, "RCTL"},
+       {E1000_RDLEN, "RDLEN"},
+       {E1000_RDH, "RDH"},
+       {E1000_RDT, "RDT"},
+       {E1000_RDTR, "RDTR"},
+       {E1000_RXDCTL(0), "RXDCTL"},
+       {E1000_ERT, "ERT"},
+       {E1000_RDBAL, "RDBAL"},
+       {E1000_RDBAH, "RDBAH"},
+       {E1000_RDFH, "RDFH"},
+       {E1000_RDFT, "RDFT"},
+       {E1000_RDFHS, "RDFHS"},
+       {E1000_RDFTS, "RDFTS"},
+       {E1000_RDFPC, "RDFPC"},
+       /* TX Registers */
+       {E1000_TCTL, "TCTL"},
+       {E1000_TDBAL, "TDBAL"},
+       {E1000_TDBAH, "TDBAH"},
+       {E1000_TDLEN, "TDLEN"},
+       {E1000_TDH, "TDH"},
+       {E1000_TDT, "TDT"},
+       {E1000_TIDV, "TIDV"},
+       {E1000_TXDCTL(0), "TXDCTL"},
+       {E1000_TADV, "TADV"},
+       {E1000_TARC(0), "TARC"},
+       {E1000_TDFH, "TDFH"},
+       {E1000_TDFT, "TDFT"},
+       {E1000_TDFHS, "TDFHS"},
+       {E1000_TDFTS, "TDFTS"},
+       {E1000_TDFPC, "TDFPC"},
+       /* List Terminator */
+       {}
+ };
+ /*
+  * e1000_regdump - register printout routine
+  */
+ static void e1000_regdump(struct e1000_hw *hw, struct e1000_reg_info *reginfo)
+ {
+       int n = 0;
+       char rname[16];
+       u32 regs[8];
+       switch (reginfo->ofs) {
+       case E1000_RXDCTL(0):
+               for (n = 0; n < 2; n++)
+                       regs[n] = __er32(hw, E1000_RXDCTL(n));
+               break;
+       case E1000_TXDCTL(0):
+               for (n = 0; n < 2; n++)
+                       regs[n] = __er32(hw, E1000_TXDCTL(n));
+               break;
+       case E1000_TARC(0):
+               for (n = 0; n < 2; n++)
+                       regs[n] = __er32(hw, E1000_TARC(n));
+               break;
+       default:
+               printk(KERN_INFO "%-15s %08x\n",
+                       reginfo->name, __er32(hw, reginfo->ofs));
+               return;
+       }
+       snprintf(rname, 16, "%s%s", reginfo->name, "[0-1]");
+       printk(KERN_INFO "%-15s ", rname);
+       for (n = 0; n < 2; n++)
+               printk(KERN_CONT "%08x ", regs[n]);
+       printk(KERN_CONT "\n");
+ }
+ /*
+  * e1000e_dump - Print registers, tx-ring and rx-ring
+  */
+ static void e1000e_dump(struct e1000_adapter *adapter)
+ {
+       struct net_device *netdev = adapter->netdev;
+       struct e1000_hw *hw = &adapter->hw;
+       struct e1000_reg_info *reginfo;
+       struct e1000_ring *tx_ring = adapter->tx_ring;
+       struct e1000_tx_desc *tx_desc;
+       struct my_u0 { u64 a; u64 b; } *u0;
+       struct e1000_buffer *buffer_info;
+       struct e1000_ring *rx_ring = adapter->rx_ring;
+       union e1000_rx_desc_packet_split *rx_desc_ps;
+       struct e1000_rx_desc *rx_desc;
+       struct my_u1 { u64 a; u64 b; u64 c; u64 d; } *u1;
+       u32 staterr;
+       int i = 0;
+       if (!netif_msg_hw(adapter))
+               return;
+       /* Print netdevice Info */
+       if (netdev) {
+               dev_info(&adapter->pdev->dev, "Net device Info\n");
+               printk(KERN_INFO "Device Name     state            "
+                       "trans_start      last_rx\n");
+               printk(KERN_INFO "%-15s %016lX %016lX %016lX\n",
+                       netdev->name,
+                       netdev->state,
+                       netdev->trans_start,
+                       netdev->last_rx);
+       }
+       /* Print Registers */
+       dev_info(&adapter->pdev->dev, "Register Dump\n");
+       printk(KERN_INFO " Register Name   Value\n");
+       for (reginfo = (struct e1000_reg_info *)e1000_reg_info_tbl;
+            reginfo->name; reginfo++) {
+               e1000_regdump(hw, reginfo);
+       }
+       /* Print TX Ring Summary */
+       if (!netdev || !netif_running(netdev))
+               goto exit;
+       dev_info(&adapter->pdev->dev, "TX Rings Summary\n");
+       printk(KERN_INFO "Queue [NTU] [NTC] [bi(ntc)->dma  ]"
+               " leng ntw timestamp\n");
+       buffer_info = &tx_ring->buffer_info[tx_ring->next_to_clean];
+       printk(KERN_INFO " %5d %5X %5X %016llX %04X %3X %016llX\n",
+               0, tx_ring->next_to_use, tx_ring->next_to_clean,
+               (u64)buffer_info->dma,
+               buffer_info->length,
+               buffer_info->next_to_watch,
+               (u64)buffer_info->time_stamp);
+       /* Print TX Rings */
+       if (!netif_msg_tx_done(adapter))
+               goto rx_ring_summary;
+       dev_info(&adapter->pdev->dev, "TX Rings Dump\n");
+       /* Transmit Descriptor Formats - DEXT[29] is 0 (Legacy) or 1 (Extended)
+        *
+        * Legacy Transmit Descriptor
+        *   +--------------------------------------------------------------+
+        * 0 |         Buffer Address [63:0] (Reserved on Write Back)       |
+        *   +--------------------------------------------------------------+
+        * 8 | Special  |    CSS     | Status |  CMD    |  CSO   |  Length  |
+        *   +--------------------------------------------------------------+
+        *   63       48 47        36 35    32 31     24 23    16 15        0
+        *
+        * Extended Context Descriptor (DTYP=0x0) for TSO or checksum offload
+        *   63      48 47    40 39       32 31             16 15    8 7      0
+        *   +----------------------------------------------------------------+
+        * 0 |  TUCSE  | TUCS0  |   TUCSS   |     IPCSE       | IPCS0 | IPCSS |
+        *   +----------------------------------------------------------------+
+        * 8 |   MSS   | HDRLEN | RSV | STA | TUCMD | DTYP |      PAYLEN      |
+        *   +----------------------------------------------------------------+
+        *   63      48 47    40 39 36 35 32 31   24 23  20 19                0
+        *
+        * Extended Data Descriptor (DTYP=0x1)
+        *   +----------------------------------------------------------------+
+        * 0 |                     Buffer Address [63:0]                      |
+        *   +----------------------------------------------------------------+
+        * 8 | VLAN tag |  POPTS  | Rsvd | Status | Command | DTYP |  DTALEN  |
+        *   +----------------------------------------------------------------+
+        *   63       48 47     40 39  36 35    32 31     24 23  20 19        0
+        */
+       printk(KERN_INFO "Tl[desc]     [address 63:0  ] [SpeCssSCmCsLen]"
+               " [bi->dma       ] leng  ntw timestamp        bi->skb "
+               "<-- Legacy format\n");
+       printk(KERN_INFO "Tc[desc]     [Ce CoCsIpceCoS] [MssHlRSCm0Plen]"
+               " [bi->dma       ] leng  ntw timestamp        bi->skb "
+               "<-- Ext Context format\n");
+       printk(KERN_INFO "Td[desc]     [address 63:0  ] [VlaPoRSCm1Dlen]"
+               " [bi->dma       ] leng  ntw timestamp        bi->skb "
+               "<-- Ext Data format\n");
+       for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
+               tx_desc = E1000_TX_DESC(*tx_ring, i);
+               buffer_info = &tx_ring->buffer_info[i];
+               u0 = (struct my_u0 *)tx_desc;
+               printk(KERN_INFO "T%c[0x%03X]    %016llX %016llX %016llX "
+                       "%04X  %3X %016llX %p",
+                      (!(le64_to_cpu(u0->b) & (1<<29)) ? 'l' :
+                       ((le64_to_cpu(u0->b) & (1<<20)) ? 'd' : 'c')), i,
+                      le64_to_cpu(u0->a), le64_to_cpu(u0->b),
+                      (u64)buffer_info->dma, buffer_info->length,
+                      buffer_info->next_to_watch, (u64)buffer_info->time_stamp,
+                      buffer_info->skb);
+               if (i == tx_ring->next_to_use && i == tx_ring->next_to_clean)
+                       printk(KERN_CONT " NTC/U\n");
+               else if (i == tx_ring->next_to_use)
+                       printk(KERN_CONT " NTU\n");
+               else if (i == tx_ring->next_to_clean)
+                       printk(KERN_CONT " NTC\n");
+               else
+                       printk(KERN_CONT "\n");
+               if (netif_msg_pktdata(adapter) && buffer_info->dma != 0)
+                       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS,
+                                       16, 1, phys_to_virt(buffer_info->dma),
+                                       buffer_info->length, true);
+       }
+       /* Print RX Rings Summary */
+ rx_ring_summary:
+       dev_info(&adapter->pdev->dev, "RX Rings Summary\n");
+       printk(KERN_INFO "Queue [NTU] [NTC]\n");
+       printk(KERN_INFO " %5d %5X %5X\n", 0,
+               rx_ring->next_to_use, rx_ring->next_to_clean);
+       /* Print RX Rings */
+       if (!netif_msg_rx_status(adapter))
+               goto exit;
+       dev_info(&adapter->pdev->dev, "RX Rings Dump\n");
+       switch (adapter->rx_ps_pages) {
+       case 1:
+       case 2:
+       case 3:
+               /* [Extended] Packet Split Receive Descriptor Format
+                *
+                *    +-----------------------------------------------------+
+                *  0 |                Buffer Address 0 [63:0]              |
+                *    +-----------------------------------------------------+
+                *  8 |                Buffer Address 1 [63:0]              |
+                *    +-----------------------------------------------------+
+                * 16 |                Buffer Address 2 [63:0]              |
+                *    +-----------------------------------------------------+
+                * 24 |                Buffer Address 3 [63:0]              |
+                *    +-----------------------------------------------------+
+                */
+               printk(KERN_INFO "R  [desc]      [buffer 0 63:0 ] "
+                       "[buffer 1 63:0 ] "
+                      "[buffer 2 63:0 ] [buffer 3 63:0 ] [bi->dma       ] "
+                      "[bi->skb] <-- Ext Pkt Split format\n");
+               /* [Extended] Receive Descriptor (Write-Back) Format
+                *
+                *   63       48 47    32 31     13 12    8 7    4 3        0
+                *   +------------------------------------------------------+
+                * 0 | Packet   | IP     |  Rsvd   | MRQ   | Rsvd | MRQ RSS |
+                *   | Checksum | Ident  |         | Queue |      |  Type   |
+                *   +------------------------------------------------------+
+                * 8 | VLAN Tag | Length | Extended Error | Extended Status |
+                *   +------------------------------------------------------+
+                *   63       48 47    32 31            20 19               0
+                */
+               printk(KERN_INFO "RWB[desc]      [ck ipid mrqhsh] "
+                       "[vl   l0 ee  es] "
+                      "[ l3  l2  l1 hs] [reserved      ] ---------------- "
+                      "[bi->skb] <-- Ext Rx Write-Back format\n");
+               for (i = 0; i < rx_ring->count; i++) {
+                       buffer_info = &rx_ring->buffer_info[i];
+                       rx_desc_ps = E1000_RX_DESC_PS(*rx_ring, i);
+                       u1 = (struct my_u1 *)rx_desc_ps;
+                       staterr =
+                               le32_to_cpu(rx_desc_ps->wb.middle.status_error);
+                       if (staterr & E1000_RXD_STAT_DD) {
+                               /* Descriptor Done */
+                               printk(KERN_INFO "RWB[0x%03X]     %016llX "
+                                       "%016llX %016llX %016llX "
+                                       "---------------- %p", i,
+                                       le64_to_cpu(u1->a),
+                                       le64_to_cpu(u1->b),
+                                       le64_to_cpu(u1->c),
+                                       le64_to_cpu(u1->d),
+                                       buffer_info->skb);
+                       } else {
+                               printk(KERN_INFO "R  [0x%03X]     %016llX "
+                                       "%016llX %016llX %016llX %016llX %p", i,
+                                       le64_to_cpu(u1->a),
+                                       le64_to_cpu(u1->b),
+                                       le64_to_cpu(u1->c),
+                                       le64_to_cpu(u1->d),
+                                       (u64)buffer_info->dma,
+                                       buffer_info->skb);
+                               if (netif_msg_pktdata(adapter))
+                                       print_hex_dump(KERN_INFO, "",
+                                               DUMP_PREFIX_ADDRESS, 16, 1,
+                                               phys_to_virt(buffer_info->dma),
+                                               adapter->rx_ps_bsize0, true);
+                       }
+                       if (i == rx_ring->next_to_use)
+                               printk(KERN_CONT " NTU\n");
+                       else if (i == rx_ring->next_to_clean)
+                               printk(KERN_CONT " NTC\n");
+                       else
+                               printk(KERN_CONT "\n");
+               }
+               break;
+       default:
+       case 0:
+               /* Legacy Receive Descriptor Format
+                *
+                * +-----------------------------------------------------+
+                * |                Buffer Address [63:0]                |
+                * +-----------------------------------------------------+
+                * | VLAN Tag | Errors | Status 0 | Packet csum | Length |
+                * +-----------------------------------------------------+
+                * 63       48 47    40 39      32 31         16 15      0
+                */
+               printk(KERN_INFO "Rl[desc]     [address 63:0  ] "
+                       "[vl er S cks ln] [bi->dma       ] [bi->skb] "
+                       "<-- Legacy format\n");
+               for (i = 0; rx_ring->desc && (i < rx_ring->count); i++) {
+                       rx_desc = E1000_RX_DESC(*rx_ring, i);
+                       buffer_info = &rx_ring->buffer_info[i];
+                       u0 = (struct my_u0 *)rx_desc;
+                       printk(KERN_INFO "Rl[0x%03X]    %016llX %016llX "
+                               "%016llX %p",
+                               i, le64_to_cpu(u0->a), le64_to_cpu(u0->b),
+                               (u64)buffer_info->dma, buffer_info->skb);
+                       if (i == rx_ring->next_to_use)
+                               printk(KERN_CONT " NTU\n");
+                       else if (i == rx_ring->next_to_clean)
+                               printk(KERN_CONT " NTC\n");
+                       else
+                               printk(KERN_CONT "\n");
+                       if (netif_msg_pktdata(adapter))
+                               print_hex_dump(KERN_INFO, "",
+                                       DUMP_PREFIX_ADDRESS,
+                                       16, 1, phys_to_virt(buffer_info->dma),
+                                       adapter->rx_buffer_len, true);
+               }
+       }
+ exit:
+       return;
+ }
  /**
   * e1000_desc_unused - calculate if we have unused descriptors
   **/
@@@ -178,10 -536,10 +536,10 @@@ static void e1000_alloc_rx_buffers(stru
  
                buffer_info->skb = skb;
  map_skb:
-               buffer_info->dma = pci_map_single(pdev, skb->data,
+               buffer_info->dma = dma_map_single(&pdev->dev, skb->data,
                                                  adapter->rx_buffer_len,
-                                                 PCI_DMA_FROMDEVICE);
-               if (pci_dma_mapping_error(pdev, buffer_info->dma)) {
+                                                 DMA_FROM_DEVICE);
+               if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
                        dev_err(&pdev->dev, "RX DMA map failed\n");
                        adapter->rx_dma_failed++;
                        break;
                rx_desc = E1000_RX_DESC(*rx_ring, i);
                rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
  
+               if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) {
+                       /*
+                        * Force memory writes to complete before letting h/w
+                        * know there are new descriptors to fetch.  (Only
+                        * applicable for weak-ordered memory model archs,
+                        * such as IA-64).
+                        */
+                       wmb();
+                       writel(i, adapter->hw.hw_addr + rx_ring->tail);
+               }
                i++;
                if (i == rx_ring->count)
                        i = 0;
                buffer_info = &rx_ring->buffer_info[i];
        }
  
-       if (rx_ring->next_to_use != i) {
-               rx_ring->next_to_use = i;
-               if (i-- == 0)
-                       i = (rx_ring->count - 1);
-               /*
-                * Force memory writes to complete before letting h/w
-                * know there are new descriptors to fetch.  (Only
-                * applicable for weak-ordered memory model archs,
-                * such as IA-64).
-                */
-               wmb();
-               writel(i, adapter->hw.hw_addr + rx_ring->tail);
-       }
+       rx_ring->next_to_use = i;
  }
  
  /**
@@@ -247,11 -602,12 +602,12 @@@ static void e1000_alloc_rx_buffers_ps(s
                                        adapter->alloc_rx_buff_failed++;
                                        goto no_buffers;
                                }
-                               ps_page->dma = pci_map_page(pdev,
-                                                  ps_page->page,
-                                                  0, PAGE_SIZE,
-                                                  PCI_DMA_FROMDEVICE);
-                               if (pci_dma_mapping_error(pdev, ps_page->dma)) {
+                               ps_page->dma = dma_map_page(&pdev->dev,
+                                                           ps_page->page,
+                                                           0, PAGE_SIZE,
+                                                           DMA_FROM_DEVICE);
+                               if (dma_mapping_error(&pdev->dev,
+                                                     ps_page->dma)) {
                                        dev_err(&adapter->pdev->dev,
                                          "RX DMA page map failed\n");
                                        adapter->rx_dma_failed++;
                }
  
                buffer_info->skb = skb;
-               buffer_info->dma = pci_map_single(pdev, skb->data,
+               buffer_info->dma = dma_map_single(&pdev->dev, skb->data,
                                                  adapter->rx_ps_bsize0,
-                                                 PCI_DMA_FROMDEVICE);
-               if (pci_dma_mapping_error(pdev, buffer_info->dma)) {
+                                                 DMA_FROM_DEVICE);
+               if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
                        dev_err(&pdev->dev, "RX DMA map failed\n");
                        adapter->rx_dma_failed++;
                        /* cleanup skb */
  
                rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma);
  
+               if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) {
+                       /*
+                        * Force memory writes to complete before letting h/w
+                        * know there are new descriptors to fetch.  (Only
+                        * applicable for weak-ordered memory model archs,
+                        * such as IA-64).
+                        */
+                       wmb();
+                       writel(i<<1, adapter->hw.hw_addr + rx_ring->tail);
+               }
                i++;
                if (i == rx_ring->count)
                        i = 0;
        }
  
  no_buffers:
-       if (rx_ring->next_to_use != i) {
-               rx_ring->next_to_use = i;
-               if (!(i--))
-                       i = (rx_ring->count - 1);
-               /*
-                * Force memory writes to complete before letting h/w
-                * know there are new descriptors to fetch.  (Only
-                * applicable for weak-ordered memory model archs,
-                * such as IA-64).
-                */
-               wmb();
-               /*
-                * Hardware increments by 16 bytes, but packet split
-                * descriptors are 32 bytes...so we increment tail
-                * twice as much.
-                */
-               writel(i<<1, adapter->hw.hw_addr + rx_ring->tail);
-       }
+       rx_ring->next_to_use = i;
  }
  
  /**
@@@ -366,10 -714,10 +714,10 @@@ check_page
                }
  
                if (!buffer_info->dma)
-                       buffer_info->dma = pci_map_page(pdev,
+                       buffer_info->dma = dma_map_page(&pdev->dev,
                                                        buffer_info->page, 0,
                                                        PAGE_SIZE,
-                                                       PCI_DMA_FROMDEVICE);
+                                                       DMA_FROM_DEVICE);
  
                rx_desc = E1000_RX_DESC(*rx_ring, i);
                rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
@@@ -443,10 -791,10 +791,10 @@@ static bool e1000_clean_rx_irq(struct e
  
                cleaned = 1;
                cleaned_count++;
-               pci_unmap_single(pdev,
+               dma_unmap_single(&pdev->dev,
                                 buffer_info->dma,
                                 adapter->rx_buffer_len,
-                                PCI_DMA_FROMDEVICE);
+                                DMA_FROM_DEVICE);
                buffer_info->dma = 0;
  
                length = le16_to_cpu(rx_desc->length);
@@@ -547,12 -895,11 +895,11 @@@ static void e1000_put_txbuf(struct e100
  {
        if (buffer_info->dma) {
                if (buffer_info->mapped_as_page)
-                       pci_unmap_page(adapter->pdev, buffer_info->dma,
-                                      buffer_info->length, PCI_DMA_TODEVICE);
+                       dma_unmap_page(&adapter->pdev->dev, buffer_info->dma,
+                                      buffer_info->length, DMA_TO_DEVICE);
                else
-                       pci_unmap_single(adapter->pdev, buffer_info->dma,
-                                        buffer_info->length,
-                                        PCI_DMA_TODEVICE);
+                       dma_unmap_single(&adapter->pdev->dev, buffer_info->dma,
+                                        buffer_info->length, DMA_TO_DEVICE);
                buffer_info->dma = 0;
        }
        if (buffer_info->skb) {
@@@ -643,14 -990,8 +990,8 @@@ static bool e1000_clean_tx_irq(struct e
                        cleaned = (i == eop);
  
                        if (cleaned) {
-                               struct sk_buff *skb = buffer_info->skb;
-                               unsigned int segs, bytecount;
-                               segs = skb_shinfo(skb)->gso_segs ?: 1;
-                               /* multiply data chunks by size of headers */
-                               bytecount = ((segs - 1) * skb_headlen(skb)) +
-                                           skb->len;
-                               total_tx_packets += segs;
-                               total_tx_bytes += bytecount;
+                               total_tx_packets += buffer_info->segs;
+                               total_tx_bytes += buffer_info->bytecount;
                        }
  
                        e1000_put_txbuf(adapter, buffer_info);
@@@ -753,9 -1094,9 +1094,9 @@@ static bool e1000_clean_rx_irq_ps(struc
  
                cleaned = 1;
                cleaned_count++;
-               pci_unmap_single(pdev, buffer_info->dma,
+               dma_unmap_single(&pdev->dev, buffer_info->dma,
                                 adapter->rx_ps_bsize0,
-                                PCI_DMA_FROMDEVICE);
+                                DMA_FROM_DEVICE);
                buffer_info->dma = 0;
  
                /* see !EOP comment in other rx routine */
                         * kmap_atomic, so we can't hold the mapping
                         * very long
                         */
-                       pci_dma_sync_single_for_cpu(pdev, ps_page->dma,
-                               PAGE_SIZE, PCI_DMA_FROMDEVICE);
+                       dma_sync_single_for_cpu(&pdev->dev, ps_page->dma,
+                                               PAGE_SIZE, DMA_FROM_DEVICE);
                        vaddr = kmap_atomic(ps_page->page, KM_SKB_DATA_SOFTIRQ);
                        memcpy(skb_tail_pointer(skb), vaddr, l1);
                        kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ);
-                       pci_dma_sync_single_for_device(pdev, ps_page->dma,
-                               PAGE_SIZE, PCI_DMA_FROMDEVICE);
+                       dma_sync_single_for_device(&pdev->dev, ps_page->dma,
+                                                  PAGE_SIZE, DMA_FROM_DEVICE);
  
                        /* remove the CRC */
                        if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
                                break;
  
                        ps_page = &buffer_info->ps_pages[j];
-                       pci_unmap_page(pdev, ps_page->dma, PAGE_SIZE,
-                                      PCI_DMA_FROMDEVICE);
+                       dma_unmap_page(&pdev->dev, ps_page->dma, PAGE_SIZE,
+                                      DMA_FROM_DEVICE);
                        ps_page->dma = 0;
                        skb_fill_page_desc(skb, j, ps_page->page, 0, length);
                        ps_page->page = NULL;
@@@ -953,8 -1294,8 +1294,8 @@@ static bool e1000_clean_jumbo_rx_irq(st
  
                cleaned = true;
                cleaned_count++;
-               pci_unmap_page(pdev, buffer_info->dma, PAGE_SIZE,
-                              PCI_DMA_FROMDEVICE);
+               dma_unmap_page(&pdev->dev, buffer_info->dma, PAGE_SIZE,
+                              DMA_FROM_DEVICE);
                buffer_info->dma = 0;
  
                length = le16_to_cpu(rx_desc->length);
@@@ -1090,17 -1431,17 +1431,17 @@@ static void e1000_clean_rx_ring(struct 
                buffer_info = &rx_ring->buffer_info[i];
                if (buffer_info->dma) {
                        if (adapter->clean_rx == e1000_clean_rx_irq)
-                               pci_unmap_single(pdev, buffer_info->dma,
+                               dma_unmap_single(&pdev->dev, buffer_info->dma,
                                                 adapter->rx_buffer_len,
-                                                PCI_DMA_FROMDEVICE);
+                                                DMA_FROM_DEVICE);
                        else if (adapter->clean_rx == e1000_clean_jumbo_rx_irq)
-                               pci_unmap_page(pdev, buffer_info->dma,
+                               dma_unmap_page(&pdev->dev, buffer_info->dma,
                                               PAGE_SIZE,
-                                              PCI_DMA_FROMDEVICE);
+                                              DMA_FROM_DEVICE);
                        else if (adapter->clean_rx == e1000_clean_rx_irq_ps)
-                               pci_unmap_single(pdev, buffer_info->dma,
+                               dma_unmap_single(&pdev->dev, buffer_info->dma,
                                                 adapter->rx_ps_bsize0,
-                                                PCI_DMA_FROMDEVICE);
+                                                DMA_FROM_DEVICE);
                        buffer_info->dma = 0;
                }
  
                        ps_page = &buffer_info->ps_pages[j];
                        if (!ps_page->page)
                                break;
-                       pci_unmap_page(pdev, ps_page->dma, PAGE_SIZE,
-                                      PCI_DMA_FROMDEVICE);
+                       dma_unmap_page(&pdev->dev, ps_page->dma, PAGE_SIZE,
+                                      DMA_FROM_DEVICE);
                        ps_page->dma = 0;
                        put_page(ps_page->page);
                        ps_page->page = NULL;
@@@ -1426,8 -1767,6 +1767,6 @@@ void e1000e_reset_interrupt_capability(
                pci_disable_msi(adapter->pdev);
                adapter->flags &= ~FLAG_MSI_ENABLED;
        }
-       return;
  }
  
  /**
@@@ -1479,8 -1818,6 +1818,6 @@@ void e1000e_set_interrupt_capability(st
                /* Don't do anything; this is the system default */
                break;
        }
-       return;
  }
  
  /**
@@@ -2185,10 -2522,10 +2522,10 @@@ static void e1000_restore_vlan(struct e
        }
  }
  
- static void e1000_init_manageability(struct e1000_adapter *adapter)
+ static void e1000_init_manageability_pt(struct e1000_adapter *adapter)
  {
        struct e1000_hw *hw = &adapter->hw;
-       u32 manc, manc2h;
+       u32 manc, manc2h, mdef, i, j;
  
        if (!(adapter->flags & FLAG_MNG_PT_ENABLED))
                return;
         */
        manc |= E1000_MANC_EN_MNG2HOST;
        manc2h = er32(MANC2H);
- #define E1000_MNG2HOST_PORT_623 (1 << 5)
- #define E1000_MNG2HOST_PORT_664 (1 << 6)
-       manc2h |= E1000_MNG2HOST_PORT_623;
-       manc2h |= E1000_MNG2HOST_PORT_664;
+       switch (hw->mac.type) {
+       default:
+               manc2h |= (E1000_MANC2H_PORT_623 | E1000_MANC2H_PORT_664);
+               break;
+       case e1000_82574:
+       case e1000_82583:
+               /*
+                * Check if IPMI pass-through decision filter already exists;
+                * if so, enable it.
+                */
+               for (i = 0, j = 0; i < 8; i++) {
+                       mdef = er32(MDEF(i));
+                       /* Ignore filters with anything other than IPMI ports */
+                       if (mdef & !(E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664))
+                               continue;
+                       /* Enable this decision filter in MANC2H */
+                       if (mdef)
+                               manc2h |= (1 << i);
+                       j |= mdef;
+               }
+               if (j == (E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664))
+                       break;
+               /* Create new decision filter in an empty filter */
+               for (i = 0, j = 0; i < 8; i++)
+                       if (er32(MDEF(i)) == 0) {
+                               ew32(MDEF(i), (E1000_MDEF_PORT_623 |
+                                              E1000_MDEF_PORT_664));
+                               manc2h |= (1 << 1);
+                               j++;
+                               break;
+                       }
+               if (!j)
+                       e_warn("Unable to create IPMI pass-through filter\n");
+               break;
+       }
        ew32(MANC2H, manc2h);
        ew32(MANC, manc);
  }
@@@ -2524,12 -2900,12 +2900,12 @@@ static void e1000_configure_rx(struct e
                         * excessive C-state transition latencies result in
                         * dropped transactions.
                         */
 -                      pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY,
 -                                                adapter->netdev->name, 55);
 +                      pm_qos_update_request(
 +                              adapter->netdev->pm_qos_req, 55);
                } else {
 -                      pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY,
 -                                                adapter->netdev->name,
 -                                                PM_QOS_DEFAULT_VALUE);
 +                      pm_qos_update_request(
 +                              adapter->netdev->pm_qos_req,
 +                              PM_QOS_DEFAULT_VALUE);
                }
        }
  
@@@ -2565,7 -2941,7 +2941,7 @@@ static void e1000_set_multi(struct net_
  {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
-       struct dev_mc_list *mc_ptr;
+       struct netdev_hw_addr *ha;
        u8  *mta_list;
        u32 rctl;
        int i;
  
                /* prepare a packed array of only addresses. */
                i = 0;
-               netdev_for_each_mc_addr(mc_ptr, netdev)
-                       memcpy(mta_list + (i++ * ETH_ALEN),
-                              mc_ptr->dmi_addr, ETH_ALEN);
+               netdev_for_each_mc_addr(ha, netdev)
+                       memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN);
  
                e1000_update_mc_addr_list(hw, mta_list, i);
                kfree(mta_list);
@@@ -2621,7 -2996,7 +2996,7 @@@ static void e1000_configure(struct e100
        e1000_set_multi(adapter->netdev);
  
        e1000_restore_vlan(adapter);
-       e1000_init_manageability(adapter);
+       e1000_init_manageability_pt(adapter);
  
        e1000_configure_tx(adapter);
        e1000_setup_rctl(adapter);
@@@ -2755,6 -3130,7 +3130,7 @@@ void e1000e_reset(struct e1000_adapter 
                        fc->high_water = 0x5000;
                        fc->low_water  = 0x3000;
                }
+               fc->refresh_time = 0x1000;
        } else {
                if ((adapter->flags & FLAG_HAS_ERT) &&
                    (adapter->netdev->mtu > ETH_DATA_LEN))
        if (mac->ops.init_hw(hw))
                e_err("Hardware Error\n");
  
-       /* additional part of the flow-control workaround above */
-       if (hw->mac.type == e1000_pchlan)
-               ew32(FCRTV_PCH, 0x1000);
        e1000_update_mng_vlan(adapter);
  
        /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
@@@ -2824,8 -3196,8 +3196,8 @@@ int e1000e_up(struct e1000_adapter *ada
  
        /* DMA latency requirement to workaround early-receive/jumbo issue */
        if (adapter->flags & FLAG_HAS_ERT)
 -              pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY,
 -                                     adapter->netdev->name,
 +              adapter->netdev->pm_qos_req =
 +                      pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
                                       PM_QOS_DEFAULT_VALUE);
  
        /* hardware has been reset, we need to reload some things */
        netif_wake_queue(adapter->netdev);
  
        /* fire a link change interrupt to start the watchdog */
-       ew32(ICS, E1000_ICS_LSC);
+       if (adapter->msix_entries)
+               ew32(ICS, E1000_ICS_LSC | E1000_ICR_OTHER);
+       else
+               ew32(ICS, E1000_ICS_LSC);
        return 0;
  }
  
@@@ -2887,11 -3263,9 +3263,11 @@@ void e1000e_down(struct e1000_adapter *
        e1000_clean_tx_ring(adapter);
        e1000_clean_rx_ring(adapter);
  
 -      if (adapter->flags & FLAG_HAS_ERT)
 -              pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
 -                                        adapter->netdev->name);
 +      if (adapter->flags & FLAG_HAS_ERT) {
 +              pm_qos_remove_request(
 +                            adapter->netdev->pm_qos_req);
 +              adapter->netdev->pm_qos_req = NULL;
 +      }
  
        /*
         * TODO: for power management, we could drop the link and
@@@ -3085,12 -3459,15 +3461,15 @@@ static int e1000_open(struct net_devic
  {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
+       struct pci_dev *pdev = adapter->pdev;
        int err;
  
        /* disallow open during test */
        if (test_bit(__E1000_TESTING, &adapter->state))
                return -EBUSY;
  
+       pm_runtime_get_sync(&pdev->dev);
        netif_carrier_off(netdev);
  
        /* allocate transmit descriptors */
        if (err)
                goto err_setup_rx;
  
+       /*
+        * If AMT is enabled, let the firmware know that the network
+        * interface is now open and reset the part to a known state.
+        */
+       if (adapter->flags & FLAG_HAS_AMT) {
+               e1000_get_hw_control(adapter);
+               e1000e_reset(adapter);
+       }
        e1000e_power_up_phy(adapter);
  
        adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
                e1000_update_mng_vlan(adapter);
  
        /*
-        * If AMT is enabled, let the firmware know that the network
-        * interface is now open
-        */
-       if (adapter->flags & FLAG_HAS_AMT)
-               e1000_get_hw_control(adapter);
-       /*
         * before we allocate an interrupt, we must be ready to handle it.
         * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
         * as soon as we call pci_request_irq, so we have to setup our
  
        netif_start_queue(netdev);
  
+       adapter->idle_check = true;
+       pm_runtime_put(&pdev->dev);
        /* fire a link status change interrupt to start the watchdog */
-       ew32(ICS, E1000_ICS_LSC);
+       if (adapter->msix_entries)
+               ew32(ICS, E1000_ICS_LSC | E1000_ICR_OTHER);
+       else
+               ew32(ICS, E1000_ICS_LSC);
  
        return 0;
  
@@@ -3164,6 -3549,7 +3551,7 @@@ err_setup_rx
        e1000e_free_tx_resources(adapter);
  err_setup_tx:
        e1000e_reset(adapter);
+       pm_runtime_put_sync(&pdev->dev);
  
        return err;
  }
  static int e1000_close(struct net_device *netdev)
  {
        struct e1000_adapter *adapter = netdev_priv(netdev);
+       struct pci_dev *pdev = adapter->pdev;
  
        WARN_ON(test_bit(__E1000_RESETTING, &adapter->state));
-       e1000e_down(adapter);
+       pm_runtime_get_sync(&pdev->dev);
+       if (!test_bit(__E1000_DOWN, &adapter->state)) {
+               e1000e_down(adapter);
+               e1000_free_irq(adapter);
+       }
        e1000_power_down_phy(adapter);
-       e1000_free_irq(adapter);
  
        e1000e_free_tx_resources(adapter);
        e1000e_free_rx_resources(adapter);
        if (adapter->flags & FLAG_HAS_AMT)
                e1000_release_hw_control(adapter);
  
+       pm_runtime_put_sync(&pdev->dev);
        return 0;
  }
  /**
@@@ -3552,6 -3946,9 +3948,9 @@@ static void e1000_watchdog_task(struct 
  
        link = e1000e_has_link(adapter);
        if ((netif_carrier_ok(netdev)) && link) {
+               /* Cancel scheduled suspend requests. */
+               pm_runtime_resume(netdev->dev.parent);
                e1000e_enable_receives(adapter);
                goto link_up;
        }
        if (link) {
                if (!netif_carrier_ok(netdev)) {
                        bool txb2b = 1;
+                       /* Cancel scheduled suspend requests. */
+                       pm_runtime_resume(netdev->dev.parent);
                        /* update snapshot of PHY registers on LSC */
                        e1000_phy_read_status(adapter);
                        mac->ops.get_link_up_info(&adapter->hw,
  
                        if (adapter->flags & FLAG_RX_NEEDS_RESTART)
                                schedule_work(&adapter->reset_task);
+                       else
+                               pm_schedule_suspend(netdev->dev.parent,
+                                                       LINK_TIMEOUT);
                }
        }
  
@@@ -3707,6 -4111,22 +4113,22 @@@ link_up
                }
        }
  
+       /* Simple mode for Interrupt Throttle Rate (ITR) */
+       if (adapter->itr_setting == 4) {
+               /*
+                * Symmetric Tx/Rx gets a reduced ITR=2000;
+                * Total asymmetrical Tx or Rx gets ITR=8000;
+                * everyone else is between 2000-8000.
+                */
+               u32 goc = (adapter->gotc + adapter->gorc) / 10000;
+               u32 dif = (adapter->gotc > adapter->gorc ?
+                           adapter->gotc - adapter->gorc :
+                           adapter->gorc - adapter->gotc) / 10000;
+               u32 itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000;
+               ew32(ITR, 1000000000 / (itr * 256));
+       }
        /* Cause software interrupt to ensure Rx ring is cleaned */
        if (adapter->msix_entries)
                ew32(ICS, adapter->rx_ring->ims_val);
@@@ -3881,7 -4301,7 +4303,7 @@@ static int e1000_tx_map(struct e1000_ad
        struct e1000_buffer *buffer_info;
        unsigned int len = skb_headlen(skb);
        unsigned int offset = 0, size, count = 0, i;
-       unsigned int f;
+       unsigned int f, bytecount, segs;
  
        i = tx_ring->next_to_use;
  
                buffer_info->length = size;
                buffer_info->time_stamp = jiffies;
                buffer_info->next_to_watch = i;
-               buffer_info->dma = pci_map_single(pdev, skb->data + offset,
-                                                 size, PCI_DMA_TODEVICE);
+               buffer_info->dma = dma_map_single(&pdev->dev,
+                                                 skb->data + offset,
+                                                 size, DMA_TO_DEVICE);
                buffer_info->mapped_as_page = false;
-               if (pci_dma_mapping_error(pdev, buffer_info->dma))
+               if (dma_mapping_error(&pdev->dev, buffer_info->dma))
                        goto dma_error;
  
                len -= size;
                        buffer_info->length = size;
                        buffer_info->time_stamp = jiffies;
                        buffer_info->next_to_watch = i;
-                       buffer_info->dma = pci_map_page(pdev, frag->page,
+                       buffer_info->dma = dma_map_page(&pdev->dev, frag->page,
                                                        offset, size,
-                                                       PCI_DMA_TODEVICE);
+                                                       DMA_TO_DEVICE);
                        buffer_info->mapped_as_page = true;
-                       if (pci_dma_mapping_error(pdev, buffer_info->dma))
+                       if (dma_mapping_error(&pdev->dev, buffer_info->dma))
                                goto dma_error;
  
                        len -= size;
                }
        }
  
+       segs = skb_shinfo(skb)->gso_segs ?: 1;
+       /* multiply data chunks by size of headers */
+       bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len;
        tx_ring->buffer_info[i].skb = skb;
+       tx_ring->buffer_info[i].segs = segs;
+       tx_ring->buffer_info[i].bytecount = bytecount;
        tx_ring->buffer_info[first].next_to_watch = i;
  
        return count;
@@@ -4107,7 -4534,7 +4536,7 @@@ static netdev_tx_t e1000_xmit_frame(str
        unsigned int max_per_txd = E1000_MAX_PER_TXD;
        unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
        unsigned int tx_flags = 0;
-       unsigned int len = skb->len - skb->data_len;
+       unsigned int len = skb_headlen(skb);
        unsigned int nr_frags;
        unsigned int mss;
        int count = 0;
                                dev_kfree_skb_any(skb);
                                return NETDEV_TX_OK;
                        }
-                       len = skb->len - skb->data_len;
+                       len = skb_headlen(skb);
                }
        }
  
@@@ -4243,6 -4670,8 +4672,8 @@@ static void e1000_reset_task(struct wor
        struct e1000_adapter *adapter;
        adapter = container_of(work, struct e1000_adapter, reset_task);
  
+       e1000e_dump(adapter);
+       e_err("Reset adapter\n");
        e1000e_reinit_locked(adapter);
  }
  
        return retval;
  }
  
- static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
+ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
+                           bool runtime)
  {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
        u32 ctrl, ctrl_ext, rctl, status;
-       u32 wufc = adapter->wol;
+       /* Runtime suspend should only enable wakeup for link changes */
+       u32 wufc = runtime ? E1000_WUFC_LNKC : adapter->wol;
        int retval = 0;
  
        netif_device_detach(netdev);
@@@ -4653,20 -5084,13 +5086,13 @@@ void e1000e_disable_aspm(struct pci_de
        __e1000e_disable_aspm(pdev, state);
  }
  
- #ifdef CONFIG_PM
- static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
+ #ifdef CONFIG_PM_OPS
+ static bool e1000e_pm_ready(struct e1000_adapter *adapter)
  {
-       int retval;
-       bool wake;
-       retval = __e1000_shutdown(pdev, &wake);
-       if (!retval)
-               e1000_complete_shutdown(pdev, true, wake);
-       return retval;
+       return !!adapter->tx_ring->buffer_info;
  }
  
- static int e1000_resume(struct pci_dev *pdev)
+ static int __e1000_resume(struct pci_dev *pdev)
  {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
        if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1)
                e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1);
  
-       err = pci_enable_device_mem(pdev);
-       if (err) {
-               dev_err(&pdev->dev,
-                       "Cannot enable PCI device from suspend\n");
-               return err;
-       }
-       pci_set_master(pdev);
-       pci_enable_wake(pdev, PCI_D3hot, 0);
-       pci_enable_wake(pdev, PCI_D3cold, 0);
        e1000e_set_interrupt_capability(adapter);
        if (netif_running(netdev)) {
                err = e1000_request_irq(adapter);
  
        e1000e_reset(adapter);
  
-       e1000_init_manageability(adapter);
+       e1000_init_manageability_pt(adapter);
  
        if (netif_running(netdev))
                e1000e_up(adapter);
  
        return 0;
  }
- #endif
+ #ifdef CONFIG_PM_SLEEP
+ static int e1000_suspend(struct device *dev)
+ {
+       struct pci_dev *pdev = to_pci_dev(dev);
+       int retval;
+       bool wake;
+       retval = __e1000_shutdown(pdev, &wake, false);
+       if (!retval)
+               e1000_complete_shutdown(pdev, true, wake);
+       return retval;
+ }
+ static int e1000_resume(struct device *dev)
+ {
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct e1000_adapter *adapter = netdev_priv(netdev);
+       if (e1000e_pm_ready(adapter))
+               adapter->idle_check = true;
+       return __e1000_resume(pdev);
+ }
+ #endif /* CONFIG_PM_SLEEP */
+ #ifdef CONFIG_PM_RUNTIME
+ static int e1000_runtime_suspend(struct device *dev)
+ {
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct e1000_adapter *adapter = netdev_priv(netdev);
+       if (e1000e_pm_ready(adapter)) {
+               bool wake;
+               __e1000_shutdown(pdev, &wake, true);
+       }
+       return 0;
+ }
+ static int e1000_idle(struct device *dev)
+ {
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct e1000_adapter *adapter = netdev_priv(netdev);
+       if (!e1000e_pm_ready(adapter))
+               return 0;
+       if (adapter->idle_check) {
+               adapter->idle_check = false;
+               if (!e1000e_has_link(adapter))
+                       pm_schedule_suspend(dev, MSEC_PER_SEC);
+       }
+       return -EBUSY;
+ }
+ static int e1000_runtime_resume(struct device *dev)
+ {
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct e1000_adapter *adapter = netdev_priv(netdev);
+       if (!e1000e_pm_ready(adapter))
+               return 0;
+       adapter->idle_check = !dev->power.runtime_auto;
+       return __e1000_resume(pdev);
+ }
+ #endif /* CONFIG_PM_RUNTIME */
+ #endif /* CONFIG_PM_OPS */
  
  static void e1000_shutdown(struct pci_dev *pdev)
  {
        bool wake = false;
  
-       __e1000_shutdown(pdev, &wake);
+       __e1000_shutdown(pdev, &wake, false);
  
        if (system_state == SYSTEM_POWER_OFF)
                e1000_complete_shutdown(pdev, false, wake);
@@@ -4828,8 -5315,8 +5317,8 @@@ static pci_ers_result_t e1000_io_slot_r
                result = PCI_ERS_RESULT_DISCONNECT;
        } else {
                pci_set_master(pdev);
+               pdev->state_saved = true;
                pci_restore_state(pdev);
-               pci_save_state(pdev);
  
                pci_enable_wake(pdev, PCI_D3hot, 0);
                pci_enable_wake(pdev, PCI_D3cold, 0);
@@@ -4857,7 -5344,7 +5346,7 @@@ static void e1000_io_resume(struct pci_
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
  
-       e1000_init_manageability(adapter);
+       e1000_init_manageability_pt(adapter);
  
        if (netif_running(netdev)) {
                if (e1000e_up(adapter)) {
@@@ -4970,16 -5457,16 +5459,16 @@@ static int __devinit e1000_probe(struc
                return err;
  
        pci_using_dac = 0;
-       err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+       err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
        if (!err) {
-               err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+               err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
                if (!err)
                        pci_using_dac = 1;
        } else {
-               err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+               err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
                if (err) {
-                       err = pci_set_consistent_dma_mask(pdev,
-                                                         DMA_BIT_MASK(32));
+                       err = dma_set_coherent_mask(&pdev->dev,
+                                                   DMA_BIT_MASK(32));
                        if (err) {
                                dev_err(&pdev->dev, "No usable DMA "
                                        "configuration, aborting\n");
  
        SET_NETDEV_DEV(netdev, &pdev->dev);
  
+       netdev->irq = pdev->irq;
        pci_set_drvdata(pdev, netdev);
        adapter = netdev_priv(netdev);
        hw = &adapter->hw;
  
        e1000_print_device_info(adapter);
  
+       if (pci_dev_run_wake(pdev)) {
+               pm_runtime_set_active(&pdev->dev);
+               pm_runtime_enable(&pdev->dev);
+       }
+       pm_schedule_suspend(&pdev->dev, MSEC_PER_SEC);
        return 0;
  
  err_register:
@@@ -5272,12 -5767,16 +5769,16 @@@ static void __devexit e1000_remove(stru
  {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
+       bool down = test_bit(__E1000_DOWN, &adapter->state);
+       pm_runtime_get_sync(&pdev->dev);
  
        /*
         * flush_scheduled work may reschedule our watchdog task, so
         * explicitly disable watchdog tasks from being rescheduled
         */
-       set_bit(__E1000_DOWN, &adapter->state);
+       if (!down)
+               set_bit(__E1000_DOWN, &adapter->state);
        del_timer_sync(&adapter->watchdog_timer);
        del_timer_sync(&adapter->phy_info_timer);
  
        if (!(netdev->flags & IFF_UP))
                e1000_power_down_phy(adapter);
  
+       /* Don't lie to e1000_close() down the road. */
+       if (!down)
+               clear_bit(__E1000_DOWN, &adapter->state);
        unregister_netdev(netdev);
  
+       if (pci_dev_run_wake(pdev)) {
+               pm_runtime_disable(&pdev->dev);
+               pm_runtime_set_suspended(&pdev->dev);
+       }
+       pm_runtime_put_noidle(&pdev->dev);
        /*
         * Release control of h/w to f/w.  If f/w is AMT enabled, this
         * would have already happened in close and is redundant.
@@@ -5382,6 -5890,7 +5892,7 @@@ static DEFINE_PCI_DEVICE_TABLE(e1000_pc
  
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LM), board_ich10lan },
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LF), board_ich10lan },
+       { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_V), board_ich10lan },
  
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LM), board_pchlan },
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LC), board_pchlan },
  };
  MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
  
+ #ifdef CONFIG_PM_OPS
+ static const struct dev_pm_ops e1000_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(e1000_suspend, e1000_resume)
+       SET_RUNTIME_PM_OPS(e1000_runtime_suspend,
+                               e1000_runtime_resume, e1000_idle)
+ };
+ #endif
  /* PCI Device API Driver */
  static struct pci_driver e1000_driver = {
        .name     = e1000e_driver_name,
        .id_table = e1000_pci_tbl,
        .probe    = e1000_probe,
        .remove   = __devexit_p(e1000_remove),
- #ifdef CONFIG_PM
-       /* Power Management Hooks */
-       .suspend  = e1000_suspend,
-       .resume   = e1000_resume,
+ #ifdef CONFIG_PM_OPS
+       .driver.pm = &e1000_pm_ops,
  #endif
        .shutdown = e1000_shutdown,
        .err_handler = &e1000_err_handler
  static int __init e1000_init_module(void)
  {
        int ret;
-       printk(KERN_INFO "%s: Intel(R) PRO/1000 Network Driver - %s\n",
-              e1000e_driver_name, e1000e_driver_version);
-       printk(KERN_INFO "%s: Copyright (c) 1999 - 2009 Intel Corporation.\n",
-              e1000e_driver_name);
+       pr_info("Intel(R) PRO/1000 Network Driver - %s\n",
+               e1000e_driver_version);
+       pr_info("Copyright (c) 1999 - 2009 Intel Corporation.\n");
        ret = pci_register_driver(&e1000_driver);
  
        return ret;
@@@ -48,7 -48,6 +48,7 @@@
  #define DRV_VERSION "1.0.0-k0"
  char igbvf_driver_name[] = "igbvf";
  const char igbvf_driver_version[] = DRV_VERSION;
 +struct pm_qos_request_list *igbvf_driver_pm_qos_req;
  static const char igbvf_driver_string[] =
                                "Intel(R) Virtual Function Network Driver";
  static const char igbvf_copyright[] = "Copyright (c) 2009 Intel Corporation.";
@@@ -165,10 -164,10 +165,10 @@@ static void igbvf_alloc_rx_buffers(stru
                                buffer_info->page_offset ^= PAGE_SIZE / 2;
                        }
                        buffer_info->page_dma =
-                               pci_map_page(pdev, buffer_info->page,
+                               dma_map_page(&pdev->dev, buffer_info->page,
                                             buffer_info->page_offset,
                                             PAGE_SIZE / 2,
-                                            PCI_DMA_FROMDEVICE);
+                                            DMA_FROM_DEVICE);
                }
  
                if (!buffer_info->skb) {
                        }
  
                        buffer_info->skb = skb;
-                       buffer_info->dma = pci_map_single(pdev, skb->data,
+                       buffer_info->dma = dma_map_single(&pdev->dev, skb->data,
                                                          bufsz,
-                                                         PCI_DMA_FROMDEVICE);
+                                                         DMA_FROM_DEVICE);
                }
                /* Refresh the desc even if buffer_addrs didn't change because
                 * each write-back erases this info. */
@@@ -269,28 -268,28 +269,28 @@@ static bool igbvf_clean_rx_irq(struct i
                prefetch(skb->data - NET_IP_ALIGN);
                buffer_info->skb = NULL;
                if (!adapter->rx_ps_hdr_size) {
-                       pci_unmap_single(pdev, buffer_info->dma,
+                       dma_unmap_single(&pdev->dev, buffer_info->dma,
                                         adapter->rx_buffer_len,
-                                        PCI_DMA_FROMDEVICE);
+                                        DMA_FROM_DEVICE);
                        buffer_info->dma = 0;
                        skb_put(skb, length);
                        goto send_up;
                }
  
                if (!skb_shinfo(skb)->nr_frags) {
-                       pci_unmap_single(pdev, buffer_info->dma,
+                       dma_unmap_single(&pdev->dev, buffer_info->dma,
                                         adapter->rx_ps_hdr_size,
-                                        PCI_DMA_FROMDEVICE);
+                                        DMA_FROM_DEVICE);
                        skb_put(skb, hlen);
                }
  
                if (length) {
-                       pci_unmap_page(pdev, buffer_info->page_dma,
+                       dma_unmap_page(&pdev->dev, buffer_info->page_dma,
                                       PAGE_SIZE / 2,
-                                      PCI_DMA_FROMDEVICE);
+                                      DMA_FROM_DEVICE);
                        buffer_info->page_dma = 0;
  
-                       skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags++,
+                       skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
                                           buffer_info->page,
                                           buffer_info->page_offset,
                                           length);
@@@ -370,15 -369,15 +370,15 @@@ static void igbvf_put_txbuf(struct igbv
  {
        if (buffer_info->dma) {
                if (buffer_info->mapped_as_page)
-                       pci_unmap_page(adapter->pdev,
+                       dma_unmap_page(&adapter->pdev->dev,
                                       buffer_info->dma,
                                       buffer_info->length,
-                                      PCI_DMA_TODEVICE);
+                                      DMA_TO_DEVICE);
                else
-                       pci_unmap_single(adapter->pdev,
+                       dma_unmap_single(&adapter->pdev->dev,
                                         buffer_info->dma,
                                         buffer_info->length,
-                                        PCI_DMA_TODEVICE);
+                                        DMA_TO_DEVICE);
                buffer_info->dma = 0;
        }
        if (buffer_info->skb) {
@@@ -439,8 -438,8 +439,8 @@@ int igbvf_setup_tx_resources(struct igb
        tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
        tx_ring->size = ALIGN(tx_ring->size, 4096);
  
-       tx_ring->desc = pci_alloc_consistent(pdev, tx_ring->size,
-                                            &tx_ring->dma);
+       tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,
+                                          &tx_ring->dma, GFP_KERNEL);
  
        if (!tx_ring->desc)
                goto err;
@@@ -481,8 -480,8 +481,8 @@@ int igbvf_setup_rx_resources(struct igb
        rx_ring->size = rx_ring->count * desc_len;
        rx_ring->size = ALIGN(rx_ring->size, 4096);
  
-       rx_ring->desc = pci_alloc_consistent(pdev, rx_ring->size,
-                                            &rx_ring->dma);
+       rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
+                                          &rx_ring->dma, GFP_KERNEL);
  
        if (!rx_ring->desc)
                goto err;
@@@ -550,7 -549,8 +550,8 @@@ void igbvf_free_tx_resources(struct igb
        vfree(tx_ring->buffer_info);
        tx_ring->buffer_info = NULL;
  
-       pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma);
+       dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc,
+                         tx_ring->dma);
  
        tx_ring->desc = NULL;
  }
@@@ -575,13 -575,13 +576,13 @@@ static void igbvf_clean_rx_ring(struct 
                buffer_info = &rx_ring->buffer_info[i];
                if (buffer_info->dma) {
                        if (adapter->rx_ps_hdr_size){
-                               pci_unmap_single(pdev, buffer_info->dma,
+                               dma_unmap_single(&pdev->dev, buffer_info->dma,
                                                 adapter->rx_ps_hdr_size,
-                                                PCI_DMA_FROMDEVICE);
+                                                DMA_FROM_DEVICE);
                        } else {
-                               pci_unmap_single(pdev, buffer_info->dma,
+                               dma_unmap_single(&pdev->dev, buffer_info->dma,
                                                 adapter->rx_buffer_len,
-                                                PCI_DMA_FROMDEVICE);
+                                                DMA_FROM_DEVICE);
                        }
                        buffer_info->dma = 0;
                }
  
                if (buffer_info->page) {
                        if (buffer_info->page_dma)
-                               pci_unmap_page(pdev, buffer_info->page_dma,
+                               dma_unmap_page(&pdev->dev,
+                                              buffer_info->page_dma,
                                               PAGE_SIZE / 2,
-                                              PCI_DMA_FROMDEVICE);
+                                              DMA_FROM_DEVICE);
                        put_page(buffer_info->page);
                        buffer_info->page = NULL;
                        buffer_info->page_dma = 0;
@@@ -1399,7 -1400,7 +1401,7 @@@ static void igbvf_set_multi(struct net_
  {
        struct igbvf_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
-       struct dev_mc_list *mc_ptr;
+       struct netdev_hw_addr *ha;
        u8  *mta_list = NULL;
        int i;
  
  
        /* prepare a packed array of only addresses. */
        i = 0;
-       netdev_for_each_mc_addr(mc_ptr, netdev)
-               memcpy(mta_list + (i++ * ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN);
+       netdev_for_each_mc_addr(ha, netdev)
+               memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN);
  
        hw->mac.ops.update_mc_addr_list(hw, mta_list, i, 0, 0);
        kfree(mta_list);
@@@ -2105,9 -2106,9 +2107,9 @@@ static inline int igbvf_tx_map_adv(stru
        buffer_info->time_stamp = jiffies;
        buffer_info->next_to_watch = i;
        buffer_info->mapped_as_page = false;
-       buffer_info->dma = pci_map_single(pdev, skb->data, len,
-                                         PCI_DMA_TODEVICE);
-       if (pci_dma_mapping_error(pdev, buffer_info->dma))
+       buffer_info->dma = dma_map_single(&pdev->dev, skb->data, len,
+                                         DMA_TO_DEVICE);
+       if (dma_mapping_error(&pdev->dev, buffer_info->dma))
                goto dma_error;
  
  
                buffer_info->time_stamp = jiffies;
                buffer_info->next_to_watch = i;
                buffer_info->mapped_as_page = true;
-               buffer_info->dma = pci_map_page(pdev,
+               buffer_info->dma = dma_map_page(&pdev->dev,
                                                frag->page,
                                                frag->page_offset,
                                                len,
-                                               PCI_DMA_TODEVICE);
-               if (pci_dma_mapping_error(pdev, buffer_info->dma))
+                                               DMA_TO_DEVICE);
+               if (dma_mapping_error(&pdev->dev, buffer_info->dma))
                        goto dma_error;
        }
  
@@@ -2645,16 -2646,16 +2647,16 @@@ static int __devinit igbvf_probe(struc
                return err;
  
        pci_using_dac = 0;
-       err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+       err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
        if (!err) {
-               err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+               err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
                if (!err)
                        pci_using_dac = 1;
        } else {
-               err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+               err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
                if (err) {
-                       err = pci_set_consistent_dma_mask(pdev,
-                                                         DMA_BIT_MASK(32));
+                       err = dma_set_coherent_mask(&pdev->dev,
+                                                   DMA_BIT_MASK(32));
                        if (err) {
                                dev_err(&pdev->dev, "No usable DMA "
                                        "configuration, aborting\n");
@@@ -2900,7 -2901,7 +2902,7 @@@ static int __init igbvf_init_module(voi
        printk(KERN_INFO "%s\n", igbvf_copyright);
  
        ret = pci_register_driver(&igbvf_driver);
 -      pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, igbvf_driver_name,
 +      igbvf_driver_pm_qos_req = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
                               PM_QOS_DEFAULT_VALUE);
  
        return ret;
@@@ -2916,8 -2917,7 +2918,8 @@@ module_init(igbvf_init_module)
  static void __exit igbvf_exit_module(void)
  {
        pci_unregister_driver(&igbvf_driver);
 -      pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, igbvf_driver_name);
 +      pm_qos_remove_request(igbvf_driver_pm_qos_req);
 +      igbvf_driver_pm_qos_req = NULL;
  }
  module_exit(igbvf_exit_module);
  
@@@ -93,6 -93,7 +93,6 @@@ earlier 3Com products
  #include <pcmcia/cisreg.h>
  #include <pcmcia/ciscode.h>
  #include <pcmcia/ds.h>
 -#include <pcmcia/mem_op.h>
  
  #include <asm/uaccess.h>
  #include <asm/io.h>
@@@ -199,6 -200,7 +199,6 @@@ enum Window4 {             /* Window 4: Xcvr/medi
  
  struct el3_private {
        struct pcmcia_device    *p_dev;
 -      dev_node_t node;
        u16 advertising, partner;               /* NWay media advertisement */
        unsigned char phys;                     /* MII device address */
        unsigned int autoselect:1, default_media:3;     /* Read from the EEPROM/Wn3_Config. */
@@@ -281,6 -283,8 +281,6 @@@ static int tc574_probe(struct pcmcia_de
        spin_lock_init(&lp->window_lock);
        link->io.NumPorts1 = 32;
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
 -      link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
 -      link->irq.Handler = &el3_interrupt;
        link->conf.Attributes = CONF_ENABLE_IRQ;
        link->conf.IntType = INT_MEMORY_AND_IO;
        link->conf.ConfigIndex = 1;
@@@ -307,7 -311,8 +307,7 @@@ static void tc574_detach(struct pcmcia_
  
        dev_dbg(&link->dev, "3c574_detach()\n");
  
 -      if (link->dev_node)
 -              unregister_netdev(dev);
 +      unregister_netdev(dev);
  
        tc574_release(link);
  
@@@ -348,7 -353,7 +348,7 @@@ static int tc574_config(struct pcmcia_d
        if (i != 0)
                goto failed;
  
 -      ret = pcmcia_request_irq(link, &link->irq);
 +      ret = pcmcia_request_irq(link, el3_interrupt);
        if (ret)
                goto failed;
  
        if (ret)
                goto failed;
  
 -      dev->irq = link->irq.AssignedIRQ;
 +      dev->irq = link->irq;
        dev->base_addr = link->io.BasePort1;
  
        ioaddr = dev->base_addr;
                }
        }
  
 -      link->dev_node = &lp->node;
        SET_NETDEV_DEV(dev, &link->dev);
  
        if (register_netdev(dev) != 0) {
                printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
                goto failed;
        }
  
 -      strcpy(lp->node.dev_name, dev->name);
 -
        printk(KERN_INFO "%s: %s at io %#3lx, irq %d, "
               "hw_addr %pM.\n",
               dev->name, cardname, dev->base_addr, dev->irq,
@@@ -613,8 -622,6 +613,6 @@@ static void mdio_write(unsigned int ioa
                outw(MDIO_ENB_IN, mdio_addr);
                outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
        }
-       return;
  }
  
  /* Reset and restore all of the 3c574 registers. */
@@@ -730,7 -737,7 +728,7 @@@ static void el3_tx_timeout(struct net_d
        printk(KERN_NOTICE "%s: Transmit timed out!\n", dev->name);
        dump_status(dev);
        dev->stats.tx_errors++;
-       dev->trans_start = jiffies;
+       dev->trans_start = jiffies; /* prevent tx timeout */
        /* Issue TX_RESET and TX_START commands. */
        tc574_wait_for_completion(dev, TxReset);
        outw(TxEnable, ioaddr + EL3_CMD);
@@@ -781,8 -788,6 +779,6 @@@ static netdev_tx_t el3_start_xmit(struc
        /* ... and the packet rounded to a doubleword. */
        outsl(ioaddr + TX_FIFO, skb->data, (skb->len+3)>>2);
  
-       dev->trans_start = jiffies;
        /* TxFree appears only in Window 1, not offset 0x1c. */
        if (inw(ioaddr + TxFree) <= 1536) {
                netif_stop_queue(dev);
@@@ -1,20 -1,20 +1,20 @@@
  /*======================================================================
  
      A PCMCIA ethernet driver for the 3com 3c589 card.
-     
      Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
  
      3c589_cs.c 1.162 2001/10/13 00:08:50
  
      The network driver code is based on Donald Becker's 3c589 code:
-     
      Written 1994 by Donald Becker.
      Copyright 1993 United States Government as represented by the
      Director, National Security Agency.  This software may be used and
      distributed according to the terms of the GNU General Public License,
      incorporated herein by reference.
      Donald Becker may be reached at becker@scyld.com
-     
      Updated for 2.5.x by Alan Cox <alan@lxorguk.ukuu.org.uk>
  
  ======================================================================*/
  /* The top five bits written to EL3_CMD are a command, the lower
     11 bits are the parameter, if applicable. */
  enum c509cmd {
-     TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
-     RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11,
-     TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
-     FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
-     SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
-     SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11,
-     StatsDisable = 22<<11, StopCoax = 23<<11,
+       TotalReset      = 0<<11,
+       SelectWindow    = 1<<11,
+       StartCoax       = 2<<11,
+       RxDisable       = 3<<11,
+       RxEnable        = 4<<11,
+       RxReset         = 5<<11,
+       RxDiscard       = 8<<11,
+       TxEnable        = 9<<11,
+       TxDisable       = 10<<11,
+       TxReset         = 11<<11,
+       FakeIntr        = 12<<11,
+       AckIntr         = 13<<11,
+       SetIntrEnb      = 14<<11,
+       SetStatusEnb    = 15<<11,
+       SetRxFilter     = 16<<11,
+       SetRxThreshold  = 17<<11,
+       SetTxThreshold  = 18<<11,
+       SetTxStart      = 19<<11,
+       StatsEnable     = 21<<11,
+       StatsDisable    = 22<<11,
+       StopCoax        = 23<<11
  };
  
  enum c509status {
-     IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
-     TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
-     IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000
+       IntLatch        = 0x0001,
+       AdapterFailure  = 0x0002,
+       TxComplete      = 0x0004,
+       TxAvailable     = 0x0008,
+       RxComplete      = 0x0010,
+       RxEarly         = 0x0020,
+       IntReq          = 0x0040,
+       StatsFull       = 0x0080,
+       CmdBusy         = 0x1000
  };
  
  /* The SetRxFilter command accepts the following classes: */
  enum RxFilter {
-     RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
+       RxStation       = 1,
+       RxMulticast     = 2,
+       RxBroadcast     = 4,
+       RxProm          = 8
  };
  
  /* Register window 1 offsets, the window used in normal operation. */
  #define TX_FIFO               0x00
  #define RX_FIFO               0x00
- #define RX_STATUS     0x08
- #define TX_STATUS     0x0B
+ #define RX_STATUS     0x08
+ #define TX_STATUS     0x0B
  #define TX_FREE               0x0C    /* Remaining free bytes in Tx buffer. */
  
  #define WN0_IRQ               0x08    /* Window 0: Set IRQ line in bits 12-15. */
  
  struct el3_private {
        struct pcmcia_device    *p_dev;
-     /* For transceiver monitoring */
-     struct timer_list media;
-     u16                       media_status;
-     u16                       fast_poll;
-     unsigned long     last_irq;
-     spinlock_t                lock;
 -      dev_node_t              node;
+       /* For transceiver monitoring */
+       struct timer_list       media;
+       u16                     media_status;
+       u16                     fast_poll;
+       unsigned long           last_irq;
+       spinlock_t              lock;
  };
  
  static const char *if_names[] = { "auto", "10baseT", "10base2", "AUI" };
@@@ -163,15 -187,15 +186,15 @@@ static void tc589_detach(struct pcmcia_
  ======================================================================*/
  
  static const struct net_device_ops el3_netdev_ops = {
-       .ndo_open               = el3_open,
-       .ndo_stop               = el3_close,
+       .ndo_open               = el3_open,
+       .ndo_stop               = el3_close,
        .ndo_start_xmit         = el3_start_xmit,
-       .ndo_tx_timeout         = el3_tx_timeout,
+       .ndo_tx_timeout         = el3_tx_timeout,
        .ndo_set_config         = el3_config,
        .ndo_get_stats          = el3_get_stats,
        .ndo_set_multicast_list = set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
-       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
  };
  
@@@ -193,7 -217,8 +216,7 @@@ static int tc589_probe(struct pcmcia_de
      spin_lock_init(&lp->lock);
      link->io.NumPorts1 = 16;
      link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
 -    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
 -    link->irq.Handler = &el3_interrupt;
 +
      link->conf.Attributes = CONF_ENABLE_IRQ;
      link->conf.IntType = INT_MEMORY_AND_IO;
      link->conf.ConfigIndex = 1;
@@@ -221,7 -246,8 +244,7 @@@ static void tc589_detach(struct pcmcia_
  
      dev_dbg(&link->dev, "3c589_detach\n");
  
 -    if (link->dev_node)
 -      unregister_netdev(dev);
 +    unregister_netdev(dev);
  
      tc589_release(link);
  
      tc589_config() is scheduled to run after a CARD_INSERTION event
      is received, to configure the PCMCIA socket, and to make the
      ethernet device available to the system.
-     
  ======================================================================*/
  
  static int tc589_config(struct pcmcia_device *link)
  {
      struct net_device *dev = link->priv;
 -    struct el3_private *lp = netdev_priv(dev);
      __be16 *phys_addr;
      int ret, i, j, multi = 0, fifo;
      unsigned int ioaddr;
      char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
      u8 *buf;
      size_t len;
-     
      dev_dbg(&link->dev, "3c589_config\n");
  
      phys_addr = (__be16 *)dev->dev_addr;
      if (i != 0)
        goto failed;
  
 -    ret = pcmcia_request_irq(link, &link->irq);
 +    ret = pcmcia_request_irq(link, el3_interrupt);
      if (ret)
            goto failed;
  
      ret = pcmcia_request_configuration(link, &link->conf);
      if (ret)
            goto failed;
-       
 -    dev->irq = link->irq.AssignedIRQ;
 +    dev->irq = link->irq;
      dev->base_addr = link->io.BasePort1;
      ioaddr = dev->base_addr;
      EL3WINDOW(0);
        dev->if_port = if_port;
      else
        printk(KERN_ERR "3c589_cs: invalid if_port requested\n");
-     
 -    link->dev_node = &lp->node;
      SET_NETDEV_DEV(dev, &link->dev);
  
      if (register_netdev(dev) != 0) {
        printk(KERN_ERR "3c589_cs: register_netdev() failed\n");
        goto failed;
      }
  
-     printk(KERN_INFO "%s: 3Com 3c%s, io %#3lx, irq %d, "
-          "hw_addr %pM\n",
-          dev->name, (multi ? "562" : "589"), dev->base_addr, dev->irq,
-          dev->dev_addr);
-     printk(KERN_INFO "  %dK FIFO split %s Rx:Tx, %s xcvr\n",
-          (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3],
-          if_names[dev->if_port]);
 -    strcpy(lp->node.dev_name, dev->name);
 -
+     netdev_info(dev, "3Com 3c%s, io %#3lx, irq %d, hw_addr %pM\n",
+               (multi ? "562" : "589"), dev->base_addr, dev->irq,
+               dev->dev_addr);
+     netdev_info(dev, "  %dK FIFO split %s Rx:Tx, %s xcvr\n",
+               (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3],
+               if_names[dev->if_port]);
      return 0;
  
  failed:
      After a card is removed, tc589_release() will unregister the net
      device, and release the PCMCIA configuration.  If the device is
      still open, this will be postponed until it is closed.
-     
  ======================================================================*/
  
  static void tc589_release(struct pcmcia_device *link)
@@@ -357,7 -387,7 +379,7 @@@ static int tc589_resume(struct pcmcia_d
  {
        struct net_device *dev = link->priv;
  
-       if (link->open) {
+       if (link->open) {
                tc589_reset(dev);
                netif_device_attach(dev);
        }
@@@ -377,8 -407,7 +399,7 @@@ static void tc589_wait_for_completion(s
      while (--i > 0)
        if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000)) break;
      if (i == 0)
-       printk(KERN_WARNING "%s: command 0x%04x did not complete!\n",
-              dev->name, cmd);
+       netdev_warn(dev, "command 0x%04x did not complete!\n", cmd);
  }
  
  /*
@@@ -404,7 -433,7 +425,7 @@@ static void tc589_set_xcvr(struct net_d
  {
      struct el3_private *lp = netdev_priv(dev);
      unsigned int ioaddr = dev->base_addr;
-     
      EL3WINDOW(0);
      switch (if_port) {
      case 0: case 1: outw(0, ioaddr + 6); break;
@@@ -427,14 -456,13 +448,13 @@@ static void dump_status(struct net_devi
  {
      unsigned int ioaddr = dev->base_addr;
      EL3WINDOW(1);
-     printk(KERN_INFO "  irq status %04x, rx status %04x, tx status "
-          "%02x  tx free %04x\n", inw(ioaddr+EL3_STATUS),
-          inw(ioaddr+RX_STATUS), inb(ioaddr+TX_STATUS),
-          inw(ioaddr+TX_FREE));
+     netdev_info(dev, "  irq status %04x, rx status %04x, tx status %02x  tx free %04x\n",
+               inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS),
+               inb(ioaddr+TX_STATUS), inw(ioaddr+TX_FREE));
      EL3WINDOW(4);
-     printk(KERN_INFO "  diagnostics: fifo %04x net %04x ethernet %04x"
-          " media %04x\n", inw(ioaddr+0x04), inw(ioaddr+0x06),
-          inw(ioaddr+0x08), inw(ioaddr+0x0a));
+     netdev_info(dev, "  diagnostics: fifo %04x net %04x ethernet %04x media %04x\n",
+               inw(ioaddr+0x04), inw(ioaddr+0x06), inw(ioaddr+0x08),
+               inw(ioaddr+0x0a));
      EL3WINDOW(1);
  }
  
@@@ -443,18 -471,18 +463,18 @@@ static void tc589_reset(struct net_devi
  {
      unsigned int ioaddr = dev->base_addr;
      int i;
-     
      EL3WINDOW(0);
-     outw(0x0001, ioaddr + 4);                 /* Activate board. */ 
+     outw(0x0001, ioaddr + 4);                 /* Activate board. */
      outw(0x3f00, ioaddr + 8);                 /* Set the IRQ line. */
-     
      /* Set the station address in window 2. */
      EL3WINDOW(2);
      for (i = 0; i < 6; i++)
        outb(dev->dev_addr[i], ioaddr + i);
  
      tc589_set_xcvr(dev, dev->if_port);
-     
      /* Switch to the stats window, and clear all stats by reading. */
      outw(StatsDisable, ioaddr + EL3_CMD);
      EL3WINDOW(6);
        inb(ioaddr+i);
      inw(ioaddr + 10);
      inw(ioaddr + 12);
-     
      /* Switch to register set 1 for normal use. */
      EL3WINDOW(1);
  
@@@ -496,8 -524,7 +516,7 @@@ static int el3_config(struct net_devic
      if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
        if (map->port <= 3) {
            dev->if_port = map->port;
-           printk(KERN_INFO "%s: switched to %s port\n",
-                  dev->name, if_names[dev->if_port]);
+           netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]);
            tc589_set_xcvr(dev, dev->if_port);
        } else
            return -EINVAL;
@@@ -509,13 -536,13 +528,13 @@@ static int el3_open(struct net_device *
  {
      struct el3_private *lp = netdev_priv(dev);
      struct pcmcia_device *link = lp->p_dev;
-     
      if (!pcmcia_dev_present(link))
        return -ENODEV;
  
      link->open++;
      netif_start_queue(dev);
-     
      tc589_reset(dev);
      init_timer(&lp->media);
      lp->media.function = &media_check;
  
      dev_dbg(&link->dev, "%s: opened, status %4.4x.\n",
          dev->name, inw(dev->base_addr + EL3_STATUS));
-     
      return 0;
  }
  
  static void el3_tx_timeout(struct net_device *dev)
  {
      unsigned int ioaddr = dev->base_addr;
-     
-     printk(KERN_WARNING "%s: Transmit timed out!\n", dev->name);
+     netdev_warn(dev, "Transmit timed out!\n");
      dump_status(dev);
      dev->stats.tx_errors++;
-     dev->trans_start = jiffies;
+     dev->trans_start = jiffies; /* prevent tx timeout */
      /* Issue TX_RESET and TX_START commands. */
      tc589_wait_for_completion(dev, TxReset);
      outw(TxEnable, ioaddr + EL3_CMD);
@@@ -547,19 -574,18 +566,18 @@@ static void pop_tx_status(struct net_de
  {
      unsigned int ioaddr = dev->base_addr;
      int i;
-     
      /* Clear the Tx status stack. */
      for (i = 32; i > 0; i--) {
        u_char tx_status = inb(ioaddr + TX_STATUS);
        if (!(tx_status & 0x84)) break;
        /* reset transmitter on jabber error or underrun */
        if (tx_status & 0x30)
-           tc589_wait_for_completion(dev, TxReset);
+               tc589_wait_for_completion(dev, TxReset);
        if (tx_status & 0x38) {
-           pr_debug("%s: transmit error: status 0x%02x\n",
-                 dev->name, tx_status);
-           outw(TxEnable, ioaddr + EL3_CMD);
-           dev->stats.tx_aborted_errors++;
+               netdev_dbg(dev, "transmit error: status 0x%02x\n", tx_status);
+               outw(TxEnable, ioaddr + EL3_CMD);
+               dev->stats.tx_aborted_errors++;
        }
        outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
      }
@@@ -572,11 -598,10 +590,10 @@@ static netdev_tx_t el3_start_xmit(struc
      struct el3_private *priv = netdev_priv(dev);
      unsigned long flags;
  
-     pr_debug("%s: el3_start_xmit(length = %ld) called, "
-         "status %4.4x.\n", dev->name, (long)skb->len,
-         inw(ioaddr + EL3_STATUS));
+     netdev_dbg(dev, "el3_start_xmit(length = %ld) called, status %4.4x.\n",
+              (long)skb->len, inw(ioaddr + EL3_STATUS));
  
-     spin_lock_irqsave(&priv->lock, flags);    
+     spin_lock_irqsave(&priv->lock, flags);
  
      dev->stats.tx_bytes += skb->len;
  
      /* ... and the packet rounded to a doubleword. */
      outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
  
-     dev->trans_start = jiffies;
      if (inw(ioaddr + TX_FREE) <= 1536) {
        netif_stop_queue(dev);
        /* Interrupt us when the FIFO has room for max-sized packet. */
      }
  
      pop_tx_status(dev);
-     spin_unlock_irqrestore(&priv->lock, flags);    
+     spin_unlock_irqrestore(&priv->lock, flags);
      dev_kfree_skb(skb);
-     
      return NETDEV_TX_OK;
  }
  
@@@ -608,37 -632,32 +624,32 @@@ static irqreturn_t el3_interrupt(int ir
      unsigned int ioaddr;
      __u16 status;
      int i = 0, handled = 1;
-     
      if (!netif_device_present(dev))
        return IRQ_NONE;
  
      ioaddr = dev->base_addr;
  
-     pr_debug("%s: interrupt, status %4.4x.\n",
-         dev->name, inw(ioaddr + EL3_STATUS));
+     netdev_dbg(dev, "interrupt, status %4.4x.\n", inw(ioaddr + EL3_STATUS));
  
-     spin_lock(&lp->lock);    
+     spin_lock(&lp->lock);
      while ((status = inw(ioaddr + EL3_STATUS)) &
        (IntLatch | RxComplete | StatsFull)) {
        if ((status & 0xe000) != 0x2000) {
-           pr_debug("%s: interrupt from dead card\n", dev->name);
-           handled = 0;
-           break;
+               netdev_dbg(dev, "interrupt from dead card\n");
+               handled = 0;
+               break;
        }
-       
        if (status & RxComplete)
-           el3_rx(dev);
-       
+               el3_rx(dev);
        if (status & TxAvailable) {
-           pr_debug("    TX room bit was handled.\n");
-           /* There's room in the FIFO for a full-sized packet. */
-           outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
-           netif_wake_queue(dev);
+               netdev_dbg(dev, "    TX room bit was handled.\n");
+               /* There's room in the FIFO for a full-sized packet. */
+               outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
+               netif_wake_queue(dev);
        }
-       
        if (status & TxComplete)
-           pop_tx_status(dev);
+               pop_tx_status(dev);
        if (status & (AdapterFailure | RxEarly | StatsFull)) {
            /* Handle all uncommon interrupts. */
            if (status & StatsFull)             /* Empty statistics. */
                EL3WINDOW(4);
                fifo_diag = inw(ioaddr + 4);
                EL3WINDOW(1);
-               printk(KERN_WARNING "%s: adapter failure, FIFO diagnostic"
-                      " register %04x.\n", dev->name, fifo_diag);
+               netdev_warn(dev, "adapter failure, FIFO diagnostic register %04x.\n",
+                           fifo_diag);
                if (fifo_diag & 0x0400) {
                    /* Tx overrun */
                    tc589_wait_for_completion(dev, TxReset);
                outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
            }
        }
-       
        if (++i > 10) {
-           printk(KERN_ERR "%s: infinite loop in interrupt, "
-                  "status %4.4x.\n", dev->name, status);
-           /* Clear all interrupts */
-           outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
-           break;
+               netdev_err(dev, "infinite loop in interrupt, status %4.4x.\n",
+                          status);
+               /* Clear all interrupts */
+               outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
+               break;
        }
        /* Acknowledge the IRQ. */
        outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
      }
      lp->last_irq = jiffies;
-     spin_unlock(&lp->lock);    
-     pr_debug("%s: exiting interrupt, status %4.4x.\n",
-         dev->name, inw(ioaddr + EL3_STATUS));
+     spin_unlock(&lp->lock);
+     netdev_dbg(dev, "exiting interrupt, status %4.4x.\n",
+              inw(ioaddr + EL3_STATUS));
      return IRQ_RETVAL(handled);
  }
  
@@@ -702,7 -719,7 +711,7 @@@ static void media_check(unsigned long a
      if ((inw(ioaddr + EL3_STATUS) & IntLatch) &&
        (inb(ioaddr + EL3_TIMER) == 0xff)) {
        if (!lp->fast_poll)
-           printk(KERN_WARNING "%s: interrupt(s) dropped!\n", dev->name);
+               netdev_warn(dev, "interrupt(s) dropped!\n");
  
        local_irq_save(flags);
        el3_interrupt(dev->irq, dev);
  
      /* lp->lock guards the EL3 window. Window should always be 1 except
         when the lock is held */
-     spin_lock_irqsave(&lp->lock, flags);    
+     spin_lock_irqsave(&lp->lock, flags);
      EL3WINDOW(4);
      media = inw(ioaddr+WN4_MEDIA) & 0xc810;
  
      if (media != lp->media_status) {
        if ((media & lp->media_status & 0x8000) &&
            ((lp->media_status ^ media) & 0x0800))
-           printk(KERN_INFO "%s: %s link beat\n", dev->name,
-                  (lp->media_status & 0x0800 ? "lost" : "found"));
+               netdev_info(dev, "%s link beat\n",
+                           (lp->media_status & 0x0800 ? "lost" : "found"));
        else if ((media & lp->media_status & 0x4000) &&
                 ((lp->media_status ^ media) & 0x0010))
-           printk(KERN_INFO "%s: coax cable %s\n", dev->name,
-                  (lp->media_status & 0x0010 ? "ok" : "problem"));
+               netdev_info(dev, "coax cable %s\n",
+                           (lp->media_status & 0x0010 ? "ok" : "problem"));
        if (dev->if_port == 0) {
            if (media & 0x8000) {
                if (media & 0x0800)
-                   printk(KERN_INFO "%s: flipped to 10baseT\n",
-                          dev->name);
+                       netdev_info(dev, "flipped to 10baseT\n");
                else
-                   tc589_set_xcvr(dev, 2);
+                       tc589_set_xcvr(dev, 2);
            } else if (media & 0x4000) {
                if (media & 0x0010)
                    tc589_set_xcvr(dev, 1);
                else
-                   printk(KERN_INFO "%s: flipped to 10base2\n",
-                          dev->name);
+                   netdev_info(dev, "flipped to 10base2\n");
            }
        }
        lp->media_status = media;
      }
-     
      EL3WINDOW(1);
-     spin_unlock_irqrestore(&lp->lock, flags);    
+     spin_unlock_irqrestore(&lp->lock, flags);
  
  reschedule:
      lp->media.expires = jiffies + HZ;
@@@ -778,7 -793,7 +785,7 @@@ static struct net_device_stats *el3_get
      struct pcmcia_device *link = lp->p_dev;
  
      if (pcmcia_dev_present(link)) {
-       spin_lock_irqsave(&lp->lock, flags);
+       spin_lock_irqsave(&lp->lock, flags);
        update_stats(dev);
        spin_unlock_irqrestore(&lp->lock, flags);
      }
    single-threaded if the device is active. This is expected to be a rare
    operation, and it's simpler for the rest of the driver to assume that
    window 1 is always valid rather than use a special window-state variable.
-   
    Caller must hold the lock for this
  */
  static void update_stats(struct net_device *dev)
  {
      unsigned int ioaddr = dev->base_addr;
  
-     pr_debug("%s: updating the statistics.\n", dev->name);
+     netdev_dbg(dev, "updating the statistics.\n");
      /* Turn off statistics updates while reading. */
      outw(StatsDisable, ioaddr + EL3_CMD);
      /* Switch to the stats window, and read everything. */
      EL3WINDOW(6);
-     dev->stats.tx_carrier_errors      += inb(ioaddr + 0);
+     dev->stats.tx_carrier_errors      += inb(ioaddr + 0);
      dev->stats.tx_heartbeat_errors    += inb(ioaddr + 1);
-     /* Multiple collisions. */                inb(ioaddr + 2);
+     /* Multiple collisions. */                inb(ioaddr + 2);
      dev->stats.collisions             += inb(ioaddr + 3);
      dev->stats.tx_window_errors               += inb(ioaddr + 4);
      dev->stats.rx_fifo_errors         += inb(ioaddr + 5);
      /* Tx deferrals */                        inb(ioaddr + 8);
      /* Rx octets */                   inw(ioaddr + 10);
      /* Tx octets */                   inw(ioaddr + 12);
-     
      /* Back to window 1, and turn statistics back on. */
      EL3WINDOW(1);
      outw(StatsEnable, ioaddr + EL3_CMD);
@@@ -824,9 -839,9 +831,9 @@@ static int el3_rx(struct net_device *de
      unsigned int ioaddr = dev->base_addr;
      int worklimit = 32;
      short rx_status;
-     
-     pr_debug("%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n",
-         dev->name, inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
+     netdev_dbg(dev, "in rx_packet(), status %4.4x, rx_status %4.4x.\n",
+              inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
      while (!((rx_status = inw(ioaddr + RX_STATUS)) & 0x8000) &&
                    worklimit > 0) {
        worklimit--;
        } else {
            short pkt_len = rx_status & 0x7ff;
            struct sk_buff *skb;
-           
            skb = dev_alloc_skb(pkt_len+5);
-           
-           pr_debug("    Receiving packet size %d status %4.4x.\n",
-                 pkt_len, rx_status);
+           netdev_dbg(dev, "    Receiving packet size %d status %4.4x.\n",
+                      pkt_len, rx_status);
            if (skb != NULL) {
                skb_reserve(skb, 2);
                insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len),
                dev->stats.rx_packets++;
                dev->stats.rx_bytes += pkt_len;
            } else {
-               pr_debug("%s: couldn't allocate a sk_buff of"
-                     " size %d.\n", dev->name, pkt_len);
+               netdev_dbg(dev, "couldn't allocate a sk_buff of size %d.\n",
+                          pkt_len);
                dev->stats.rx_dropped++;
            }
        }
        tc589_wait_for_completion(dev, RxDiscard);
      }
      if (worklimit == 0)
-       printk(KERN_WARNING "%s: too much work in el3_rx!\n", dev->name);
+       netdev_warn(dev, "too much work in el3_rx!\n");
      return 0;
  }
  
@@@ -898,17 -913,17 +905,17 @@@ static int el3_close(struct net_device 
      struct el3_private *lp = netdev_priv(dev);
      struct pcmcia_device *link = lp->p_dev;
      unsigned int ioaddr = dev->base_addr;
-     
      dev_dbg(&link->dev, "%s: shutting down ethercard.\n", dev->name);
  
      if (pcmcia_dev_present(link)) {
        /* Turn off statistics ASAP.  We update dev->stats below. */
        outw(StatsDisable, ioaddr + EL3_CMD);
-       
        /* Disable the receiver and transmitter. */
        outw(RxDisable, ioaddr + EL3_CMD);
        outw(TxDisable, ioaddr + EL3_CMD);
-       
        if (dev->if_port == 2)
            /* Turn off thinnet power.  Green! */
            outw(StopCoax, ioaddr + EL3_CMD);
            EL3WINDOW(4);
            outw(0, ioaddr + WN4_MEDIA);
        }
-       
        /* Switching back to window 0 disables the IRQ. */
        EL3WINDOW(0);
        /* But we explicitly zero the IRQ line select anyway. */
        outw(0x0f00, ioaddr + WN0_IRQ);
-         
        /* Check if the card still exists */
        if ((inw(ioaddr+EL3_STATUS) & 0xe000) == 0x2000)
            update_stats(dev);
      link->open--;
      netif_stop_queue(dev);
      del_timer_sync(&lp->media);
-     
      return 0;
  }
  
@@@ -953,7 -968,7 +960,7 @@@ static struct pcmcia_driver tc589_drive
        },
        .probe          = tc589_probe,
        .remove         = tc589_detach,
-         .id_table       = tc589_ids,
+       .id_table       = tc589_ids,
        .suspend        = tc589_suspend,
        .resume         = tc589_resume,
  };
@@@ -113,6 -113,7 +113,6 @@@ static irqreturn_t ax_interrupt(int irq
  
  typedef struct axnet_dev_t {
        struct pcmcia_device    *p_dev;
 -    dev_node_t                node;
      caddr_t           base;
      struct timer_list watchdog;
      int                       stale, fast_poll;
@@@ -167,6 -168,7 +167,6 @@@ static int axnet_probe(struct pcmcia_de
      info = PRIV(dev);
      info->p_dev = link;
      link->priv = dev;
 -    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
      link->conf.Attributes = CONF_ENABLE_IRQ;
      link->conf.IntType = INT_MEMORY_AND_IO;
  
@@@ -193,7 -195,8 +193,7 @@@ static void axnet_detach(struct pcmcia_
  
      dev_dbg(&link->dev, "axnet_detach(0x%p)\n", link);
  
 -    if (link->dev_node)
 -      unregister_netdev(dev);
 +    unregister_netdev(dev);
  
      axnet_release(link);
  
@@@ -262,9 -265,12 +262,9 @@@ static int try_io_port(struct pcmcia_de
      int j, ret;
      if (link->io.NumPorts1 == 32) {
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
 -      if (link->io.NumPorts2 > 0) {
 -          /* for master/slave multifunction cards */
 +      /* for master/slave multifunction cards */
 +      if (link->io.NumPorts2 > 0)
            link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
 -          link->irq.Attributes =
 -              IRQ_TYPE_DYNAMIC_SHARING;
 -      }
      } else {
        /* This should be two 16-port windows */
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@@ -330,7 -336,8 +330,7 @@@ static int axnet_config(struct pcmcia_d
      if (ret != 0)
        goto failed;
  
 -    ret = pcmcia_request_irq(link, &link->irq);
 -    if (ret)
 +    if (!link->irq)
            goto failed;
      
      if (link->io.NumPorts2 == 8) {
      if (ret)
            goto failed;
  
 -    dev->irq = link->irq.AssignedIRQ;
 +    dev->irq = link->irq;
      dev->base_addr = link->io.BasePort1;
  
      if (!get_prom(link)) {
      }
  
      info->phy_id = (i < 32) ? i : -1;
 -    link->dev_node = &info->node;
      SET_NETDEV_DEV(dev, &link->dev);
  
      if (register_netdev(dev) != 0) {
        printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n");
        goto failed;
      }
  
 -    strcpy(info->node.dev_name, dev->name);
 -
      printk(KERN_INFO "%s: Asix AX88%d90: io %#3lx, irq %d, "
           "hw_addr %pM\n",
           dev->name, ((info->flags & IS_AX88790) ? 7 : 1),
@@@ -994,7 -1005,7 +994,7 @@@ static void axnet_tx_timeout(struct net
  {
        long e8390_base = dev->base_addr;
        struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
-       int txsr, isr, tickssofar = jiffies - dev->trans_start;
+       int txsr, isr, tickssofar = jiffies - dev_trans_start(dev);
        unsigned long flags;
  
        dev->stats.tx_errors++;
@@@ -1499,8 -1510,6 +1499,6 @@@ static void ei_receive(struct net_devic
                ei_local->current_page = next_frame;
                outb_p(next_frame-1, e8390_base+EN0_BOUNDARY);
        }
-       return;
  }
  
  /**
@@@ -1611,11 -1620,11 +1609,11 @@@ static struct net_device_stats *get_sta
   
  static inline void make_mc_bits(u8 *bits, struct net_device *dev)
  {
-       struct dev_mc_list *dmi;
+       struct netdev_hw_addr *ha;
        u32 crc;
  
-       netdev_for_each_mc_addr(dmi, dev) {
-               crc = ether_crc(ETH_ALEN, dmi->dmi_addr);
+       netdev_for_each_mc_addr(ha, dev) {
+               crc = ether_crc(ETH_ALEN, ha->addr);
                /* 
                 * The 8390 uses the 6 most significant bits of the
                 * CRC to index the multicast table.
@@@ -110,6 -110,7 +110,6 @@@ typedef enum { MBH10302, MBH10304, TDK
  */
  typedef struct local_info_t {
        struct pcmcia_device    *p_dev;
 -    dev_node_t node;
      long open_time;
      uint tx_started:1;
      uint tx_queue;
@@@ -253,6 -254,10 +253,6 @@@ static int fmvj18x_probe(struct pcmcia_
      link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
      link->io.IOAddrLines = 5;
  
 -    /* Interrupt setup */
 -    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
 -    link->irq.Handler = fjn_interrupt;
 -
      /* General socket configuration */
      link->conf.Attributes = CONF_ENABLE_IRQ;
      link->conf.IntType = INT_MEMORY_AND_IO;
@@@ -273,7 -278,8 +273,7 @@@ static void fmvj18x_detach(struct pcmci
  
      dev_dbg(&link->dev, "fmvj18x_detach\n");
  
 -    if (link->dev_node)
 -      unregister_netdev(dev);
 +    unregister_netdev(dev);
  
      fmvj18x_release(link);
  
@@@ -419,6 -425,8 +419,6 @@@ static int fmvj18x_config(struct pcmcia
      }
  
      if (link->io.NumPorts2 != 0) {
 -      link->irq.Attributes =
 -              IRQ_TYPE_DYNAMIC_SHARING;
        ret = mfc_try_io_port(link);
        if (ret != 0) goto failed;
      } else if (cardtype == UNGERMANN) {
            if (ret)
                    goto failed;
      }
 -    ret = pcmcia_request_irq(link, &link->irq);
 +    ret = pcmcia_request_irq(link, fjn_interrupt);
      if (ret)
            goto failed;
      ret = pcmcia_request_configuration(link, &link->conf);
      if (ret)
            goto failed;
  
 -    dev->irq = link->irq.AssignedIRQ;
 +    dev->irq = link->irq;
      dev->base_addr = link->io.BasePort1;
  
      if (link->io.BasePort2 != 0) {
      }
  
      lp->cardtype = cardtype;
 -    link->dev_node = &lp->node;
      SET_NETDEV_DEV(dev, &link->dev);
  
      if (register_netdev(dev) != 0) {
        printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
        goto failed;
      }
  
 -    strcpy(lp->node.dev_name, dev->name);
 -
      /* print current configuration */
      printk(KERN_INFO "%s: %s, sram %s, port %#3lx, irq %d, "
           "hw_addr %pM\n",
@@@ -878,7 -890,6 +878,6 @@@ static netdev_tx_t fjn_start_xmit(struc
            lp->sent = lp->tx_queue ;
            lp->tx_queue = 0;
            lp->tx_queue_len = 0;
-           dev->trans_start = jiffies;
            lp->tx_started = 1;
            netif_start_queue(dev);
        } else {
@@@ -1070,8 -1081,6 +1069,6 @@@ static void fjn_rx(struct net_device *d
                  "%d ticks.\n", dev->name, inb(ioaddr + RX_MODE), i);
      }
  */
-     return;
  } /* fjn_rx */
  
  /*====================================================================*/
@@@ -1184,11 -1193,11 +1181,11 @@@ static void set_rx_mode(struct net_devi
        memset(mc_filter, 0x00, sizeof(mc_filter));
        outb(1, ioaddr + RX_MODE);      /* Ignore almost all multicasts. */
      } else {
-       struct dev_mc_list *mclist;
+       struct netdev_hw_addr *ha;
  
        memset(mc_filter, 0, sizeof(mc_filter));
-       netdev_for_each_mc_addr(mclist, dev) {
-           unsigned int bit = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 26;
+       netdev_for_each_mc_addr(ha, dev) {
+           unsigned int bit = ether_crc_le(ETH_ALEN, ha->addr) >> 26;
            mc_filter[bit >> 3] |= (1 << (bit & 7));
        }
        outb(2, ioaddr + RX_MODE);      /* Use normal mode. */
@@@ -104,6 -104,7 +104,6 @@@ static void ibmtr_detach(struct pcmcia_
  typedef struct ibmtr_dev_t {
        struct pcmcia_device    *p_dev;
      struct net_device *dev;
 -    dev_node_t          node;
      window_handle_t     sram_win_handle;
      struct tok_info   *ti;
  } ibmtr_dev_t;
@@@ -155,6 -156,8 +155,6 @@@ static int __devinit ibmtr_attach(struc
      link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
      link->io.NumPorts1 = 4;
      link->io.IOAddrLines = 16;
 -    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
 -    link->irq.Handler = ibmtr_interrupt;
      link->conf.Attributes = CONF_ENABLE_IRQ;
      link->conf.IntType = INT_MEMORY_AND_IO;
      link->conf.Present = PRESENT_OPTION;
@@@ -189,7 -192,8 +189,7 @@@ static void ibmtr_detach(struct pcmcia_
       */
      ti->sram_phys |= 1;
  
 -    if (link->dev_node)
 -      unregister_netdev(dev);
 +    unregister_netdev(dev);
      
      del_timer_sync(&(ti->tr_timer));
  
@@@ -234,11 -238,11 +234,11 @@@ static int __devinit ibmtr_config(struc
      }
      dev->base_addr = link->io.BasePort1;
  
 -    ret = pcmcia_request_irq(link, &link->irq);
 +    ret = pcmcia_request_exclusive_irq(link, ibmtr_interrupt);
      if (ret)
            goto failed;
 -    dev->irq = link->irq.AssignedIRQ;
 -    ti->irq = link->irq.AssignedIRQ;
 +    dev->irq = link->irq;
 +    ti->irq = link->irq;
      ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
  
      /* Allocate the MMIO memory window */
          Adapters Technical Reference"  SC30-3585 for this info.  */
      ibmtr_hw_setup(dev, mmiobase);
  
 -    link->dev_node = &info->node;
      SET_NETDEV_DEV(dev, &link->dev);
  
      i = ibmtr_probe_card(dev);
      if (i != 0) {
        printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n");
        goto failed;
      }
  
 -    strcpy(info->node.dev_name, dev->name);
 -
      printk(KERN_INFO
           "%s: port %#3lx, irq %d,  mmio %#5lx, sram %#5lx, hwaddr=%pM\n",
             dev->name, dev->base_addr, dev->irq,
@@@ -394,8 -402,6 +394,6 @@@ static void ibmtr_hw_setup(struct net_d
  
      /* 0x40 will release the card for use */
      outb(0x40, dev->base_addr);
-     return;
  }
  
  static struct pcmcia_device_id ibmtr_ids[] = {
@@@ -363,6 -363,7 +363,6 @@@ typedef struct _mace_statistics 
  
  typedef struct _mace_private {
        struct pcmcia_device    *p_dev;
 -    dev_node_t node;
      struct net_device_stats linux_stats; /* Linux statistics counters */
      mace_statistics mace_stats; /* MACE chip statistics counters */
  
@@@ -462,6 -463,8 +462,6 @@@ static int nmclan_probe(struct pcmcia_d
      link->io.NumPorts1 = 32;
      link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
      link->io.IOAddrLines = 5;
 -    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
 -    link->irq.Handler = mace_interrupt;
      link->conf.Attributes = CONF_ENABLE_IRQ;
      link->conf.IntType = INT_MEMORY_AND_IO;
      link->conf.ConfigIndex = 1;
@@@ -490,7 -493,8 +490,7 @@@ static void nmclan_detach(struct pcmcia
  
      dev_dbg(&link->dev, "nmclan_detach\n");
  
 -    if (link->dev_node)
 -      unregister_netdev(dev);
 +    unregister_netdev(dev);
  
      nmclan_release(link);
  
@@@ -648,14 -652,14 +648,14 @@@ static int nmclan_config(struct pcmcia_
    ret = pcmcia_request_io(link, &link->io);
    if (ret)
          goto failed;
 -  ret = pcmcia_request_irq(link, &link->irq);
 +  ret = pcmcia_request_exclusive_irq(link, mace_interrupt);
    if (ret)
          goto failed;
    ret = pcmcia_request_configuration(link, &link->conf);
    if (ret)
          goto failed;
  
 -  dev->irq = link->irq.AssignedIRQ;
 +  dev->irq = link->irq;
    dev->base_addr = link->io.BasePort1;
  
    ioaddr = dev->base_addr;
    else
      printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n");
  
 -  link->dev_node = &lp->node;
    SET_NETDEV_DEV(dev, &link->dev);
  
    i = register_netdev(dev);
    if (i != 0) {
      printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n");
      goto failed;
    }
  
 -  strcpy(lp->node.dev_name, dev->name);
 -
    printk(KERN_INFO "%s: nmclan: port %#3lx, irq %d, %s port,"
         " hw_addr %pM\n",
         dev->name, dev->base_addr, dev->irq, if_names[dev->if_port],
@@@ -895,7 -903,7 +895,7 @@@ static void mace_tx_timeout(struct net_
  #else /* #if RESET_ON_TIMEOUT */
    printk("NOT resetting card\n");
  #endif /* #if RESET_ON_TIMEOUT */
-   dev->trans_start = jiffies;
+   dev->trans_start = jiffies; /* prevent tx timeout */
    netif_wake_queue(dev);
  }
  
@@@ -937,8 -945,6 +937,6 @@@ static netdev_tx_t mace_start_xmit(stru
        outb(skb->data[skb->len-1], ioaddr + AM2150_XMT);
      }
  
-     dev->trans_start = jiffies;
  #if MULTI_TX
      if (lp->tx_free_frames > 0)
        netif_start_queue(dev);
@@@ -1307,8 -1313,6 +1305,6 @@@ static void update_stats(unsigned int i
    lp->linux_stats.tx_fifo_errors = lp->mace_stats.uflo;
    lp->linux_stats.tx_heartbeat_errors = lp->mace_stats.cerr;
    /* lp->linux_stats.tx_window_errors; */
-   return;
  } /* update_stats */
  
  /* ----------------------------------------------------------------------------
@@@ -1467,7 -1471,7 +1463,7 @@@ static void set_multicast_list(struct n
  {
    mace_private *lp = netdev_priv(dev);
    int adr[ETHER_ADDR_LEN] = {0}; /* Ethernet address */
-   struct dev_mc_list *dmi;
+   struct netdev_hw_addr *ha;
  
  #ifdef PCMCIA_DEBUG
    {
    if (num_addrs > 0) {
      /* Calculate multicast logical address filter */
      memset(lp->multicast_ladrf, 0, MACE_LADRF_LEN);
-     netdev_for_each_mc_addr(dmi, dev) {
-       memcpy(adr, dmi->dmi_addr, ETHER_ADDR_LEN);
+     netdev_for_each_mc_addr(ha, dev) {
+       memcpy(adr, ha->addr, ETHER_ADDR_LEN);
        BuildLAF(lp->multicast_ladrf, adr);
      }
    }
@@@ -103,6 -103,7 +103,6 @@@ struct smc_private 
      u_short                   manfid;
      u_short                   cardid;
  
 -    dev_node_t                        node;
      struct sk_buff            *saved_skb;
      int                               packets_waiting;
      void                      __iomem *base;
@@@ -322,11 -323,14 +322,11 @@@ static int smc91c92_probe(struct pcmcia
        return -ENOMEM;
      smc = netdev_priv(dev);
      smc->p_dev = link;
 -    link->priv = dev;
  
      spin_lock_init(&smc->lock);
      link->io.NumPorts1 = 16;
      link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
      link->io.IOAddrLines = 4;
 -    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
 -    link->irq.Handler = &smc_interrupt;
      link->conf.Attributes = CONF_ENABLE_IRQ;
      link->conf.IntType = INT_MEMORY_AND_IO;
  
@@@ -359,7 -363,8 +359,7 @@@ static void smc91c92_detach(struct pcmc
  
      dev_dbg(&link->dev, "smc91c92_detach\n");
  
 -    if (link->dev_node)
 -      unregister_netdev(dev);
 +    unregister_netdev(dev);
  
      smc91c92_release(link);
  
@@@ -448,6 -453,7 +448,6 @@@ static int mhz_mfc_config(struct pcmcia
  
      link->conf.Attributes |= CONF_ENABLE_SPKR;
      link->conf.Status = CCSR_AUDIO_ENA;
 -    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
      link->io.IOAddrLines = 16;
      link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
      link->io.NumPorts2 = 8;
@@@ -646,6 -652,7 +646,6 @@@ static int osi_config(struct pcmcia_dev
  
      link->conf.Attributes |= CONF_ENABLE_SPKR;
      link->conf.Status = CCSR_AUDIO_ENA;
 -    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
      link->io.NumPorts1 = 64;
      link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
      link->io.NumPorts2 = 8;
@@@ -870,7 -877,7 +870,7 @@@ static int smc91c92_config(struct pcmci
      if (i)
            goto config_failed;
  
 -    i = pcmcia_request_irq(link, &link->irq);
 +    i = pcmcia_request_irq(link, smc_interrupt);
      if (i)
            goto config_failed;
      i = pcmcia_request_configuration(link, &link->conf);
      if (smc->manfid == MANFID_MOTOROLA)
        mot_config(link);
  
 -    dev->irq = link->irq.AssignedIRQ;
 +    dev->irq = link->irq;
  
      if ((if_port >= 0) && (if_port <= 2))
        dev->if_port = if_port;
        SMC_SELECT_BANK(0);
      }
  
 -    link->dev_node = &smc->node;
      SET_NETDEV_DEV(dev, &link->dev);
  
      if (register_netdev(dev) != 0) {
        printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
        goto config_undo;
      }
  
 -    strcpy(smc->node.dev_name, dev->name);
 -
      printk(KERN_INFO "%s: smc91c%s rev %d: io %#3lx, irq %d, "
           "hw_addr %pM\n",
           dev->name, name, (rev & 0x0f), dev->base_addr, dev->irq,
@@@ -1228,7 -1239,6 +1228,6 @@@ static void smc_hardware_send_packet(st
      dev_kfree_skb_irq(skb);
      dev->trans_start = jiffies;
      netif_start_queue(dev);
-     return;
  }
  
  /*====================================================================*/
@@@ -1243,7 -1253,7 +1242,7 @@@ static void smc_tx_timeout(struct net_d
           dev->name, inw(ioaddr)&0xff, inw(ioaddr + 2));
      dev->stats.tx_errors++;
      smc_reset(dev);
-     dev->trans_start = jiffies;
+     dev->trans_start = jiffies; /* prevent tx timeout */
      smc->saved_skb = NULL;
      netif_wake_queue(dev);
  }
@@@ -1358,7 -1368,6 +1357,6 @@@ static void smc_tx_err(struct net_devic
      smc->packets_waiting--;
  
      outw(saved_packet, ioaddr + PNR_ARR);
-     return;
  }
  
  /*====================================================================*/
@@@ -1578,8 -1587,6 +1576,6 @@@ static void smc_rx(struct net_device *d
      }
      /* Let the MMU free the memory of this packet. */
      outw(MC_RELEASE, ioaddr + MMU_CMD);
-     return;
  }
  
  /*======================================================================
@@@ -1610,10 -1617,10 +1606,10 @@@ static void set_rx_mode(struct net_devi
        rx_cfg_setting = RxStripCRC | RxEnable | RxAllMulti;
      else {
        if (!netdev_mc_empty(dev)) {
-           struct dev_mc_list *mc_addr;
+           struct netdev_hw_addr *ha;
  
-           netdev_for_each_mc_addr(mc_addr, dev) {
-               u_int position = ether_crc(6, mc_addr->dmi_addr);
+           netdev_for_each_mc_addr(ha, dev) {
+               u_int position = ether_crc(6, ha->addr);
                multicast_table[position >> 29] |= 1 << ((position >> 26) & 7);
            }
        }
      outw(rx_cfg_setting, ioaddr + RCR);
      SMC_SELECT_BANK(2);
      spin_unlock_irqrestore(&smc->lock, flags);
-     return;
  }
  
  /*======================================================================
@@@ -297,9 -297,31 +297,9 @@@ static void xirc2ps_detach(struct pcmci
  
  static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id);
  
  typedef struct local_info_t {
        struct net_device       *dev;
        struct pcmcia_device    *p_dev;
 -    dev_node_t node;
  
      int card_type;
      int probe_port;
@@@ -533,6 -555,7 +533,6 @@@ xirc2ps_probe(struct pcmcia_device *lin
      link->conf.Attributes = CONF_ENABLE_IRQ;
      link->conf.IntType = INT_MEMORY_AND_IO;
      link->conf.ConfigIndex = 1;
 -    link->irq.Handler = xirc2ps_interrupt;
  
      /* Fill in card specific entries */
      dev->netdev_ops = &netdev_ops;
@@@ -557,7 -580,8 +557,7 @@@ xirc2ps_detach(struct pcmcia_device *li
  
      dev_dbg(&link->dev, "detach\n");
  
 -    if (link->dev_node)
 -      unregister_netdev(dev);
 +    unregister_netdev(dev);
  
      xirc2ps_release(link);
  
@@@ -817,6 -841,7 +817,6 @@@ xirc2ps_config(struct pcmcia_device * l
            link->conf.Attributes |= CONF_ENABLE_SPKR;
            link->conf.Status |= CCSR_AUDIO_ENA;
        }
 -      link->irq.Attributes |= IRQ_TYPE_DYNAMIC_SHARING;
        link->io.NumPorts2 = 8;
        link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
        if (local->dingo) {
        }
        printk(KNOT_XIRC "no ports available\n");
      } else {
 -      link->irq.Attributes |= IRQ_TYPE_DYNAMIC_SHARING;
        link->io.NumPorts1 = 16;
        for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
            link->io.BasePort1 = ioaddr;
       * Now allocate an interrupt line.        Note that this does not
       * actually assign a handler to the interrupt.
       */
 -    if ((err=pcmcia_request_irq(link, &link->irq)))
 +    if ((err=pcmcia_request_irq(link, xirc2ps_interrupt)))
        goto config_error;
  
      /****************
        printk(KNOT_XIRC "invalid if_port requested\n");
  
      /* we can now register the device with the net subsystem */
 -    dev->irq = link->irq.AssignedIRQ;
 +    dev->irq = link->irq;
      dev->base_addr = link->io.BasePort1;
  
      if (local->dingo)
        do_reset(dev, 1); /* a kludge to make the cem56 work */
  
 -    link->dev_node = &local->node;
      SET_NETDEV_DEV(dev, &link->dev);
  
      if ((err=register_netdev(dev))) {
        printk(KNOT_XIRC "register_netdev() failed\n");
        goto config_error;
      }
  
 -    strcpy(local->node.dev_name, dev->name);
 -
      /* give some infos about the hardware */
      printk(KERN_INFO "%s: %s: port %#3lx, irq %d, hwaddr %pM\n",
           dev->name, local->manf_str,(u_long)dev->base_addr, (int)dev->irq,
@@@ -1265,7 -1295,7 +1265,7 @@@ xirc2ps_tx_timeout_task(struct work_str
        struct net_device *dev = local->dev;
      /* reset the card */
      do_reset(dev,1);
-     dev->trans_start = jiffies;
+     dev->trans_start = jiffies; /* prevent tx timeout */
      netif_wake_queue(dev);
  }
  
@@@ -1328,7 -1358,6 +1328,6 @@@ do_start_xmit(struct sk_buff *skb, stru
        PutByte(XIRCREG_CR, TransmitPacket|EnableIntr);
  
      dev_kfree_skb (skb);
-     dev->trans_start = jiffies;
      dev->stats.tx_bytes += pktlen;
      netif_start_queue(dev);
      return NETDEV_TX_OK;
@@@ -1368,7 -1397,7 +1367,7 @@@ static void set_addresses(struct net_de
  {
        unsigned int ioaddr = dev->base_addr;
        local_info_t *lp = netdev_priv(dev);
-       struct dev_mc_list *dmi;
+       struct netdev_hw_addr *ha;
        struct set_address_info sa_info;
        int i;
  
  
        set_address(&sa_info, dev->dev_addr);
        i = 0;
-       netdev_for_each_mc_addr(dmi, dev) {
+       netdev_for_each_mc_addr(ha, dev) {
                if (i++ == 9)
                        break;
-               set_address(&sa_info, dmi->dmi_addr);
+               set_address(&sa_info, ha->addr);
        }
        while (i++ < 9)
                set_address(&sa_info, dev->dev_addr);
@@@ -96,7 -96,7 +96,7 @@@ static inline int precise_ie(void
   * post_eurus_cmd helpers
   */
  struct eurus_cmd_arg_info {
 -      int pre_arg; /* command requres arg1, arg2 at POST COMMAND */
 +      int pre_arg; /* command requires arg1, arg2 at POST COMMAND */
        int post_arg; /* command requires arg1, arg2 at GET_RESULT */
  };
  
@@@ -301,7 -301,6 +301,6 @@@ static void gelic_wl_get_ch_info(struc
                        /* 16 bits of MSB has available channels */
                        wl->ch_info = ch_info_raw >> 48;
        }
-       return;
  }
  
  /* SIOGIWRANGE */
@@@ -528,7 -527,7 +527,7 @@@ static void gelic_wl_parse_ie(u8 *data
        u8 item_len;
        u8 item_id;
  
-       pr_debug("%s: data=%p len=%ld \n", __func__,
+       pr_debug("%s: data=%p len=%ld\n", __func__,
                 data, len);
        memset(ie_info, 0, sizeof(struct ie_info));
  
@@@ -897,7 -896,7 +896,7 @@@ static int gelic_wl_set_auth(struct net
        default:
                ret = -EOPNOTSUPP;
                break;
-       };
+       }
  
        if (!ret)
                set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat);
@@@ -979,7 -978,7 +978,7 @@@ static int gelic_wl_set_essid(struct ne
                pr_debug("%s: essid = '%s'\n", __func__, extra);
                set_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat);
        } else {
-               pr_debug("%s: ESSID any \n", __func__);
+               pr_debug("%s: ESSID any\n", __func__);
                clear_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat);
        }
        set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat);
  
  
        gelic_wl_try_associate(netdev); /* FIXME */
-       pr_debug("%s: -> \n", __func__);
+       pr_debug("%s: ->\n", __func__);
        return 0;
  }
  
@@@ -998,7 -997,7 +997,7 @@@ static int gelic_wl_get_essid(struct ne
        struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));
        unsigned long irqflag;
  
-       pr_debug("%s: <- \n", __func__);
+       pr_debug("%s: <-\n", __func__);
        mutex_lock(&wl->assoc_stat_lock);
        spin_lock_irqsave(&wl->lock, irqflag);
        if (test_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat) ||
  
        mutex_unlock(&wl->assoc_stat_lock);
        spin_unlock_irqrestore(&wl->lock, irqflag);
-       pr_debug("%s: -> len=%d \n", __func__, data->essid.length);
+       pr_debug("%s: -> len=%d\n", __func__, data->essid.length);
  
        return 0;
  }
@@@ -1028,7 -1027,7 +1027,7 @@@ static int gelic_wl_set_encode(struct n
        int key_index, index_specified;
        int ret = 0;
  
-       pr_debug("%s: <- \n", __func__);
+       pr_debug("%s: <-\n", __func__);
        flags = enc->flags & IW_ENCODE_FLAGS;
        key_index = enc->flags & IW_ENCODE_INDEX;
  
        set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat);
  done:
        spin_unlock_irqrestore(&wl->lock, irqflag);
-       pr_debug("%s: -> \n", __func__);
+       pr_debug("%s: ->\n", __func__);
        return ret;
  }
  
@@@ -1101,7 -1100,7 +1100,7 @@@ static int gelic_wl_get_encode(struct n
        unsigned int key_index, index_specified;
        int ret = 0;
  
-       pr_debug("%s: <- \n", __func__);
+       pr_debug("%s: <-\n", __func__);
        key_index = enc->flags & IW_ENCODE_INDEX;
        pr_debug("%s: flag=%#x point=%p len=%d extra=%p\n", __func__,
                 enc->flags, enc->pointer, enc->length, extra);
@@@ -1215,7 -1214,7 +1214,7 @@@ static int gelic_wl_set_encodeext(struc
        int key_index;
        int ret = 0;
  
-       pr_debug("%s: <- \n", __func__);
+       pr_debug("%s: <-\n", __func__);
        flags = enc->flags & IW_ENCODE_FLAGS;
        alg = ext->alg;
        key_index = enc->flags & IW_ENCODE_INDEX;
        }
  done:
        spin_unlock_irqrestore(&wl->lock, irqflag);
-       pr_debug("%s: -> \n", __func__);
+       pr_debug("%s: ->\n", __func__);
        return ret;
  }
  
@@@ -1304,7 -1303,7 +1303,7 @@@ static int gelic_wl_get_encodeext(struc
        int ret = 0;
        int max_key_len;
  
-       pr_debug("%s: <- \n", __func__);
+       pr_debug("%s: <-\n", __func__);
  
        max_key_len = enc->length - sizeof(struct iw_encode_ext);
        if (max_key_len < 0)
        }
  out:
        spin_unlock_irqrestore(&wl->lock, irqflag);
-       pr_debug("%s: -> \n", __func__);
+       pr_debug("%s: ->\n", __func__);
        return ret;
  }
  /* SIOC{S,G}IWMODE */
@@@ -1370,7 -1369,7 +1369,7 @@@ static int gelic_wl_set_mode(struct net
        __u32 mode = data->mode;
        int ret;
  
-       pr_debug("%s: <- \n", __func__);
+       pr_debug("%s: <-\n", __func__);
        if (mode == IW_MODE_INFRA)
                ret = 0;
        else
@@@ -1384,7 -1383,7 +1383,7 @@@ static int gelic_wl_get_mode(struct net
                             union iwreq_data *data, char *extra)
  {
        __u32 *mode = &data->mode;
-       pr_debug("%s: <- \n", __func__);
+       pr_debug("%s: <-\n", __func__);
        *mode = IW_MODE_INFRA;
        pr_debug("%s: ->\n", __func__);
        return 0;
@@@ -1992,7 -1991,7 +1991,7 @@@ static int gelic_wl_associate_bss(struc
        case GELIC_WL_WPA_LEVEL_WPA2:
                ret = gelic_wl_do_wpa_setup(wl);
                break;
-       };
+       }
  
        if (ret) {
                pr_debug("%s: WEP/WPA setup failed %d\n", __func__,
  
        if (!rc) {
                /* timeouted.  Maybe key or cyrpt mode is wrong */
-               pr_info("%s: connect timeout \n", __func__);
+               pr_info("%s: connect timeout\n", __func__);
                cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_DISASSOC,
                                           NULL, 0);
                kfree(cmd);
@@@ -2063,7 -2062,7 +2062,7 @@@ static void gelic_wl_connected_event(st
        }
  
        if (desired_event == event) {
-               pr_debug("%s: completed \n", __func__);
+               pr_debug("%s: completed\n", __func__);
                complete(&wl->assoc_done);
                netif_carrier_on(port_to_netdev(wl_port(wl)));
        } else
@@@ -2280,26 -2279,25 +2279,25 @@@ void gelic_wl_interrupt(struct net_devi
  /*
   * driver helpers
   */
- #define IW_IOCTL(n) [(n) - SIOCSIWCOMMIT]
  static const iw_handler gelic_wl_wext_handler[] =
  {
-       IW_IOCTL(SIOCGIWNAME)           = gelic_wl_get_name,
-       IW_IOCTL(SIOCGIWRANGE)          = gelic_wl_get_range,
-       IW_IOCTL(SIOCSIWSCAN)           = gelic_wl_set_scan,
-       IW_IOCTL(SIOCGIWSCAN)           = gelic_wl_get_scan,
-       IW_IOCTL(SIOCSIWAUTH)           = gelic_wl_set_auth,
-       IW_IOCTL(SIOCGIWAUTH)           = gelic_wl_get_auth,
-       IW_IOCTL(SIOCSIWESSID)          = gelic_wl_set_essid,
-       IW_IOCTL(SIOCGIWESSID)          = gelic_wl_get_essid,
-       IW_IOCTL(SIOCSIWENCODE)         = gelic_wl_set_encode,
-       IW_IOCTL(SIOCGIWENCODE)         = gelic_wl_get_encode,
-       IW_IOCTL(SIOCSIWAP)             = gelic_wl_set_ap,
-       IW_IOCTL(SIOCGIWAP)             = gelic_wl_get_ap,
-       IW_IOCTL(SIOCSIWENCODEEXT)      = gelic_wl_set_encodeext,
-       IW_IOCTL(SIOCGIWENCODEEXT)      = gelic_wl_get_encodeext,
-       IW_IOCTL(SIOCSIWMODE)           = gelic_wl_set_mode,
-       IW_IOCTL(SIOCGIWMODE)           = gelic_wl_get_mode,
-       IW_IOCTL(SIOCGIWNICKN)          = gelic_wl_get_nick,
+       IW_HANDLER(SIOCGIWNAME, gelic_wl_get_name),
+       IW_HANDLER(SIOCGIWRANGE, gelic_wl_get_range),
+       IW_HANDLER(SIOCSIWSCAN, gelic_wl_set_scan),
+       IW_HANDLER(SIOCGIWSCAN, gelic_wl_get_scan),
+       IW_HANDLER(SIOCSIWAUTH, gelic_wl_set_auth),
+       IW_HANDLER(SIOCGIWAUTH, gelic_wl_get_auth),
+       IW_HANDLER(SIOCSIWESSID, gelic_wl_set_essid),
+       IW_HANDLER(SIOCGIWESSID, gelic_wl_get_essid),
+       IW_HANDLER(SIOCSIWENCODE, gelic_wl_set_encode),
+       IW_HANDLER(SIOCGIWENCODE, gelic_wl_get_encode),
+       IW_HANDLER(SIOCSIWAP, gelic_wl_set_ap),
+       IW_HANDLER(SIOCGIWAP, gelic_wl_get_ap),
+       IW_HANDLER(SIOCSIWENCODEEXT, gelic_wl_set_encodeext),
+       IW_HANDLER(SIOCGIWENCODEEXT, gelic_wl_get_encodeext),
+       IW_HANDLER(SIOCSIWMODE, gelic_wl_set_mode),
+       IW_HANDLER(SIOCGIWMODE, gelic_wl_get_mode),
+       IW_HANDLER(SIOCGIWNICKN, gelic_wl_get_nick),
  };
  
  static const struct iw_handler_def gelic_wl_wext_handler_def = {
@@@ -2318,7 -2316,7 +2316,7 @@@ static struct net_device * __devinit ge
        pr_debug("%s:start\n", __func__);
        netdev = alloc_etherdev(sizeof(struct gelic_port) +
                                sizeof(struct gelic_wl_info));
-       pr_debug("%s: netdev =%p card=%p \np", __func__, netdev, card);
+       pr_debug("%s: netdev =%p card=%p\n", __func__, netdev, card);
        if (!netdev)
                return NULL;
  
diff --combined drivers/net/smsc911x.c
@@@ -736,7 -736,7 +736,7 @@@ static void smsc911x_phy_adjust_link(st
                        SMSC_TRACE(HW, "configuring for carrier OK");
                        if ((pdata->gpio_orig_setting & GPIO_CFG_LED1_EN_) &&
                            (!pdata->using_extphy)) {
 -                              /* Restore orginal GPIO configuration */
 +                              /* Restore original GPIO configuration */
                                pdata->gpio_setting = pdata->gpio_orig_setting;
                                smsc911x_reg_write(pdata, GPIO_CFG,
                                        pdata->gpio_setting);
                        if ((pdata->gpio_setting & GPIO_CFG_LED1_EN_) &&
                            (!pdata->using_extphy)) {
                                /* Force 10/100 LED off, after saving
 -                               * orginal GPIO configuration */
 +                               * original GPIO configuration */
                                pdata->gpio_orig_setting = pdata->gpio_setting;
  
                                pdata->gpio_setting &= ~GPIO_CFG_LED1_EN_;
@@@ -1335,7 -1335,6 +1335,6 @@@ static int smsc911x_hard_start_xmit(str
        smsc911x_tx_writefifo(pdata, (unsigned int *)bufp, wrsz);
        freespace -= (skb->len + 32);
        dev_kfree_skb(skb);
-       dev->trans_start = jiffies;
  
        if (unlikely(smsc911x_tx_get_txstatcount(pdata) >= 30))
                smsc911x_tx_update_txcounters(dev);
@@@ -1382,13 -1381,13 +1381,13 @@@ static void smsc911x_set_multicast_list
                /* Enabling specific multicast addresses */
                unsigned int hash_high = 0;
                unsigned int hash_low = 0;
-               struct dev_mc_list *mc_list;
+               struct netdev_hw_addr *ha;
  
                pdata->set_bits_mask = MAC_CR_HPFILT_;
                pdata->clear_bits_mask = (MAC_CR_PRMS_ | MAC_CR_MCPAS_);
  
-               netdev_for_each_mc_addr(mc_list, dev) {
-                       unsigned int bitnum = smsc911x_hash(mc_list->dmi_addr);
+               netdev_for_each_mc_addr(ha, dev) {
+                       unsigned int bitnum = smsc911x_hash(ha->addr);
                        unsigned int mask = 0x01 << (bitnum & 0x1F);
  
                        if (bitnum & 0x20)
@@@ -174,8 -174,6 +174,8 @@@ that only one external action is invoke
  #define DRV_DESCRIPTION       "Intel(R) PRO/Wireless 2100 Network Driver"
  #define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation"
  
 +struct pm_qos_request_list *ipw2100_pm_qos_req;
 +
  /* Debugging stuff */
  #ifdef CONFIG_IPW2100_DEBUG
  #define IPW2100_RX_DEBUG      /* Reception debugging */
@@@ -1741,7 -1739,7 +1741,7 @@@ static int ipw2100_up(struct ipw2100_pr
        /* the ipw2100 hardware really doesn't want power management delays
         * longer than 175usec
         */
 -      pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100", 175);
 +      pm_qos_update_request(ipw2100_pm_qos_req, 175);
  
        /* If the interrupt is enabled, turn it off... */
        spin_lock_irqsave(&priv->low_lock, flags);
@@@ -1889,7 -1887,8 +1889,7 @@@ static void ipw2100_down(struct ipw2100
        ipw2100_disable_interrupts(priv);
        spin_unlock_irqrestore(&priv->low_lock, flags);
  
 -      pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
 -                      PM_QOS_DEFAULT_VALUE);
 +      pm_qos_update_request(ipw2100_pm_qos_req, PM_QOS_DEFAULT_VALUE);
  
        /* We have to signal any supplicant if we are disassociating */
        if (associated)
@@@ -2141,7 -2140,7 +2141,7 @@@ static void isr_indicate_association_lo
        DECLARE_SSID_BUF(ssid);
  
        IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC,
-                 "disassociated: '%s' %pM \n",
+                 "disassociated: '%s' %pM\n",
                  print_ssid(ssid, priv->essid, priv->essid_len),
                  priv->bssid);
  
@@@ -3240,7 -3239,6 +3240,6 @@@ static void ipw2100_tx_send_data(struc
                               IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX,
                               txq->next);
        }
-       return;
  }
  
  static void ipw2100_irq_tasklet(struct ipw2100_priv *priv)
  
        if (inta & IPW2100_INTA_PARITY_ERROR) {
                printk(KERN_ERR DRV_NAME
-                      ": ***** PARITY ERROR INTERRUPT !!!! \n");
+                      ": ***** PARITY ERROR INTERRUPT !!!!\n");
                priv->inta_other++;
                write_register(dev, IPW_REG_INTA, IPW2100_INTA_PARITY_ERROR);
        }
@@@ -6103,7 -6101,7 +6102,7 @@@ static const struct net_device_ops ipw2
        .ndo_validate_addr      = eth_validate_addr,
  };
  
- /* Look into using netdev destructor to shutdown ieee80211? */
+ /* Look into using netdev destructor to shutdown libipw? */
  
  static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
                                               void __iomem * base_addr,
        struct ipw2100_priv *priv;
        struct net_device *dev;
  
-       dev = alloc_ieee80211(sizeof(struct ipw2100_priv), 0);
+       dev = alloc_libipw(sizeof(struct ipw2100_priv), 0);
        if (!dev)
                return NULL;
        priv = libipw_priv(dev);
@@@ -6426,7 -6424,7 +6425,7 @@@ static int ipw2100_pci_init_one(struct 
                sysfs_remove_group(&pci_dev->dev.kobj,
                                   &ipw2100_attribute_group);
  
-               free_ieee80211(dev, 0);
+               free_libipw(dev, 0);
                pci_set_drvdata(pci_dev, NULL);
        }
  
@@@ -6484,10 -6482,10 +6483,10 @@@ static void __devexit ipw2100_pci_remov
                if (dev->base_addr)
                        iounmap((void __iomem *)dev->base_addr);
  
-               /* wiphy_unregister needs to be here, before free_ieee80211 */
+               /* wiphy_unregister needs to be here, before free_libipw */
                wiphy_unregister(priv->ieee->wdev.wiphy);
                kfree(priv->ieee->bg_band.channels);
-               free_ieee80211(dev, 0);
+               free_libipw(dev, 0);
        }
  
        pci_release_regions(pci_dev);
@@@ -6670,7 -6668,7 +6669,7 @@@ static int __init ipw2100_init(void
        if (ret)
                goto out;
  
 -      pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
 +      ipw2100_pm_qos_req = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
                        PM_QOS_DEFAULT_VALUE);
  #ifdef CONFIG_IPW2100_DEBUG
        ipw2100_debug_level = debug;
@@@ -6693,7 -6691,7 +6692,7 @@@ static void __exit ipw2100_exit(void
                           &driver_attr_debug_level);
  #endif
        pci_unregister_driver(&ipw2100_pci_driver);
 -      pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100");
 +      pm_qos_remove_request(ipw2100_pm_qos_req);
  }
  
  module_init(ipw2100_init);
@@@ -6754,7 -6752,7 +6753,7 @@@ static int ipw2100_wx_set_freq(struct n
                err = -EOPNOTSUPP;
                goto done;
        } else {                /* Set the channel */
-               IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m);
+               IPW_DEBUG_WX("SET Freq/Channel -> %d\n", fwrq->m);
                err = ipw2100_set_channel(priv, fwrq->m, 0);
        }
  
@@@ -6783,7 -6781,7 +6782,7 @@@ static int ipw2100_wx_get_freq(struct n
        else
                wrqu->freq.m = 0;
  
-       IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel);
+       IPW_DEBUG_WX("GET Freq/Channel -> %d\n", priv->channel);
        return 0;
  
  }
@@@ -6795,7 -6793,7 +6794,7 @@@ static int ipw2100_wx_set_mode(struct n
        struct ipw2100_priv *priv = libipw_priv(dev);
        int err = 0;
  
-       IPW_DEBUG_WX("SET Mode -> %d \n", wrqu->mode);
+       IPW_DEBUG_WX("SET Mode -> %d\n", wrqu->mode);
  
        if (wrqu->mode == priv->ieee->iw_mode)
                return 0;
@@@ -7150,7 -7148,7 +7149,7 @@@ static int ipw2100_wx_set_nick(struct n
        memset(priv->nick, 0, sizeof(priv->nick));
        memcpy(priv->nick, extra, wrqu->data.length);
  
-       IPW_DEBUG_WX("SET Nickname -> %s \n", priv->nick);
+       IPW_DEBUG_WX("SET Nickname -> %s\n", priv->nick);
  
        return 0;
  }
@@@ -7169,7 -7167,7 +7168,7 @@@ static int ipw2100_wx_get_nick(struct n
        memcpy(extra, priv->nick, wrqu->data.length);
        wrqu->data.flags = 1;   /* active */
  
-       IPW_DEBUG_WX("GET Nickname -> %s \n", extra);
+       IPW_DEBUG_WX("GET Nickname -> %s\n", extra);
  
        return 0;
  }
@@@ -7208,7 -7206,7 +7207,7 @@@ static int ipw2100_wx_set_rate(struct n
  
        err = ipw2100_set_tx_rates(priv, rate, 0);
  
-       IPW_DEBUG_WX("SET Rate -> %04X \n", rate);
+       IPW_DEBUG_WX("SET Rate -> %04X\n", rate);
        done:
        mutex_unlock(&priv->action_mutex);
        return err;
@@@ -7259,7 -7257,7 +7258,7 @@@ static int ipw2100_wx_get_rate(struct n
                wrqu->bitrate.value = 0;
        }
  
-       IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value);
+       IPW_DEBUG_WX("GET Rate -> %d\n", wrqu->bitrate.value);
  
        done:
        mutex_unlock(&priv->action_mutex);
@@@ -7295,7 -7293,7 +7294,7 @@@ static int ipw2100_wx_set_rts(struct ne
  
        err = ipw2100_set_rts_threshold(priv, value);
  
-       IPW_DEBUG_WX("SET RTS Threshold -> 0x%08X \n", value);
+       IPW_DEBUG_WX("SET RTS Threshold -> 0x%08X\n", value);
        done:
        mutex_unlock(&priv->action_mutex);
        return err;
@@@ -7317,7 -7315,7 +7316,7 @@@ static int ipw2100_wx_get_rts(struct ne
        /* If RTS is set to the default value, then it is disabled */
        wrqu->rts.disabled = (priv->rts_threshold & RTS_DISABLED) ? 1 : 0;
  
-       IPW_DEBUG_WX("GET RTS Threshold -> 0x%08X \n", wrqu->rts.value);
+       IPW_DEBUG_WX("GET RTS Threshold -> 0x%08X\n", wrqu->rts.value);
  
        return 0;
  }
@@@ -7356,7 -7354,7 +7355,7 @@@ static int ipw2100_wx_set_txpow(struct 
  
        err = ipw2100_set_tx_power(priv, value);
  
-       IPW_DEBUG_WX("SET TX Power -> %d \n", value);
+       IPW_DEBUG_WX("SET TX Power -> %d\n", value);
  
        done:
        mutex_unlock(&priv->action_mutex);
@@@ -7385,7 -7383,7 +7384,7 @@@ static int ipw2100_wx_get_txpow(struct 
  
        wrqu->txpower.flags = IW_TXPOW_DBM;
  
-       IPW_DEBUG_WX("GET TX Power -> %d \n", wrqu->txpower.value);
+       IPW_DEBUG_WX("GET TX Power -> %d\n", wrqu->txpower.value);
  
        return 0;
  }
@@@ -7415,7 -7413,7 +7414,7 @@@ static int ipw2100_wx_set_frag(struct n
                priv->frag_threshold = priv->ieee->fts;
        }
  
-       IPW_DEBUG_WX("SET Frag Threshold -> %d \n", priv->ieee->fts);
+       IPW_DEBUG_WX("SET Frag Threshold -> %d\n", priv->ieee->fts);
  
        return 0;
  }
@@@ -7433,7 -7431,7 +7432,7 @@@ static int ipw2100_wx_get_frag(struct n
        wrqu->frag.fixed = 0;   /* no auto select */
        wrqu->frag.disabled = (priv->frag_threshold & FRAG_DISABLED) ? 1 : 0;
  
-       IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value);
+       IPW_DEBUG_WX("GET Frag Threshold -> %d\n", wrqu->frag.value);
  
        return 0;
  }
@@@ -7459,14 -7457,14 +7458,14 @@@ static int ipw2100_wx_set_retry(struct 
  
        if (wrqu->retry.flags & IW_RETRY_SHORT) {
                err = ipw2100_set_short_retry(priv, wrqu->retry.value);
-               IPW_DEBUG_WX("SET Short Retry Limit -> %d \n",
+               IPW_DEBUG_WX("SET Short Retry Limit -> %d\n",
                             wrqu->retry.value);
                goto done;
        }
  
        if (wrqu->retry.flags & IW_RETRY_LONG) {
                err = ipw2100_set_long_retry(priv, wrqu->retry.value);
-               IPW_DEBUG_WX("SET Long Retry Limit -> %d \n",
+               IPW_DEBUG_WX("SET Long Retry Limit -> %d\n",
                             wrqu->retry.value);
                goto done;
        }
        if (!err)
                err = ipw2100_set_long_retry(priv, wrqu->retry.value);
  
-       IPW_DEBUG_WX("SET Both Retry Limits -> %d \n", wrqu->retry.value);
+       IPW_DEBUG_WX("SET Both Retry Limits -> %d\n", wrqu->retry.value);
  
        done:
        mutex_unlock(&priv->action_mutex);
@@@ -7509,7 -7507,7 +7508,7 @@@ static int ipw2100_wx_get_retry(struct 
                wrqu->retry.value = priv->short_retry_limit;
        }
  
-       IPW_DEBUG_WX("GET Retry -> %d \n", wrqu->retry.value);
+       IPW_DEBUG_WX("GET Retry -> %d\n", wrqu->retry.value);
  
        return 0;
  }
@@@ -50,6 -50,7 +50,6 @@@ MODULE_PARM_DESC(ignore_cis_vcc, "Allo
   * struct orinoco_private */
  struct orinoco_pccard {
        struct pcmcia_device    *p_dev;
 -      dev_node_t node;
  
        /* Used to handle hard reset */
        /* yuck, we need this hack to work around the insanity of the
@@@ -118,6 -119,10 +118,6 @@@ orinoco_cs_probe(struct pcmcia_device *
        card->p_dev = link;
        link->priv = priv;
  
 -      /* Interrupt setup */
 -      link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
 -      link->irq.Handler = orinoco_interrupt;
 -
        /* General socket configuration defaults can go here.  In this
         * client, we assume very little, and rely on the CIS for
         * almost everything.  In most clients, many details (i.e.,
@@@ -139,7 -144,8 +139,7 @@@ static void orinoco_cs_detach(struct pc
  {
        struct orinoco_private *priv = link->priv;
  
 -      if (link->dev_node)
 -              orinoco_if_del(priv);
 +      orinoco_if_del(priv);
  
        orinoco_cs_release(link);
  
@@@ -224,6 -230,7 +224,6 @@@ static in
  orinoco_cs_config(struct pcmcia_device *link)
  {
        struct orinoco_private *priv = link->priv;
 -      struct orinoco_pccard *card = priv->card;
        hermes_t *hw = &priv->hw;
        int ret;
        void __iomem *mem;
                goto failed;
        }
  
 -      /*
 -       * Allocate an interrupt line.  Note that this does not assign
 -       * a handler to the interrupt, unless the 'Handler' member of
 -       * the irq structure is initialized.
 -       */
 -      ret = pcmcia_request_irq(link, &link->irq);
 +      ret = pcmcia_request_irq(link, orinoco_interrupt);
        if (ret)
                goto failed;
  
        if (ret)
                goto failed;
  
 -      /* Ok, we have the configuration, prepare to register the netdev */
 -      card->node.major = card->node.minor = 0;
 -
        /* Initialise the main driver */
        if (orinoco_init(priv) != 0) {
                printk(KERN_ERR PFX "orinoco_init() failed\n");
  
        /* Register an interface with the stack */
        if (orinoco_if_add(priv, link->io.BasePort1,
-                          link->irq) != 0) {
 -                         link->irq.AssignedIRQ, NULL) != 0) {
++                         link->irq, NULL) != 0) {
                printk(KERN_ERR PFX "orinoco_if_add() failed\n");
                goto failed;
        }
  
 -      /* At this point, the dev_node_t structure(s) needs to be
 -       * initialized and arranged in a linked list at link->dev_node. */
 -      strcpy(card->node.dev_name, priv->ndev->name);
 -      link->dev_node = &card->node; /* link->dev_node being non-NULL is also
 -                                     * used to indicate that the
 -                                     * net_device has been registered */
        return 0;
  
   failed:
@@@ -306,9 -327,9 +306,9 @@@ orinoco_cs_release(struct pcmcia_devic
  
        /* We're committed to taking the device away now, so mark the
         * hardware as unavailable */
-       spin_lock_irqsave(&priv->lock, flags);
+       priv->hw.ops->lock_irqsave(&priv->lock, &flags);
        priv->hw_unavailable++;
-       spin_unlock_irqrestore(&priv->lock, flags);
+       priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
  
        pcmcia_disable_device(link);
        if (priv->hw.iobase)
@@@ -353,87 -374,90 +353,90 @@@ static char version[] __initdata = DRIV
        "Pavel Roskin <proski@gnu.org>, et al)";
  
  static struct pcmcia_device_id orinoco_cs_ids[] = {
-       PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */
-       PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */
-       PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */
        PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */
        PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */
        PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */
        PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */
-       PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */
-       PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
        PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */
        PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */
        PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0003), /* ARtem Onair Comcard 11 */
        PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */
-       PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
-       PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
-       PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */
-       PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */
        PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */
        PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */
        PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x3021), /* SpeedStream Wireless Adapter */
        PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */
+       PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
+       PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),
+       PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e),
+       PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842),
+       PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169),
+       PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb),
+       PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
+       PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916),
+       PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
+       PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c),
+       PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077),
+       PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92),
+       PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
+       PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410),
+       PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3),
+       PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a),
+       PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767),
+       PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed),
+       PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
+       PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
+       PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
+       PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
+ #ifdef CONFIG_HERMES_PRISM
+       /* Only entries that certainly identify Prism chipset */
+       PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */
+       PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */
+       PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */
+       PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */
+       PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */
+       PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */
+       PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
+       PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
+       PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
+       PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */
+       PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */
        PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */
        PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */
        PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), /* CONTEC FLEXSCAN/FX-DDS110-PCC */
        PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), /* Conceptronic CON11Cpro, EMTAC A2424i */
        PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */
        PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */
-       PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9),
-       PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
+       PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
        PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5),
        PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2),
-       PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),
-       PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842),
-       PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e),
-       PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169),
-       PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb),
-       PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3),
        PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18),
-       PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
+       PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3),
        PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b),
        PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
        PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
        PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
+       PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146),
        PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
        PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
-       PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916),
-       PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146),
-       PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
-       PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c),
-       PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
-       PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077),
+       PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9),
        PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18),
        PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77),
        PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf),
-       PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92),
        PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395),
-       PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
-       PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410),
-       PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3),
        PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01),
-       PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a),
-       PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1),
        PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1),
-       PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767),
+       PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1),
        PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6),
-       PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed),
        PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264),
        PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178),
-       PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
-       PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
-       PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
        PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757),
        PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a),
-       PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
        PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee),
        PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092),
        PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2),
        PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b),
        PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39),
+ #endif
        PCMCIA_DEVICE_NULL,
  };
  MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids);
@@@ -57,6 -57,7 +57,6 @@@ MODULE_PARM_DESC(ignore_cis_vcc, "Allo
   * struct orinoco_private */
  struct orinoco_pccard {
        struct pcmcia_device    *p_dev;
 -      dev_node_t node;
  };
  
  /********************************************************************/
@@@ -192,6 -193,10 +192,6 @@@ spectrum_cs_probe(struct pcmcia_device 
        card->p_dev = link;
        link->priv = priv;
  
 -      /* Interrupt setup */
 -      link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
 -      link->irq.Handler = orinoco_interrupt;
 -
        /* General socket configuration defaults can go here.  In this
         * client, we assume very little, and rely on the CIS for
         * almost everything.  In most clients, many details (i.e.,
@@@ -213,7 -218,8 +213,7 @@@ static void spectrum_cs_detach(struct p
  {
        struct orinoco_private *priv = link->priv;
  
 -      if (link->dev_node)
 -              orinoco_if_del(priv);
 +      orinoco_if_del(priv);
  
        spectrum_cs_release(link);
  
@@@ -298,6 -304,7 +298,6 @@@ static in
  spectrum_cs_config(struct pcmcia_device *link)
  {
        struct orinoco_private *priv = link->priv;
 -      struct orinoco_pccard *card = priv->card;
        hermes_t *hw = &priv->hw;
        int ret;
        void __iomem *mem;
                goto failed;
        }
  
 -      /*
 -       * Allocate an interrupt line.  Note that this does not assign
 -       * a handler to the interrupt, unless the 'Handler' member of
 -       * the irq structure is initialized.
 -       */
 -      ret = pcmcia_request_irq(link, &link->irq);
 +      ret = pcmcia_request_irq(link, orinoco_interrupt);
        if (ret)
                goto failed;
  
                goto failed;
  
        hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
+       hw->eeprom_pda = true;
  
        /*
         * This actually configures the PCMCIA socket -- setting up
        if (ret)
                goto failed;
  
 -      /* Ok, we have the configuration, prepare to register the netdev */
 -      card->node.major = card->node.minor = 0;
 -
        /* Reset card */
        if (spectrum_cs_hard_reset(priv) != 0)
                goto failed;
  
        /* Register an interface with the stack */
        if (orinoco_if_add(priv, link->io.BasePort1,
-                          link->irq) != 0) {
 -                         link->irq.AssignedIRQ, NULL) != 0) {
++                         link->irq, NULL) != 0) {
                printk(KERN_ERR PFX "orinoco_if_add() failed\n");
                goto failed;
        }
  
 -      /* At this point, the dev_node_t structure(s) needs to be
 -       * initialized and arranged in a linked list at link->dev_node. */
 -      strcpy(card->node.dev_name, priv->ndev->name);
 -      link->dev_node = &card->node; /* link->dev_node being non-NULL is also
 -                                     * used to indicate that the
 -                                     * net_device has been registered */
        return 0;
  
   failed:
@@@ -384,9 -406,9 +385,9 @@@ spectrum_cs_release(struct pcmcia_devic
  
        /* We're committed to taking the device away now, so mark the
         * hardware as unavailable */
-       spin_lock_irqsave(&priv->lock, flags);
+       priv->hw.ops->lock_irqsave(&priv->lock, &flags);
        priv->hw_unavailable++;
-       spin_unlock_irqrestore(&priv->lock, flags);
+       priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
  
        pcmcia_disable_device(link);
        if (priv->hw.iobase)
@@@ -51,6 -51,7 +51,6 @@@
  #include <pcmcia/cistpl.h>
  #include <pcmcia/cisreg.h>
  #include <pcmcia/ds.h>
 -#include <pcmcia/mem_op.h>
  
  #include <linux/wireless.h>
  #include <net/iw_handler.h>
@@@ -320,6 -321,10 +320,6 @@@ static int ray_probe(struct pcmcia_devi
        p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
        p_dev->io.IOAddrLines = 5;
  
 -      /* Interrupt setup. For PCMCIA, driver takes what's given */
 -      p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
 -      p_dev->irq.Handler = &ray_interrupt;
 -
        /* General socket configuration */
        p_dev->conf.Attributes = CONF_ENABLE_IRQ;
        p_dev->conf.IntType = INT_MEMORY_AND_IO;
@@@ -378,7 -383,8 +378,7 @@@ static void ray_detach(struct pcmcia_de
        del_timer(&local->timer);
  
        if (link->priv) {
 -              if (link->dev_node)
 -                      unregister_netdev(dev);
 +              unregister_netdev(dev);
                free_netdev(dev);
        }
        dev_dbg(&link->dev, "ray_cs ray_detach ending\n");
@@@ -411,10 -417,10 +411,10 @@@ static int ray_config(struct pcmcia_dev
        /* Now allocate an interrupt line.  Note that this does not
           actually assign a handler to the interrupt.
         */
 -      ret = pcmcia_request_irq(link, &link->irq);
 +      ret = pcmcia_request_irq(link, ray_interrupt);
        if (ret)
                goto failed;
 -      dev->irq = link->irq.AssignedIRQ;
 +      dev->irq = link->irq;
  
        /* This actually configures the PCMCIA socket -- setting up
           the I/O windows and the interrupt mapping.
                return i;
        }
  
 -      strcpy(local->node.dev_name, dev->name);
 -      link->dev_node = &local->node;
 -
        printk(KERN_INFO "%s: RayLink, irq %d, hw_addr %pM\n",
               dev->name, dev->irq, dev->dev_addr);
  
@@@ -546,7 -555,7 +546,7 @@@ static int ray_init(struct net_device *
        local->fw_ver = local->startup_res.firmware_version[0];
        local->fw_bld = local->startup_res.firmware_version[1];
        local->fw_var = local->startup_res.firmware_version[2];
-       dev_dbg(&link->dev, "ray_init firmware version %d.%d \n", local->fw_ver,
+       dev_dbg(&link->dev, "ray_init firmware version %d.%d\n", local->fw_ver,
              local->fw_bld);
  
        local->tib_length = 0x20;
@@@ -726,8 -735,6 +726,6 @@@ static void verify_dl_startup(u_long da
                start_net((u_long) local);
        else
                join_net((u_long) local);
-       return;
  } /* end verify_dl_startup */
  
  /*===========================================================================*/
@@@ -755,7 -762,6 +753,6 @@@ static void start_net(u_long data
                return;
        }
        local->card_status = CARD_DOING_ACQ;
-       return;
  } /* end start_net */
  
  /*===========================================================================*/
@@@ -786,7 -792,6 +783,6 @@@ static void join_net(u_long data
                return;
        }
        local->card_status = CARD_DOING_ACQ;
-       return;
  }
  
  /*============================================================================
@@@ -932,7 -937,6 +928,6 @@@ static netdev_tx_t ray_dev_start_xmit(s
        case XMIT_MSG_BAD:
        case XMIT_OK:
        default:
-               dev->trans_start = jiffies;
                dev_kfree_skb(skb);
        }
  
@@@ -1103,10 -1107,10 +1098,10 @@@ static const struct ethtool_ops netdev_
  /*
   * Wireless Handler : get protocol name
   */
- static int ray_get_name(struct net_device *dev,
-                       struct iw_request_info *info, char *cwrq, char *extra)
+ static int ray_get_name(struct net_device *dev, struct iw_request_info *info,
+                       union iwreq_data *wrqu, char *extra)
  {
-       strcpy(cwrq, "IEEE 802.11-FH");
+       strcpy(wrqu->name, "IEEE 802.11-FH");
        return 0;
  }
  
  /*
   * Wireless Handler : set frequency
   */
- static int ray_set_freq(struct net_device *dev,
-                       struct iw_request_info *info,
-                       struct iw_freq *fwrq, char *extra)
+ static int ray_set_freq(struct net_device *dev, struct iw_request_info *info,
+                       union iwreq_data *wrqu, char *extra)
  {
        ray_dev_t *local = netdev_priv(dev);
        int err = -EINPROGRESS; /* Call commit handler */
                return -EBUSY;
  
        /* Setting by channel number */
-       if ((fwrq->m > USA_HOP_MOD) || (fwrq->e > 0))
+       if ((wrqu->freq.m > USA_HOP_MOD) || (wrqu->freq.e > 0))
                err = -EOPNOTSUPP;
        else
-               local->sparm.b5.a_hop_pattern = fwrq->m;
+               local->sparm.b5.a_hop_pattern = wrqu->freq.m;
  
        return err;
  }
  /*
   * Wireless Handler : get frequency
   */
- static int ray_get_freq(struct net_device *dev,
-                       struct iw_request_info *info,
-                       struct iw_freq *fwrq, char *extra)
+ static int ray_get_freq(struct net_device *dev, struct iw_request_info *info,
+                       union iwreq_data *wrqu, char *extra)
  {
        ray_dev_t *local = netdev_priv(dev);
  
-       fwrq->m = local->sparm.b5.a_hop_pattern;
-       fwrq->e = 0;
+       wrqu->freq.m = local->sparm.b5.a_hop_pattern;
+       wrqu->freq.e = 0;
        return 0;
  }
  
  /*
   * Wireless Handler : set ESSID
   */
- static int ray_set_essid(struct net_device *dev,
-                        struct iw_request_info *info,
-                        struct iw_point *dwrq, char *extra)
+ static int ray_set_essid(struct net_device *dev, struct iw_request_info *info,
+                        union iwreq_data *wrqu, char *extra)
  {
        ray_dev_t *local = netdev_priv(dev);
  
                return -EBUSY;
  
        /* Check if we asked for `any' */
-       if (dwrq->flags == 0) {
+       if (wrqu->essid.flags == 0)
                /* Corey : can you do that ? */
                return -EOPNOTSUPP;
-       } else {
-               /* Check the size of the string */
-               if (dwrq->length > IW_ESSID_MAX_SIZE) {
-                       return -E2BIG;
-               }
  
-               /* Set the ESSID in the card */
-               memset(local->sparm.b5.a_current_ess_id, 0, IW_ESSID_MAX_SIZE);
-               memcpy(local->sparm.b5.a_current_ess_id, extra, dwrq->length);
-       }
+       /* Check the size of the string */
+       if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
+               return -E2BIG;
+       /* Set the ESSID in the card */
+       memset(local->sparm.b5.a_current_ess_id, 0, IW_ESSID_MAX_SIZE);
+       memcpy(local->sparm.b5.a_current_ess_id, extra, wrqu->essid.length);
  
        return -EINPROGRESS;    /* Call commit handler */
  }
  /*
   * Wireless Handler : get ESSID
   */
- static int ray_get_essid(struct net_device *dev,
-                        struct iw_request_info *info,
-                        struct iw_point *dwrq, char *extra)
+ static int ray_get_essid(struct net_device *dev, struct iw_request_info *info,
+                        union iwreq_data *wrqu, char *extra)
  {
        ray_dev_t *local = netdev_priv(dev);
  
        memcpy(extra, local->sparm.b5.a_current_ess_id, IW_ESSID_MAX_SIZE);
  
        /* Push it out ! */
-       dwrq->length = strlen(extra);
-       dwrq->flags = 1;        /* active */
+       wrqu->essid.length = strlen(extra);
+       wrqu->essid.flags = 1;  /* active */
  
        return 0;
  }
  /*
   * Wireless Handler : get AP address
   */
- static int ray_get_wap(struct net_device *dev,
-                      struct iw_request_info *info,
-                      struct sockaddr *awrq, char *extra)
+ static int ray_get_wap(struct net_device *dev, struct iw_request_info *info,
+                      union iwreq_data *wrqu, char *extra)
  {
        ray_dev_t *local = netdev_priv(dev);
  
-       memcpy(awrq->sa_data, local->bss_id, ETH_ALEN);
-       awrq->sa_family = ARPHRD_ETHER;
+       memcpy(wrqu->ap_addr.sa_data, local->bss_id, ETH_ALEN);
+       wrqu->ap_addr.sa_family = ARPHRD_ETHER;
  
        return 0;
  }
  /*
   * Wireless Handler : set Bit-Rate
   */
- static int ray_set_rate(struct net_device *dev,
-                       struct iw_request_info *info,
-                       struct iw_param *vwrq, char *extra)
+ static int ray_set_rate(struct net_device *dev, struct iw_request_info *info,
+                       union iwreq_data *wrqu, char *extra)
  {
        ray_dev_t *local = netdev_priv(dev);
  
                return -EBUSY;
  
        /* Check if rate is in range */
-       if ((vwrq->value != 1000000) && (vwrq->value != 2000000))
+       if ((wrqu->bitrate.value != 1000000) && (wrqu->bitrate.value != 2000000))
                return -EINVAL;
  
        /* Hack for 1.5 Mb/s instead of 2 Mb/s */
        if ((local->fw_ver == 0x55) &&  /* Please check */
-           (vwrq->value == 2000000))
+           (wrqu->bitrate.value == 2000000))
                local->net_default_tx_rate = 3;
        else
-               local->net_default_tx_rate = vwrq->value / 500000;
+               local->net_default_tx_rate = wrqu->bitrate.value / 500000;
  
        return 0;
  }
  /*
   * Wireless Handler : get Bit-Rate
   */
- static int ray_get_rate(struct net_device *dev,
-                       struct iw_request_info *info,
-                       struct iw_param *vwrq, char *extra)
+ static int ray_get_rate(struct net_device *dev, struct iw_request_info *info,
+                       union iwreq_data *wrqu, char *extra)
  {
        ray_dev_t *local = netdev_priv(dev);
  
        if (local->net_default_tx_rate == 3)
-               vwrq->value = 2000000;  /* Hum... */
+               wrqu->bitrate.value = 2000000;  /* Hum... */
        else
-               vwrq->value = local->net_default_tx_rate * 500000;
-       vwrq->fixed = 0;        /* We are in auto mode */
+               wrqu->bitrate.value = local->net_default_tx_rate * 500000;
+       wrqu->bitrate.fixed = 0;        /* We are in auto mode */
  
        return 0;
  }
  /*
   * Wireless Handler : set RTS threshold
   */
- static int ray_set_rts(struct net_device *dev,
-                      struct iw_request_info *info,
-                      struct iw_param *vwrq, char *extra)
+ static int ray_set_rts(struct net_device *dev, struct iw_request_info *info,
+                      union iwreq_data *wrqu, char *extra)
  {
        ray_dev_t *local = netdev_priv(dev);
-       int rthr = vwrq->value;
+       int rthr = wrqu->rts.value;
  
        /* Reject if card is already initialised */
        if (local->card_status != CARD_AWAITING_PARAM)
                return -EBUSY;
  
        /* if(wrq->u.rts.fixed == 0) we should complain */
-       if (vwrq->disabled)
+       if (wrqu->rts.disabled)
                rthr = 32767;
        else {
                if ((rthr < 0) || (rthr > 2347))   /* What's the max packet size ??? */
  /*
   * Wireless Handler : get RTS threshold
   */
- static int ray_get_rts(struct net_device *dev,
-                      struct iw_request_info *info,
-                      struct iw_param *vwrq, char *extra)
+ static int ray_get_rts(struct net_device *dev, struct iw_request_info *info,
+                      union iwreq_data *wrqu, char *extra)
  {
        ray_dev_t *local = netdev_priv(dev);
  
-       vwrq->value = (local->sparm.b5.a_rts_threshold[0] << 8)
+       wrqu->rts.value = (local->sparm.b5.a_rts_threshold[0] << 8)
            + local->sparm.b5.a_rts_threshold[1];
-       vwrq->disabled = (vwrq->value == 32767);
-       vwrq->fixed = 1;
+       wrqu->rts.disabled = (wrqu->rts.value == 32767);
+       wrqu->rts.fixed = 1;
  
        return 0;
  }
  /*
   * Wireless Handler : set Fragmentation threshold
   */
- static int ray_set_frag(struct net_device *dev,
-                       struct iw_request_info *info,
-                       struct iw_param *vwrq, char *extra)
+ static int ray_set_frag(struct net_device *dev, struct iw_request_info *info,
+                       union iwreq_data *wrqu, char *extra)
  {
        ray_dev_t *local = netdev_priv(dev);
-       int fthr = vwrq->value;
+       int fthr = wrqu->frag.value;
  
        /* Reject if card is already initialised */
        if (local->card_status != CARD_AWAITING_PARAM)
                return -EBUSY;
  
        /* if(wrq->u.frag.fixed == 0) should complain */
-       if (vwrq->disabled)
+       if (wrqu->frag.disabled)
                fthr = 32767;
        else {
                if ((fthr < 256) || (fthr > 2347))      /* To check out ! */
  /*
   * Wireless Handler : get Fragmentation threshold
   */
- static int ray_get_frag(struct net_device *dev,
-                       struct iw_request_info *info,
-                       struct iw_param *vwrq, char *extra)
+ static int ray_get_frag(struct net_device *dev, struct iw_request_info *info,
+                       union iwreq_data *wrqu, char *extra)
  {
        ray_dev_t *local = netdev_priv(dev);
  
-       vwrq->value = (local->sparm.b5.a_frag_threshold[0] << 8)
+       wrqu->frag.value = (local->sparm.b5.a_frag_threshold[0] << 8)
            + local->sparm.b5.a_frag_threshold[1];
-       vwrq->disabled = (vwrq->value == 32767);
-       vwrq->fixed = 1;
+       wrqu->frag.disabled = (wrqu->frag.value == 32767);
+       wrqu->frag.fixed = 1;
  
        return 0;
  }
  /*
   * Wireless Handler : set Mode of Operation
   */
- static int ray_set_mode(struct net_device *dev,
-                       struct iw_request_info *info, __u32 *uwrq, char *extra)
+ static int ray_set_mode(struct net_device *dev, struct iw_request_info *info,
+                       union iwreq_data *wrqu, char *extra)
  {
        ray_dev_t *local = netdev_priv(dev);
        int err = -EINPROGRESS; /* Call commit handler */
        if (local->card_status != CARD_AWAITING_PARAM)
                return -EBUSY;
  
-       switch (*uwrq) {
+       switch (wrqu->mode) {
        case IW_MODE_ADHOC:
                card_mode = 0;
                /* Fall through */
  /*
   * Wireless Handler : get Mode of Operation
   */
- static int ray_get_mode(struct net_device *dev,
-                       struct iw_request_info *info, __u32 *uwrq, char *extra)
+ static int ray_get_mode(struct net_device *dev, struct iw_request_info *info,
+                       union iwreq_data *wrqu, char *extra)
  {
        ray_dev_t *local = netdev_priv(dev);
  
        if (local->sparm.b5.a_network_type)
-               *uwrq = IW_MODE_INFRA;
+               wrqu->mode = IW_MODE_INFRA;
        else
-               *uwrq = IW_MODE_ADHOC;
+               wrqu->mode = IW_MODE_ADHOC;
  
        return 0;
  }
  /*
   * Wireless Handler : get range info
   */
- static int ray_get_range(struct net_device *dev,
-                        struct iw_request_info *info,
-                        struct iw_point *dwrq, char *extra)
+ static int ray_get_range(struct net_device *dev, struct iw_request_info *info,
+                        union iwreq_data *wrqu, char *extra)
  {
        struct iw_range *range = (struct iw_range *)extra;
  
-       memset((char *)range, 0, sizeof(struct iw_range));
+       memset(range, 0, sizeof(struct iw_range));
  
        /* Set the length (very important for backward compatibility) */
-       dwrq->length = sizeof(struct iw_range);
+       wrqu->data.length = sizeof(struct iw_range);
  
        /* Set the Wireless Extension versions */
        range->we_version_compiled = WIRELESS_EXT;
  /*
   * Wireless Private Handler : set framing mode
   */
- static int ray_set_framing(struct net_device *dev,
-                          struct iw_request_info *info,
+ static int ray_set_framing(struct net_device *dev, struct iw_request_info *info,
                           union iwreq_data *wrqu, char *extra)
  {
        translate = *(extra);   /* Set framing mode */
  /*
   * Wireless Private Handler : get framing mode
   */
- static int ray_get_framing(struct net_device *dev,
-                          struct iw_request_info *info,
+ static int ray_get_framing(struct net_device *dev, struct iw_request_info *info,
                           union iwreq_data *wrqu, char *extra)
  {
        *(extra) = translate;
  /*
   * Wireless Private Handler : get country
   */
- static int ray_get_country(struct net_device *dev,
-                          struct iw_request_info *info,
+ static int ray_get_country(struct net_device *dev, struct iw_request_info *info,
                           union iwreq_data *wrqu, char *extra)
  {
        *(extra) = country;
  /*
   * Commit handler : called after a bunch of SET operations
   */
- static int ray_commit(struct net_device *dev, struct iw_request_info *info,   /* NULL */
-                     void *zwrq,       /* NULL */
-                     char *extra)
- { /* NULL */
+ static int ray_commit(struct net_device *dev, struct iw_request_info *info,
+                     union iwreq_data *wrqu, char *extra)
+ {
        return 0;
  }
  
@@@ -1521,28 -1507,28 +1498,28 @@@ static iw_stats *ray_get_wireless_stats
   */
  
  static const iw_handler ray_handler[] = {
-       [SIOCSIWCOMMIT - SIOCIWFIRST] = (iw_handler) ray_commit,
-       [SIOCGIWNAME - SIOCIWFIRST] = (iw_handler) ray_get_name,
-       [SIOCSIWFREQ - SIOCIWFIRST] = (iw_handler) ray_set_freq,
-       [SIOCGIWFREQ - SIOCIWFIRST] = (iw_handler) ray_get_freq,
-       [SIOCSIWMODE - SIOCIWFIRST] = (iw_handler) ray_set_mode,
-       [SIOCGIWMODE - SIOCIWFIRST] = (iw_handler) ray_get_mode,
-       [SIOCGIWRANGE - SIOCIWFIRST] = (iw_handler) ray_get_range,
+       IW_HANDLER(SIOCSIWCOMMIT, ray_commit),
+       IW_HANDLER(SIOCGIWNAME, ray_get_name),
+       IW_HANDLER(SIOCSIWFREQ, ray_set_freq),
+       IW_HANDLER(SIOCGIWFREQ, ray_get_freq),
+       IW_HANDLER(SIOCSIWMODE, ray_set_mode),
+       IW_HANDLER(SIOCGIWMODE, ray_get_mode),
+       IW_HANDLER(SIOCGIWRANGE, ray_get_range),
  #ifdef WIRELESS_SPY
-       [SIOCSIWSPY - SIOCIWFIRST] = (iw_handler) iw_handler_set_spy,
-       [SIOCGIWSPY - SIOCIWFIRST] = (iw_handler) iw_handler_get_spy,
-       [SIOCSIWTHRSPY - SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy,
-       [SIOCGIWTHRSPY - SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy,
+       IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
+       IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
+       IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy),
+       IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy),
  #endif /* WIRELESS_SPY */
-       [SIOCGIWAP - SIOCIWFIRST] = (iw_handler) ray_get_wap,
-       [SIOCSIWESSID - SIOCIWFIRST] = (iw_handler) ray_set_essid,
-       [SIOCGIWESSID - SIOCIWFIRST] = (iw_handler) ray_get_essid,
-       [SIOCSIWRATE - SIOCIWFIRST] = (iw_handler) ray_set_rate,
-       [SIOCGIWRATE - SIOCIWFIRST] = (iw_handler) ray_get_rate,
-       [SIOCSIWRTS - SIOCIWFIRST] = (iw_handler) ray_set_rts,
-       [SIOCGIWRTS - SIOCIWFIRST] = (iw_handler) ray_get_rts,
-       [SIOCSIWFRAG - SIOCIWFIRST] = (iw_handler) ray_set_frag,
-       [SIOCGIWFRAG - SIOCIWFIRST] = (iw_handler) ray_get_frag,
+       IW_HANDLER(SIOCGIWAP, ray_get_wap),
+       IW_HANDLER(SIOCSIWESSID, ray_set_essid),
+       IW_HANDLER(SIOCGIWESSID, ray_get_essid),
+       IW_HANDLER(SIOCSIWRATE, ray_set_rate),
+       IW_HANDLER(SIOCGIWRATE, ray_get_rate),
+       IW_HANDLER(SIOCSIWRTS, ray_set_rts),
+       IW_HANDLER(SIOCGIWRTS, ray_get_rts),
+       IW_HANDLER(SIOCSIWFRAG, ray_set_frag),
+       IW_HANDLER(SIOCGIWFRAG, ray_get_frag),
  };
  
  #define SIOCSIPFRAMING        SIOCIWFIRSTPRIV /* Set framing mode */
  #define SIOCGIPCOUNTRY        SIOCIWFIRSTPRIV + 3     /* Get country code */
  
  static const iw_handler ray_private_handler[] = {
-       [0] = (iw_handler) ray_set_framing,
-       [1] = (iw_handler) ray_get_framing,
-       [3] = (iw_handler) ray_get_country,
+       [0] = ray_set_framing,
+       [1] = ray_get_framing,
+       [3] = ray_get_country,
  };
  
  static const struct iw_priv_args ray_private_args[] = {
@@@ -1636,7 -1622,6 +1613,6 @@@ static int ray_dev_close(struct net_dev
  static void ray_reset(struct net_device *dev)
  {
        pr_debug("ray_reset entered\n");
-       return;
  }
  
  /*===========================================================================*/
@@@ -1883,17 -1868,17 +1859,17 @@@ static void ray_update_multi_list(struc
                writeb(0xff, &pccs->var);
                local->num_multi = 0xff;
        } else {
-               struct dev_mc_list *dmi;
+               struct netdev_hw_addr *ha;
                int i = 0;
  
                /* Copy the kernel's list of MC addresses to card */
-               netdev_for_each_mc_addr(dmi, dev) {
-                       memcpy_toio(p, dmi->dmi_addr, ETH_ALEN);
+               netdev_for_each_mc_addr(ha, dev) {
+                       memcpy_toio(p, ha->addr, ETH_ALEN);
                        dev_dbg(&link->dev,
                              "ray_update_multi add addr %02x%02x%02x%02x%02x%02x\n",
-                             dmi->dmi_addr[0], dmi->dmi_addr[1],
-                             dmi->dmi_addr[2], dmi->dmi_addr[3],
-                             dmi->dmi_addr[4], dmi->dmi_addr[5]);
+                             ha->addr[0], ha->addr[1],
+                             ha->addr[2], ha->addr[3],
+                             ha->addr[4], ha->addr[5]);
                        p += ETH_ALEN;
                        i++;
                }
@@@ -2242,7 -2227,7 +2218,7 @@@ static void rx_data(struct net_device *
                            (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN +
                             FCS_LEN)) {
                                pr_debug(
-                                     "ray_cs invalid packet length %d received \n",
+                                     "ray_cs invalid packet length %d received\n",
                                      rx_len);
                                return;
                        }
                            (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN +
                             FCS_LEN)) {
                                pr_debug(
-                                     "ray_cs invalid packet length %d received \n",
+                                     "ray_cs invalid packet length %d received\n",
                                      rx_len);
                                return;
                        }
@@@ -2761,11 -2746,11 +2737,11 @@@ static int ray_cs_proc_show(struct seq_
                        seq_printf(m, "Hop dwell            = %d Kus\n",
                                   pfh->dwell_time[0] +
                                   256 * pfh->dwell_time[1]);
-                       seq_printf(m, "Hop set              = %d \n",
+                       seq_printf(m, "Hop set              = %d\n",
                                   pfh->hop_set);
-                       seq_printf(m, "Hop pattern          = %d \n",
+                       seq_printf(m, "Hop pattern          = %d\n",
                                   pfh->hop_pattern);
-                       seq_printf(m, "Hop index            = %d \n",
+                       seq_printf(m, "Hop index            = %d\n",
                                   pfh->hop_index);
                        p += p[1] + 2;
                } else {
@@@ -1307,7 -1307,7 +1307,7 @@@ static void wl3501_tx_timeout(struct ne
                printk(KERN_ERR "%s: Error %d resetting card on Tx timeout!\n",
                       dev->name, rc);
        else {
-               dev->trans_start = jiffies;
+               dev->trans_start = jiffies; /* prevent tx timeout */
                netif_wake_queue(dev);
        }
  }
@@@ -1326,7 -1326,6 +1326,6 @@@ static netdev_tx_t wl3501_hard_start_xm
  
        spin_lock_irqsave(&this->lock, flags);
        enabled = wl3501_block_interrupt(this);
-       dev->trans_start = jiffies;
        rc = wl3501_send_pkt(this, skb->data, skb->len);
        if (enabled)
                wl3501_unblock_interrupt(this);
@@@ -1451,12 -1450,8 +1450,10 @@@ static void wl3501_detach(struct pcmcia
        netif_device_detach(dev);
        wl3501_release(link);
  
 +      unregister_netdev(dev);
 +
        if (link->priv)
                free_netdev(link->priv);
-       return;
  }
  
  static int wl3501_get_name(struct net_device *dev, struct iw_request_info *info,
  }
  
  static const iw_handler       wl3501_handler[] = {
-       [SIOCGIWNAME    - SIOCIWFIRST] = wl3501_get_name,
-       [SIOCSIWFREQ    - SIOCIWFIRST] = wl3501_set_freq,
-       [SIOCGIWFREQ    - SIOCIWFIRST] = wl3501_get_freq,
-       [SIOCSIWMODE    - SIOCIWFIRST] = wl3501_set_mode,
-       [SIOCGIWMODE    - SIOCIWFIRST] = wl3501_get_mode,
-       [SIOCGIWSENS    - SIOCIWFIRST] = wl3501_get_sens,
-       [SIOCGIWRANGE   - SIOCIWFIRST] = wl3501_get_range,
-       [SIOCSIWSPY     - SIOCIWFIRST] = iw_handler_set_spy,
-       [SIOCGIWSPY     - SIOCIWFIRST] = iw_handler_get_spy,
-       [SIOCSIWTHRSPY  - SIOCIWFIRST] = iw_handler_set_thrspy,
-       [SIOCGIWTHRSPY  - SIOCIWFIRST] = iw_handler_get_thrspy,
-       [SIOCSIWAP      - SIOCIWFIRST] = wl3501_set_wap,
-       [SIOCGIWAP      - SIOCIWFIRST] = wl3501_get_wap,
-       [SIOCSIWSCAN    - SIOCIWFIRST] = wl3501_set_scan,
-       [SIOCGIWSCAN    - SIOCIWFIRST] = wl3501_get_scan,
-       [SIOCSIWESSID   - SIOCIWFIRST] = wl3501_set_essid,
-       [SIOCGIWESSID   - SIOCIWFIRST] = wl3501_get_essid,
-       [SIOCSIWNICKN   - SIOCIWFIRST] = wl3501_set_nick,
-       [SIOCGIWNICKN   - SIOCIWFIRST] = wl3501_get_nick,
-       [SIOCGIWRATE    - SIOCIWFIRST] = wl3501_get_rate,
-       [SIOCGIWRTS     - SIOCIWFIRST] = wl3501_get_rts_threshold,
-       [SIOCGIWFRAG    - SIOCIWFIRST] = wl3501_get_frag_threshold,
-       [SIOCGIWTXPOW   - SIOCIWFIRST] = wl3501_get_txpow,
-       [SIOCGIWRETRY   - SIOCIWFIRST] = wl3501_get_retry,
-       [SIOCGIWENCODE  - SIOCIWFIRST] = wl3501_get_encode,
-       [SIOCGIWPOWER   - SIOCIWFIRST] = wl3501_get_power,
+       IW_HANDLER(SIOCGIWNAME, wl3501_get_name),
+       IW_HANDLER(SIOCSIWFREQ, wl3501_set_freq),
+       IW_HANDLER(SIOCGIWFREQ, wl3501_get_freq),
+       IW_HANDLER(SIOCSIWMODE, wl3501_set_mode),
+       IW_HANDLER(SIOCGIWMODE, wl3501_get_mode),
+       IW_HANDLER(SIOCGIWSENS, wl3501_get_sens),
+       IW_HANDLER(SIOCGIWRANGE, wl3501_get_range),
+       IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
+       IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
+       IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy),
+       IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy),
+       IW_HANDLER(SIOCSIWAP, wl3501_set_wap),
+       IW_HANDLER(SIOCGIWAP, wl3501_get_wap),
+       IW_HANDLER(SIOCSIWSCAN, wl3501_set_scan),
+       IW_HANDLER(SIOCGIWSCAN, wl3501_get_scan),
+       IW_HANDLER(SIOCSIWESSID, wl3501_set_essid),
+       IW_HANDLER(SIOCGIWESSID, wl3501_get_essid),
+       IW_HANDLER(SIOCSIWNICKN, wl3501_set_nick),
+       IW_HANDLER(SIOCGIWNICKN, wl3501_get_nick),
+       IW_HANDLER(SIOCGIWRATE, wl3501_get_rate),
+       IW_HANDLER(SIOCGIWRTS, wl3501_get_rts_threshold),
+       IW_HANDLER(SIOCGIWFRAG, wl3501_get_frag_threshold),
+       IW_HANDLER(SIOCGIWTXPOW, wl3501_get_txpow),
+       IW_HANDLER(SIOCGIWRETRY, wl3501_get_retry),
+       IW_HANDLER(SIOCGIWENCODE, wl3501_get_encode),
+       IW_HANDLER(SIOCGIWPOWER, wl3501_get_power),
  };
  
  static const struct iw_handler_def wl3501_handler_def = {
@@@ -1899,6 -1894,10 +1896,6 @@@ static int wl3501_probe(struct pcmcia_d
        p_dev->io.Attributes1   = IO_DATA_PATH_WIDTH_8;
        p_dev->io.IOAddrLines   = 5;
  
 -      /* Interrupt setup */
 -      p_dev->irq.Attributes   = IRQ_TYPE_DYNAMIC_SHARING;
 -      p_dev->irq.Handler = wl3501_interrupt;
 -
        /* General socket configuration */
        p_dev->conf.Attributes  = CONF_ENABLE_IRQ;
        p_dev->conf.IntType     = INT_MEMORY_AND_IO;
@@@ -1959,7 -1958,7 +1956,7 @@@ static int wl3501_config(struct pcmcia_
        /* Now allocate an interrupt line. Note that this does not actually
         * assign a handler to the interrupt. */
  
 -      ret = pcmcia_request_irq(link, &link->irq);
 +      ret = pcmcia_request_irq(link, wl3501_interrupt);
        if (ret)
                goto failed;
  
        if (ret)
                goto failed;
  
 -      dev->irq = link->irq.AssignedIRQ;
 +      dev->irq = link->irq;
        dev->base_addr = link->io.BasePort1;
        SET_NETDEV_DEV(dev, &link->dev);
        if (register_netdev(dev)) {
        }
  
        this = netdev_priv(dev);
 -      /*
 -       * At this point, the dev_node_t structure(s) should be initialized and
 -       * arranged in a linked list at link->dev_node.
 -       */
 -      link->dev_node = &this->node;
  
        this->base_addr = dev->base_addr;
  
        if (!wl3501_get_flash_mac_addr(this)) {
                printk(KERN_WARNING "%s: Cant read MAC addr in flash ROM?\n",
                       dev->name);
 +              unregister_netdev(dev);
                goto failed;
        }
 -      strcpy(this->node.dev_name, dev->name);
  
        for (i = 0; i < 6; i++)
                dev->dev_addr[i] = ((char *)&this->mac_addr)[i];
@@@ -2031,6 -2035,12 +2028,6 @@@ failed
   */
  static void wl3501_release(struct pcmcia_device *link)
  {
 -      struct net_device *dev = link->priv;
 -
 -      /* Unlink the device chain */
 -      if (link->dev_node)
 -              unregister_netdev(dev);
 -
        pcmcia_disable_device(link);
  }
  
@@@ -53,7 -53,7 +53,7 @@@ struct kmem_cache *qeth_core_header_cac
  EXPORT_SYMBOL_GPL(qeth_core_header_cache);
  
  static struct device *qeth_core_root_dev;
- static unsigned int known_devices[][10] = QETH_MODELLIST_ARRAY;
+ static unsigned int known_devices[][6] = QETH_MODELLIST_ARRAY;
  static struct lock_class_key qdio_out_skb_queue_key;
  
  static void qeth_send_control_data_cb(struct qeth_channel *,
@@@ -111,21 -111,29 +111,29 @@@ static inline const char *qeth_get_card
  {
        if (card->info.guestlan) {
                switch (card->info.type) {
-               case QETH_CARD_TYPE_OSAE:
+               case QETH_CARD_TYPE_OSD:
                        return " Guest LAN QDIO";
                case QETH_CARD_TYPE_IQD:
                        return " Guest LAN Hiper";
+               case QETH_CARD_TYPE_OSM:
+                       return " Guest LAN QDIO - OSM";
+               case QETH_CARD_TYPE_OSX:
+                       return " Guest LAN QDIO - OSX";
                default:
                        return " unknown";
                }
        } else {
                switch (card->info.type) {
-               case QETH_CARD_TYPE_OSAE:
+               case QETH_CARD_TYPE_OSD:
                        return " OSD Express";
                case QETH_CARD_TYPE_IQD:
                        return " HiperSockets";
                case QETH_CARD_TYPE_OSN:
                        return " OSN QDIO";
+               case QETH_CARD_TYPE_OSM:
+                       return " OSM QDIO";
+               case QETH_CARD_TYPE_OSX:
+                       return " OSX QDIO";
                default:
                        return " unknown";
                }
@@@ -138,16 -146,20 +146,20 @@@ const char *qeth_get_cardname_short(str
  {
        if (card->info.guestlan) {
                switch (card->info.type) {
-               case QETH_CARD_TYPE_OSAE:
+               case QETH_CARD_TYPE_OSD:
                        return "GuestLAN QDIO";
                case QETH_CARD_TYPE_IQD:
                        return "GuestLAN Hiper";
+               case QETH_CARD_TYPE_OSM:
+                       return "GuestLAN OSM";
+               case QETH_CARD_TYPE_OSX:
+                       return "GuestLAN OSX";
                default:
                        return "unknown";
                }
        } else {
                switch (card->info.type) {
-               case QETH_CARD_TYPE_OSAE:
+               case QETH_CARD_TYPE_OSD:
                        switch (card->info.link_type) {
                        case QETH_LINK_TYPE_FAST_ETH:
                                return "OSD_100";
                        return "HiperSockets";
                case QETH_CARD_TYPE_OSN:
                        return "OSN";
+               case QETH_CARD_TYPE_OSM:
+                       return "OSM_1000";
+               case QETH_CARD_TYPE_OSX:
+                       return "OSX_10GIG";
                default:
                        return "unknown";
                }
@@@ -419,7 -435,8 +435,8 @@@ void qeth_clear_ipacmd_list(struct qeth
  }
  EXPORT_SYMBOL_GPL(qeth_clear_ipacmd_list);
  
- static int qeth_check_idx_response(unsigned char *buffer)
+ static int qeth_check_idx_response(struct qeth_card *card,
+       unsigned char *buffer)
  {
        if (!buffer)
                return 0;
                QETH_DBF_TEXT(TRACE, 2, "ckidxres");
                QETH_DBF_TEXT(TRACE, 2, " idxterm");
                QETH_DBF_TEXT_(TRACE, 2, "  rc%d", -EIO);
+               if (buffer[4] == 0xf6) {
+                       dev_err(&card->gdev->dev,
+                       "The qeth device is not configured "
+                       "for the OSI layer required by z/VM\n");
+                       return -EPERM;
+               }
                return -EIO;
        }
        return 0;
@@@ -528,18 -551,19 +551,19 @@@ static void qeth_send_control_data_cb(s
        struct qeth_ipa_cmd *cmd;
        unsigned long flags;
        int keep_reply;
+       int rc = 0;
  
        QETH_DBF_TEXT(TRACE, 4, "sndctlcb");
  
        card = CARD_FROM_CDEV(channel->ccwdev);
-       if (qeth_check_idx_response(iob->data)) {
+       rc = qeth_check_idx_response(card, iob->data);
+       switch (rc) {
+       case 0:
+               break;
+       case -EIO:
                qeth_clear_ipacmd_list(card);
-               if (((iob->data[2] & 0xc0) == 0xc0) && iob->data[4] == 0xf6)
-                       dev_err(&card->gdev->dev,
-                               "The qeth device is not configured "
-                               "for the OSI layer required by z/VM\n");
-               else
-                       qeth_schedule_recovery(card);
+               qeth_schedule_recovery(card);
+       default:
                goto out;
        }
  
@@@ -606,7 -630,7 +630,7 @@@ static int qeth_setup_channel(struct qe
  
        QETH_DBF_TEXT(SETUP, 2, "setupch");
        for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++) {
-               channel->iob[cnt].data = (char *)
+               channel->iob[cnt].data =
                        kmalloc(QETH_BUFSIZE, GFP_DMA|GFP_KERNEL);
                if (channel->iob[cnt].data == NULL)
                        break;
@@@ -719,7 -743,7 +743,7 @@@ static int qeth_get_problem(struct ccw_
                QETH_DBF_TEXT(TRACE, 2, "CGENCHK");
                dev_warn(&cdev->dev, "The qeth device driver "
                        "failed to recover an error on the device\n");
-               QETH_DBF_MESSAGE(2, "%s check on device dstat=x%x, cstat=x%x ",
+               QETH_DBF_MESSAGE(2, "%s check on device dstat=x%x, cstat=x%x\n",
                        dev_name(&cdev->dev), dstat, cstat);
                print_hex_dump(KERN_WARNING, "qeth: irb ", DUMP_PREFIX_OFFSET,
                                16, 1, irb, 64, 1);
@@@ -998,9 -1022,8 +1022,8 @@@ static void qeth_clean_channel(struct q
                kfree(channel->iob[cnt].data);
  }
  
- static int qeth_is_1920_device(struct qeth_card *card)
+ static void qeth_get_channel_path_desc(struct qeth_card *card)
  {
-       int single_queue = 0;
        struct ccw_device *ccwdev;
        struct channelPath_dsc {
                u8 flags;
                u8 chpp;
        } *chp_dsc;
  
-       QETH_DBF_TEXT(SETUP, 2, "chk_1920");
+       QETH_DBF_TEXT(SETUP, 2, "chp_desc");
  
        ccwdev = card->data.ccwdev;
        chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0);
        if (chp_dsc != NULL) {
                /* CHPP field bit 6 == 1 -> single queue */
-               single_queue = ((chp_dsc->chpp & 0x02) == 0x02);
+               if ((chp_dsc->chpp & 0x02) == 0x02)
+                       card->qdio.no_out_queues = 1;
+               card->info.func_level = 0x4100 + chp_dsc->desc;
                kfree(chp_dsc);
        }
-       QETH_DBF_TEXT_(SETUP, 2, "rc:%x", single_queue);
-       return single_queue;
+       if (card->qdio.no_out_queues == 1) {
+               card->qdio.default_out_queue = 0;
+               dev_info(&card->gdev->dev,
+                       "Priority Queueing not supported\n");
+       }
+       QETH_DBF_TEXT_(SETUP, 2, "nr:%x", card->qdio.no_out_queues);
+       QETH_DBF_TEXT_(SETUP, 2, "lvl:%02x", card->info.func_level);
+       return;
  }
  
  static void qeth_init_qdio_info(struct qeth_card *card)
@@@ -1100,6 -1131,7 +1131,7 @@@ static int qeth_setup_card(struct qeth_
        spin_lock_init(&card->lock);
        spin_lock_init(&card->ip_lock);
        spin_lock_init(&card->thread_mask_lock);
+       mutex_init(&card->conf_mutex);
        card->thread_start_mask = 0;
        card->thread_allowed_mask = 0;
        card->thread_running_mask = 0;
@@@ -1170,18 -1202,17 +1202,17 @@@ static int qeth_determine_card_type(str
  
        card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
        card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
-       while (known_devices[i][4]) {
-               if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) &&
-                   (CARD_RDEV(card)->id.dev_model == known_devices[i][3])) {
-                       card->info.type = known_devices[i][4];
-                       card->qdio.no_out_queues = known_devices[i][8];
-                       card->info.is_multicast_different = known_devices[i][9];
-                       if (qeth_is_1920_device(card)) {
-                               dev_info(&card->gdev->dev,
-                                       "Priority Queueing not supported\n");
-                               card->qdio.no_out_queues = 1;
-                               card->qdio.default_out_queue = 0;
-                       }
+       while (known_devices[i][QETH_DEV_MODEL_IND]) {
+               if ((CARD_RDEV(card)->id.dev_type ==
+                               known_devices[i][QETH_DEV_TYPE_IND]) &&
+                   (CARD_RDEV(card)->id.dev_model ==
+                               known_devices[i][QETH_DEV_MODEL_IND])) {
+                       card->info.type = known_devices[i][QETH_DEV_MODEL_IND];
+                       card->qdio.no_out_queues =
+                               known_devices[i][QETH_QUEUE_NO_IND];
+                       card->info.is_multicast_different =
+                               known_devices[i][QETH_MULTICAST_IND];
+                       qeth_get_channel_path_desc(card);
                        return 0;
                }
                i++;
@@@ -1292,14 -1323,13 +1323,14 @@@ int qeth_qdio_clear_card(struct qeth_ca
                QETH_QDIO_CLEANING)) {
        case QETH_QDIO_ESTABLISHED:
                if (card->info.type == QETH_CARD_TYPE_IQD)
 -                      rc = qdio_cleanup(CARD_DDEV(card),
 +                      rc = qdio_shutdown(CARD_DDEV(card),
                                QDIO_FLAG_CLEANUP_USING_HALT);
                else
 -                      rc = qdio_cleanup(CARD_DDEV(card),
 +                      rc = qdio_shutdown(CARD_DDEV(card),
                                QDIO_FLAG_CLEANUP_USING_CLEAR);
                if (rc)
                        QETH_DBF_TEXT_(TRACE, 3, "1err%d", rc);
 +              qdio_free(CARD_DDEV(card));
                atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
                break;
        case QETH_QDIO_CLEANING:
@@@ -1399,22 -1429,20 +1430,20 @@@ static void qeth_init_tokens(struct qet
  
  static void qeth_init_func_level(struct qeth_card *card)
  {
-       if (card->ipato.enabled) {
-               if (card->info.type == QETH_CARD_TYPE_IQD)
-                               card->info.func_level =
-                                       QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT;
-               else
-                               card->info.func_level =
-                                       QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT;
-       } else {
-               if (card->info.type == QETH_CARD_TYPE_IQD)
-               /*FIXME:why do we have same values for  dis and ena for
-                 osae??? */
+       switch (card->info.type) {
+       case QETH_CARD_TYPE_IQD:
+               if (card->ipato.enabled)
                        card->info.func_level =
-                               QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT;
+                               QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT;
                else
                        card->info.func_level =
-                               QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT;
+                               QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT;
+               break;
+       case QETH_CARD_TYPE_OSD:
+               card->info.func_level = QETH_IDX_FUNC_LEVEL_OSD;
+               break;
+       default:
+               break;
        }
  }
  
@@@ -1561,7 -1589,7 +1590,7 @@@ static void qeth_idx_write_cb(struct qe
        card = CARD_FROM_CDEV(channel->ccwdev);
  
        if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
-               if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
+               if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == QETH_IDX_ACT_ERR_EXCL)
                        dev_err(&card->write.ccwdev->dev,
                                "The adapter is used exclusively by another "
                                "host\n");
@@@ -1597,27 -1625,35 +1626,35 @@@ static void qeth_idx_read_cb(struct qet
        }
  
        card = CARD_FROM_CDEV(channel->ccwdev);
-       if (qeth_check_idx_response(iob->data))
+       if (qeth_check_idx_response(card, iob->data))
                        goto out;
  
        if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
-               if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
+               switch (QETH_IDX_ACT_CAUSE_CODE(iob->data)) {
+               case QETH_IDX_ACT_ERR_EXCL:
                        dev_err(&card->write.ccwdev->dev,
                                "The adapter is used exclusively by another "
                                "host\n");
-               else
+                       break;
+               case QETH_IDX_ACT_ERR_AUTH:
+                       dev_err(&card->read.ccwdev->dev,
+                               "Setting the device online failed because of "
+                               "insufficient LPAR authorization\n");
+                       break;
+               default:
                        QETH_DBF_MESSAGE(2, "%s IDX_ACTIVATE on read channel:"
                                " negative reply\n",
                                dev_name(&card->read.ccwdev->dev));
+               }
                goto out;
        }
  
  /**
-  * temporary fix for microcode bug
-  * to revert it,replace OR by AND
-  */
+  *  * temporary fix for microcode bug
+  *   * to revert it,replace OR by AND
+  *    */
        if ((!QETH_IDX_NO_PORTNAME_REQUIRED(iob->data)) ||
-            (card->info.type == QETH_CARD_TYPE_OSAE))
+            (card->info.type == QETH_CARD_TYPE_OSD))
                card->info.portname_required = 1;
  
        memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
@@@ -1826,7 -1862,7 +1863,7 @@@ static inline int qeth_get_initial_mtu_
                return 1500;
        case QETH_CARD_TYPE_IQD:
                return card->info.max_mtu;
-       case QETH_CARD_TYPE_OSAE:
+       case QETH_CARD_TYPE_OSD:
                switch (card->info.link_type) {
                case QETH_LINK_TYPE_HSTR:
                case QETH_LINK_TYPE_LANE_TR:
                default:
                        return 1492;
                }
+       case QETH_CARD_TYPE_OSM:
+       case QETH_CARD_TYPE_OSX:
+               return 1492;
        default:
                return 1500;
        }
@@@ -1844,8 -1883,10 +1884,10 @@@ static inline int qeth_get_max_mtu_for_
        switch (cardtype) {
  
        case QETH_CARD_TYPE_UNKNOWN:
-       case QETH_CARD_TYPE_OSAE:
+       case QETH_CARD_TYPE_OSD:
        case QETH_CARD_TYPE_OSN:
+       case QETH_CARD_TYPE_OSM:
+       case QETH_CARD_TYPE_OSX:
                return 61440;
        case QETH_CARD_TYPE_IQD:
                return 57344;
@@@ -1883,7 -1924,9 +1925,9 @@@ static inline int qeth_get_mtu_outof_fr
  static inline int qeth_mtu_is_valid(struct qeth_card *card, int mtu)
  {
        switch (card->info.type) {
-       case QETH_CARD_TYPE_OSAE:
+       case QETH_CARD_TYPE_OSD:
+       case QETH_CARD_TYPE_OSM:
+       case QETH_CARD_TYPE_OSX:
                return ((mtu >= 576) && (mtu <= 61440));
        case QETH_CARD_TYPE_IQD:
                return ((mtu >= 576) &&
@@@ -1934,6 -1977,7 +1978,7 @@@ static int qeth_ulp_enable_cb(struct qe
                card->info.link_type = link_type;
        } else
                card->info.link_type = 0;
+       QETH_DBF_TEXT_(SETUP, 2, "link%d", link_type);
        QETH_DBF_TEXT_(SETUP, 2, "  rc%d", iob->rc);
        return 0;
  }
@@@ -1977,6 -2021,7 +2022,7 @@@ static int qeth_ulp_setup_cb(struct qet
                unsigned long data)
  {
        struct qeth_cmd_buffer *iob;
+       int rc = 0;
  
        QETH_DBF_TEXT(SETUP, 2, "ulpstpcb");
  
        memcpy(&card->token.ulp_connection_r,
               QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(iob->data),
               QETH_MPC_TOKEN_LENGTH);
+       if (!strncmp("00S", QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(iob->data),
+                    3)) {
+               QETH_DBF_TEXT(SETUP, 2, "olmlimit");
+               dev_err(&card->gdev->dev, "A connection could not be "
+                       "established because of an OLM limit\n");
+               rc = -EMLINK;
+       }
        QETH_DBF_TEXT_(SETUP, 2, "  rc%d", iob->rc);
-       return 0;
+       return rc;
  }
  
  static int qeth_ulp_setup(struct qeth_card *card)
@@@ -2238,7 -2290,9 +2291,9 @@@ static void qeth_print_status_no_portna
  void qeth_print_status_message(struct qeth_card *card)
  {
        switch (card->info.type) {
-       case QETH_CARD_TYPE_OSAE:
+       case QETH_CARD_TYPE_OSD:
+       case QETH_CARD_TYPE_OSM:
+       case QETH_CARD_TYPE_OSX:
                /* VM will use a non-zero first character
                 * to indicate a HiperSockets like reporting
                 * of the level OSA sets the first character to zero
@@@ -2545,9 -2599,11 +2600,11 @@@ static int qeth_query_setadapterparms_c
        QETH_DBF_TEXT(TRACE, 3, "quyadpcb");
  
        cmd = (struct qeth_ipa_cmd *) data;
-       if (cmd->data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f)
+       if (cmd->data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f) {
                card->info.link_type =
                      cmd->data.setadapterparms.data.query_cmds_supp.lan_type;
+               QETH_DBF_TEXT_(SETUP, 2, "lnk %d", card->info.link_type);
+       }
        card->options.adp.supported_funcs =
                cmd->data.setadapterparms.data.query_cmds_supp.supported_cmds;
        return qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
@@@ -2937,7 -2993,8 +2994,8 @@@ EXPORT_SYMBOL_GPL(qeth_qdio_output_hand
  int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
                        int ipv, int cast_type)
  {
-       if (!ipv && (card->info.type == QETH_CARD_TYPE_OSAE))
+       if (!ipv && (card->info.type == QETH_CARD_TYPE_OSD ||
+                    card->info.type == QETH_CARD_TYPE_OSX))
                return card->qdio.default_out_queue;
        switch (card->qdio.no_out_queues) {
        case 4:
@@@ -3499,13 -3556,14 +3557,14 @@@ int qeth_set_access_ctrl_online(struct 
  
        QETH_DBF_TEXT(TRACE, 4, "setactlo");
  
-       if (card->info.type == QETH_CARD_TYPE_OSAE &&
-           qeth_adp_supported(card, IPA_SETADP_SET_ACCESS_CONTROL)) {
+       if ((card->info.type == QETH_CARD_TYPE_OSD ||
+            card->info.type == QETH_CARD_TYPE_OSX) &&
+            qeth_adp_supported(card, IPA_SETADP_SET_ACCESS_CONTROL)) {
                rc = qeth_setadpparms_set_access_ctrl(card,
                        card->options.isolation);
                if (rc) {
                        QETH_DBF_MESSAGE(3,
-                               "IPA(SET_ACCESS_CTRL,%s,%d) sent failed",
+                               "IPA(SET_ACCESS_CTRL,%s,%d) sent failed\n",
                                card->gdev->dev.kobj.name,
                                rc);
                }
@@@ -3811,18 -3869,10 +3870,18 @@@ static int qeth_qdio_establish(struct q
  
        if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED,
                QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) {
 -              rc = qdio_initialize(&init_data);
 -              if (rc)
 +              rc = qdio_allocate(&init_data);
 +              if (rc) {
 +                      atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
 +                      goto out;
 +              }
 +              rc = qdio_establish(&init_data);
 +              if (rc) {
                        atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
 +                      qdio_free(CARD_DDEV(card));
 +              }
        }
 +out:
        kfree(out_sbal_ptrs);
        kfree(in_sbal_ptrs);
        kfree(qib_param_field);
@@@ -3845,9 -3895,16 +3904,16 @@@ static void qeth_core_free_card(struct 
  }
  
  static struct ccw_device_id qeth_ids[] = {
-       {CCW_DEVICE(0x1731, 0x01), .driver_info = QETH_CARD_TYPE_OSAE},
-       {CCW_DEVICE(0x1731, 0x05), .driver_info = QETH_CARD_TYPE_IQD},
-       {CCW_DEVICE(0x1731, 0x06), .driver_info = QETH_CARD_TYPE_OSN},
+       {CCW_DEVICE_DEVTYPE(0x1731, 0x01, 0x1732, 0x01),
+                                       .driver_info = QETH_CARD_TYPE_OSD},
+       {CCW_DEVICE_DEVTYPE(0x1731, 0x05, 0x1732, 0x05),
+                                       .driver_info = QETH_CARD_TYPE_IQD},
+       {CCW_DEVICE_DEVTYPE(0x1731, 0x06, 0x1732, 0x06),
+                                       .driver_info = QETH_CARD_TYPE_OSN},
+       {CCW_DEVICE_DEVTYPE(0x1731, 0x02, 0x1732, 0x03),
+                                       .driver_info = QETH_CARD_TYPE_OSM},
+       {CCW_DEVICE_DEVTYPE(0x1731, 0x02, 0x1732, 0x02),
+                                       .driver_info = QETH_CARD_TYPE_OSX},
        {},
  };
  MODULE_DEVICE_TABLE(ccw, qeth_ids);
@@@ -4251,25 -4308,25 +4317,25 @@@ static int qeth_core_probe_device(struc
                goto err_card;
        }
  
-       if (card->info.type == QETH_CARD_TYPE_OSN) {
+       if (card->info.type == QETH_CARD_TYPE_OSN)
                rc = qeth_core_create_osn_attributes(dev);
-               if (rc)
-                       goto err_card;
+       else
+               rc = qeth_core_create_device_attributes(dev);
+       if (rc)
+               goto err_card;
+       switch (card->info.type) {
+       case QETH_CARD_TYPE_OSN:
+       case QETH_CARD_TYPE_OSM:
                rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
-               if (rc) {
-                       qeth_core_remove_osn_attributes(dev);
-                       goto err_card;
-               }
+               if (rc)
+                       goto err_attr;
                rc = card->discipline.ccwgdriver->probe(card->gdev);
-               if (rc) {
-                       qeth_core_free_discipline(card);
-                       qeth_core_remove_osn_attributes(dev);
-                       goto err_card;
-               }
-       } else {
-               rc = qeth_core_create_device_attributes(dev);
                if (rc)
-                       goto err_card;
+                       goto err_disc;
+       case QETH_CARD_TYPE_OSD:
+       case QETH_CARD_TYPE_OSX:
+       default:
+               break;
        }
  
        write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
        qeth_determine_capabilities(card);
        return 0;
  
+ err_disc:
+       qeth_core_free_discipline(card);
+ err_attr:
+       if (card->info.type == QETH_CARD_TYPE_OSN)
+               qeth_core_remove_osn_attributes(dev);
+       else
+               qeth_core_remove_device_attributes(dev);
  err_card:
        qeth_core_free_card(card);
  err_dev:
diff --combined drivers/ssb/main.c
@@@ -490,7 -490,7 +490,7 @@@ static int ssb_devices_register(struct 
                        break;
                case SSB_BUSTYPE_PCMCIA:
  #ifdef CONFIG_SSB_PCMCIAHOST
 -                      sdev->irq = bus->host_pcmcia->irq.AssignedIRQ;
 +                      sdev->irq = bus->host_pcmcia->irq;
                        dev->parent = &bus->host_pcmcia->dev;
  #endif
                        break;
@@@ -834,6 -834,9 +834,9 @@@ int ssb_bus_pcibus_register(struct ssb_
        if (!err) {
                ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "
                           "PCI device %s\n", dev_name(&host_pci->dev));
+       } else {
+               ssb_printk(KERN_ERR PFX "Failed to register PCI version"
+                          " of SSB with error %d\n", err);
        }
  
        return err;
@@@ -3591,20 -3591,20 +3591,20 @@@ wv_82593_config(struct net_device *  dev
      /* If roaming is enabled, join the "Beacon Request" multicast group... */
      /* But only if it's not in there already! */
    if(do_roaming)
-     dev_mc_add(dev,WAVELAN_BEACON_ADDRESS, WAVELAN_ADDR_SIZE, 1);
+     dev_mc_add(dev, WAVELAN_BEACON_ADDRESS);
  #endif        /* WAVELAN_ROAMING */
  
    /* If any multicast address to set */
    if(lp->mc_count)
      {
-       struct dev_mc_list *dmi;
+       struct netdev_hw_addr *ha;
        int                     addrs_len = WAVELAN_ADDR_SIZE * lp->mc_count;
  
  #ifdef DEBUG_CONFIG_INFO
        printk(KERN_DEBUG "%s: wv_hw_config(): set %d multicast addresses:\n",
             dev->name, lp->mc_count);
-       netdev_for_each_mc_addr(dmi, dev)
-       printk(KERN_DEBUG " %pM\n", dmi->dmi_addr);
+       netdev_for_each_mc_addr(ha, dev)
+       printk(KERN_DEBUG " %pM\n", ha->addr);
  #endif
  
        /* Initialize adapter's ethernet multicast addresses */
        outb(((TX_BASE >> 8) & PIORH_MASK) | PIORH_SEL_TX, PIORH(base));
        outb(addrs_len & 0xff, PIOP(base));     /* byte count lsb */
        outb((addrs_len >> 8), PIOP(base));     /* byte count msb */
-       netdev_for_each_mc_addr(dmi, dev)
-       outsb(PIOP(base), dmi->dmi_addr, dmi->dmi_addrlen);
+       netdev_for_each_mc_addr(ha, dev)
+       outsb(PIOP(base), ha->addr, dev->addr_len);
  
        /* reset transmit DMA pointer */
        hacr_write_slow(base, HACR_PWR_STAT | HACR_TX_DMA_RESET);
@@@ -3850,8 -3850,12 +3850,8 @@@ wv_pcmcia_config(struct pcmcia_device 
        if (i != 0)
          break;
  
 -      /*
 -       * Now allocate an interrupt line.  Note that this does not
 -       * actually assign a handler to the interrupt.
 -       */
 -      i = pcmcia_request_irq(link, &link->irq);
 -      if (i != 0)
 +      i = pcmcia_request_interrupt(link, wavelan_interrupt);
 +      if (!i)
          break;
  
        /*
          break;
  
        /* Feed device with this info... */
 -      dev->irq = link->irq.AssignedIRQ;
 +      dev->irq = link->irq;
        dev->base_addr = link->io.BasePort1;
        netif_start_queue(dev);
  
@@@ -4433,6 -4437,10 +4433,6 @@@ wavelan_probe(struct pcmcia_device *p_d
    p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
    p_dev->io.IOAddrLines = 3;
  
 -  /* Interrupt setup */
 -  p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
 -  p_dev->irq.Handler = wavelan_interrupt;
 -
    /* General socket configuration */
    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
    p_dev->conf.IntType = INT_MEMORY_AND_IO;
  
    ret = wv_hw_config(dev);
    if (ret) {
 -        dev->irq = 0;
          pcmcia_disable_device(p_dev);
          return ret;
    }
diff --combined include/linux/fs.h
@@@ -1280,10 -1280,12 +1280,12 @@@ static inline int lock_may_write(struc
  
  
  struct fasync_struct {
-       int     magic;
-       int     fa_fd;
-       struct  fasync_struct   *fa_next; /* singly linked list */
-       struct  file            *fa_file;
+       spinlock_t              fa_lock;
+       int                     magic;
+       int                     fa_fd;
+       struct fasync_struct    *fa_next; /* singly linked list */
+       struct file             *fa_file;
+       struct rcu_head         fa_rcu;
  };
  
  #define FASYNC_MAGIC 0x4601
  extern int fasync_helper(int, struct file *, int, struct fasync_struct **);
  /* can be called from interrupts */
  extern void kill_fasync(struct fasync_struct **, int, int);
- /* only for net: no internal synchronization */
- extern void __kill_fasync(struct fasync_struct *, int, int);
  
  extern int __f_setown(struct file *filp, struct pid *, enum pid_type, int force);
  extern int f_setown(struct file *filp, unsigned long arg, int force);
@@@ -2362,8 -2362,6 +2362,8 @@@ extern void simple_release_fs(struct vf
  
  extern ssize_t simple_read_from_buffer(void __user *to, size_t count,
                        loff_t *ppos, const void *from, size_t available);
 +extern ssize_t simple_write_to_buffer(void *to, size_t available, loff_t *ppos,
 +              const void __user *from, size_t count);
  
  extern int simple_fsync(struct file *, struct dentry *, int);
  
@@@ -31,7 -31,6 +31,7 @@@
  #include <linux/if_link.h>
  
  #ifdef __KERNEL__
 +#include <linux/pm_qos_params.h>
  #include <linux/timer.h>
  #include <linux/delay.h>
  #include <linux/mm.h>
@@@ -219,34 -218,6 +219,6 @@@ struct neighbour
  struct neigh_parms;
  struct sk_buff;
  
- struct netif_rx_stats {
-       unsigned total;
-       unsigned dropped;
-       unsigned time_squeeze;
-       unsigned cpu_collision;
- };
- DECLARE_PER_CPU(struct netif_rx_stats, netdev_rx_stat);
- struct dev_addr_list {
-       struct dev_addr_list    *next;
-       u8                      da_addr[MAX_ADDR_LEN];
-       u8                      da_addrlen;
-       u8                      da_synced;
-       int                     da_users;
-       int                     da_gusers;
- };
- /*
-  *    We tag multicasts with these structures.
-  */
- #define dev_mc_list   dev_addr_list
- #define dmi_addr      da_addr
- #define dmi_addrlen   da_addrlen
- #define dmi_users     da_users
- #define dmi_gusers    da_gusers
  struct netdev_hw_addr {
        struct list_head        list;
        unsigned char           addr[MAX_ADDR_LEN];
  #define NETDEV_HW_ADDR_T_SAN          2
  #define NETDEV_HW_ADDR_T_SLAVE                3
  #define NETDEV_HW_ADDR_T_UNICAST      4
+ #define NETDEV_HW_ADDR_T_MULTICAST    5
        int                     refcount;
        bool                    synced;
+       bool                    global_use;
        struct rcu_head         rcu_head;
  };
  
@@@ -265,16 -238,20 +239,20 @@@ struct netdev_hw_addr_list 
        int                     count;
  };
  
- #define netdev_uc_count(dev) ((dev)->uc.count)
- #define netdev_uc_empty(dev) ((dev)->uc.count == 0)
- #define netdev_for_each_uc_addr(ha, dev) \
-       list_for_each_entry(ha, &dev->uc.list, list)
+ #define netdev_hw_addr_list_count(l) ((l)->count)
+ #define netdev_hw_addr_list_empty(l) (netdev_hw_addr_list_count(l) == 0)
+ #define netdev_hw_addr_list_for_each(ha, l) \
+       list_for_each_entry(ha, &(l)->list, list)
  
- #define netdev_mc_count(dev) ((dev)->mc_count)
- #define netdev_mc_empty(dev) (netdev_mc_count(dev) == 0)
+ #define netdev_uc_count(dev) netdev_hw_addr_list_count(&(dev)->uc)
+ #define netdev_uc_empty(dev) netdev_hw_addr_list_empty(&(dev)->uc)
+ #define netdev_for_each_uc_addr(ha, dev) \
+       netdev_hw_addr_list_for_each(ha, &(dev)->uc)
  
- #define netdev_for_each_mc_addr(mclist, dev) \
-       for (mclist = dev->mc_list; mclist; mclist = mclist->next)
+ #define netdev_mc_count(dev) netdev_hw_addr_list_count(&(dev)->mc)
+ #define netdev_mc_empty(dev) netdev_hw_addr_list_empty(&(dev)->mc)
+ #define netdev_for_each_mc_addr(ha, dev) \
+       netdev_hw_addr_list_for_each(ha, &(dev)->mc)
  
  struct hh_cache {
        struct hh_cache *hh_next;       /* Next entry                        */
@@@ -531,6 -508,85 +509,85 @@@ struct netdev_queue 
        unsigned long           tx_dropped;
  } ____cacheline_aligned_in_smp;
  
+ #ifdef CONFIG_RPS
+ /*
+  * This structure holds an RPS map which can be of variable length.  The
+  * map is an array of CPUs.
+  */
+ struct rps_map {
+       unsigned int len;
+       struct rcu_head rcu;
+       u16 cpus[0];
+ };
+ #define RPS_MAP_SIZE(_num) (sizeof(struct rps_map) + (_num * sizeof(u16)))
+ /*
+  * The rps_dev_flow structure contains the mapping of a flow to a CPU and the
+  * tail pointer for that CPU's input queue at the time of last enqueue.
+  */
+ struct rps_dev_flow {
+       u16 cpu;
+       u16 fill;
+       unsigned int last_qtail;
+ };
+ /*
+  * The rps_dev_flow_table structure contains a table of flow mappings.
+  */
+ struct rps_dev_flow_table {
+       unsigned int mask;
+       struct rcu_head rcu;
+       struct work_struct free_work;
+       struct rps_dev_flow flows[0];
+ };
+ #define RPS_DEV_FLOW_TABLE_SIZE(_num) (sizeof(struct rps_dev_flow_table) + \
+     (_num * sizeof(struct rps_dev_flow)))
+ /*
+  * The rps_sock_flow_table contains mappings of flows to the last CPU
+  * on which they were processed by the application (set in recvmsg).
+  */
+ struct rps_sock_flow_table {
+       unsigned int mask;
+       u16 ents[0];
+ };
+ #define       RPS_SOCK_FLOW_TABLE_SIZE(_num) (sizeof(struct rps_sock_flow_table) + \
+     (_num * sizeof(u16)))
+ #define RPS_NO_CPU 0xffff
+ static inline void rps_record_sock_flow(struct rps_sock_flow_table *table,
+                                       u32 hash)
+ {
+       if (table && hash) {
+               unsigned int cpu, index = hash & table->mask;
+               /* We only give a hint, preemption can change cpu under us */
+               cpu = raw_smp_processor_id();
+               if (table->ents[index] != cpu)
+                       table->ents[index] = cpu;
+       }
+ }
+ static inline void rps_reset_sock_flow(struct rps_sock_flow_table *table,
+                                      u32 hash)
+ {
+       if (table && hash)
+               table->ents[hash & table->mask] = RPS_NO_CPU;
+ }
+ extern struct rps_sock_flow_table *rps_sock_flow_table;
+ /* This structure contains an instance of an RX queue. */
+ struct netdev_rx_queue {
+       struct rps_map *rps_map;
+       struct rps_dev_flow_table *rps_flow_table;
+       struct kobject kobj;
+       struct netdev_rx_queue *first;
+       atomic_t count;
+ } ____cacheline_aligned_in_smp;
+ #endif /* CONFIG_RPS */
  
  /*
   * This structure defines the management hooks for network devices.
   * int (*ndo_set_vf_tx_rate)(struct net_device *dev, int vf, int rate);
   * int (*ndo_get_vf_config)(struct net_device *dev,
   *                        int vf, struct ifla_vf_info *ivf);
+  * int (*ndo_set_vf_port)(struct net_device *dev, int vf,
+  *                      struct nlattr *port[]);
+  * int (*ndo_get_vf_port)(struct net_device *dev, int vf, struct sk_buff *skb);
   */
  #define HAVE_NET_DEVICE_OPS
  struct net_device_ops {
                                                        unsigned short vid);
  #ifdef CONFIG_NET_POLL_CONTROLLER
        void                    (*ndo_poll_controller)(struct net_device *dev);
+       void                    (*ndo_netpoll_cleanup)(struct net_device *dev);
  #endif
        int                     (*ndo_set_vf_mac)(struct net_device *dev,
                                                  int queue, u8 *mac);
        int                     (*ndo_get_vf_config)(struct net_device *dev,
                                                     int vf,
                                                     struct ifla_vf_info *ivf);
+       int                     (*ndo_set_vf_port)(struct net_device *dev,
+                                                  int vf,
+                                                  struct nlattr *port[]);
+       int                     (*ndo_get_vf_port)(struct net_device *dev,
+                                                  int vf, struct sk_buff *skb);
  #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
        int                     (*ndo_fcoe_enable)(struct net_device *dev);
        int                     (*ndo_fcoe_disable)(struct net_device *dev);
@@@ -712,9 -777,6 +778,9 @@@ struct net_device 
         * the interface.
         */
        char                    name[IFNAMSIZ];
 +
 +      struct pm_qos_request_list *pm_qos_req;
 +
        /* device name hash chain */
        struct hlist_node       name_hlist;
        /* snmp alias */
  #define NETIF_F_SCTP_CSUM     (1 << 25) /* SCTP checksum offload */
  #define NETIF_F_FCOE_MTU      (1 << 26) /* Supports max FCoE MTU, 2158 bytes*/
  #define NETIF_F_NTUPLE                (1 << 27) /* N-tuple filters supported */
+ #define NETIF_F_RXHASH                (1 << 28) /* Receive hashing offload */
  
        /* Segmentation offload features */
  #define NETIF_F_GSO_SHIFT     16
        unsigned char           operstate; /* RFC2863 operstate */
        unsigned char           link_mode; /* mapping policy to operstate */
  
-       unsigned                mtu;    /* interface MTU value          */
+       unsigned int            mtu;    /* interface MTU value          */
        unsigned short          type;   /* interface hardware type      */
        unsigned short          hard_header_len;        /* hardware hdr length  */
  
        unsigned char           addr_len;       /* hardware address length      */
        unsigned short          dev_id;         /* for shared network cards */
  
-       struct netdev_hw_addr_list      uc;     /* Secondary unicast
-                                                  mac addresses */
-       int                     uc_promisc;
        spinlock_t              addr_list_lock;
-       struct dev_addr_list    *mc_list;       /* Multicast mac addresses      */
-       int                     mc_count;       /* Number of installed mcasts   */
+       struct netdev_hw_addr_list      uc;     /* Unicast mac addresses */
+       struct netdev_hw_addr_list      mc;     /* Multicast mac addresses */
+       int                     uc_promisc;
        unsigned int            promiscuity;
        unsigned int            allmulti;
  
  
        unsigned char           broadcast[MAX_ADDR_LEN];        /* hw bcast add */
  
+ #ifdef CONFIG_RPS
+       struct kset             *queues_kset;
+       struct netdev_rx_queue  *_rx;
+       /* Number of RX queues allocated at alloc_netdev_mq() time  */
+       unsigned int            num_rx_queues;
+ #endif
        struct netdev_queue     rx_queue;
  
        struct netdev_queue     *_tx ____cacheline_aligned_in_smp;
@@@ -1310,19 -1380,44 +1384,44 @@@ static inline int unregister_gifconf(un
  }
  
  /*
-  * Incoming packets are placed on per-cpu queues so that
-  * no locking is needed.
+  * Incoming packets are placed on per-cpu queues
   */
  struct softnet_data {
        struct Qdisc            *output_queue;
-       struct sk_buff_head     input_pkt_queue;
+       struct Qdisc            **output_queue_tailp;
        struct list_head        poll_list;
        struct sk_buff          *completion_queue;
+       struct sk_buff_head     process_queue;
+       /* stats */
+       unsigned int            processed;
+       unsigned int            time_squeeze;
+       unsigned int            cpu_collision;
+       unsigned int            received_rps;
+ #ifdef CONFIG_RPS
+       struct softnet_data     *rps_ipi_list;
+       /* Elements below can be accessed between CPUs for RPS */
+       struct call_single_data csd ____cacheline_aligned_in_smp;
+       struct softnet_data     *rps_ipi_next;
+       unsigned int            cpu;
+       unsigned int            input_queue_head;
+ #endif
+       unsigned                dropped;
+       struct sk_buff_head     input_pkt_queue;
        struct napi_struct      backlog;
  };
  
- DECLARE_PER_CPU(struct softnet_data,softnet_data);
+ static inline void input_queue_head_add(struct softnet_data *sd,
+                                       unsigned int len)
+ {
+ #ifdef CONFIG_RPS
+       sd->input_queue_head += len;
+ #endif
+ }
+ DECLARE_PER_CPU_ALIGNED(struct softnet_data, softnet_data);
  
  #define HAVE_NETIF_QUEUE
  
@@@ -1949,6 -2044,22 +2048,22 @@@ extern struct net_device *alloc_netdev_
  extern int            register_netdev(struct net_device *dev);
  extern void           unregister_netdev(struct net_device *dev);
  
+ /* General hardware address lists handling functions */
+ extern int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list,
+                                 struct netdev_hw_addr_list *from_list,
+                                 int addr_len, unsigned char addr_type);
+ extern void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list,
+                                  struct netdev_hw_addr_list *from_list,
+                                  int addr_len, unsigned char addr_type);
+ extern int __hw_addr_sync(struct netdev_hw_addr_list *to_list,
+                         struct netdev_hw_addr_list *from_list,
+                         int addr_len);
+ extern void __hw_addr_unsync(struct netdev_hw_addr_list *to_list,
+                            struct netdev_hw_addr_list *from_list,
+                            int addr_len);
+ extern void __hw_addr_flush(struct netdev_hw_addr_list *list);
+ extern void __hw_addr_init(struct netdev_hw_addr_list *list);
  /* Functions used for device addresses handling */
  extern int dev_addr_add(struct net_device *dev, unsigned char *addr,
                        unsigned char addr_type);
@@@ -1960,26 -2071,34 +2075,34 @@@ extern int dev_addr_add_multiple(struc
  extern int dev_addr_del_multiple(struct net_device *to_dev,
                                 struct net_device *from_dev,
                                 unsigned char addr_type);
+ extern void dev_addr_flush(struct net_device *dev);
+ extern int dev_addr_init(struct net_device *dev);
+ /* Functions used for unicast addresses handling */
+ extern int dev_uc_add(struct net_device *dev, unsigned char *addr);
+ extern int dev_uc_del(struct net_device *dev, unsigned char *addr);
+ extern int dev_uc_sync(struct net_device *to, struct net_device *from);
+ extern void dev_uc_unsync(struct net_device *to, struct net_device *from);
+ extern void dev_uc_flush(struct net_device *dev);
+ extern void dev_uc_init(struct net_device *dev);
+ /* Functions used for multicast addresses handling */
+ extern int dev_mc_add(struct net_device *dev, unsigned char *addr);
+ extern int dev_mc_add_global(struct net_device *dev, unsigned char *addr);
+ extern int dev_mc_del(struct net_device *dev, unsigned char *addr);
+ extern int dev_mc_del_global(struct net_device *dev, unsigned char *addr);
+ extern int dev_mc_sync(struct net_device *to, struct net_device *from);
+ extern void dev_mc_unsync(struct net_device *to, struct net_device *from);
+ extern void dev_mc_flush(struct net_device *dev);
+ extern void dev_mc_init(struct net_device *dev);
  
  /* Functions used for secondary unicast and multicast support */
  extern void           dev_set_rx_mode(struct net_device *dev);
  extern void           __dev_set_rx_mode(struct net_device *dev);
  extern int            dev_set_promiscuity(struct net_device *dev, int inc);
  extern int            dev_set_allmulti(struct net_device *dev, int inc);
  extern void           netdev_state_change(struct net_device *dev);
- extern void           netdev_bonding_change(struct net_device *dev,
+ extern int            netdev_bonding_change(struct net_device *dev,
                                              unsigned long event);
  extern void           netdev_features_change(struct net_device *dev);
  /* Load a device via the kmod */
@@@ -1989,6 -2108,7 +2112,7 @@@ extern const struct net_device_stats *d
  extern void           dev_txq_stats_fold(const struct net_device *dev, struct net_device_stats *stats);
  
  extern int            netdev_max_backlog;
+ extern int            netdev_tstamp_prequeue;
  extern int            weight_p;
  extern int            netdev_set_master(struct net_device *dev, struct net_device *master);
  extern int skb_checksum_help(struct sk_buff *skb);
@@@ -2049,54 -2169,14 +2173,14 @@@ static inline void netif_set_gso_max_si
        dev->gso_max_size = size;
  }
  
- static inline void skb_bond_set_mac_by_master(struct sk_buff *skb,
-                                             struct net_device *master)
- {
-       if (skb->pkt_type == PACKET_HOST) {
-               u16 *dest = (u16 *) eth_hdr(skb)->h_dest;
+ extern int __skb_bond_should_drop(struct sk_buff *skb,
+                                 struct net_device *master);
  
  static inline int skb_bond_should_drop(struct sk_buff *skb,
                                       struct net_device *master)
  {
-       if (master) {
-               struct net_device *dev = skb->dev;
-               if (master->priv_flags & IFF_MASTER_ARPMON)
-                       dev->last_rx = jiffies;
-               if ((master->priv_flags & IFF_MASTER_ALB) && master->br_port) {
-                       /* Do address unmangle. The local destination address
-                        * will be always the one master has. Provides the right
-                        * functionality in a bridge.
-                        */
-                       skb_bond_set_mac_by_master(skb, master);
-               }
-               if (dev->priv_flags & IFF_SLAVE_INACTIVE) {
-                       if ((dev->priv_flags & IFF_SLAVE_NEEDARP) &&
-                           skb->protocol == __cpu_to_be16(ETH_P_ARP))
-                               return 0;
-                       if (master->priv_flags & IFF_MASTER_ALB) {
-                               if (skb->pkt_type != PACKET_BROADCAST &&
-                                   skb->pkt_type != PACKET_MULTICAST)
-                                       return 0;
-                       }
-                       if (master->priv_flags & IFF_MASTER_8023AD &&
-                           skb->protocol == __cpu_to_be16(ETH_P_SLOW))
-                               return 0;
-                       return 1;
-               }
-       }
+       if (master)
+               return __skb_bond_should_drop(skb, master);
        return 0;
  }
  
diff --combined kernel/sysctl.c
@@@ -163,27 -163,6 +163,27 @@@ static int proc_taint(struct ctl_table 
                               void __user *buffer, size_t *lenp, loff_t *ppos);
  #endif
  
 +#ifdef CONFIG_MAGIC_SYSRQ
 +static int __sysrq_enabled; /* Note: sysrq code ises it's own private copy */
 +
 +static int sysrq_sysctl_handler(ctl_table *table, int write,
 +                              void __user *buffer, size_t *lenp,
 +                              loff_t *ppos)
 +{
 +      int error;
 +
 +      error = proc_dointvec(table, write, buffer, lenp, ppos);
 +      if (error)
 +              return error;
 +
 +      if (write)
 +              sysrq_toggle_support(__sysrq_enabled);
 +
 +      return 0;
 +}
 +
 +#endif
 +
  static struct ctl_table root_table[];
  static struct ctl_table_root sysctl_table_root;
  static struct ctl_table_header root_table_header = {
@@@ -588,7 -567,7 +588,7 @@@ static struct ctl_table kern_table[] = 
                .data           = &__sysrq_enabled,
                .maxlen         = sizeof (int),
                .mode           = 0644,
 -              .proc_handler   = proc_dointvec,
 +              .proc_handler   = sysrq_sysctl_handler,
        },
  #endif
  #ifdef CONFIG_PROC_SYSCTL
  #endif
        {
                .procname       = "userprocess_debug",
 -              .data           = &sysctl_userprocess_debug,
 +              .data           = &show_unhandled_signals,
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
@@@ -1452,8 -1431,7 +1452,8 @@@ static struct ctl_table fs_table[] = 
  };
  
  static struct ctl_table debug_table[] = {
 -#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_SPARC)
 +#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) || \
 +    defined(CONFIG_S390)
        {
                .procname       = "exception-trace",
                .data           = &show_unhandled_signals,
@@@ -2062,8 -2040,132 +2062,132 @@@ int proc_dostring(struct ctl_table *tab
                               buffer, lenp, ppos);
  }
  
+ static size_t proc_skip_spaces(char **buf)
+ {
+       size_t ret;
+       char *tmp = skip_spaces(*buf);
+       ret = tmp - *buf;
+       *buf = tmp;
+       return ret;
+ }
+ static void proc_skip_char(char **buf, size_t *size, const char v)
+ {
+       while (*size) {
+               if (**buf != v)
+                       break;
+               (*size)--;
+               (*buf)++;
+       }
+ }
+ #define TMPBUFLEN 22
+ /**
+  * proc_get_long - reads an ASCII formated integer from a user buffer
+  *
+  * @buf - a kernel buffer
+  * @size - size of the kernel buffer
+  * @val - this is where the number will be stored
+  * @neg - set to %TRUE if number is negative
+  * @perm_tr - a vector which contains the allowed trailers
+  * @perm_tr_len - size of the perm_tr vector
+  * @tr - pointer to store the trailer character
+  *
+  * In case of success 0 is returned and buf and size are updated with
+  * the amount of bytes read. If tr is non NULL and a trailing
+  * character exist (size is non zero after returning from this
+  * function) tr is updated with the trailing character.
+  */
+ static int proc_get_long(char **buf, size_t *size,
+                         unsigned long *val, bool *neg,
+                         const char *perm_tr, unsigned perm_tr_len, char *tr)
+ {
+       int len;
+       char *p, tmp[TMPBUFLEN];
+       if (!*size)
+               return -EINVAL;
+       len = *size;
+       if (len > TMPBUFLEN - 1)
+               len = TMPBUFLEN - 1;
+       memcpy(tmp, *buf, len);
+       tmp[len] = 0;
+       p = tmp;
+       if (*p == '-' && *size > 1) {
+               *neg = true;
+               p++;
+       } else
+               *neg = false;
+       if (!isdigit(*p))
+               return -EINVAL;
+       *val = simple_strtoul(p, &p, 0);
+       len = p - tmp;
+       /* We don't know if the next char is whitespace thus we may accept
+        * invalid integers (e.g. 1234...a) or two integers instead of one
+        * (e.g. 123...1). So lets not allow such large numbers. */
+       if (len == TMPBUFLEN - 1)
+               return -EINVAL;
+       if (len < *size && perm_tr_len && !memchr(perm_tr, *p, perm_tr_len))
+               return -EINVAL;
+       if (tr && (len < *size))
+               *tr = *p;
+       *buf += len;
+       *size -= len;
+       return 0;
+ }
+ /**
+  * proc_put_long - coverts an integer to a decimal ASCII formated string
+  *
+  * @buf - the user buffer
+  * @size - the size of the user buffer
+  * @val - the integer to be converted
+  * @neg - sign of the number, %TRUE for negative
+  *
+  * In case of success 0 is returned and buf and size are updated with
+  * the amount of bytes read.
+  */
+ static int proc_put_long(void __user **buf, size_t *size, unsigned long val,
+                         bool neg)
+ {
+       int len;
+       char tmp[TMPBUFLEN], *p = tmp;
+       sprintf(p, "%s%lu", neg ? "-" : "", val);
+       len = strlen(tmp);
+       if (len > *size)
+               len = *size;
+       if (copy_to_user(*buf, tmp, len))
+               return -EFAULT;
+       *size -= len;
+       *buf += len;
+       return 0;
+ }
+ #undef TMPBUFLEN
+ static int proc_put_char(void __user **buf, size_t *size, char c)
+ {
+       if (*size) {
+               char __user **buffer = (char __user **)buf;
+               if (put_user(c, *buffer))
+                       return -EFAULT;
+               (*size)--, (*buffer)++;
+               *buf = *buffer;
+       }
+       return 0;
+ }
  
- static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp,
+ static int do_proc_dointvec_conv(bool *negp, unsigned long *lvalp,
                                 int *valp,
                                 int write, void *data)
  {
        } else {
                int val = *valp;
                if (val < 0) {
-                       *negp = -1;
+                       *negp = true;
                        *lvalp = (unsigned long)-val;
                } else {
-                       *negp = 0;
+                       *negp = false;
                        *lvalp = (unsigned long)val;
                }
        }
        return 0;
  }
  
+ static const char proc_wspace_sep[] = { ' ', '\t', '\n' };
  static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
                  int write, void __user *buffer,
                  size_t *lenp, loff_t *ppos,
-                 int (*conv)(int *negp, unsigned long *lvalp, int *valp,
+                 int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
                              int write, void *data),
                  void *data)
  {
- #define TMPBUFLEN 21
-       int *i, vleft, first = 1, neg;
-       unsigned long lval;
-       size_t left, len;
+       int *i, vleft, first = 1, err = 0;
+       unsigned long page = 0;
+       size_t left;
+       char *kbuf;
        
-       char buf[TMPBUFLEN], *p;
-       char __user *s = buffer;
-       
-       if (!tbl_data || !table->maxlen || !*lenp ||
-           (*ppos && !write)) {
+       if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
                *lenp = 0;
                return 0;
        }
        if (!conv)
                conv = do_proc_dointvec_conv;
  
+       if (write) {
+               if (left > PAGE_SIZE - 1)
+                       left = PAGE_SIZE - 1;
+               page = __get_free_page(GFP_TEMPORARY);
+               kbuf = (char *) page;
+               if (!kbuf)
+                       return -ENOMEM;
+               if (copy_from_user(kbuf, buffer, left)) {
+                       err = -EFAULT;
+                       goto free;
+               }
+               kbuf[left] = 0;
+       }
        for (; left && vleft--; i++, first=0) {
-               if (write) {
-                       while (left) {
-                               char c;
-                               if (get_user(c, s))
-                                       return -EFAULT;
-                               if (!isspace(c))
-                                       break;
-                               left--;
-                               s++;
-                       }
-                       if (!left)
-                               break;
-                       neg = 0;
-                       len = left;
-                       if (len > sizeof(buf) - 1)
-                               len = sizeof(buf) - 1;
-                       if (copy_from_user(buf, s, len))
-                               return -EFAULT;
-                       buf[len] = 0;
-                       p = buf;
-                       if (*p == '-' && left > 1) {
-                               neg = 1;
-                               p++;
-                       }
-                       if (*p < '0' || *p > '9')
-                               break;
+               unsigned long lval;
+               bool neg;
  
-                       lval = simple_strtoul(p, &p, 0);
+               if (write) {
+                       left -= proc_skip_spaces(&kbuf);
  
-                       len = p-buf;
-                       if ((len < left) && *p && !isspace(*p))
+                       err = proc_get_long(&kbuf, &left, &lval, &neg,
+                                            proc_wspace_sep,
+                                            sizeof(proc_wspace_sep), NULL);
+                       if (err)
                                break;
-                       s += len;
-                       left -= len;
-                       if (conv(&neg, &lval, i, 1, data))
+                       if (conv(&neg, &lval, i, 1, data)) {
+                               err = -EINVAL;
                                break;
+                       }
                } else {
-                       p = buf;
+                       if (conv(&neg, &lval, i, 0, data)) {
+                               err = -EINVAL;
+                               break;
+                       }
                        if (!first)
-                               *p++ = '\t';
-       
-                       if (conv(&neg, &lval, i, 0, data))
+                               err = proc_put_char(&buffer, &left, '\t');
+                       if (err)
+                               break;
+                       err = proc_put_long(&buffer, &left, lval, neg);
+                       if (err)
                                break;
                }
        }
  
-       if (!write && !first && left) {
-               if(put_user('\n', s))
-                       return -EFAULT;
-               left--, s++;
-       }
+       if (!write && !first && left && !err)
+               err = proc_put_char(&buffer, &left, '\n');
+       if (write && !err)
+               left -= proc_skip_spaces(&kbuf);
+ free:
        if (write) {
-               while (left) {
-                       char c;
-                       if (get_user(c, s++))
-                               return -EFAULT;
-                       if (!isspace(c))
-                               break;
-                       left--;
-               }
+               free_page(page);
+               if (first)
+                       return err ? : -EINVAL;
        }
-       if (write && first)
-               return -EINVAL;
        *lenp -= left;
        *ppos += *lenp;
-       return 0;
- #undef TMPBUFLEN
+       return err;
  }
  
  static int do_proc_dointvec(struct ctl_table *table, int write,
                  void __user *buffer, size_t *lenp, loff_t *ppos,
-                 int (*conv)(int *negp, unsigned long *lvalp, int *valp,
+                 int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
                              int write, void *data),
                  void *data)
  {
@@@ -2260,8 -2340,8 +2362,8 @@@ struct do_proc_dointvec_minmax_conv_par
        int *max;
  };
  
- static int do_proc_dointvec_minmax_conv(int *negp, unsigned long *lvalp, 
-                                       int *valp, 
+ static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,
+                                       int *valp,
                                        int write, void *data)
  {
        struct do_proc_dointvec_minmax_conv_param *param = data;
        } else {
                int val = *valp;
                if (val < 0) {
-                       *negp = -1;
+                       *negp = true;
                        *lvalp = (unsigned long)-val;
                } else {
-                       *negp = 0;
+                       *negp = false;
                        *lvalp = (unsigned long)val;
                }
        }
@@@ -2317,102 -2397,78 +2419,78 @@@ static int __do_proc_doulongvec_minmax(
                                     unsigned long convmul,
                                     unsigned long convdiv)
  {
- #define TMPBUFLEN 21
-       unsigned long *i, *min, *max, val;
-       int vleft, first=1, neg;
-       size_t len, left;
-       char buf[TMPBUFLEN], *p;
-       char __user *s = buffer;
-       
-       if (!data || !table->maxlen || !*lenp ||
-           (*ppos && !write)) {
+       unsigned long *i, *min, *max;
+       int vleft, first = 1, err = 0;
+       unsigned long page = 0;
+       size_t left;
+       char *kbuf;
+       if (!data || !table->maxlen || !*lenp || (*ppos && !write)) {
                *lenp = 0;
                return 0;
        }
-       
        i = (unsigned long *) data;
        min = (unsigned long *) table->extra1;
        max = (unsigned long *) table->extra2;
        vleft = table->maxlen / sizeof(unsigned long);
        left = *lenp;
-       
+       if (write) {
+               if (left > PAGE_SIZE - 1)
+                       left = PAGE_SIZE - 1;
+               page = __get_free_page(GFP_TEMPORARY);
+               kbuf = (char *) page;
+               if (!kbuf)
+                       return -ENOMEM;
+               if (copy_from_user(kbuf, buffer, left)) {
+                       err = -EFAULT;
+                       goto free;
+               }
+               kbuf[left] = 0;
+       }
        for (; left && vleft--; i++, min++, max++, first=0) {
+               unsigned long val;
                if (write) {
-                       while (left) {
-                               char c;
-                               if (get_user(c, s))
-                                       return -EFAULT;
-                               if (!isspace(c))
-                                       break;
-                               left--;
-                               s++;
-                       }
-                       if (!left)
-                               break;
-                       neg = 0;
-                       len = left;
-                       if (len > TMPBUFLEN-1)
-                               len = TMPBUFLEN-1;
-                       if (copy_from_user(buf, s, len))
-                               return -EFAULT;
-                       buf[len] = 0;
-                       p = buf;
-                       if (*p == '-' && left > 1) {
-                               neg = 1;
-                               p++;
-                       }
-                       if (*p < '0' || *p > '9')
-                               break;
-                       val = simple_strtoul(p, &p, 0) * convmul / convdiv ;
-                       len = p-buf;
-                       if ((len < left) && *p && !isspace(*p))
+                       bool neg;
+                       left -= proc_skip_spaces(&kbuf);
+                       err = proc_get_long(&kbuf, &left, &val, &neg,
+                                            proc_wspace_sep,
+                                            sizeof(proc_wspace_sep), NULL);
+                       if (err)
                                break;
                        if (neg)
-                               val = -val;
-                       s += len;
-                       left -= len;
-                       if(neg)
                                continue;
                        if ((min && val < *min) || (max && val > *max))
                                continue;
                        *i = val;
                } else {
-                       p = buf;
+                       val = convdiv * (*i) / convmul;
                        if (!first)
-                               *p++ = '\t';
-                       sprintf(p, "%lu", convdiv * (*i) / convmul);
-                       len = strlen(buf);
-                       if (len > left)
-                               len = left;
-                       if(copy_to_user(s, buf, len))
-                               return -EFAULT;
-                       left -= len;
-                       s += len;
+                               err = proc_put_char(&buffer, &left, '\t');
+                       err = proc_put_long(&buffer, &left, val, false);
+                       if (err)
+                               break;
                }
        }
  
-       if (!write && !first && left) {
-               if(put_user('\n', s))
-                       return -EFAULT;
-               left--, s++;
-       }
+       if (!write && !first && left && !err)
+               err = proc_put_char(&buffer, &left, '\n');
+       if (write && !err)
+               left -= proc_skip_spaces(&kbuf);
+ free:
        if (write) {
-               while (left) {
-                       char c;
-                       if (get_user(c, s++))
-                               return -EFAULT;
-                       if (!isspace(c))
-                               break;
-                       left--;
-               }
+               free_page(page);
+               if (first)
+                       return err ? : -EINVAL;
        }
-       if (write && first)
-               return -EINVAL;
        *lenp -= left;
        *ppos += *lenp;
-       return 0;
- #undef TMPBUFLEN
+       return err;
  }
  
  static int do_proc_doulongvec_minmax(struct ctl_table *table, int write,
@@@ -2473,7 -2529,7 +2551,7 @@@ int proc_doulongvec_ms_jiffies_minmax(s
  }
  
  
- static int do_proc_dointvec_jiffies_conv(int *negp, unsigned long *lvalp,
+ static int do_proc_dointvec_jiffies_conv(bool *negp, unsigned long *lvalp,
                                         int *valp,
                                         int write, void *data)
  {
                int val = *valp;
                unsigned long lval;
                if (val < 0) {
-                       *negp = -1;
+                       *negp = true;
                        lval = (unsigned long)-val;
                } else {
-                       *negp = 0;
+                       *negp = false;
                        lval = (unsigned long)val;
                }
                *lvalp = lval / HZ;
        return 0;
  }
  
- static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp,
+ static int do_proc_dointvec_userhz_jiffies_conv(bool *negp, unsigned long *lvalp,
                                                int *valp,
                                                int write, void *data)
  {
                int val = *valp;
                unsigned long lval;
                if (val < 0) {
-                       *negp = -1;
+                       *negp = true;
                        lval = (unsigned long)-val;
                } else {
-                       *negp = 0;
+                       *negp = false;
                        lval = (unsigned long)val;
                }
                *lvalp = jiffies_to_clock_t(lval);
        return 0;
  }
  
- static int do_proc_dointvec_ms_jiffies_conv(int *negp, unsigned long *lvalp,
+ static int do_proc_dointvec_ms_jiffies_conv(bool *negp, unsigned long *lvalp,
                                            int *valp,
                                            int write, void *data)
  {
                int val = *valp;
                unsigned long lval;
                if (val < 0) {
-                       *negp = -1;
+                       *negp = true;
                        lval = (unsigned long)-val;
                } else {
-                       *negp = 0;
+                       *negp = false;
                        lval = (unsigned long)val;
                }
                *lvalp = jiffies_to_msecs(lval);
@@@ -2629,6 -2685,157 +2707,157 @@@ static int proc_do_cad_pid(struct ctl_t
        return 0;
  }
  
+ /**
+  * proc_do_large_bitmap - read/write from/to a large bitmap
+  * @table: the sysctl table
+  * @write: %TRUE if this is a write to the sysctl file
+  * @buffer: the user buffer
+  * @lenp: the size of the user buffer
+  * @ppos: file position
+  *
+  * The bitmap is stored at table->data and the bitmap length (in bits)
+  * in table->maxlen.
+  *
+  * We use a range comma separated format (e.g. 1,3-4,10-10) so that
+  * large bitmaps may be represented in a compact manner. Writing into
+  * the file will clear the bitmap then update it with the given input.
+  *
+  * Returns 0 on success.
+  */
+ int proc_do_large_bitmap(struct ctl_table *table, int write,
+                        void __user *buffer, size_t *lenp, loff_t *ppos)
+ {
+       int err = 0;
+       bool first = 1;
+       size_t left = *lenp;
+       unsigned long bitmap_len = table->maxlen;
+       unsigned long *bitmap = (unsigned long *) table->data;
+       unsigned long *tmp_bitmap = NULL;
+       char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
+       if (!bitmap_len || !left || (*ppos && !write)) {
+               *lenp = 0;
+               return 0;
+       }
+       if (write) {
+               unsigned long page = 0;
+               char *kbuf;
+               if (left > PAGE_SIZE - 1)
+                       left = PAGE_SIZE - 1;
+               page = __get_free_page(GFP_TEMPORARY);
+               kbuf = (char *) page;
+               if (!kbuf)
+                       return -ENOMEM;
+               if (copy_from_user(kbuf, buffer, left)) {
+                       free_page(page);
+                       return -EFAULT;
+                 }
+               kbuf[left] = 0;
+               tmp_bitmap = kzalloc(BITS_TO_LONGS(bitmap_len) * sizeof(unsigned long),
+                                    GFP_KERNEL);
+               if (!tmp_bitmap) {
+                       free_page(page);
+                       return -ENOMEM;
+               }
+               proc_skip_char(&kbuf, &left, '\n');
+               while (!err && left) {
+                       unsigned long val_a, val_b;
+                       bool neg;
+                       err = proc_get_long(&kbuf, &left, &val_a, &neg, tr_a,
+                                            sizeof(tr_a), &c);
+                       if (err)
+                               break;
+                       if (val_a >= bitmap_len || neg) {
+                               err = -EINVAL;
+                               break;
+                       }
+                       val_b = val_a;
+                       if (left) {
+                               kbuf++;
+                               left--;
+                       }
+                       if (c == '-') {
+                               err = proc_get_long(&kbuf, &left, &val_b,
+                                                    &neg, tr_b, sizeof(tr_b),
+                                                    &c);
+                               if (err)
+                                       break;
+                               if (val_b >= bitmap_len || neg ||
+                                   val_a > val_b) {
+                                       err = -EINVAL;
+                                       break;
+                               }
+                               if (left) {
+                                       kbuf++;
+                                       left--;
+                               }
+                       }
+                       while (val_a <= val_b)
+                               set_bit(val_a++, tmp_bitmap);
+                       first = 0;
+                       proc_skip_char(&kbuf, &left, '\n');
+               }
+               free_page(page);
+       } else {
+               unsigned long bit_a, bit_b = 0;
+               while (left) {
+                       bit_a = find_next_bit(bitmap, bitmap_len, bit_b);
+                       if (bit_a >= bitmap_len)
+                               break;
+                       bit_b = find_next_zero_bit(bitmap, bitmap_len,
+                                                  bit_a + 1) - 1;
+                       if (!first) {
+                               err = proc_put_char(&buffer, &left, ',');
+                               if (err)
+                                       break;
+                       }
+                       err = proc_put_long(&buffer, &left, bit_a, false);
+                       if (err)
+                               break;
+                       if (bit_a != bit_b) {
+                               err = proc_put_char(&buffer, &left, '-');
+                               if (err)
+                                       break;
+                               err = proc_put_long(&buffer, &left, bit_b, false);
+                               if (err)
+                                       break;
+                       }
+                       first = 0; bit_b++;
+               }
+               if (!err)
+                       err = proc_put_char(&buffer, &left, '\n');
+       }
+       if (!err) {
+               if (write) {
+                       if (*ppos)
+                               bitmap_or(bitmap, bitmap, tmp_bitmap, bitmap_len);
+                       else
+                               memcpy(bitmap, tmp_bitmap,
+                                       BITS_TO_LONGS(bitmap_len) * sizeof(unsigned long));
+               }
+               kfree(tmp_bitmap);
+               *lenp -= left;
+               *ppos += *lenp;
+               return 0;
+       } else {
+               kfree(tmp_bitmap);
+               return err;
+       }
+ }
  #else /* CONFIG_PROC_FS */
  
  int proc_dostring(struct ctl_table *table, int write,
diff --combined net/ipv4/ipmr.c
@@@ -22,7 -22,7 +22,7 @@@
   *                                    overflow.
   *      Carlos Picoto           :       PIMv1 Support
   *    Pavlin Ivanov Radoslavov:       PIMv2 Registers must checksum only PIM header
 - *                                    Relax this requrement to work with older peers.
 + *                                    Relax this requirement to work with older peers.
   *
   */
  
  #include <net/ipip.h>
  #include <net/checksum.h>
  #include <net/netlink.h>
+ #include <net/fib_rules.h>
  
  #if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
  #define CONFIG_IP_PIMSM       1
  #endif
  
+ struct mr_table {
+       struct list_head        list;
+ #ifdef CONFIG_NET_NS
+       struct net              *net;
+ #endif
+       u32                     id;
+       struct sock             *mroute_sk;
+       struct timer_list       ipmr_expire_timer;
+       struct list_head        mfc_unres_queue;
+       struct list_head        mfc_cache_array[MFC_LINES];
+       struct vif_device       vif_table[MAXVIFS];
+       int                     maxvif;
+       atomic_t                cache_resolve_queue_len;
+       int                     mroute_do_assert;
+       int                     mroute_do_pim;
+ #if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
+       int                     mroute_reg_vif_num;
+ #endif
+ };
+ struct ipmr_rule {
+       struct fib_rule         common;
+ };
+ struct ipmr_result {
+       struct mr_table         *mrt;
+ };
  /* Big lock, protecting vif table, mrt cache and mroute socket state.
     Note that the changes are semaphored via rtnl_lock.
   */
@@@ -78,9 -107,7 +107,7 @@@ static DEFINE_RWLOCK(mrt_lock)
   *    Multicast router control variables
   */
  
- #define VIF_EXISTS(_net, _idx) ((_net)->ipv4.vif_table[_idx].dev != NULL)
- static struct mfc_cache *mfc_unres_queue;             /* Queue of unresolved entries */
+ #define VIF_EXISTS(_mrt, _idx) ((_mrt)->vif_table[_idx].dev != NULL)
  
  /* Special spinlock for queue of unresolved entries */
  static DEFINE_SPINLOCK(mfc_unres_lock);
  
  static struct kmem_cache *mrt_cachep __read_mostly;
  
- static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local);
- static int ipmr_cache_report(struct net *net,
+ static struct mr_table *ipmr_new_table(struct net *net, u32 id);
+ static int ip_mr_forward(struct net *net, struct mr_table *mrt,
+                        struct sk_buff *skb, struct mfc_cache *cache,
+                        int local);
+ static int ipmr_cache_report(struct mr_table *mrt,
                             struct sk_buff *pkt, vifi_t vifi, int assert);
- static int ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm);
+ static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
+                             struct mfc_cache *c, struct rtmsg *rtm);
+ static void ipmr_expire_process(unsigned long arg);
+ #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES
+ #define ipmr_for_each_table(mrt, net) \
+       list_for_each_entry_rcu(mrt, &net->ipv4.mr_tables, list)
+ static struct mr_table *ipmr_get_table(struct net *net, u32 id)
+ {
+       struct mr_table *mrt;
+       ipmr_for_each_table(mrt, net) {
+               if (mrt->id == id)
+                       return mrt;
+       }
+       return NULL;
+ }
+ static int ipmr_fib_lookup(struct net *net, struct flowi *flp,
+                          struct mr_table **mrt)
+ {
+       struct ipmr_result res;
+       struct fib_lookup_arg arg = { .result = &res, };
+       int err;
+       err = fib_rules_lookup(net->ipv4.mr_rules_ops, flp, 0, &arg);
+       if (err < 0)
+               return err;
+       *mrt = res.mrt;
+       return 0;
+ }
+ static int ipmr_rule_action(struct fib_rule *rule, struct flowi *flp,
+                           int flags, struct fib_lookup_arg *arg)
+ {
+       struct ipmr_result *res = arg->result;
+       struct mr_table *mrt;
  
- static struct timer_list ipmr_expire_timer;
+       switch (rule->action) {
+       case FR_ACT_TO_TBL:
+               break;
+       case FR_ACT_UNREACHABLE:
+               return -ENETUNREACH;
+       case FR_ACT_PROHIBIT:
+               return -EACCES;
+       case FR_ACT_BLACKHOLE:
+       default:
+               return -EINVAL;
+       }
+       mrt = ipmr_get_table(rule->fr_net, rule->table);
+       if (mrt == NULL)
+               return -EAGAIN;
+       res->mrt = mrt;
+       return 0;
+ }
+ static int ipmr_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
+ {
+       return 1;
+ }
+ static const struct nla_policy ipmr_rule_policy[FRA_MAX + 1] = {
+       FRA_GENERIC_POLICY,
+ };
+ static int ipmr_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
+                              struct fib_rule_hdr *frh, struct nlattr **tb)
+ {
+       return 0;
+ }
+ static int ipmr_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
+                            struct nlattr **tb)
+ {
+       return 1;
+ }
+ static int ipmr_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
+                         struct fib_rule_hdr *frh)
+ {
+       frh->dst_len = 0;
+       frh->src_len = 0;
+       frh->tos     = 0;
+       return 0;
+ }
+ static const struct fib_rules_ops __net_initdata ipmr_rules_ops_template = {
+       .family         = RTNL_FAMILY_IPMR,
+       .rule_size      = sizeof(struct ipmr_rule),
+       .addr_size      = sizeof(u32),
+       .action         = ipmr_rule_action,
+       .match          = ipmr_rule_match,
+       .configure      = ipmr_rule_configure,
+       .compare        = ipmr_rule_compare,
+       .default_pref   = fib_default_rule_pref,
+       .fill           = ipmr_rule_fill,
+       .nlgroup        = RTNLGRP_IPV4_RULE,
+       .policy         = ipmr_rule_policy,
+       .owner          = THIS_MODULE,
+ };
+ static int __net_init ipmr_rules_init(struct net *net)
+ {
+       struct fib_rules_ops *ops;
+       struct mr_table *mrt;
+       int err;
+       ops = fib_rules_register(&ipmr_rules_ops_template, net);
+       if (IS_ERR(ops))
+               return PTR_ERR(ops);
+       INIT_LIST_HEAD(&net->ipv4.mr_tables);
+       mrt = ipmr_new_table(net, RT_TABLE_DEFAULT);
+       if (mrt == NULL) {
+               err = -ENOMEM;
+               goto err1;
+       }
+       err = fib_default_rule_add(ops, 0x7fff, RT_TABLE_DEFAULT, 0);
+       if (err < 0)
+               goto err2;
+       net->ipv4.mr_rules_ops = ops;
+       return 0;
+ err2:
+       kfree(mrt);
+ err1:
+       fib_rules_unregister(ops);
+       return err;
+ }
+ static void __net_exit ipmr_rules_exit(struct net *net)
+ {
+       struct mr_table *mrt, *next;
+       list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list)
+               kfree(mrt);
+       fib_rules_unregister(net->ipv4.mr_rules_ops);
+ }
+ #else
+ #define ipmr_for_each_table(mrt, net) \
+       for (mrt = net->ipv4.mrt; mrt; mrt = NULL)
+ static struct mr_table *ipmr_get_table(struct net *net, u32 id)
+ {
+       return net->ipv4.mrt;
+ }
+ static int ipmr_fib_lookup(struct net *net, struct flowi *flp,
+                          struct mr_table **mrt)
+ {
+       *mrt = net->ipv4.mrt;
+       return 0;
+ }
+ static int __net_init ipmr_rules_init(struct net *net)
+ {
+       net->ipv4.mrt = ipmr_new_table(net, RT_TABLE_DEFAULT);
+       return net->ipv4.mrt ? 0 : -ENOMEM;
+ }
+ static void __net_exit ipmr_rules_exit(struct net *net)
+ {
+       kfree(net->ipv4.mrt);
+ }
+ #endif
+ static struct mr_table *ipmr_new_table(struct net *net, u32 id)
+ {
+       struct mr_table *mrt;
+       unsigned int i;
+       mrt = ipmr_get_table(net, id);
+       if (mrt != NULL)
+               return mrt;
+       mrt = kzalloc(sizeof(*mrt), GFP_KERNEL);
+       if (mrt == NULL)
+               return NULL;
+       write_pnet(&mrt->net, net);
+       mrt->id = id;
+       /* Forwarding cache */
+       for (i = 0; i < MFC_LINES; i++)
+               INIT_LIST_HEAD(&mrt->mfc_cache_array[i]);
+       INIT_LIST_HEAD(&mrt->mfc_unres_queue);
+       setup_timer(&mrt->ipmr_expire_timer, ipmr_expire_process,
+                   (unsigned long)mrt);
+ #ifdef CONFIG_IP_PIMSM
+       mrt->mroute_reg_vif_num = -1;
+ #endif
+ #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES
+       list_add_tail_rcu(&mrt->list, &net->ipv4.mr_tables);
+ #endif
+       return mrt;
+ }
  
  /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */
  
@@@ -201,12 -431,22 +431,22 @@@ failure
  static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
  {
        struct net *net = dev_net(dev);
+       struct mr_table *mrt;
+       struct flowi fl = {
+               .oif            = dev->ifindex,
+               .iif            = skb->skb_iif,
+               .mark           = skb->mark,
+       };
+       int err;
+       err = ipmr_fib_lookup(net, &fl, &mrt);
+       if (err < 0)
+               return err;
  
        read_lock(&mrt_lock);
        dev->stats.tx_bytes += skb->len;
        dev->stats.tx_packets++;
-       ipmr_cache_report(net, skb, net->ipv4.mroute_reg_vif_num,
-                         IGMPMSG_WHOLEPKT);
+       ipmr_cache_report(mrt, skb, mrt->mroute_reg_vif_num, IGMPMSG_WHOLEPKT);
        read_unlock(&mrt_lock);
        kfree_skb(skb);
        return NETDEV_TX_OK;
@@@ -226,12 -466,18 +466,18 @@@ static void reg_vif_setup(struct net_de
        dev->features           |= NETIF_F_NETNS_LOCAL;
  }
  
- static struct net_device *ipmr_reg_vif(struct net *net)
+ static struct net_device *ipmr_reg_vif(struct net *net, struct mr_table *mrt)
  {
        struct net_device *dev;
        struct in_device *in_dev;
+       char name[IFNAMSIZ];
+       if (mrt->id == RT_TABLE_DEFAULT)
+               sprintf(name, "pimreg");
+       else
+               sprintf(name, "pimreg%u", mrt->id);
  
-       dev = alloc_netdev(0, "pimreg", reg_vif_setup);
+       dev = alloc_netdev(0, name, reg_vif_setup);
  
        if (dev == NULL)
                return NULL;
@@@ -276,17 -522,17 +522,17 @@@ failure
   *    @notify: Set to 1, if the caller is a notifier_call
   */
  
- static int vif_delete(struct net *net, int vifi, int notify,
+ static int vif_delete(struct mr_table *mrt, int vifi, int notify,
                      struct list_head *head)
  {
        struct vif_device *v;
        struct net_device *dev;
        struct in_device *in_dev;
  
-       if (vifi < 0 || vifi >= net->ipv4.maxvif)
+       if (vifi < 0 || vifi >= mrt->maxvif)
                return -EADDRNOTAVAIL;
  
-       v = &net->ipv4.vif_table[vifi];
+       v = &mrt->vif_table[vifi];
  
        write_lock_bh(&mrt_lock);
        dev = v->dev;
        }
  
  #ifdef CONFIG_IP_PIMSM
-       if (vifi == net->ipv4.mroute_reg_vif_num)
-               net->ipv4.mroute_reg_vif_num = -1;
+       if (vifi == mrt->mroute_reg_vif_num)
+               mrt->mroute_reg_vif_num = -1;
  #endif
  
-       if (vifi+1 == net->ipv4.maxvif) {
+       if (vifi+1 == mrt->maxvif) {
                int tmp;
                for (tmp=vifi-1; tmp>=0; tmp--) {
-                       if (VIF_EXISTS(net, tmp))
+                       if (VIF_EXISTS(mrt, tmp))
                                break;
                }
-               net->ipv4.maxvif = tmp+1;
+               mrt->maxvif = tmp+1;
        }
  
        write_unlock_bh(&mrt_lock);
  
  static inline void ipmr_cache_free(struct mfc_cache *c)
  {
-       release_net(mfc_net(c));
        kmem_cache_free(mrt_cachep, c);
  }
  
     and reporting error to netlink readers.
   */
  
- static void ipmr_destroy_unres(struct mfc_cache *c)
+ static void ipmr_destroy_unres(struct mr_table *mrt, struct mfc_cache *c)
  {
+       struct net *net = read_pnet(&mrt->net);
        struct sk_buff *skb;
        struct nlmsgerr *e;
-       struct net *net = mfc_net(c);
  
-       atomic_dec(&net->ipv4.cache_resolve_queue_len);
+       atomic_dec(&mrt->cache_resolve_queue_len);
  
        while ((skb = skb_dequeue(&c->mfc_un.unres.unresolved))) {
                if (ip_hdr(skb)->version == 0) {
  }
  
  
- /* Single timer process for all the unresolved queue. */
+ /* Timer process for the unresolved queue. */
  
- static void ipmr_expire_process(unsigned long dummy)
+ static void ipmr_expire_process(unsigned long arg)
  {
+       struct mr_table *mrt = (struct mr_table *)arg;
        unsigned long now;
        unsigned long expires;
-       struct mfc_cache *c, **cp;
+       struct mfc_cache *c, *next;
  
        if (!spin_trylock(&mfc_unres_lock)) {
-               mod_timer(&ipmr_expire_timer, jiffies+HZ/10);
+               mod_timer(&mrt->ipmr_expire_timer, jiffies+HZ/10);
                return;
        }
  
-       if (mfc_unres_queue == NULL)
+       if (list_empty(&mrt->mfc_unres_queue))
                goto out;
  
        now = jiffies;
        expires = 10*HZ;
-       cp = &mfc_unres_queue;
  
-       while ((c=*cp) != NULL) {
+       list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) {
                if (time_after(c->mfc_un.unres.expires, now)) {
                        unsigned long interval = c->mfc_un.unres.expires - now;
                        if (interval < expires)
                                expires = interval;
                        continue;
                }
  
-               *cp = c->next;
-               ipmr_destroy_unres(c);
+               list_del(&c->list);
+               ipmr_destroy_unres(mrt, c);
        }
  
-       if (mfc_unres_queue != NULL)
-               mod_timer(&ipmr_expire_timer, jiffies + expires);
+       if (!list_empty(&mrt->mfc_unres_queue))
+               mod_timer(&mrt->ipmr_expire_timer, jiffies + expires);
  
  out:
        spin_unlock(&mfc_unres_lock);
  
  /* Fill oifs list. It is called under write locked mrt_lock. */
  
- static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls)
+ static void ipmr_update_thresholds(struct mr_table *mrt, struct mfc_cache *cache,
+                                  unsigned char *ttls)
  {
        int vifi;
-       struct net *net = mfc_net(cache);
  
        cache->mfc_un.res.minvif = MAXVIFS;
        cache->mfc_un.res.maxvif = 0;
        memset(cache->mfc_un.res.ttls, 255, MAXVIFS);
  
-       for (vifi = 0; vifi < net->ipv4.maxvif; vifi++) {
-               if (VIF_EXISTS(net, vifi) &&
+       for (vifi = 0; vifi < mrt->maxvif; vifi++) {
+               if (VIF_EXISTS(mrt, vifi) &&
                    ttls[vifi] && ttls[vifi] < 255) {
                        cache->mfc_un.res.ttls[vifi] = ttls[vifi];
                        if (cache->mfc_un.res.minvif > vifi)
        }
  }
  
- static int vif_add(struct net *net, struct vifctl *vifc, int mrtsock)
+ static int vif_add(struct net *net, struct mr_table *mrt,
+                  struct vifctl *vifc, int mrtsock)
  {
        int vifi = vifc->vifc_vifi;
-       struct vif_device *v = &net->ipv4.vif_table[vifi];
+       struct vif_device *v = &mrt->vif_table[vifi];
        struct net_device *dev;
        struct in_device *in_dev;
        int err;
  
        /* Is vif busy ? */
-       if (VIF_EXISTS(net, vifi))
+       if (VIF_EXISTS(mrt, vifi))
                return -EADDRINUSE;
  
        switch (vifc->vifc_flags) {
                 * Special Purpose VIF in PIM
                 * All the packets will be sent to the daemon
                 */
-               if (net->ipv4.mroute_reg_vif_num >= 0)
+               if (mrt->mroute_reg_vif_num >= 0)
                        return -EADDRINUSE;
-               dev = ipmr_reg_vif(net);
+               dev = ipmr_reg_vif(net, mrt);
                if (!dev)
                        return -ENOBUFS;
                err = dev_set_allmulti(dev, 1);
        v->dev = dev;
  #ifdef CONFIG_IP_PIMSM
        if (v->flags&VIFF_REGISTER)
-               net->ipv4.mroute_reg_vif_num = vifi;
+               mrt->mroute_reg_vif_num = vifi;
  #endif
-       if (vifi+1 > net->ipv4.maxvif)
-               net->ipv4.maxvif = vifi+1;
+       if (vifi+1 > mrt->maxvif)
+               mrt->maxvif = vifi+1;
        write_unlock_bh(&mrt_lock);
        return 0;
  }
  
- static struct mfc_cache *ipmr_cache_find(struct net *net,
+ static struct mfc_cache *ipmr_cache_find(struct mr_table *mrt,
                                         __be32 origin,
                                         __be32 mcastgrp)
  {
        int line = MFC_HASH(mcastgrp, origin);
        struct mfc_cache *c;
  
-       for (c = net->ipv4.mfc_cache_array[line]; c; c = c->next) {
-               if (c->mfc_origin==origin && c->mfc_mcastgrp==mcastgrp)
-                       break;
+       list_for_each_entry(c, &mrt->mfc_cache_array[line], list) {
+               if (c->mfc_origin == origin && c->mfc_mcastgrp == mcastgrp)
+                       return c;
        }
-       return c;
+       return NULL;
  }
  
  /*
   *    Allocate a multicast cache entry
   */
- static struct mfc_cache *ipmr_cache_alloc(struct net *net)
+ static struct mfc_cache *ipmr_cache_alloc(void)
  {
        struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
        if (c == NULL)
                return NULL;
        c->mfc_un.res.minvif = MAXVIFS;
        return c;
  }
  
- static struct mfc_cache *ipmr_cache_alloc_unres(struct net *net)
+ static struct mfc_cache *ipmr_cache_alloc_unres(void)
  {
        struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
        if (c == NULL)
                return NULL;
        skb_queue_head_init(&c->mfc_un.unres.unresolved);
        c->mfc_un.unres.expires = jiffies + 10*HZ;
-       mfc_net_set(c, net);
        return c;
  }
  
   *    A cache entry has gone into a resolved state from queued
   */
  
- static void ipmr_cache_resolve(struct mfc_cache *uc, struct mfc_cache *c)
+ static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt,
+                              struct mfc_cache *uc, struct mfc_cache *c)
  {
        struct sk_buff *skb;
        struct nlmsgerr *e;
                if (ip_hdr(skb)->version == 0) {
                        struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr));
  
-                       if (ipmr_fill_mroute(skb, c, NLMSG_DATA(nlh)) > 0) {
+                       if (__ipmr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) {
                                nlh->nlmsg_len = (skb_tail_pointer(skb) -
                                                  (u8 *)nlh);
                        } else {
                                memset(&e->msg, 0, sizeof(e->msg));
                        }
  
-                       rtnl_unicast(skb, mfc_net(c), NETLINK_CB(skb).pid);
+                       rtnl_unicast(skb, net, NETLINK_CB(skb).pid);
                } else
-                       ip_mr_forward(skb, c, 0);
+                       ip_mr_forward(net, mrt, skb, c, 0);
        }
  }
  
   *    Called under mrt_lock.
   */
  
- static int ipmr_cache_report(struct net *net,
+ static int ipmr_cache_report(struct mr_table *mrt,
                             struct sk_buff *pkt, vifi_t vifi, int assert)
  {
        struct sk_buff *skb;
                memcpy(msg, skb_network_header(pkt), sizeof(struct iphdr));
                msg->im_msgtype = IGMPMSG_WHOLEPKT;
                msg->im_mbz = 0;
-               msg->im_vif = net->ipv4.mroute_reg_vif_num;
+               msg->im_vif = mrt->mroute_reg_vif_num;
                ip_hdr(skb)->ihl = sizeof(struct iphdr) >> 2;
                ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(pkt)->tot_len) +
                                             sizeof(struct iphdr));
        skb->transport_header = skb->network_header;
        }
  
-       if (net->ipv4.mroute_sk == NULL) {
+       if (mrt->mroute_sk == NULL) {
                kfree_skb(skb);
                return -EINVAL;
        }
        /*
         *      Deliver to mrouted
         */
-       ret = sock_queue_rcv_skb(net->ipv4.mroute_sk, skb);
+       ret = sock_queue_rcv_skb(mrt->mroute_sk, skb);
        if (ret < 0) {
                if (net_ratelimit())
                        printk(KERN_WARNING "mroute: pending queue full, dropping entries.\n");
   */
  
  static int
- ipmr_cache_unresolved(struct net *net, vifi_t vifi, struct sk_buff *skb)
+ ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, struct sk_buff *skb)
  {
+       bool found = false;
        int err;
        struct mfc_cache *c;
        const struct iphdr *iph = ip_hdr(skb);
  
        spin_lock_bh(&mfc_unres_lock);
-       for (c=mfc_unres_queue; c; c=c->next) {
-               if (net_eq(mfc_net(c), net) &&
-                   c->mfc_mcastgrp == iph->daddr &&
-                   c->mfc_origin == iph->saddr)
+       list_for_each_entry(c, &mrt->mfc_unres_queue, list) {
+               if (c->mfc_mcastgrp == iph->daddr &&
+                   c->mfc_origin == iph->saddr) {
+                       found = true;
                        break;
+               }
        }
  
-       if (c == NULL) {
+       if (!found) {
                /*
                 *      Create a new entry if allowable
                 */
  
-               if (atomic_read(&net->ipv4.cache_resolve_queue_len) >= 10 ||
-                   (c = ipmr_cache_alloc_unres(net)) == NULL) {
+               if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 ||
+                   (c = ipmr_cache_alloc_unres()) == NULL) {
                        spin_unlock_bh(&mfc_unres_lock);
  
                        kfree_skb(skb);
                /*
                 *      Reflect first query at mrouted.
                 */
-               err = ipmr_cache_report(net, skb, vifi, IGMPMSG_NOCACHE);
+               err = ipmr_cache_report(mrt, skb, vifi, IGMPMSG_NOCACHE);
                if (err < 0) {
                        /* If the report failed throw the cache entry
                           out - Brad Parker
                        return err;
                }
  
-               atomic_inc(&net->ipv4.cache_resolve_queue_len);
-               c->next = mfc_unres_queue;
-               mfc_unres_queue = c;
+               atomic_inc(&mrt->cache_resolve_queue_len);
+               list_add(&c->list, &mrt->mfc_unres_queue);
  
-               if (atomic_read(&net->ipv4.cache_resolve_queue_len) == 1)
-                       mod_timer(&ipmr_expire_timer, c->mfc_un.unres.expires);
+               if (atomic_read(&mrt->cache_resolve_queue_len) == 1)
+                       mod_timer(&mrt->ipmr_expire_timer, c->mfc_un.unres.expires);
        }
  
        /*
   *    MFC cache manipulation by user space mroute daemon
   */
  
- static int ipmr_mfc_delete(struct net *net, struct mfcctl *mfc)
+ static int ipmr_mfc_delete(struct mr_table *mrt, struct mfcctl *mfc)
  {
        int line;
-       struct mfc_cache *c, **cp;
+       struct mfc_cache *c, *next;
  
        line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr);
  
-       for (cp = &net->ipv4.mfc_cache_array[line];
-            (c = *cp) != NULL; cp = &c->next) {
+       list_for_each_entry_safe(c, next, &mrt->mfc_cache_array[line], list) {
                if (c->mfc_origin == mfc->mfcc_origin.s_addr &&
                    c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) {
                        write_lock_bh(&mrt_lock);
-                       *cp = c->next;
+                       list_del(&c->list);
                        write_unlock_bh(&mrt_lock);
  
                        ipmr_cache_free(c);
        return -ENOENT;
  }
  
- static int ipmr_mfc_add(struct net *net, struct mfcctl *mfc, int mrtsock)
+ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
+                       struct mfcctl *mfc, int mrtsock)
  {
+       bool found = false;
        int line;
-       struct mfc_cache *uc, *c, **cp;
+       struct mfc_cache *uc, *c;
  
        if (mfc->mfcc_parent >= MAXVIFS)
                return -ENFILE;
  
        line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr);
  
-       for (cp = &net->ipv4.mfc_cache_array[line];
-            (c = *cp) != NULL; cp = &c->next) {
+       list_for_each_entry(c, &mrt->mfc_cache_array[line], list) {
                if (c->mfc_origin == mfc->mfcc_origin.s_addr &&
-                   c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr)
+                   c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) {
+                       found = true;
                        break;
+               }
        }
  
-       if (c != NULL) {
+       if (found) {
                write_lock_bh(&mrt_lock);
                c->mfc_parent = mfc->mfcc_parent;
-               ipmr_update_thresholds(c, mfc->mfcc_ttls);
+               ipmr_update_thresholds(mrt, c, mfc->mfcc_ttls);
                if (!mrtsock)
                        c->mfc_flags |= MFC_STATIC;
                write_unlock_bh(&mrt_lock);
        if (!ipv4_is_multicast(mfc->mfcc_mcastgrp.s_addr))
                return -EINVAL;
  
-       c = ipmr_cache_alloc(net);
+       c = ipmr_cache_alloc();
        if (c == NULL)
                return -ENOMEM;
  
        c->mfc_origin = mfc->mfcc_origin.s_addr;
        c->mfc_mcastgrp = mfc->mfcc_mcastgrp.s_addr;
        c->mfc_parent = mfc->mfcc_parent;
-       ipmr_update_thresholds(c, mfc->mfcc_ttls);
+       ipmr_update_thresholds(mrt, c, mfc->mfcc_ttls);
        if (!mrtsock)
                c->mfc_flags |= MFC_STATIC;
  
        write_lock_bh(&mrt_lock);
-       c->next = net->ipv4.mfc_cache_array[line];
-       net->ipv4.mfc_cache_array[line] = c;
+       list_add(&c->list, &mrt->mfc_cache_array[line]);
        write_unlock_bh(&mrt_lock);
  
        /*
         *      Check to see if we resolved a queued list. If so we
         *      need to send on the frames and tidy up.
         */
+       found = false;
        spin_lock_bh(&mfc_unres_lock);
-       for (cp = &mfc_unres_queue; (uc=*cp) != NULL;
-            cp = &uc->next) {
-               if (net_eq(mfc_net(uc), net) &&
-                   uc->mfc_origin == c->mfc_origin &&
+       list_for_each_entry(uc, &mrt->mfc_unres_queue, list) {
+               if (uc->mfc_origin == c->mfc_origin &&
                    uc->mfc_mcastgrp == c->mfc_mcastgrp) {
-                       *cp = uc->next;
-                       atomic_dec(&net->ipv4.cache_resolve_queue_len);
+                       list_del(&uc->list);
+                       atomic_dec(&mrt->cache_resolve_queue_len);
+                       found = true;
                        break;
                }
        }
-       if (mfc_unres_queue == NULL)
-               del_timer(&ipmr_expire_timer);
+       if (list_empty(&mrt->mfc_unres_queue))
+               del_timer(&mrt->ipmr_expire_timer);
        spin_unlock_bh(&mfc_unres_lock);
  
-       if (uc) {
-               ipmr_cache_resolve(uc, c);
+       if (found) {
+               ipmr_cache_resolve(net, mrt, uc, c);
                ipmr_cache_free(uc);
        }
        return 0;
   *    Close the multicast socket, and clear the vif tables etc
   */
  
- static void mroute_clean_tables(struct net *net)
+ static void mroute_clean_tables(struct mr_table *mrt)
  {
        int i;
        LIST_HEAD(list);
+       struct mfc_cache *c, *next;
  
        /*
         *      Shut down all active vif entries
         */
-       for (i = 0; i < net->ipv4.maxvif; i++) {
-               if (!(net->ipv4.vif_table[i].flags&VIFF_STATIC))
-                       vif_delete(net, i, 0, &list);
+       for (i = 0; i < mrt->maxvif; i++) {
+               if (!(mrt->vif_table[i].flags&VIFF_STATIC))
+                       vif_delete(mrt, i, 0, &list);
        }
        unregister_netdevice_many(&list);
  
        /*
         *      Wipe the cache
         */
-       for (i=0; i<MFC_LINES; i++) {
-               struct mfc_cache *c, **cp;
-               cp = &net->ipv4.mfc_cache_array[i];
-               while ((c = *cp) != NULL) {
-                       if (c->mfc_flags&MFC_STATIC) {
-                               cp = &c->next;
+       for (i = 0; i < MFC_LINES; i++) {
+               list_for_each_entry_safe(c, next, &mrt->mfc_cache_array[i], list) {
+                       if (c->mfc_flags&MFC_STATIC)
                                continue;
-                       }
                        write_lock_bh(&mrt_lock);
-                       *cp = c->next;
+                       list_del(&c->list);
                        write_unlock_bh(&mrt_lock);
  
                        ipmr_cache_free(c);
                }
        }
  
-       if (atomic_read(&net->ipv4.cache_resolve_queue_len) != 0) {
-               struct mfc_cache *c, **cp;
+       if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
                spin_lock_bh(&mfc_unres_lock);
-               cp = &mfc_unres_queue;
-               while ((c = *cp) != NULL) {
-                       if (!net_eq(mfc_net(c), net)) {
-                               cp = &c->next;
-                               continue;
-                       }
-                       *cp = c->next;
-                       ipmr_destroy_unres(c);
+               list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) {
+                       list_del(&c->list);
+                       ipmr_destroy_unres(mrt, c);
                }
                spin_unlock_bh(&mfc_unres_lock);
        }
  static void mrtsock_destruct(struct sock *sk)
  {
        struct net *net = sock_net(sk);
+       struct mr_table *mrt;
  
        rtnl_lock();
-       if (sk == net->ipv4.mroute_sk) {
-               IPV4_DEVCONF_ALL(net, MC_FORWARDING)--;
+       ipmr_for_each_table(mrt, net) {
+               if (sk == mrt->mroute_sk) {
+                       IPV4_DEVCONF_ALL(net, MC_FORWARDING)--;
  
-               write_lock_bh(&mrt_lock);
-               net->ipv4.mroute_sk = NULL;
-               write_unlock_bh(&mrt_lock);
+                       write_lock_bh(&mrt_lock);
+                       mrt->mroute_sk = NULL;
+                       write_unlock_bh(&mrt_lock);
  
-               mroute_clean_tables(net);
+                       mroute_clean_tables(mrt);
+               }
        }
        rtnl_unlock();
  }
@@@ -957,9 -1193,14 +1193,14 @@@ int ip_mroute_setsockopt(struct sock *s
        struct vifctl vif;
        struct mfcctl mfc;
        struct net *net = sock_net(sk);
+       struct mr_table *mrt;
+       mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
+       if (mrt == NULL)
+               return -ENOENT;
  
        if (optname != MRT_INIT) {
-               if (sk != net->ipv4.mroute_sk && !capable(CAP_NET_ADMIN))
+               if (sk != mrt->mroute_sk && !capable(CAP_NET_ADMIN))
                        return -EACCES;
        }
  
                        return -ENOPROTOOPT;
  
                rtnl_lock();
-               if (net->ipv4.mroute_sk) {
+               if (mrt->mroute_sk) {
                        rtnl_unlock();
                        return -EADDRINUSE;
                }
                ret = ip_ra_control(sk, 1, mrtsock_destruct);
                if (ret == 0) {
                        write_lock_bh(&mrt_lock);
-                       net->ipv4.mroute_sk = sk;
+                       mrt->mroute_sk = sk;
                        write_unlock_bh(&mrt_lock);
  
                        IPV4_DEVCONF_ALL(net, MC_FORWARDING)++;
                rtnl_unlock();
                return ret;
        case MRT_DONE:
-               if (sk != net->ipv4.mroute_sk)
+               if (sk != mrt->mroute_sk)
                        return -EACCES;
                return ip_ra_control(sk, 0, NULL);
        case MRT_ADD_VIF:
                        return -ENFILE;
                rtnl_lock();
                if (optname == MRT_ADD_VIF) {
-                       ret = vif_add(net, &vif, sk == net->ipv4.mroute_sk);
+                       ret = vif_add(net, mrt, &vif, sk == mrt->mroute_sk);
                } else {
-                       ret = vif_delete(net, vif.vifc_vifi, 0, NULL);
+                       ret = vif_delete(mrt, vif.vifc_vifi, 0, NULL);
                }
                rtnl_unlock();
                return ret;
                        return -EFAULT;
                rtnl_lock();
                if (optname == MRT_DEL_MFC)
-                       ret = ipmr_mfc_delete(net, &mfc);
+                       ret = ipmr_mfc_delete(mrt, &mfc);
                else
-                       ret = ipmr_mfc_add(net, &mfc, sk == net->ipv4.mroute_sk);
+                       ret = ipmr_mfc_add(net, mrt, &mfc, sk == mrt->mroute_sk);
                rtnl_unlock();
                return ret;
                /*
                int v;
                if (get_user(v,(int __user *)optval))
                        return -EFAULT;
-               net->ipv4.mroute_do_assert = (v) ? 1 : 0;
+               mrt->mroute_do_assert = (v) ? 1 : 0;
                return 0;
        }
  #ifdef CONFIG_IP_PIMSM
  
                rtnl_lock();
                ret = 0;
-               if (v != net->ipv4.mroute_do_pim) {
-                       net->ipv4.mroute_do_pim = v;
-                       net->ipv4.mroute_do_assert = v;
+               if (v != mrt->mroute_do_pim) {
+                       mrt->mroute_do_pim = v;
+                       mrt->mroute_do_assert = v;
                }
                rtnl_unlock();
                return ret;
        }
  #endif
+ #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES
+       case MRT_TABLE:
+       {
+               u32 v;
+               if (optlen != sizeof(u32))
+                       return -EINVAL;
+               if (get_user(v, (u32 __user *)optval))
+                       return -EFAULT;
+               if (sk == mrt->mroute_sk)
+                       return -EBUSY;
+               rtnl_lock();
+               ret = 0;
+               if (!ipmr_new_table(net, v))
+                       ret = -ENOMEM;
+               raw_sk(sk)->ipmr_table = v;
+               rtnl_unlock();
+               return ret;
+       }
+ #endif
        /*
         *      Spurious command, or MRT_VERSION which you cannot
         *      set.
@@@ -1073,6 -1335,11 +1335,11 @@@ int ip_mroute_getsockopt(struct sock *s
        int olr;
        int val;
        struct net *net = sock_net(sk);
+       struct mr_table *mrt;
+       mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
+       if (mrt == NULL)
+               return -ENOENT;
  
        if (optname != MRT_VERSION &&
  #ifdef CONFIG_IP_PIMSM
                val = 0x0305;
  #ifdef CONFIG_IP_PIMSM
        else if (optname == MRT_PIM)
-               val = net->ipv4.mroute_do_pim;
+               val = mrt->mroute_do_pim;
  #endif
        else
-               val = net->ipv4.mroute_do_assert;
+               val = mrt->mroute_do_assert;
        if (copy_to_user(optval, &val, olr))
                return -EFAULT;
        return 0;
@@@ -1114,16 -1381,21 +1381,21 @@@ int ipmr_ioctl(struct sock *sk, int cmd
        struct vif_device *vif;
        struct mfc_cache *c;
        struct net *net = sock_net(sk);
+       struct mr_table *mrt;
+       mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
+       if (mrt == NULL)
+               return -ENOENT;
  
        switch (cmd) {
        case SIOCGETVIFCNT:
                if (copy_from_user(&vr, arg, sizeof(vr)))
                        return -EFAULT;
-               if (vr.vifi >= net->ipv4.maxvif)
+               if (vr.vifi >= mrt->maxvif)
                        return -EINVAL;
                read_lock(&mrt_lock);
-               vif = &net->ipv4.vif_table[vr.vifi];
-               if (VIF_EXISTS(net, vr.vifi)) {
+               vif = &mrt->vif_table[vr.vifi];
+               if (VIF_EXISTS(mrt, vr.vifi)) {
                        vr.icount = vif->pkt_in;
                        vr.ocount = vif->pkt_out;
                        vr.ibytes = vif->bytes_in;
                        return -EFAULT;
  
                read_lock(&mrt_lock);
-               c = ipmr_cache_find(net, sr.src.s_addr, sr.grp.s_addr);
+               c = ipmr_cache_find(mrt, sr.src.s_addr, sr.grp.s_addr);
                if (c) {
                        sr.pktcnt = c->mfc_un.res.pkt;
                        sr.bytecnt = c->mfc_un.res.bytes;
@@@ -1164,16 -1436,20 +1436,20 @@@ static int ipmr_device_event(struct not
  {
        struct net_device *dev = ptr;
        struct net *net = dev_net(dev);
+       struct mr_table *mrt;
        struct vif_device *v;
        int ct;
        LIST_HEAD(list);
  
        if (event != NETDEV_UNREGISTER)
                return NOTIFY_DONE;
-       v = &net->ipv4.vif_table[0];
-       for (ct = 0; ct < net->ipv4.maxvif; ct++, v++) {
-               if (v->dev == dev)
-                       vif_delete(net, ct, 1, &list);
+       ipmr_for_each_table(mrt, net) {
+               v = &mrt->vif_table[0];
+               for (ct = 0; ct < mrt->maxvif; ct++, v++) {
+                       if (v->dev == dev)
+                               vif_delete(mrt, ct, 1, &list);
+               }
        }
        unregister_netdevice_many(&list);
        return NOTIFY_DONE;
@@@ -1232,11 -1508,11 +1508,11 @@@ static inline int ipmr_forward_finish(s
   *    Processing handlers for ipmr_forward
   */
  
- static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi)
+ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
+                           struct sk_buff *skb, struct mfc_cache *c, int vifi)
  {
-       struct net *net = mfc_net(c);
        const struct iphdr *iph = ip_hdr(skb);
-       struct vif_device *vif = &net->ipv4.vif_table[vifi];
+       struct vif_device *vif = &mrt->vif_table[vifi];
        struct net_device *dev;
        struct rtable *rt;
        int    encap = 0;
                vif->bytes_out += skb->len;
                vif->dev->stats.tx_bytes += skb->len;
                vif->dev->stats.tx_packets++;
-               ipmr_cache_report(net, skb, vifi, IGMPMSG_WHOLEPKT);
+               ipmr_cache_report(mrt, skb, vifi, IGMPMSG_WHOLEPKT);
                goto out_free;
        }
  #endif
         * not mrouter) cannot join to more than one interface - it will
         * result in receiving multiple packets.
         */
-       NF_HOOK(PF_INET, NF_INET_FORWARD, skb, skb->dev, dev,
+       NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, skb, skb->dev, dev,
                ipmr_forward_finish);
        return;
  
  out_free:
        kfree_skb(skb);
-       return;
  }
  
- static int ipmr_find_vif(struct net_device *dev)
+ static int ipmr_find_vif(struct mr_table *mrt, struct net_device *dev)
  {
-       struct net *net = dev_net(dev);
        int ct;
-       for (ct = net->ipv4.maxvif-1; ct >= 0; ct--) {
-               if (net->ipv4.vif_table[ct].dev == dev)
+       for (ct = mrt->maxvif-1; ct >= 0; ct--) {
+               if (mrt->vif_table[ct].dev == dev)
                        break;
        }
        return ct;
  
  /* "local" means that we should preserve one skb (for local delivery) */
  
- static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local)
+ static int ip_mr_forward(struct net *net, struct mr_table *mrt,
+                        struct sk_buff *skb, struct mfc_cache *cache,
+                        int local)
  {
        int psend = -1;
        int vif, ct;
-       struct net *net = mfc_net(cache);
  
        vif = cache->mfc_parent;
        cache->mfc_un.res.pkt++;
        /*
         * Wrong interface: drop packet and (maybe) send PIM assert.
         */
-       if (net->ipv4.vif_table[vif].dev != skb->dev) {
+       if (mrt->vif_table[vif].dev != skb->dev) {
                int true_vifi;
  
                if (skb_rtable(skb)->fl.iif == 0) {
                }
  
                cache->mfc_un.res.wrong_if++;
-               true_vifi = ipmr_find_vif(skb->dev);
+               true_vifi = ipmr_find_vif(mrt, skb->dev);
  
-               if (true_vifi >= 0 && net->ipv4.mroute_do_assert &&
+               if (true_vifi >= 0 && mrt->mroute_do_assert &&
                    /* pimsm uses asserts, when switching from RPT to SPT,
                       so that we cannot check that packet arrived on an oif.
                       It is bad, but otherwise we would need to move pretty
                       large chunk of pimd to kernel. Ough... --ANK
                     */
-                   (net->ipv4.mroute_do_pim ||
+                   (mrt->mroute_do_pim ||
                     cache->mfc_un.res.ttls[true_vifi] < 255) &&
                    time_after(jiffies,
                               cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) {
                        cache->mfc_un.res.last_assert = jiffies;
-                       ipmr_cache_report(net, skb, true_vifi, IGMPMSG_WRONGVIF);
+                       ipmr_cache_report(mrt, skb, true_vifi, IGMPMSG_WRONGVIF);
                }
                goto dont_forward;
        }
  
-       net->ipv4.vif_table[vif].pkt_in++;
-       net->ipv4.vif_table[vif].bytes_in += skb->len;
+       mrt->vif_table[vif].pkt_in++;
+       mrt->vif_table[vif].bytes_in += skb->len;
  
        /*
         *      Forward the frame
                        if (psend != -1) {
                                struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
                                if (skb2)
-                                       ipmr_queue_xmit(skb2, cache, psend);
+                                       ipmr_queue_xmit(net, mrt, skb2, cache,
+                                                       psend);
                        }
                        psend = ct;
                }
                if (local) {
                        struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
                        if (skb2)
-                               ipmr_queue_xmit(skb2, cache, psend);
+                               ipmr_queue_xmit(net, mrt, skb2, cache, psend);
                } else {
-                       ipmr_queue_xmit(skb, cache, psend);
+                       ipmr_queue_xmit(net, mrt, skb, cache, psend);
                        return 0;
                }
        }
@@@ -1439,6 -1716,8 +1716,8 @@@ int ip_mr_input(struct sk_buff *skb
        struct mfc_cache *cache;
        struct net *net = dev_net(skb->dev);
        int local = skb_rtable(skb)->rt_flags & RTCF_LOCAL;
+       struct mr_table *mrt;
+       int err;
  
        /* Packet is looped back after forward, it should not be
           forwarded second time, but still can be delivered locally.
        if (IPCB(skb)->flags&IPSKB_FORWARDED)
                goto dont_forward;
  
+       err = ipmr_fib_lookup(net, &skb_rtable(skb)->fl, &mrt);
+       if (err < 0)
+               return err;
        if (!local) {
                    if (IPCB(skb)->opt.router_alert) {
                            if (ip_call_ra_chain(skb))
                               that we can forward NO IGMP messages.
                             */
                            read_lock(&mrt_lock);
-                           if (net->ipv4.mroute_sk) {
+                           if (mrt->mroute_sk) {
                                    nf_reset(skb);
-                                   raw_rcv(net->ipv4.mroute_sk, skb);
+                                   raw_rcv(mrt->mroute_sk, skb);
                                    read_unlock(&mrt_lock);
                                    return 0;
                            }
        }
  
        read_lock(&mrt_lock);
-       cache = ipmr_cache_find(net, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr);
+       cache = ipmr_cache_find(mrt, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr);
  
        /*
         *      No usable cache entry
                        skb = skb2;
                }
  
-               vif = ipmr_find_vif(skb->dev);
+               vif = ipmr_find_vif(mrt, skb->dev);
                if (vif >= 0) {
-                       int err = ipmr_cache_unresolved(net, vif, skb);
+                       int err2 = ipmr_cache_unresolved(mrt, vif, skb);
                        read_unlock(&mrt_lock);
  
-                       return err;
+                       return err2;
                }
                read_unlock(&mrt_lock);
                kfree_skb(skb);
                return -ENODEV;
        }
  
-       ip_mr_forward(skb, cache, local);
+       ip_mr_forward(net, mrt, skb, cache, local);
  
        read_unlock(&mrt_lock);
  
@@@ -1516,11 -1799,11 +1799,11 @@@ dont_forward
  }
  
  #ifdef CONFIG_IP_PIMSM
- static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen)
+ static int __pim_rcv(struct mr_table *mrt, struct sk_buff *skb,
+                    unsigned int pimlen)
  {
        struct net_device *reg_dev = NULL;
        struct iphdr *encap;
-       struct net *net = dev_net(skb->dev);
  
        encap = (struct iphdr *)(skb_transport_header(skb) + pimlen);
        /*
                return 1;
  
        read_lock(&mrt_lock);
-       if (net->ipv4.mroute_reg_vif_num >= 0)
-               reg_dev = net->ipv4.vif_table[net->ipv4.mroute_reg_vif_num].dev;
+       if (mrt->mroute_reg_vif_num >= 0)
+               reg_dev = mrt->vif_table[mrt->mroute_reg_vif_num].dev;
        if (reg_dev)
                dev_hold(reg_dev);
        read_unlock(&mrt_lock);
        skb->mac_header = skb->network_header;
        skb_pull(skb, (u8*)encap - skb->data);
        skb_reset_network_header(skb);
        skb->protocol = htons(ETH_P_IP);
        skb->ip_summed = 0;
        skb->pkt_type = PACKET_HOST;
-       skb_dst_drop(skb);
-       reg_dev->stats.rx_bytes += skb->len;
-       reg_dev->stats.rx_packets++;
-       nf_reset(skb);
+       skb_tunnel_rx(skb, reg_dev);
        netif_rx(skb);
        dev_put(reg_dev);
  
@@@ -1571,17 -1852,21 +1852,21 @@@ int pim_rcv_v1(struct sk_buff * skb
  {
        struct igmphdr *pim;
        struct net *net = dev_net(skb->dev);
+       struct mr_table *mrt;
  
        if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr)))
                goto drop;
  
        pim = igmp_hdr(skb);
  
-       if (!net->ipv4.mroute_do_pim ||
+       if (ipmr_fib_lookup(net, &skb_rtable(skb)->fl, &mrt) < 0)
+               goto drop;
+       if (!mrt->mroute_do_pim ||
            pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER)
                goto drop;
  
-       if (__pim_rcv(skb, sizeof(*pim))) {
+       if (__pim_rcv(mrt, skb, sizeof(*pim))) {
  drop:
                kfree_skb(skb);
        }
  static int pim_rcv(struct sk_buff * skb)
  {
        struct pimreghdr *pim;
+       struct net *net = dev_net(skb->dev);
+       struct mr_table *mrt;
  
        if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr)))
                goto drop;
             csum_fold(skb_checksum(skb, 0, skb->len, 0))))
                goto drop;
  
-       if (__pim_rcv(skb, sizeof(*pim))) {
+       if (ipmr_fib_lookup(net, &skb_rtable(skb)->fl, &mrt) < 0)
+               goto drop;
+       if (__pim_rcv(mrt, skb, sizeof(*pim))) {
  drop:
                kfree_skb(skb);
        }
  }
  #endif
  
- static int
ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm)
+ static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
                            struct mfc_cache *c, struct rtmsg *rtm)
  {
        int ct;
        struct rtnexthop *nhp;
-       struct net *net = mfc_net(c);
        u8 *b = skb_tail_pointer(skb);
        struct rtattr *mp_head;
  
        if (c->mfc_parent > MAXVIFS)
                return -ENOENT;
  
-       if (VIF_EXISTS(net, c->mfc_parent))
-               RTA_PUT(skb, RTA_IIF, 4, &net->ipv4.vif_table[c->mfc_parent].dev->ifindex);
+       if (VIF_EXISTS(mrt, c->mfc_parent))
+               RTA_PUT(skb, RTA_IIF, 4, &mrt->vif_table[c->mfc_parent].dev->ifindex);
  
        mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0));
  
        for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) {
-               if (VIF_EXISTS(net, ct) && c->mfc_un.res.ttls[ct] < 255) {
+               if (VIF_EXISTS(mrt, ct) && c->mfc_un.res.ttls[ct] < 255) {
                        if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
                                goto rtattr_failure;
                        nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
                        nhp->rtnh_flags = 0;
                        nhp->rtnh_hops = c->mfc_un.res.ttls[ct];
-                       nhp->rtnh_ifindex = net->ipv4.vif_table[ct].dev->ifindex;
+                       nhp->rtnh_ifindex = mrt->vif_table[ct].dev->ifindex;
                        nhp->rtnh_len = sizeof(*nhp);
                }
        }
@@@ -1655,11 -1944,16 +1944,16 @@@ int ipmr_get_route(struct net *net
                   struct sk_buff *skb, struct rtmsg *rtm, int nowait)
  {
        int err;
+       struct mr_table *mrt;
        struct mfc_cache *cache;
        struct rtable *rt = skb_rtable(skb);
  
+       mrt = ipmr_get_table(net, RT_TABLE_DEFAULT);
+       if (mrt == NULL)
+               return -ENOENT;
        read_lock(&mrt_lock);
-       cache = ipmr_cache_find(net, rt->rt_src, rt->rt_dst);
+       cache = ipmr_cache_find(mrt, rt->rt_src, rt->rt_dst);
  
        if (cache == NULL) {
                struct sk_buff *skb2;
                }
  
                dev = skb->dev;
-               if (dev == NULL || (vif = ipmr_find_vif(dev)) < 0) {
+               if (dev == NULL || (vif = ipmr_find_vif(mrt, dev)) < 0) {
                        read_unlock(&mrt_lock);
                        return -ENODEV;
                }
                iph->saddr = rt->rt_src;
                iph->daddr = rt->rt_dst;
                iph->version = 0;
-               err = ipmr_cache_unresolved(net, vif, skb2);
+               err = ipmr_cache_unresolved(mrt, vif, skb2);
                read_unlock(&mrt_lock);
                return err;
        }
  
        if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY))
                cache->mfc_flags |= MFC_NOTIFY;
-       err = ipmr_fill_mroute(skb, cache, rtm);
+       err = __ipmr_fill_mroute(mrt, skb, cache, rtm);
        read_unlock(&mrt_lock);
        return err;
  }
  
+ static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
+                           u32 pid, u32 seq, struct mfc_cache *c)
+ {
+       struct nlmsghdr *nlh;
+       struct rtmsg *rtm;
+       nlh = nlmsg_put(skb, pid, seq, RTM_NEWROUTE, sizeof(*rtm), NLM_F_MULTI);
+       if (nlh == NULL)
+               return -EMSGSIZE;
+       rtm = nlmsg_data(nlh);
+       rtm->rtm_family   = RTNL_FAMILY_IPMR;
+       rtm->rtm_dst_len  = 32;
+       rtm->rtm_src_len  = 32;
+       rtm->rtm_tos      = 0;
+       rtm->rtm_table    = mrt->id;
+       NLA_PUT_U32(skb, RTA_TABLE, mrt->id);
+       rtm->rtm_type     = RTN_MULTICAST;
+       rtm->rtm_scope    = RT_SCOPE_UNIVERSE;
+       rtm->rtm_protocol = RTPROT_UNSPEC;
+       rtm->rtm_flags    = 0;
+       NLA_PUT_BE32(skb, RTA_SRC, c->mfc_origin);
+       NLA_PUT_BE32(skb, RTA_DST, c->mfc_mcastgrp);
+       if (__ipmr_fill_mroute(mrt, skb, c, rtm) < 0)
+               goto nla_put_failure;
+       return nlmsg_end(skb, nlh);
+ nla_put_failure:
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
+ }
+ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+       struct net *net = sock_net(skb->sk);
+       struct mr_table *mrt;
+       struct mfc_cache *mfc;
+       unsigned int t = 0, s_t;
+       unsigned int h = 0, s_h;
+       unsigned int e = 0, s_e;
+       s_t = cb->args[0];
+       s_h = cb->args[1];
+       s_e = cb->args[2];
+       read_lock(&mrt_lock);
+       ipmr_for_each_table(mrt, net) {
+               if (t < s_t)
+                       goto next_table;
+               if (t > s_t)
+                       s_h = 0;
+               for (h = s_h; h < MFC_LINES; h++) {
+                       list_for_each_entry(mfc, &mrt->mfc_cache_array[h], list) {
+                               if (e < s_e)
+                                       goto next_entry;
+                               if (ipmr_fill_mroute(mrt, skb,
+                                                    NETLINK_CB(cb->skb).pid,
+                                                    cb->nlh->nlmsg_seq,
+                                                    mfc) < 0)
+                                       goto done;
+ next_entry:
+                               e++;
+                       }
+                       e = s_e = 0;
+               }
+               s_h = 0;
+ next_table:
+               t++;
+       }
+ done:
+       read_unlock(&mrt_lock);
+       cb->args[2] = e;
+       cb->args[1] = h;
+       cb->args[0] = t;
+       return skb->len;
+ }
  #ifdef CONFIG_PROC_FS
  /*
   *    The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif
   */
  struct ipmr_vif_iter {
        struct seq_net_private p;
+       struct mr_table *mrt;
        int ct;
  };
  
@@@ -1715,11 -2092,13 +2092,13 @@@ static struct vif_device *ipmr_vif_seq_
                                           struct ipmr_vif_iter *iter,
                                           loff_t pos)
  {
-       for (iter->ct = 0; iter->ct < net->ipv4.maxvif; ++iter->ct) {
-               if (!VIF_EXISTS(net, iter->ct))
+       struct mr_table *mrt = iter->mrt;
+       for (iter->ct = 0; iter->ct < mrt->maxvif; ++iter->ct) {
+               if (!VIF_EXISTS(mrt, iter->ct))
                        continue;
                if (pos-- == 0)
-                       return &net->ipv4.vif_table[iter->ct];
+                       return &mrt->vif_table[iter->ct];
        }
        return NULL;
  }
  static void *ipmr_vif_seq_start(struct seq_file *seq, loff_t *pos)
        __acquires(mrt_lock)
  {
+       struct ipmr_vif_iter *iter = seq->private;
        struct net *net = seq_file_net(seq);
+       struct mr_table *mrt;
+       mrt = ipmr_get_table(net, RT_TABLE_DEFAULT);
+       if (mrt == NULL)
+               return ERR_PTR(-ENOENT);
+       iter->mrt = mrt;
  
        read_lock(&mrt_lock);
        return *pos ? ipmr_vif_seq_idx(net, seq->private, *pos - 1)
@@@ -1738,15 -2125,16 +2125,16 @@@ static void *ipmr_vif_seq_next(struct s
  {
        struct ipmr_vif_iter *iter = seq->private;
        struct net *net = seq_file_net(seq);
+       struct mr_table *mrt = iter->mrt;
  
        ++*pos;
        if (v == SEQ_START_TOKEN)
                return ipmr_vif_seq_idx(net, iter, 0);
  
-       while (++iter->ct < net->ipv4.maxvif) {
-               if (!VIF_EXISTS(net, iter->ct))
+       while (++iter->ct < mrt->maxvif) {
+               if (!VIF_EXISTS(mrt, iter->ct))
                        continue;
-               return &net->ipv4.vif_table[iter->ct];
+               return &mrt->vif_table[iter->ct];
        }
        return NULL;
  }
@@@ -1759,7 -2147,8 +2147,8 @@@ static void ipmr_vif_seq_stop(struct se
  
  static int ipmr_vif_seq_show(struct seq_file *seq, void *v)
  {
-       struct net *net = seq_file_net(seq);
+       struct ipmr_vif_iter *iter = seq->private;
+       struct mr_table *mrt = iter->mrt;
  
        if (v == SEQ_START_TOKEN) {
                seq_puts(seq,
  
                seq_printf(seq,
                           "%2Zd %-10s %8ld %7ld  %8ld %7ld %05X %08X %08X\n",
-                          vif - net->ipv4.vif_table,
+                          vif - mrt->vif_table,
                           name, vif->bytes_in, vif->pkt_in,
                           vif->bytes_out, vif->pkt_out,
                           vif->flags, vif->local, vif->remote);
@@@ -1801,7 -2190,8 +2190,8 @@@ static const struct file_operations ipm
  
  struct ipmr_mfc_iter {
        struct seq_net_private p;
-       struct mfc_cache **cache;
+       struct mr_table *mrt;
+       struct list_head *cache;
        int ct;
  };
  
  static struct mfc_cache *ipmr_mfc_seq_idx(struct net *net,
                                          struct ipmr_mfc_iter *it, loff_t pos)
  {
+       struct mr_table *mrt = it->mrt;
        struct mfc_cache *mfc;
  
-       it->cache = net->ipv4.mfc_cache_array;
        read_lock(&mrt_lock);
-       for (it->ct = 0; it->ct < MFC_LINES; it->ct++)
-               for (mfc = net->ipv4.mfc_cache_array[it->ct];
-                    mfc; mfc = mfc->next)
+       for (it->ct = 0; it->ct < MFC_LINES; it->ct++) {
+               it->cache = &mrt->mfc_cache_array[it->ct];
+               list_for_each_entry(mfc, it->cache, list)
                        if (pos-- == 0)
                                return mfc;
+       }
        read_unlock(&mrt_lock);
  
-       it->cache = &mfc_unres_queue;
        spin_lock_bh(&mfc_unres_lock);
-       for (mfc = mfc_unres_queue; mfc; mfc = mfc->next)
-               if (net_eq(mfc_net(mfc), net) &&
-                   pos-- == 0)
+       it->cache = &mrt->mfc_unres_queue;
+       list_for_each_entry(mfc, it->cache, list)
+               if (pos-- == 0)
                        return mfc;
        spin_unlock_bh(&mfc_unres_lock);
  
@@@ -1837,7 -2227,13 +2227,13 @@@ static void *ipmr_mfc_seq_start(struct 
  {
        struct ipmr_mfc_iter *it = seq->private;
        struct net *net = seq_file_net(seq);
+       struct mr_table *mrt;
  
+       mrt = ipmr_get_table(net, RT_TABLE_DEFAULT);
+       if (mrt == NULL)
+               return ERR_PTR(-ENOENT);
+       it->mrt = mrt;
        it->cache = NULL;
        it->ct = 0;
        return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1)
@@@ -1849,37 -2245,36 +2245,36 @@@ static void *ipmr_mfc_seq_next(struct s
        struct mfc_cache *mfc = v;
        struct ipmr_mfc_iter *it = seq->private;
        struct net *net = seq_file_net(seq);
+       struct mr_table *mrt = it->mrt;
  
        ++*pos;
  
        if (v == SEQ_START_TOKEN)
                return ipmr_mfc_seq_idx(net, seq->private, 0);
  
-       if (mfc->next)
-               return mfc->next;
+       if (mfc->list.next != it->cache)
+               return list_entry(mfc->list.next, struct mfc_cache, list);
  
-       if (it->cache == &mfc_unres_queue)
+       if (it->cache == &mrt->mfc_unres_queue)
                goto end_of_list;
  
-       BUG_ON(it->cache != net->ipv4.mfc_cache_array);
+       BUG_ON(it->cache != &mrt->mfc_cache_array[it->ct]);
  
        while (++it->ct < MFC_LINES) {
-               mfc = net->ipv4.mfc_cache_array[it->ct];
-               if (mfc)
-                       return mfc;
+               it->cache = &mrt->mfc_cache_array[it->ct];
+               if (list_empty(it->cache))
+                       continue;
+               return list_first_entry(it->cache, struct mfc_cache, list);
        }
  
        /* exhausted cache_array, show unresolved */
        read_unlock(&mrt_lock);
-       it->cache = &mfc_unres_queue;
+       it->cache = &mrt->mfc_unres_queue;
        it->ct = 0;
  
        spin_lock_bh(&mfc_unres_lock);
-       mfc = mfc_unres_queue;
-       while (mfc && !net_eq(mfc_net(mfc), net))
-               mfc = mfc->next;
-       if (mfc)
-               return mfc;
+       if (!list_empty(it->cache))
+               return list_first_entry(it->cache, struct mfc_cache, list);
  
   end_of_list:
        spin_unlock_bh(&mfc_unres_lock);
  static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v)
  {
        struct ipmr_mfc_iter *it = seq->private;
-       struct net *net = seq_file_net(seq);
+       struct mr_table *mrt = it->mrt;
  
-       if (it->cache == &mfc_unres_queue)
+       if (it->cache == &mrt->mfc_unres_queue)
                spin_unlock_bh(&mfc_unres_lock);
-       else if (it->cache == net->ipv4.mfc_cache_array)
+       else if (it->cache == &mrt->mfc_cache_array[it->ct])
                read_unlock(&mrt_lock);
  }
  
  static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
  {
        int n;
-       struct net *net = seq_file_net(seq);
  
        if (v == SEQ_START_TOKEN) {
                seq_puts(seq,
        } else {
                const struct mfc_cache *mfc = v;
                const struct ipmr_mfc_iter *it = seq->private;
+               const struct mr_table *mrt = it->mrt;
  
-               seq_printf(seq, "%08lX %08lX %-3hd",
-                          (unsigned long) mfc->mfc_mcastgrp,
-                          (unsigned long) mfc->mfc_origin,
+               seq_printf(seq, "%08X %08X %-3hd",
+                          (__force u32) mfc->mfc_mcastgrp,
+                          (__force u32) mfc->mfc_origin,
                           mfc->mfc_parent);
  
-               if (it->cache != &mfc_unres_queue) {
+               if (it->cache != &mrt->mfc_unres_queue) {
                        seq_printf(seq, " %8lu %8lu %8lu",
                                   mfc->mfc_un.res.pkt,
                                   mfc->mfc_un.res.bytes,
                                   mfc->mfc_un.res.wrong_if);
                        for (n = mfc->mfc_un.res.minvif;
                             n < mfc->mfc_un.res.maxvif; n++ ) {
-                               if (VIF_EXISTS(net, n) &&
+                               if (VIF_EXISTS(mrt, n) &&
                                    mfc->mfc_un.res.ttls[n] < 255)
                                        seq_printf(seq,
                                           " %2d:%-3d",
@@@ -1975,27 -2370,11 +2370,11 @@@ static const struct net_protocol pim_pr
   */
  static int __net_init ipmr_net_init(struct net *net)
  {
-       int err = 0;
+       int err;
  
-       net->ipv4.vif_table = kcalloc(MAXVIFS, sizeof(struct vif_device),
-                                     GFP_KERNEL);
-       if (!net->ipv4.vif_table) {
-               err = -ENOMEM;
+       err = ipmr_rules_init(net);
+       if (err < 0)
                goto fail;
-       }
-       /* Forwarding cache */
-       net->ipv4.mfc_cache_array = kcalloc(MFC_LINES,
-                                           sizeof(struct mfc_cache *),
-                                           GFP_KERNEL);
-       if (!net->ipv4.mfc_cache_array) {
-               err = -ENOMEM;
-               goto fail_mfc_cache;
-       }
- #ifdef CONFIG_IP_PIMSM
-       net->ipv4.mroute_reg_vif_num = -1;
- #endif
  
  #ifdef CONFIG_PROC_FS
        err = -ENOMEM;
  proc_cache_fail:
        proc_net_remove(net, "ip_mr_vif");
  proc_vif_fail:
-       kfree(net->ipv4.mfc_cache_array);
+       ipmr_rules_exit(net);
  #endif
- fail_mfc_cache:
-       kfree(net->ipv4.vif_table);
  fail:
        return err;
  }
@@@ -2024,8 -2401,7 +2401,7 @@@ static void __net_exit ipmr_net_exit(st
        proc_net_remove(net, "ip_mr_cache");
        proc_net_remove(net, "ip_mr_vif");
  #endif
-       kfree(net->ipv4.mfc_cache_array);
-       kfree(net->ipv4.vif_table);
+       ipmr_rules_exit(net);
  }
  
  static struct pernet_operations ipmr_net_ops = {
@@@ -2048,7 -2424,6 +2424,6 @@@ int __init ip_mr_init(void
        if (err)
                goto reg_pernet_fail;
  
-       setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0);
        err = register_netdevice_notifier(&ip_mr_notifier);
        if (err)
                goto reg_notif_fail;
                goto add_proto_fail;
        }
  #endif
+       rtnl_register(RTNL_FAMILY_IPMR, RTM_GETROUTE, NULL, ipmr_rtm_dumproute);
        return 0;
  
  #ifdef CONFIG_IP_PIMSM_V2
@@@ -2066,7 -2442,6 +2442,6 @@@ add_proto_fail
        unregister_netdevice_notifier(&ip_mr_notifier);
  #endif
  reg_notif_fail:
-       del_timer(&ipmr_expire_timer);
        unregister_pernet_subsys(&ipmr_net_ops);
  reg_pernet_fail:
        kmem_cache_destroy(mrt_cachep);
diff --combined net/mac80211/mlme.c
   */
  #define IEEE80211_PROBE_WAIT          (HZ / 2)
  
+ /*
+  * Weight given to the latest Beacon frame when calculating average signal
+  * strength for Beacon frames received in the current BSS. This must be
+  * between 1 and 15.
+  */
+ #define IEEE80211_SIGNAL_AVE_WEIGHT   3
  #define TMR_RUNNING_TIMER     0
  #define TMR_RUNNING_CHANSW    1
  
@@@ -130,11 -137,14 +137,14 @@@ static u32 ieee80211_enable_ht(struct i
        struct sta_info *sta;
        u32 changed = 0;
        u16 ht_opmode;
-       bool enable_ht = true, ht_changed;
+       bool enable_ht = true;
+       enum nl80211_channel_type prev_chantype;
        enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
  
        sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
  
+       prev_chantype = sdata->vif.bss_conf.channel_type;
        /* HT is not supported */
        if (!sband->ht_cap.ht_supported)
                enable_ht = false;
                }
        }
  
-       ht_changed = conf_is_ht(&local->hw.conf) != enable_ht ||
-                    channel_type != local->hw.conf.channel_type;
        if (local->tmp_channel)
                local->tmp_channel_type = channel_type;
-       local->oper_channel_type = channel_type;
  
-       if (ht_changed) {
-                 /* channel_type change automatically detected */
-               ieee80211_hw_config(local, 0);
+       if (!ieee80211_set_channel_type(local, sdata, channel_type)) {
+               /* can only fail due to HT40+/- mismatch */
+               channel_type = NL80211_CHAN_HT20;
+               WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type));
+       }
+       /* channel_type change automatically detected */
+       ieee80211_hw_config(local, 0);
  
+       if (prev_chantype != channel_type) {
                rcu_read_lock();
                sta = sta_info_get(sdata, bssid);
                if (sta)
                        rate_control_rate_update(local, sband, sta,
                                                 IEEE80211_RC_HT_CHANGED,
-                                                local->oper_channel_type);
+                                                channel_type);
                rcu_read_unlock();
-         }
-       /* disable HT */
-       if (!enable_ht)
-               return 0;
+       }
  
        ht_opmode = le16_to_cpu(hti->operation_mode);
  
        /* if bss configuration changed store the new one */
-       if (!sdata->ht_opmode_valid ||
-           sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
+       if (sdata->ht_opmode_valid != enable_ht ||
+           sdata->vif.bss_conf.ht_operation_mode != ht_opmode ||
+           prev_chantype != channel_type) {
                changed |= BSS_CHANGED_HT;
                sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
-               sdata->ht_opmode_valid = true;
+               sdata->ht_opmode_valid = enable_ht;
        }
  
        return changed;
  
  static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
                                           const u8 *bssid, u16 stype, u16 reason,
-                                          void *cookie)
+                                          void *cookie, bool send_frame)
  {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
                        cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
        if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED))
                IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
-       ieee80211_tx_skb(sdata, skb);
+       if (send_frame)
+               ieee80211_tx_skb(sdata, skb);
+       else
+               kfree_skb(skb);
  }
  
  void ieee80211_send_pspoll(struct ieee80211_local *local,
@@@ -329,7 -342,11 +342,11 @@@ static void ieee80211_chswitch_work(str
                goto out;
  
        sdata->local->oper_channel = sdata->local->csa_channel;
-       ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL);
+       if (!sdata->local->ops->channel_switch) {
+               /* call "hw_config" only if doing sw channel switch */
+               ieee80211_hw_config(sdata->local,
+                       IEEE80211_CONF_CHANGE_CHANNEL);
+       }
  
        /* XXX: shouldn't really modify cfg80211-owned data! */
        ifmgd->associated->channel = sdata->local->oper_channel;
        mutex_unlock(&ifmgd->mtx);
  }
  
+ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
+ {
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_if_managed *ifmgd;
+       sdata = vif_to_sdata(vif);
+       ifmgd = &sdata->u.mgd;
+       trace_api_chswitch_done(sdata, success);
+       if (!success) {
+               /*
+                * If the channel switch was not successful, stay
+                * around on the old channel. We currently lack
+                * good handling of this situation, possibly we
+                * should just drop the association.
+                */
+               sdata->local->csa_channel = sdata->local->oper_channel;
+       }
+       ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
+ }
+ EXPORT_SYMBOL(ieee80211_chswitch_done);
  static void ieee80211_chswitch_timer(unsigned long data)
  {
        struct ieee80211_sub_if_data *sdata =
  
  void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
                                      struct ieee80211_channel_sw_ie *sw_elem,
-                                     struct ieee80211_bss *bss)
+                                     struct ieee80211_bss *bss,
+                                     u64 timestamp)
  {
        struct cfg80211_bss *cbss =
                container_of((void *)bss, struct cfg80211_bss, priv);
  
        sdata->local->csa_channel = new_ch;
  
+       if (sdata->local->ops->channel_switch) {
+               /* use driver's channel switch callback */
+               struct ieee80211_channel_switch ch_switch;
+               memset(&ch_switch, 0, sizeof(ch_switch));
+               ch_switch.timestamp = timestamp;
+               if (sw_elem->mode) {
+                       ch_switch.block_tx = true;
+                       ieee80211_stop_queues_by_reason(&sdata->local->hw,
+                                       IEEE80211_QUEUE_STOP_REASON_CSA);
+               }
+               ch_switch.channel = new_ch;
+               ch_switch.count = sw_elem->count;
+               ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
+               drv_channel_switch(sdata->local, &ch_switch);
+               return;
+       }
+       /* channel switch handled in software */
        if (sw_elem->count <= 1) {
                ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
        } else {
-               ieee80211_stop_queues_by_reason(&sdata->local->hw,
+               if (sw_elem->mode)
+                       ieee80211_stop_queues_by_reason(&sdata->local->hw,
                                        IEEE80211_QUEUE_STOP_REASON_CSA);
                ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
                mod_timer(&ifmgd->chswitch_timer,
@@@ -467,6 -527,7 +527,7 @@@ void ieee80211_recalc_ps(struct ieee802
  {
        struct ieee80211_sub_if_data *sdata, *found = NULL;
        int count = 0;
+       int timeout;
  
        if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) {
                local->ps_sdata = NULL;
                s32 beaconint_us;
  
                if (latency < 0)
 -                      latency = pm_qos_requirement(PM_QOS_NETWORK_LATENCY);
 +                      latency = pm_qos_request(PM_QOS_NETWORK_LATENCY);
  
                beaconint_us = ieee80211_tu_to_usec(
                                        found->vif.bss_conf.beacon_int);
  
+               timeout = local->hw.conf.dynamic_ps_forced_timeout;
+               if (timeout < 0) {
+                       /*
+                        * The 2 second value is there for compatibility until
+                        * the PM_QOS_NETWORK_LATENCY is configured with real
+                        * values.
+                        */
+                       if (latency == 2000000000)
+                               timeout = 100;
+                       else if (latency <= 50000)
+                               timeout = 300;
+                       else if (latency <= 100000)
+                               timeout = 100;
+                       else if (latency <= 500000)
+                               timeout = 50;
+                       else
+                               timeout = 0;
+               }
+               local->hw.conf.dynamic_ps_timeout = timeout;
                if (beaconint_us > latency) {
                        local->ps_sdata = NULL;
                } else {
@@@ -592,6 -673,9 +673,9 @@@ static void ieee80211_sta_wmm_params(st
        int count;
        u8 *pos, uapsd_queues = 0;
  
+       if (!local->ops->conf_tx)
+               return;
        if (local->hw.queues < 4)
                return;
  
                       params.aifs, params.cw_min, params.cw_max, params.txop,
                       params.uapsd);
  #endif
-               if (drv_conf_tx(local, queue, &params) && local->ops->conf_tx)
+               if (drv_conf_tx(local, queue, &params))
                        printk(KERN_DEBUG "%s: failed to set TX queue "
                               "parameters for queue %d\n",
                               wiphy_name(local->hw.wiphy), queue);
        }
+       /* enable WMM or activate new settings */
+       local->hw.conf.flags |= IEEE80211_CONF_QOS;
+       drv_config(local, IEEE80211_CONF_CHANGE_QOS);
  }
  
  static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
@@@ -731,6 -819,8 +819,8 @@@ static void ieee80211_set_associated(st
        sdata->u.mgd.associated = cbss;
        memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN);
  
+       sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE;
        /* just to be sure */
        sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL |
                                IEEE80211_STA_BEACON_POLL);
        /* And the BSSID changed - we're associated now */
        bss_info_changed |= BSS_CHANGED_BSSID;
  
+       /* Tell the driver to monitor connection quality (if supported) */
+       if ((local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI) &&
+           sdata->vif.bss_conf.cqm_rssi_thold)
+               bss_info_changed |= BSS_CHANGED_CQM;
        ieee80211_bss_info_change_notify(sdata, bss_info_changed);
  
        mutex_lock(&local->iflist_mtx);
        netif_carrier_on(sdata->dev);
  }
  
- static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata)
+ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
+                                  bool remove_sta)
  {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct ieee80211_local *local = sdata->local;
        ieee80211_set_wmm_default(sdata);
  
        /* channel(_type) changes are handled by ieee80211_hw_config */
-       local->oper_channel_type = NL80211_CHAN_NO_HT;
+       WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT));
  
        /* on the next assoc, re-program HT parameters */
        sdata->ht_opmode_valid = false;
  
        ieee80211_hw_config(local, config_changed);
  
-       /* And the BSSID changed -- not very interesting here */
-       changed |= BSS_CHANGED_BSSID;
+       /* The BSSID (not really interesting) and HT changed */
+       changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT;
        ieee80211_bss_info_change_notify(sdata, changed);
  
-       sta_info_destroy_addr(sdata, bssid);
+       if (remove_sta)
+               sta_info_destroy_addr(sdata, bssid);
  }
  
  void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
        if (is_multicast_ether_addr(hdr->addr1))
                return;
  
+       if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
+               return;
        mod_timer(&sdata->u.mgd.conn_mon_timer,
                  round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
  }
@@@ -934,23 -1034,72 +1034,72 @@@ static void ieee80211_mgd_probe_ap(stru
        mutex_unlock(&ifmgd->mtx);
  }
  
- void ieee80211_beacon_loss_work(struct work_struct *work)
+ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
+ {
+       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+       struct ieee80211_local *local = sdata->local;
+       u8 bssid[ETH_ALEN];
+       mutex_lock(&ifmgd->mtx);
+       if (!ifmgd->associated) {
+               mutex_unlock(&ifmgd->mtx);
+               return;
+       }
+       memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
+       printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid);
+       ieee80211_set_disassoc(sdata, true);
+       ieee80211_recalc_idle(local);
+       mutex_unlock(&ifmgd->mtx);
+       /*
+        * must be outside lock due to cfg80211,
+        * but that's not a problem.
+        */
+       ieee80211_send_deauth_disassoc(sdata, bssid,
+                                      IEEE80211_STYPE_DEAUTH,
+                                      WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
+                                      NULL, true);
+ }
+ void ieee80211_beacon_connection_loss_work(struct work_struct *work)
  {
        struct ieee80211_sub_if_data *sdata =
                container_of(work, struct ieee80211_sub_if_data,
-                            u.mgd.beacon_loss_work);
+                            u.mgd.beacon_connection_loss_work);
  
-       ieee80211_mgd_probe_ap(sdata, true);
+       if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
+               __ieee80211_connection_loss(sdata);
+       else
+               ieee80211_mgd_probe_ap(sdata, true);
  }
  
  void ieee80211_beacon_loss(struct ieee80211_vif *vif)
  {
        struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+       struct ieee80211_hw *hw = &sdata->local->hw;
  
-       ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work);
+       trace_api_beacon_loss(sdata);
+       WARN_ON(hw->flags & IEEE80211_HW_CONNECTION_MONITOR);
+       ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
  }
  EXPORT_SYMBOL(ieee80211_beacon_loss);
  
+ void ieee80211_connection_loss(struct ieee80211_vif *vif)
+ {
+       struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+       struct ieee80211_hw *hw = &sdata->local->hw;
+       trace_api_connection_loss(sdata);
+       WARN_ON(!(hw->flags & IEEE80211_HW_CONNECTION_MONITOR));
+       ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
+ }
+ EXPORT_SYMBOL(ieee80211_connection_loss);
  static enum rx_mgmt_action __must_check
  ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
                         struct ieee80211_mgmt *mgmt, size_t len)
        printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n",
                        sdata->name, bssid, reason_code);
  
-       ieee80211_set_disassoc(sdata);
+       ieee80211_set_disassoc(sdata, true);
        ieee80211_recalc_idle(sdata->local);
  
        return RX_MGMT_CFG80211_DEAUTH;
@@@ -1001,7 -1150,7 +1150,7 @@@ ieee80211_rx_mgmt_disassoc(struct ieee8
        printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n",
                        sdata->name, mgmt->sa, reason_code);
  
-       ieee80211_set_disassoc(sdata);
+       ieee80211_set_disassoc(sdata, true);
        ieee80211_recalc_idle(sdata->local);
        return RX_MGMT_CFG80211_DISASSOC;
  }
@@@ -1215,7 -1364,8 +1364,8 @@@ static void ieee80211_rx_bss_info(struc
                                                        ETH_ALEN) == 0)) {
                struct ieee80211_channel_sw_ie *sw_elem =
                        (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem;
-               ieee80211_sta_process_chanswitch(sdata, sw_elem, bss);
+               ieee80211_sta_process_chanswitch(sdata, sw_elem,
+                                                bss, rx_status->mactime);
        }
  }
  
@@@ -1254,12 -1404,17 +1404,17 @@@ static void ieee80211_rx_mgmt_probe_res
                mutex_lock(&sdata->local->iflist_mtx);
                ieee80211_recalc_ps(sdata->local, -1);
                mutex_unlock(&sdata->local->iflist_mtx);
+               if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
+                       return;
                /*
                 * We've received a probe response, but are not sure whether
                 * we have or will be receiving any beacons or data, so let's
                 * schedule the timers again, just in case.
                 */
                mod_beacon_timer(sdata);
                mod_timer(&ifmgd->conn_mon_timer,
                          round_jiffies_up(jiffies +
                                           IEEE80211_CONNECTION_IDLE_TIME));
@@@ -1293,6 -1448,7 +1448,7 @@@ static void ieee80211_rx_mgmt_beacon(st
                                     struct ieee80211_rx_status *rx_status)
  {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+       struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
        size_t baselen;
        struct ieee802_11_elems elems;
        struct ieee80211_local *local = sdata->local;
        if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0)
                return;
  
+       /* Track average RSSI from the Beacon frames of the current AP */
+       ifmgd->last_beacon_signal = rx_status->signal;
+       if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) {
+               ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE;
+               ifmgd->ave_beacon_signal = rx_status->signal;
+               ifmgd->last_cqm_event_signal = 0;
+       } else {
+               ifmgd->ave_beacon_signal =
+                       (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 +
+                        (16 - IEEE80211_SIGNAL_AVE_WEIGHT) *
+                        ifmgd->ave_beacon_signal) / 16;
+       }
+       if (bss_conf->cqm_rssi_thold &&
+           !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) {
+               int sig = ifmgd->ave_beacon_signal / 16;
+               int last_event = ifmgd->last_cqm_event_signal;
+               int thold = bss_conf->cqm_rssi_thold;
+               int hyst = bss_conf->cqm_rssi_hyst;
+               if (sig < thold &&
+                   (last_event == 0 || sig < last_event - hyst)) {
+                       ifmgd->last_cqm_event_signal = sig;
+                       ieee80211_cqm_rssi_notify(
+                               &sdata->vif,
+                               NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+                               GFP_KERNEL);
+               } else if (sig > thold &&
+                          (last_event == 0 || sig > last_event + hyst)) {
+                       ifmgd->last_cqm_event_signal = sig;
+                       ieee80211_cqm_rssi_notify(
+                               &sdata->vif,
+                               NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+                               GFP_KERNEL);
+               }
+       }
        if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) {
  #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
                if (net_ratelimit()) {
@@@ -1506,7 -1697,8 +1697,8 @@@ static void ieee80211_sta_rx_queued_mgm
  
                        ieee80211_sta_process_chanswitch(sdata,
                                        &mgmt->u.action.u.chan_switch.sw_elem,
-                                       (void *)ifmgd->associated->priv);
+                                       (void *)ifmgd->associated->priv,
+                                       rx_status->mactime);
                        break;
                }
                mutex_unlock(&ifmgd->mtx);
@@@ -1613,7 -1805,7 +1805,7 @@@ static void ieee80211_sta_work(struct w
                        printk(KERN_DEBUG "No probe response from AP %pM"
                                " after %dms, disconnecting.\n",
                                bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
-                       ieee80211_set_disassoc(sdata);
+                       ieee80211_set_disassoc(sdata, true);
                        ieee80211_recalc_idle(local);
                        mutex_unlock(&ifmgd->mtx);
                        /*
                        ieee80211_send_deauth_disassoc(sdata, bssid,
                                        IEEE80211_STYPE_DEAUTH,
                                        WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
-                                       NULL);
+                                       NULL, true);
                        mutex_lock(&ifmgd->mtx);
                }
        }
@@@ -1640,7 -1832,8 +1832,8 @@@ static void ieee80211_sta_bcn_mon_timer
        if (local->quiescing)
                return;
  
-       ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work);
+       ieee80211_queue_work(&sdata->local->hw,
+                            &sdata->u.mgd.beacon_connection_loss_work);
  }
  
  static void ieee80211_sta_conn_mon_timer(unsigned long data)
@@@ -1692,7 -1885,7 +1885,7 @@@ void ieee80211_sta_quiesce(struct ieee8
         */
  
        cancel_work_sync(&ifmgd->work);
-       cancel_work_sync(&ifmgd->beacon_loss_work);
+       cancel_work_sync(&ifmgd->beacon_connection_loss_work);
        if (del_timer_sync(&ifmgd->timer))
                set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
  
@@@ -1726,7 -1919,8 +1919,8 @@@ void ieee80211_sta_setup_sdata(struct i
        INIT_WORK(&ifmgd->work, ieee80211_sta_work);
        INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work);
        INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
-       INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work);
+       INIT_WORK(&ifmgd->beacon_connection_loss_work,
+                 ieee80211_beacon_connection_loss_work);
        setup_timer(&ifmgd->timer, ieee80211_sta_timer,
                    (unsigned long) sdata);
        setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer,
@@@ -1805,6 -1999,9 +1999,9 @@@ int ieee80211_mgd_auth(struct ieee80211
        struct ieee80211_work *wk;
        u16 auth_alg;
  
+       if (req->local_state_change)
+               return 0; /* no need to update mac80211 state */
        switch (req->auth_type) {
        case NL80211_AUTHTYPE_OPEN_SYSTEM:
                auth_alg = WLAN_AUTH_OPEN;
@@@ -1913,7 -2110,7 +2110,7 @@@ int ieee80211_mgd_assoc(struct ieee8021
                }
  
                /* Trying to reassociate - clear previous association state */
-               ieee80211_set_disassoc(sdata);
+               ieee80211_set_disassoc(sdata, true);
        }
        mutex_unlock(&ifmgd->mtx);
  
@@@ -2017,7 -2214,7 +2214,7 @@@ int ieee80211_mgd_deauth(struct ieee802
  
        if (ifmgd->associated == req->bss) {
                bssid = req->bss->bssid;
-               ieee80211_set_disassoc(sdata);
+               ieee80211_set_disassoc(sdata, true);
                mutex_unlock(&ifmgd->mtx);
        } else {
                bool not_auth_yet = false;
        printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n",
               sdata->name, bssid, req->reason_code);
  
-       ieee80211_send_deauth_disassoc(sdata, bssid,
-                       IEEE80211_STYPE_DEAUTH, req->reason_code,
-                       cookie);
+       ieee80211_send_deauth_disassoc(sdata, bssid, IEEE80211_STYPE_DEAUTH,
+                                      req->reason_code, cookie,
+                                      !req->local_state_change);
  
        ieee80211_recalc_idle(sdata->local);
  
@@@ -2075,6 -2272,7 +2272,7 @@@ int ieee80211_mgd_disassoc(struct ieee8
                           void *cookie)
  {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+       u8 bssid[ETH_ALEN];
  
        mutex_lock(&ifmgd->mtx);
  
        printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n",
               sdata->name, req->bss->bssid, req->reason_code);
  
-       ieee80211_set_disassoc(sdata);
+       memcpy(bssid, req->bss->bssid, ETH_ALEN);
+       ieee80211_set_disassoc(sdata, false);
  
        mutex_unlock(&ifmgd->mtx);
  
        ieee80211_send_deauth_disassoc(sdata, req->bss->bssid,
                        IEEE80211_STYPE_DISASSOC, req->reason_code,
-                       cookie);
+                       cookie, !req->local_state_change);
+       sta_info_destroy_addr(sdata, bssid);
  
        ieee80211_recalc_idle(sdata->local);
  
@@@ -2118,7 -2318,7 +2318,7 @@@ int ieee80211_mgd_action(struct ieee802
        if ((chan != local->tmp_channel ||
             channel_type != local->tmp_channel_type) &&
            (chan != local->oper_channel ||
-            channel_type != local->oper_channel_type))
+            channel_type != local->_oper_channel_type))
                return -EBUSY;
  
        skb = dev_alloc_skb(local->hw.extra_tx_headroom + len);
        *cookie = (unsigned long) skb;
        return 0;
  }
+ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
+                              enum nl80211_cqm_rssi_threshold_event rssi_event,
+                              gfp_t gfp)
+ {
+       struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+       trace_api_cqm_rssi_notify(sdata, rssi_event);
+       cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp);
+ }
+ EXPORT_SYMBOL(ieee80211_cqm_rssi_notify);
diff --combined net/mac80211/scan.c
@@@ -14,6 -14,8 +14,8 @@@
  
  #include <linux/if_arp.h>
  #include <linux/rtnetlink.h>
+ #include <linux/pm_qos_params.h>
+ #include <net/sch_generic.h>
  #include <linux/slab.h>
  #include <net/mac80211.h>
  
@@@ -83,7 -85,7 +85,7 @@@ ieee80211_bss_info_update(struct ieee80
  {
        struct cfg80211_bss *cbss;
        struct ieee80211_bss *bss;
-       int clen;
+       int clen, srlen;
        s32 signal = 0;
  
        if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
                bss->dtim_period = tim_ie->dtim_period;
        }
  
-       bss->supp_rates_len = 0;
+       /* replace old supported rates if we get new values */
+       srlen = 0;
        if (elems->supp_rates) {
-               clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
+               clen = IEEE80211_MAX_SUPP_RATES;
                if (clen > elems->supp_rates_len)
                        clen = elems->supp_rates_len;
-               memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates,
-                      clen);
-               bss->supp_rates_len += clen;
+               memcpy(bss->supp_rates, elems->supp_rates, clen);
+               srlen += clen;
        }
        if (elems->ext_supp_rates) {
-               clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
+               clen = IEEE80211_MAX_SUPP_RATES - srlen;
                if (clen > elems->ext_supp_rates_len)
                        clen = elems->ext_supp_rates_len;
-               memcpy(&bss->supp_rates[bss->supp_rates_len],
-                      elems->ext_supp_rates, clen);
-               bss->supp_rates_len += clen;
+               memcpy(bss->supp_rates + srlen, elems->ext_supp_rates, clen);
+               srlen += clen;
        }
+       if (srlen)
+               bss->supp_rates_len = srlen;
  
        bss->wmm_used = elems->wmm_param || elems->wmm_info;
        bss->uapsd_supported = is_uapsd_supported(elems);
@@@ -246,6 -249,8 +249,8 @@@ void ieee80211_scan_completed(struct ie
        struct ieee80211_local *local = hw_to_local(hw);
        bool was_hw_scan;
  
+       trace_api_scan_completed(local, aborted);
        mutex_lock(&local->scan_mtx);
  
        /*
@@@ -322,6 -327,7 +327,7 @@@ static int ieee80211_start_sw_scan(stru
  
        ieee80211_offchannel_stop_beaconing(local);
  
+       local->leave_oper_channel_time = 0;
        local->next_scan_state = SCAN_DECISION;
        local->scan_channel_idx = 0;
  
@@@ -406,7 -412,7 +412,7 @@@ static int __ieee80211_start_scan(struc
  
        if (local->ops->hw_scan) {
                WARN_ON(!ieee80211_prep_hw_scan(local));
-               rc = drv_hw_scan(local, local->hw_scan_req);
+               rc = drv_hw_scan(local, sdata, local->hw_scan_req);
        } else
                rc = ieee80211_start_sw_scan(local);
  
        return rc;
  }
  
+ static unsigned long
+ ieee80211_scan_get_channel_time(struct ieee80211_channel *chan)
+ {
+       /*
+        * TODO: channel switching also consumes quite some time,
+        * add that delay as well to get a better estimation
+        */
+       if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+               return IEEE80211_PASSIVE_CHANNEL_TIME;
+       return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME;
+ }
  static int ieee80211_scan_state_decision(struct ieee80211_local *local,
                                         unsigned long *next_delay)
  {
        bool associated = false;
+       bool tx_empty = true;
+       bool bad_latency;
+       bool listen_int_exceeded;
+       unsigned long min_beacon_int = 0;
        struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_channel *next_chan;
  
        /* if no more bands/channels left, complete scan and advance to the idle state */
        if (local->scan_channel_idx >= local->scan_req->n_channels) {
                return 1;
        }
  
-       /* check if at least one STA interface is associated */
+       /*
+        * check if at least one STA interface is associated,
+        * check if at least one STA interface has pending tx frames
+        * and grab the lowest used beacon interval
+        */
        mutex_lock(&local->iflist_mtx);
        list_for_each_entry(sdata, &local->interfaces, list) {
                if (!ieee80211_sdata_running(sdata))
                if (sdata->vif.type == NL80211_IFTYPE_STATION) {
                        if (sdata->u.mgd.associated) {
                                associated = true;
-                               break;
+                               if (sdata->vif.bss_conf.beacon_int <
+                                   min_beacon_int || min_beacon_int == 0)
+                                       min_beacon_int =
+                                               sdata->vif.bss_conf.beacon_int;
+                               if (!qdisc_all_tx_empty(sdata->dev)) {
+                                       tx_empty = false;
+                                       break;
+                               }
                        }
                }
        }
        if (local->scan_channel) {
                /*
                 * we're currently scanning a different channel, let's
-                * switch back to the operating channel now if at least
-                * one interface is associated. Otherwise just scan the
-                * next channel
+                * see if we can scan another channel without interfering
+                * with the current traffic situation.
+                *
+                * Since we don't know if the AP has pending frames for us
+                * we can only check for our tx queues and use the current
+                * pm_qos requirements for rx. Hence, if no tx traffic occurs
+                * at all we will scan as many channels in a row as the pm_qos
+                * latency allows us to. Additionally we also check for the
+                * currently negotiated listen interval to prevent losing
+                * frames unnecessarily.
+                *
+                * Otherwise switch back to the operating channel.
                 */
-               if (associated)
+               next_chan = local->scan_req->channels[local->scan_channel_idx];
+               bad_latency = time_after(jiffies +
+                               ieee80211_scan_get_channel_time(next_chan),
+                               local->leave_oper_channel_time +
 -                              usecs_to_jiffies(pm_qos_requirement(PM_QOS_NETWORK_LATENCY)));
++                              usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY)));
+               listen_int_exceeded = time_after(jiffies +
+                               ieee80211_scan_get_channel_time(next_chan),
+                               local->leave_oper_channel_time +
+                               usecs_to_jiffies(min_beacon_int * 1024) *
+                               local->hw.conf.listen_interval);
+               if (associated && ( !tx_empty || bad_latency ||
+                   listen_int_exceeded))
                        local->next_scan_state = SCAN_ENTER_OPER_CHANNEL;
                else
                        local->next_scan_state = SCAN_SET_CHANNEL;
@@@ -492,6 -551,9 +551,9 @@@ static void ieee80211_scan_state_leave_
        else
                *next_delay = HZ / 10;
  
+       /* remember when we left the operating channel */
+       local->leave_oper_channel_time = jiffies;
        /* advance to the next channel to be scanned */
        local->next_scan_state = SCAN_SET_CHANNEL;
  }
@@@ -594,7 -656,7 +656,7 @@@ void ieee80211_scan_work(struct work_st
        }
  
        if (local->hw_scan_req) {
-               int rc = drv_hw_scan(local, local->hw_scan_req);
+               int rc = drv_hw_scan(local, sdata, local->hw_scan_req);
                mutex_unlock(&local->scan_mtx);
                if (rc)
                        ieee80211_scan_completed(&local->hw, true);
@@@ -667,10 -729,12 +729,12 @@@ int ieee80211_request_scan(struct ieee8
  }
  
  int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
-                                   const u8 *ssid, u8 ssid_len)
+                                   const u8 *ssid, u8 ssid_len,
+                                   struct ieee80211_channel *chan)
  {
        struct ieee80211_local *local = sdata->local;
        int ret = -EBUSY;
+       enum nl80211_band band;
  
        mutex_lock(&local->scan_mtx);
  
        if (local->scan_req)
                goto unlock;
  
+       /* fill internal scan request */
+       if (!chan) {
+               int i, nchan = 0;
+               for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+                       if (!local->hw.wiphy->bands[band])
+                               continue;
+                       for (i = 0;
+                            i < local->hw.wiphy->bands[band]->n_channels;
+                            i++) {
+                               local->int_scan_req->channels[nchan] =
+                                   &local->hw.wiphy->bands[band]->channels[i];
+                               nchan++;
+                       }
+               }
+               local->int_scan_req->n_channels = nchan;
+       } else {
+               local->int_scan_req->channels[0] = chan;
+               local->int_scan_req->n_channels = 1;
+       }
+       local->int_scan_req->ssids = &local->scan_ssid;
+       local->int_scan_req->n_ssids = 1;
        memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
        local->int_scan_req->ssids[0].ssid_len = ssid_len;
  
diff --combined net/sunrpc/clnt.c
@@@ -556,16 -556,26 +556,16 @@@ static const struct rpc_call_ops rpc_de
   */
  struct rpc_task *rpc_run_task(const struct rpc_task_setup *task_setup_data)
  {
 -      struct rpc_task *task, *ret;
 +      struct rpc_task *task;
  
        task = rpc_new_task(task_setup_data);
 -      if (task == NULL) {
 -              rpc_release_calldata(task_setup_data->callback_ops,
 -                              task_setup_data->callback_data);
 -              ret = ERR_PTR(-ENOMEM);
 +      if (IS_ERR(task))
                goto out;
 -      }
  
 -      if (task->tk_status != 0) {
 -              ret = ERR_PTR(task->tk_status);
 -              rpc_put_task(task);
 -              goto out;
 -      }
        atomic_inc(&task->tk_count);
        rpc_execute(task);
 -      ret = task;
  out:
 -      return ret;
 +      return task;
  }
  EXPORT_SYMBOL_GPL(rpc_run_task);
  
@@@ -647,8 -657,9 +647,8 @@@ struct rpc_task *rpc_run_bc_task(struc
         * Create an rpc_task to send the data
         */
        task = rpc_new_task(&task_setup_data);
 -      if (!task) {
 +      if (IS_ERR(task)) {
                xprt_free_bc_request(req);
 -              task = ERR_PTR(-ENOMEM);
                goto out;
        }
        task->tk_rqstp = req;
@@@ -1507,7 -1518,6 +1507,6 @@@ call_refreshresult(struct rpc_task *tas
        task->tk_action = call_refresh;
        if (status != -ETIMEDOUT)
                rpc_delay(task, 3*HZ);
-       return;
  }
  
  static __be32 *
diff --combined net/sunrpc/svcsock.c
@@@ -150,7 -150,6 +150,6 @@@ static void svc_set_cmsg_data(struct sv
                }
                break;
        }
-       return;
  }
  
  /*
@@@ -419,8 -418,8 +418,8 @@@ static void svc_udp_data_ready(struct s
                set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
                svc_xprt_enqueue(&svsk->sk_xprt);
        }
-       if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
-               wake_up_interruptible(sk->sk_sleep);
+       if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk)))
+               wake_up_interruptible(sk_sleep(sk));
  }
  
  /*
@@@ -436,10 -435,10 +435,10 @@@ static void svc_write_space(struct soc
                svc_xprt_enqueue(&svsk->sk_xprt);
        }
  
-       if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) {
+       if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) {
                dprintk("RPC svc_write_space: someone sleeping on %p\n",
                       svsk);
-               wake_up_interruptible(sk->sk_sleep);
+               wake_up_interruptible(sk_sleep(sk));
        }
  }
  
@@@ -547,6 -546,7 +546,6 @@@ static int svc_udp_recvfrom(struct svc_
                        dprintk("svc: recvfrom returned error %d\n", -err);
                        set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
                }
 -              svc_xprt_received(&svsk->sk_xprt);
                return -EAGAIN;
        }
        len = svc_addr_len(svc_addr(rqstp));
        svsk->sk_sk->sk_stamp = skb->tstamp;
        set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); /* there may be more data... */
  
 -      /*
 -       * Maybe more packets - kick another thread ASAP.
 -       */
 -      svc_xprt_received(&svsk->sk_xprt);
 -
        len  = skb->len - sizeof(struct udphdr);
        rqstp->rq_arg.len = len;
  
@@@ -751,8 -756,8 +750,8 @@@ static void svc_tcp_listen_data_ready(s
                        printk("svc: socket %p: no user data\n", sk);
        }
  
-       if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
-               wake_up_interruptible_all(sk->sk_sleep);
+       if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk)))
+               wake_up_interruptible_all(sk_sleep(sk));
  }
  
  /*
@@@ -771,8 -776,8 +770,8 @@@ static void svc_tcp_state_change(struc
                set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
                svc_xprt_enqueue(&svsk->sk_xprt);
        }
-       if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
-               wake_up_interruptible_all(sk->sk_sleep);
+       if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk)))
+               wake_up_interruptible_all(sk_sleep(sk));
  }
  
  static void svc_tcp_data_ready(struct sock *sk, int count)
                set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
                svc_xprt_enqueue(&svsk->sk_xprt);
        }
-       if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
-               wake_up_interruptible(sk->sk_sleep);
+       if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk)))
+               wake_up_interruptible(sk_sleep(sk));
  }
  
  /*
@@@ -911,6 -916,7 +910,6 @@@ static int svc_tcp_recv_record(struct s
                if (len < want) {
                        dprintk("svc: short recvfrom while reading record "
                                "length (%d of %d)\n", len, want);
 -                      svc_xprt_received(&svsk->sk_xprt);
                        goto err_again; /* record header not complete */
                }
  
        if (len < svsk->sk_reclen) {
                dprintk("svc: incomplete TCP record (%d of %d)\n",
                        len, svsk->sk_reclen);
 -              svc_xprt_received(&svsk->sk_xprt);
                goto err_again; /* record not complete */
        }
        len = svsk->sk_reclen;
  
        return len;
   error:
 -      if (len == -EAGAIN) {
 +      if (len == -EAGAIN)
                dprintk("RPC: TCP recv_record got EAGAIN\n");
        return len;
   err_delete:
        set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
 -      svc_xprt_received(&svsk->sk_xprt);
   err_again:
        return -EAGAIN;
  }
@@@ -1099,6 -1109,7 +1098,6 @@@ out
        svsk->sk_tcplen = 0;
  
        svc_xprt_copy_addrs(rqstp, &svsk->sk_xprt);
 -      svc_xprt_received(&svsk->sk_xprt);
        if (serv->sv_stats)
                serv->sv_stats->nettcpcnt++;
  
  err_again:
        if (len == -EAGAIN) {
                dprintk("RPC: TCP recvfrom got EAGAIN\n");
 -              svc_xprt_received(&svsk->sk_xprt);
                return len;
        }
  error:
@@@ -1481,8 -1493,8 +1480,8 @@@ static void svc_sock_detach(struct svc_
        sk->sk_data_ready = svsk->sk_odata;
        sk->sk_write_space = svsk->sk_owspace;
  
-       if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
-               wake_up_interruptible(sk->sk_sleep);
+       if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk)))
+               wake_up_interruptible(sk_sleep(sk));
  }
  
  /*
diff --combined net/sunrpc/xprt.c
@@@ -43,7 -43,6 +43,7 @@@
  #include <linux/interrupt.h>
  #include <linux/workqueue.h>
  #include <linux/net.h>
 +#include <linux/ktime.h>
  
  #include <linux/sunrpc/clnt.h>
  #include <linux/sunrpc/metrics.h>
@@@ -63,6 -62,7 +63,6 @@@
   * Local functions
   */
  static void   xprt_request_init(struct rpc_task *, struct rpc_xprt *);
 -static inline void    do_xprt_reserve(struct rpc_task *);
  static void   xprt_connect_status(struct rpc_task *task);
  static int      __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
  
@@@ -711,13 -711,8 +711,13 @@@ void xprt_connect(struct rpc_task *task
                if (task->tk_rqstp)
                        task->tk_rqstp->rq_bytes_sent = 0;
  
 -              task->tk_timeout = xprt->connect_timeout;
 +              task->tk_timeout = task->tk_rqstp->rq_timeout;
                rpc_sleep_on(&xprt->pending, task, xprt_connect_status);
 +
 +              if (test_bit(XPRT_CLOSING, &xprt->state))
 +                      return;
 +              if (xprt_test_and_set_connecting(xprt))
 +                      return;
                xprt->stat.connect_start = jiffies;
                xprt->ops->connect(task);
        }
@@@ -775,19 -770,25 +775,19 @@@ struct rpc_rqst *xprt_lookup_rqst(struc
  }
  EXPORT_SYMBOL_GPL(xprt_lookup_rqst);
  
 -/**
 - * xprt_update_rtt - update an RPC client's RTT state after receiving a reply
 - * @task: RPC request that recently completed
 - *
 - */
 -void xprt_update_rtt(struct rpc_task *task)
 +static void xprt_update_rtt(struct rpc_task *task)
  {
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_rtt *rtt = task->tk_client->cl_rtt;
        unsigned timer = task->tk_msg.rpc_proc->p_timer;
 +      long m = usecs_to_jiffies(ktime_to_us(req->rq_rtt));
  
        if (timer) {
                if (req->rq_ntrans == 1)
 -                      rpc_update_rtt(rtt, timer,
 -                                      (long)jiffies - req->rq_xtime);
 +                      rpc_update_rtt(rtt, timer, m);
                rpc_set_timeo(rtt, timer, req->rq_ntrans - 1);
        }
  }
 -EXPORT_SYMBOL_GPL(xprt_update_rtt);
  
  /**
   * xprt_complete_rqst - called when reply processing is complete
@@@ -805,9 -806,7 +805,9 @@@ void xprt_complete_rqst(struct rpc_tas
                        task->tk_pid, ntohl(req->rq_xid), copied);
  
        xprt->stat.recvs++;
 -      task->tk_rtt = (long)jiffies - req->rq_xtime;
 +      req->rq_rtt = ktime_sub(ktime_get(), req->rq_xtime);
 +      if (xprt->ops->timer != NULL)
 +              xprt_update_rtt(task);
  
        list_del_init(&req->rq_list);
        req->rq_private_buf.len = copied;
@@@ -906,7 -905,7 +906,7 @@@ void xprt_transmit(struct rpc_task *tas
                return;
  
        req->rq_connect_cookie = xprt->connect_cookie;
 -      req->rq_xtime = jiffies;
 +      req->rq_xtime = ktime_get();
        status = xprt->ops->send_request(task);
        if (status != 0) {
                task->tk_status = status;
        spin_unlock_bh(&xprt->transport_lock);
  }
  
 -static inline void do_xprt_reserve(struct rpc_task *task)
 +static void xprt_alloc_slot(struct rpc_task *task)
  {
        struct rpc_xprt *xprt = task->tk_xprt;
  
        rpc_sleep_on(&xprt->backlog, task, NULL);
  }
  
 +static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)
 +{
 +      memset(req, 0, sizeof(*req));   /* mark unused */
 +
 +      spin_lock(&xprt->reserve_lock);
 +      list_add(&req->rq_list, &xprt->free);
 +      rpc_wake_up_next(&xprt->backlog);
 +      spin_unlock(&xprt->reserve_lock);
 +}
 +
  /**
   * xprt_reserve - allocate an RPC request slot
   * @task: RPC task requesting a slot allocation
@@@ -978,13 -967,13 +978,13 @@@ void xprt_reserve(struct rpc_task *task
  
        task->tk_status = -EIO;
        spin_lock(&xprt->reserve_lock);
 -      do_xprt_reserve(task);
 +      xprt_alloc_slot(task);
        spin_unlock(&xprt->reserve_lock);
  }
  
  static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt)
  {
-       return xprt->xid++;
+       return (__force __be32)xprt->xid++;
  }
  
  static inline void xprt_init_xid(struct rpc_xprt *xprt)
@@@ -1016,10 -1005,14 +1016,10 @@@ void xprt_release(struct rpc_task *task
  {
        struct rpc_xprt *xprt;
        struct rpc_rqst *req;
 -      int is_bc_request;
  
        if (!(req = task->tk_rqstp))
                return;
  
 -      /* Preallocated backchannel request? */
 -      is_bc_request = bc_prealloc(req);
 -
        xprt = req->rq_xprt;
        rpc_count_iostats(task);
        spin_lock_bh(&xprt->transport_lock);
                mod_timer(&xprt->timer,
                                xprt->last_used + xprt->idle_timeout);
        spin_unlock_bh(&xprt->transport_lock);
 -      if (!bc_prealloc(req))
 +      if (req->rq_buffer)
                xprt->ops->buf_free(req->rq_buffer);
        task->tk_rqstp = NULL;
        if (req->rq_release_snd_buf)
                req->rq_release_snd_buf(req);
  
        dprintk("RPC: %5u release request %p\n", task->tk_pid, req);
 -      if (likely(!is_bc_request)) {
 -              memset(req, 0, sizeof(*req));   /* mark unused */
 -
 -              spin_lock(&xprt->reserve_lock);
 -              list_add(&req->rq_list, &xprt->free);
 -              rpc_wake_up_next(&xprt->backlog);
 -              spin_unlock(&xprt->reserve_lock);
 -      } else
 +      if (likely(!bc_prealloc(req)))
 +              xprt_free_slot(xprt, req);
 +      else
                xprt_free_bc_request(req);
  }
  
diff --combined net/sunrpc/xprtsock.c
@@@ -138,6 -138,20 +138,6 @@@ static ctl_table sunrpc_table[] = 
  #endif
  
  /*
 - * Time out for an RPC UDP socket connect.  UDP socket connects are
 - * synchronous, but we set a timeout anyway in case of resource
 - * exhaustion on the local host.
 - */
 -#define XS_UDP_CONN_TO                (5U * HZ)
 -
 -/*
 - * Wait duration for an RPC TCP connection to be established.  Solaris
 - * NFS over TCP uses 60 seconds, for example, which is in line with how
 - * long a server takes to reboot.
 - */
 -#define XS_TCP_CONN_TO                (60U * HZ)
 -
 -/*
   * Wait duration for a reply from the RPC portmapper.
   */
  #define XS_BIND_TO            (60U * HZ)
@@@ -528,7 -542,7 +528,7 @@@ static int xs_udp_send_request(struct r
                        xdr->len - req->rq_bytes_sent, status);
  
        if (status >= 0) {
 -              task->tk_bytes_sent += status;
 +              req->rq_xmit_bytes_sent += status;
                if (status >= req->rq_slen)
                        return 0;
                /* Still some bytes left; set up for a retry later. */
@@@ -624,7 -638,7 +624,7 @@@ static int xs_tcp_send_request(struct r
                /* If we've sent the entire packet, immediately
                 * reset the count of bytes sent. */
                req->rq_bytes_sent += status;
 -              task->tk_bytes_sent += status;
 +              req->rq_xmit_bytes_sent += status;
                if (likely(req->rq_bytes_sent >= req->rq_slen)) {
                        req->rq_bytes_sent = 0;
                        return 0;
@@@ -844,6 -858,7 +844,6 @@@ static void xs_udp_data_ready(struct so
        dst_confirm(skb_dst(skb));
  
        xprt_adjust_cwnd(task, copied);
 -      xprt_update_rtt(task);
        xprt_complete_rqst(task, copied);
  
   out_unlock:
@@@ -1035,8 -1050,6 +1035,6 @@@ static inline void xs_tcp_read_common(s
                if (transport->tcp_flags & TCP_RCV_LAST_FRAG)
                        transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
        }
-       return;
  }
  
  /*
@@@ -2001,6 -2014,9 +1999,6 @@@ static void xs_connect(struct rpc_task 
        struct rpc_xprt *xprt = task->tk_xprt;
        struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
  
 -      if (xprt_test_and_set_connecting(xprt))
 -              return;
 -
        if (transport->sock != NULL && !RPC_IS_SOFTCONN(task)) {
                dprintk("RPC:       xs_connect delayed xprt %p for %lu "
                                "seconds\n",
        }
  }
  
 -static void xs_tcp_connect(struct rpc_task *task)
 -{
 -      struct rpc_xprt *xprt = task->tk_xprt;
 -
 -      /* Exit if we need to wait for socket shutdown to complete */
 -      if (test_bit(XPRT_CLOSING, &xprt->state))
 -              return;
 -      xs_connect(task);
 -}
 -
  /**
   * xs_udp_print_stats - display UDP socket-specifc stats
   * @xprt: rpc_xprt struct containing statistics
@@@ -2182,7 -2208,6 +2180,6 @@@ static int bc_send_request(struct rpc_t
  
  static void bc_close(struct rpc_xprt *xprt)
  {
-       return;
  }
  
  /*
  
  static void bc_destroy(struct rpc_xprt *xprt)
  {
-       return;
  }
  
  static struct rpc_xprt_ops xs_udp_ops = {
@@@ -2218,7 -2242,7 +2214,7 @@@ static struct rpc_xprt_ops xs_tcp_ops 
        .release_xprt           = xs_tcp_release_xprt,
        .rpcbind                = rpcb_getport_async,
        .set_port               = xs_set_port,
 -      .connect                = xs_tcp_connect,
 +      .connect                = xs_connect,
        .buf_alloc              = rpc_malloc,
        .buf_free               = rpc_free,
        .send_request           = xs_tcp_send_request,
@@@ -2309,6 -2333,7 +2305,6 @@@ static struct rpc_xprt *xs_setup_udp(st
        xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
  
        xprt->bind_timeout = XS_BIND_TO;
 -      xprt->connect_timeout = XS_UDP_CONN_TO;
        xprt->reestablish_timeout = XS_UDP_REEST_TO;
        xprt->idle_timeout = XS_IDLE_DISC_TO;
  
@@@ -2383,6 -2408,7 +2379,6 @@@ static struct rpc_xprt *xs_setup_tcp(st
        xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;
  
        xprt->bind_timeout = XS_BIND_TO;
 -      xprt->connect_timeout = XS_TCP_CONN_TO;
        xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
        xprt->idle_timeout = XS_IDLE_DISC_TO;
  
@@@ -2442,6 -2468,9 +2438,6 @@@ static struct rpc_xprt *xs_setup_bc_tcp
        struct sock_xprt *transport;
        struct svc_sock *bc_sock;
  
 -      if (!args->bc_xprt)
 -              ERR_PTR(-EINVAL);
 -
        xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries);
        if (IS_ERR(xprt))
                return xprt;
        /* backchannel */
        xprt_set_bound(xprt);
        xprt->bind_timeout = 0;
 -      xprt->connect_timeout = 0;
        xprt->reestablish_timeout = 0;
        xprt->idle_timeout = 0;