Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
authorDavid S. Miller <davem@davemloft.net>
Sat, 23 Jan 2010 08:31:06 +0000 (00:31 -0800)
committerDavid S. Miller <davem@davemloft.net>
Sat, 23 Jan 2010 08:31:06 +0000 (00:31 -0800)
38 files changed:
1  2 
Documentation/feature-removal-schedule.txt
MAINTAINERS
drivers/net/e1000/e1000_main.c
drivers/net/e1000e/e1000.h
drivers/net/e1000e/ich8lan.c
drivers/net/e1000e/netdev.c
drivers/net/igbvf/netdev.c
drivers/net/ixgb/ixgb_main.c
drivers/net/ixgbe/Makefile
drivers/net/ixgbe/ixgbe.h
drivers/net/ixgbe/ixgbe_82599.c
drivers/net/ixgbe/ixgbe_common.c
drivers/net/ixgbe/ixgbe_ethtool.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/ixgbe/ixgbe_type.h
drivers/net/mlx4/main.c
drivers/net/s2io.c
drivers/net/sky2.c
drivers/net/tg3.c
drivers/net/tg3.h
drivers/net/ucc_geth.c
drivers/net/wireless/iwlwifi/iwl-4965.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-devtrace.c
drivers/net/wireless/iwlwifi/iwl-devtrace.h
drivers/net/wireless/p54/p54pci.c
drivers/net/wireless/zd1211rw/zd_usb.c
lib/vsprintf.c
net/ipv4/route.c
net/mac80211/cfg.c
net/mac80211/iface.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/packet/af_packet.c
net/wireless/core.c
net/wireless/sme.c

index 5b5db085fbf0be3943cb99b47dfce7fa805657e8,0a46833c1b764dfc4e983edfb55030e938e40948..2f93ac06c4144eda56c323965691be720e29687f
@@@ -88,6 -88,27 +88,6 @@@ Who: Luis R. Rodriguez <lrodriguez@athe
  
  ---------------------------
  
 -What: CONFIG_WIRELESS_OLD_REGULATORY - old static regulatory information
 -When: March 2010 / desktop catchup
 -
 -Why:  The old regulatory infrastructure has been replaced with a new one
 -      which does not require statically defined regulatory domains. We do
 -      not want to keep static regulatory domains in the kernel due to the
 -      the dynamic nature of regulatory law and localization. We kept around
 -      the old static definitions for the regulatory domains of:
 -
 -              * US
 -              * JP
 -              * EU
 -
 -      and used by default the US when CONFIG_WIRELESS_OLD_REGULATORY was
 -      set. We will remove this option once the standard Linux desktop catches
 -      up with the new userspace APIs we have implemented.
 -
 -Who:  Luis R. Rodriguez <lrodriguez@atheros.com>
 -
 ----------------------------
 -
  What: dev->power.power_state
  When: July 2007
  Why:  Broken design for runtime control over driver power states, confusing
@@@ -472,3 -493,52 +472,52 @@@ Why:     These two features use non-standar
  Who:  Corentin Chary <corentin.chary@gmail.com>
  
  ----------------------------
+ What: usbvideo quickcam_messenger driver
+ When: 2.6.35
+ Files:        drivers/media/video/usbvideo/quickcam_messenger.[ch]
+ Why:  obsolete v4l1 driver replaced by gspca_stv06xx
+ Who:  Hans de Goede <hdegoede@redhat.com>
+ ----------------------------
+ What: ov511 v4l1 driver
+ When: 2.6.35
+ Files:        drivers/media/video/ov511.[ch]
+ Why:  obsolete v4l1 driver replaced by gspca_ov519
+ Who:  Hans de Goede <hdegoede@redhat.com>
+ ----------------------------
+ What: w9968cf v4l1 driver
+ When: 2.6.35
+ Files:        drivers/media/video/w9968cf*.[ch]
+ Why:  obsolete v4l1 driver replaced by gspca_ov519
+ Who:  Hans de Goede <hdegoede@redhat.com>
+ ----------------------------
+ What: ovcamchip sensor framework
+ When: 2.6.35
+ Files:        drivers/media/video/ovcamchip/*
+ Why:  Only used by obsoleted v4l1 drivers
+ Who:  Hans de Goede <hdegoede@redhat.com>
+ ----------------------------
+ What: stv680 v4l1 driver
+ When: 2.6.35
+ Files:        drivers/media/video/stv680.[ch]
+ Why:  obsolete v4l1 driver replaced by gspca_stv0680
+ Who:  Hans de Goede <hdegoede@redhat.com>
+ ----------------------------
+ What: zc0301 v4l driver
+ When: 2.6.35
+ Files:        drivers/media/video/zc0301/*
+ Why:  Duplicate functionality with the gspca_zc3xx driver, zc0301 only
+       supports 2 USB-ID's (because it only supports a limited set of
+       sensors) wich are also supported by the gspca_zc3xx driver
+       (which supports 53 USB-ID's in total)
+ Who:  Hans de Goede <hdegoede@redhat.com>
diff --combined MAINTAINERS
index 61367ec865cb5a91dbeea22634ca3deb565307be,4067c2e50d483cd126acfecc9df504b9e1931e54..ffb65a3b12cd03bb4946efb61efeab5705a332bd
@@@ -410,9 -410,8 +410,8 @@@ F: drivers/i2c/busses/i2c-ali1563.
  
  ALPHA PORT
  M:    Richard Henderson <rth@twiddle.net>
- S:    Odd Fixes for 2.4; Maintained for 2.6.
  M:    Ivan Kokshaysky <ink@jurassic.park.msu.ru>
- S:    Maintained for 2.4; PCI support for 2.6.
+ M:    Matt Turner <mattst88@gmail.com>
  L:    linux-alpha@vger.kernel.org
  F:    arch/alpha/
  
@@@ -988,7 -987,6 +987,6 @@@ F: drivers/platform/x86/asus-laptop.
  
  ASYNCHRONOUS TRANSFERS/TRANSFORMS (IOAT) API
  M:    Dan Williams <dan.j.williams@intel.com>
- M:    Maciej Sosnowski <maciej.sosnowski@intel.com>
  W:    http://sourceforge.net/projects/xscaleiop
  S:    Supported
  F:    Documentation/crypto/async-tx-api.txt
@@@ -1472,6 -1470,12 +1470,12 @@@ L:    linux-scsi@vger.kernel.or
  S:    Supported
  F:    drivers/scsi/fnic/
  
+ CMPC ACPI DRIVER
+ M:    Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
+ M:    Daniel Oliveira Nascimento <don@syst.com.br>
+ S:    Supported
+ F:    drivers/platform/x86/classmate-laptop.c
  CODA FILE SYSTEM
  M:    Jan Harkes <jaharkes@cs.cmu.edu>
  M:    coda@cs.cmu.edu
@@@ -1632,9 -1636,8 +1636,8 @@@ S:      Maintaine
  F:    sound/pci/cs5535audio/
  
  CX18 VIDEO4LINUX DRIVER
- M:    Hans Verkuil <hverkuil@xs4all.nl>
  M:    Andy Walls <awalls@radix.net>
- L:    ivtv-devel@ivtvdriver.org
+ L:    ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
  L:    linux-media@vger.kernel.org
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
  W:    http://linuxtv.org
@@@ -1819,7 -1822,6 +1822,6 @@@ S:      Supporte
  F:    fs/dlm/
  
  DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
- M:    Maciej Sosnowski <maciej.sosnowski@intel.com>
  M:    Dan Williams <dan.j.williams@intel.com>
  S:    Supported
  F:    drivers/dma/
@@@ -2163,10 -2165,9 +2165,9 @@@ F:     drivers/hwmon/f75375s.
  F:    include/linux/f75375s.h
  
  FIREWIRE SUBSYSTEM
- M:    Kristian Hoegsberg <krh@redhat.com>
  M:    Stefan Richter <stefanr@s5r6.in-berlin.de>
  L:    linux1394-devel@lists.sourceforge.net
- W:    http://www.linux1394.org/
+ W:    http://ieee1394.wiki.kernel.org/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git
  S:    Maintained
  F:    drivers/firewire/
@@@ -2699,22 -2700,14 +2700,14 @@@ S:   Supporte
  F:    drivers/idle/i7300_idle.c
  
  IEEE 1394 SUBSYSTEM
- M:    Ben Collins <ben.collins@ubuntu.com>
  M:    Stefan Richter <stefanr@s5r6.in-berlin.de>
  L:    linux1394-devel@lists.sourceforge.net
- W:    http://www.linux1394.org/
+ W:    http://ieee1394.wiki.kernel.org/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git
- S:    Maintained
+ S:    Obsolete
  F:    Documentation/debugging-via-ohci1394.txt
  F:    drivers/ieee1394/
  
- IEEE 1394 RAW I/O DRIVER
- M:    Dan Dennedy <dan@dennedy.org>
- M:    Stefan Richter <stefanr@s5r6.in-berlin.de>
- L:    linux1394-devel@lists.sourceforge.net
- S:    Maintained
- F:    drivers/ieee1394/raw1394*
  IEEE 802.15.4 SUBSYSTEM
  M:    Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
  M:    Sergey Lapin <slapin@ossfans.org>
@@@ -2791,7 -2784,7 +2784,7 @@@ F:      arch/x86/kernel/microcode_core.
  F:    arch/x86/kernel/microcode_intel.c
  
  INTEL I/OAT DMA DRIVER
- M:    Maciej Sosnowski <maciej.sosnowski@intel.com>
+ M:    Dan Williams <dan.j.williams@intel.com>
  S:    Supported
  F:    drivers/dma/ioat*
  
@@@ -3015,8 -3008,8 +3008,8 @@@ S:      Maintaine
  F:    drivers/isdn/hardware/eicon/
  
  IVTV VIDEO4LINUX DRIVER
- M:    Hans Verkuil <hverkuil@xs4all.nl>
- L:    ivtv-devel@ivtvdriver.org
+ M:    Andy Walls <awalls@radix.net>
+ L:    ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
  L:    linux-media@vger.kernel.org
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
  W:    http://www.ivtvdriver.org
@@@ -3646,6 -3639,11 +3639,11 @@@ W:    http://0pointer.de/lennart/tchibo.ht
  S:    Maintained
  F:    drivers/platform/x86/msi-laptop.c
  
+ MSI WMI SUPPORT
+ M:    Anisse Astier <anisse@astier.eu>
+ S:    Supported
+ F:    drivers/platform/x86/msi-wmi.c
  MULTIFUNCTION DEVICES (MFD)
  M:    Samuel Ortiz <sameo@linux.intel.com>
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6.git
@@@ -3871,7 -3869,7 +3869,7 @@@ F:      drivers/net/ni5010.
  
  NILFS2 FILESYSTEM
  M:    KONISHI Ryusuke <konishi.ryusuke@lab.ntt.co.jp>
- L:    users@nilfs.org
+ L:    linux-nilfs@vger.kernel.org
  W:    http://www.nilfs.org/en/
  S:    Supported
  F:    Documentation/filesystems/nilfs2.txt
@@@ -3938,29 -3936,20 +3936,20 @@@ S:   Maintaine
  F:    sound/soc/omap/
  
  OMAP FRAMEBUFFER SUPPORT
- M:    Imre Deak <imre.deak@nokia.com>
+ M:    Tomi Valkeinen <tomi.valkeinen@nokia.com>
  L:    linux-fbdev@vger.kernel.org
  L:    linux-omap@vger.kernel.org
  S:    Maintained
  F:    drivers/video/omap/
  
- OMAP DISPLAY SUBSYSTEM SUPPORT (DSS2)
+ OMAP DISPLAY SUBSYSTEM and FRAMEBUFFER SUPPORT (DSS2)
  M:    Tomi Valkeinen <tomi.valkeinen@nokia.com>
  L:    linux-omap@vger.kernel.org
- L:    linux-fbdev@vger.kernel.org (moderated for non-subscribers)
+ L:    linux-fbdev@vger.kernel.org
  S:    Maintained
- F:    drivers/video/omap2/dss/
- F:    drivers/video/omap2/vrfb.c
- F:    drivers/video/omap2/vram.c
+ F:    drivers/video/omap2/
  F:    Documentation/arm/OMAP/DSS
  
- OMAP FRAMEBUFFER SUPPORT (FOR DSS2)
- M:    Tomi Valkeinen <tomi.valkeinen@nokia.com>
- L:    linux-omap@vger.kernel.org
- L:    linux-fbdev@vger.kernel.org (moderated for non-subscribers)
- S:    Maintained
- F:    drivers/video/omap2/omapfb/
  OMAP MMC SUPPORT
  M:    Jarkko Lavinen <jarkko.lavinen@nokia.com>
  L:    linux-omap@vger.kernel.org
@@@ -4452,13 -4441,6 +4441,13 @@@ S:    Supporte
  F:    Documentation/networking/LICENSE.qla3xxx
  F:    drivers/net/qla3xxx.*
  
 +QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
 +M:    Amit Kumar Salecha <amit.salecha@qlogic.com>
 +M:    linux-driver@qlogic.com
 +L:    netdev@vger.kernel.org
 +S:    Supported
 +F:    drivers/net/qlcnic/
 +
  QLOGIC QLGE 10Gb ETHERNET DRIVER
  M:    Ron Mercer <ron.mercer@qlogic.com>
  M:    linux-driver@qlogic.com
@@@ -5810,15 -5792,6 +5799,15 @@@ S:    Maintaine
  F:    Documentation/filesystems/vfat.txt
  F:    fs/fat/
  
 +VIRTIO HOST (VHOST)
 +M:    "Michael S. Tsirkin" <mst@redhat.com>
 +L:    kvm@vger.kernel.org
 +L:    virtualization@lists.osdl.org
 +L:    netdev@vger.kernel.org
 +S:    Maintained
 +F:    drivers/vhost/
 +F:    include/linux/vhost.h
 +
  VIA RHINE NETWORK DRIVER
  M:    Roger Luethi <rl@hellgate.ch>
  S:    Maintained
index 9ec7480be1d896eaaf8511f254f082d953d2483b,a53a2017c53773891cdc58596c79533b6f71d44b..87f575ca427dd97dd03cc53d9e54cfb4458e44c4
@@@ -42,7 -42,7 +42,7 @@@ static const char e1000_copyright[] = "
   * Macro expands to...
   *   {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
   */
 -static struct pci_device_id e1000_pci_tbl[] = {
 +static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
        INTEL_E1000_ETHERNET_DEVICE(0x1000),
        INTEL_E1000_ETHERNET_DEVICE(0x1001),
        INTEL_E1000_ETHERNET_DEVICE(0x1004),
@@@ -2802,13 -2802,13 +2802,13 @@@ static int e1000_tx_map(struct e1000_ad
  dma_error:
        dev_err(&pdev->dev, "TX DMA map failed\n");
        buffer_info->dma = 0;
-       count--;
-       while (count >= 0) {
+       if (count)
                count--;
-               i--;
-               if (i < 0)
+       while (count--) {
+               if (i==0)
                        i += tx_ring->count;
+               i--;
                buffer_info = &tx_ring->buffer_info[i];
                e1000_unmap_and_free_tx_resource(adapter, buffer_info);
        }
@@@ -3850,13 -3850,22 +3850,22 @@@ static bool e1000_clean_rx_irq(struct e
  
                length = le16_to_cpu(rx_desc->length);
                /* !EOP means multiple descriptors were used to store a single
-                * packet, also make sure the frame isn't just CRC only */
-               if (unlikely(!(status & E1000_RXD_STAT_EOP) || (length <= 4))) {
+                * packet, if thats the case we need to toss it.  In fact, we
+                * to toss every packet with the EOP bit clear and the next
+                * frame that _does_ have the EOP bit set, as it is by
+                * definition only a frame fragment
+                */
+               if (unlikely(!(status & E1000_RXD_STAT_EOP)))
+                       adapter->discarding = true;
+               if (adapter->discarding) {
                        /* All receives must fit into a single buffer */
                        E1000_DBG("%s: Receive packet consumed multiple"
                                  " buffers\n", netdev->name);
                        /* recycle */
                        buffer_info->skb = skb;
+                       if (status & E1000_RXD_STAT_EOP)
+                               adapter->discarding = false;
                        goto next_desc;
                }
  
index aec378e7441d6eafe22c281825566a9de5ddfb58,d236efaf74781d68fd41c34d591c066ee063909b..318bdb28a7cd92504700e2aff0e682c9c643b8bb
@@@ -421,6 -421,7 +421,7 @@@ struct e1000_info 
  /* CRC Stripping defines */
  #define FLAG2_CRC_STRIPPING               (1 << 0)
  #define FLAG2_HAS_PHY_WAKEUP              (1 << 1)
+ #define FLAG2_IS_DISCARDING               (1 << 2)
  
  #define E1000_RX_DESC_PS(R, i)            \
        (&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
@@@ -502,8 -503,6 +503,8 @@@ extern s32 e1000e_cleanup_led_generic(s
  extern s32 e1000e_led_on_generic(struct e1000_hw *hw);
  extern s32 e1000e_led_off_generic(struct e1000_hw *hw);
  extern s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw);
 +extern void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw);
 +extern void e1000_set_lan_id_single_port(struct e1000_hw *hw);
  extern s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u16 *duplex);
  extern s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, u16 *speed, u16 *duplex);
  extern s32 e1000e_disable_pcie_master(struct e1000_hw *hw);
@@@ -518,7 -517,9 +519,7 @@@ extern void e1000_clear_vfta_generic(st
  extern void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count);
  extern void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw,
                                               u8 *mc_addr_list,
 -                                             u32 mc_addr_count,
 -                                             u32 rar_used_count,
 -                                             u32 rar_count);
 +                                             u32 mc_addr_count);
  extern void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
  extern s32 e1000e_set_fc_watermarks(struct e1000_hw *hw);
  extern void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop);
@@@ -529,7 -530,6 +530,7 @@@ extern s32 e1000e_config_fc_after_link_
  extern s32 e1000e_force_mac_fc(struct e1000_hw *hw);
  extern s32 e1000e_blink_led(struct e1000_hw *hw);
  extern void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value);
 +extern s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw);
  extern void e1000e_reset_adaptive(struct e1000_hw *hw);
  extern void e1000e_update_adaptive(struct e1000_hw *hw);
  
@@@ -583,7 -583,6 +584,6 @@@ extern s32 e1000_read_phy_reg_hv_locked
  extern s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data);
  extern s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset,
                                           u16 data);
- extern s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow);
  extern s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw);
  extern s32 e1000_copper_link_setup_82577(struct e1000_hw *hw);
  extern s32 e1000_check_polarity_82577(struct e1000_hw *hw);
@@@ -630,15 -629,7 +630,15 @@@ extern s32 e1000e_read_nvm_eerd(struct 
  extern s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw);
  extern void e1000e_release_nvm(struct e1000_hw *hw);
  extern void e1000e_reload_nvm(struct e1000_hw *hw);
 -extern s32 e1000e_read_mac_addr(struct e1000_hw *hw);
 +extern s32 e1000_read_mac_addr_generic(struct e1000_hw *hw);
 +
 +static inline s32 e1000e_read_mac_addr(struct e1000_hw *hw)
 +{
 +      if (hw->mac.ops.read_mac_addr)
 +              return hw->mac.ops.read_mac_addr(hw);
 +
 +      return e1000_read_mac_addr_generic(hw);
 +}
  
  static inline s32 e1000_validate_nvm_checksum(struct e1000_hw *hw)
  {
index 061cd100aac20e6be3bd60804ab19936e04b973a,8b6ecd127889e6d19ed155c725dcd4f594d73666..54d03a0ce3ce268e256d23e5f12e638777a91481
  #define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */
  #define E1000_NVM_K1_ENABLE 0x1  /* NVM Enable K1 bit */
  
+ /* KMRN Mode Control */
+ #define HV_KMRN_MODE_CTRL      PHY_REG(769, 16)
+ #define HV_KMRN_MDIO_SLOW      0x0400
  /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
  /* Offset 04h HSFSTS */
  union ich8_hws_flash_status {
@@@ -219,6 -223,7 +223,7 @@@ static s32 e1000_set_lplu_state_pchlan(
  static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw);
  static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw);
  static s32  e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link);
+ static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw);
  
  static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg)
  {
@@@ -270,7 -275,21 +275,21 @@@ static s32 e1000_init_phy_params_pchlan
        phy->autoneg_mask             = AUTONEG_ADVERTISE_SPEED_DEFAULT;
  
        phy->id = e1000_phy_unknown;
-       e1000e_get_phy_id(hw);
+       ret_val = e1000e_get_phy_id(hw);
+       if (ret_val)
+               goto out;
+       if ((phy->id == 0) || (phy->id == PHY_REVISION_MASK)) {
+               /*
+                * In case the PHY needs to be in mdio slow mode (eg. 82577),
+                * set slow mode and try to get the PHY id again.
+                */
+               ret_val = e1000_set_mdio_slow_mode_hv(hw);
+               if (ret_val)
+                       goto out;
+               ret_val = e1000e_get_phy_id(hw);
+               if (ret_val)
+                       goto out;
+       }
        phy->type = e1000e_get_phy_type_from_id(phy->id);
  
        switch (phy->type) {
                break;
        }
  
+ out:
        return ret_val;
  }
  
  }
  
  
+ /**
+  *  e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode
+  *  @hw:   pointer to the HW structure
+  **/
+ static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw)
+ {
+       s32 ret_val;
+       u16 data;
+       ret_val = e1e_rphy(hw, HV_KMRN_MODE_CTRL, &data);
+       if (ret_val)
+               return ret_val;
+       data |= HV_KMRN_MDIO_SLOW;
+       ret_val = e1e_wphy(hw, HV_KMRN_MODE_CTRL, data);
+       return ret_val;
+ }
  /**
   *  e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be
   *  done after every PHY reset.
  static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
  {
        s32 ret_val = 0;
+       u16 phy_data;
  
        if (hw->mac.type != e1000_pchlan)
                return ret_val;
  
+       /* Set MDIO slow mode before any other MDIO access */
+       if (hw->phy.type == e1000_phy_82577) {
+               ret_val = e1000_set_mdio_slow_mode_hv(hw);
+               if (ret_val)
+                       goto out;
+       }
        if (((hw->phy.type == e1000_phy_82577) &&
             ((hw->phy.revision == 1) || (hw->phy.revision == 2))) ||
            ((hw->phy.type == e1000_phy_82578) && (hw->phy.revision == 1))) {
  
        hw->phy.addr = 1;
        ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0);
+       hw->phy.ops.release(hw);
        if (ret_val)
                goto out;
-       hw->phy.ops.release(hw);
  
        /*
         * Configure the K1 Si workaround during phy reset assuming there is
         * link so that it disables K1 if link is in 1Gbps.
         */
        ret_val = e1000_k1_gig_workaround_hv(hw, true);
+       if (ret_val)
+               goto out;
  
+       /* Workaround for link disconnects on a busy hub in half duplex */
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val)
+               goto out;
+       ret_val = hw->phy.ops.read_reg_locked(hw,
+                                             PHY_REG(BM_PORT_CTRL_PAGE, 17),
+                                             &phy_data);
+       if (ret_val)
+               goto release;
+       ret_val = hw->phy.ops.write_reg_locked(hw,
+                                              PHY_REG(BM_PORT_CTRL_PAGE, 17),
+                                              phy_data & 0x00FF);
+ release:
+       hw->phy.ops.release(hw);
  out:
        return ret_val;
  }
@@@ -1184,6 -1248,7 +1248,7 @@@ static s32 e1000_phy_hw_reset_ich8lan(s
        /* Allow time for h/w to get to a quiescent state after reset */
        mdelay(10);
  
+       /* Perform any necessary post-reset workarounds */
        if (hw->mac.type == e1000_pchlan) {
                ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
                if (ret_val)
@@@ -2484,6 -2549,10 +2549,10 @@@ static s32 e1000_reset_hw_ich8lan(struc
        if (!ret_val)
                e1000_release_swflag_ich8lan(hw);
  
+       /* Perform any necessary post-reset workarounds */
+       if (hw->mac.type == e1000_pchlan)
+               ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
        if (ctrl & E1000_CTRL_PHY_RST)
                ret_val = hw->phy.ops.get_cfg_done(hw);
  
        kab |= E1000_KABGTXD_BGSQLBIAS;
        ew32(KABGTXD, kab);
  
-       if (hw->mac.type == e1000_pchlan)
-               ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
  out:
        return ret_val;
  }
@@@ -3302,7 -3368,6 +3368,7 @@@ static struct e1000_mac_operations ich8
        /* cleanup_led dependent on mac type */
        .clear_hw_cntrs         = e1000_clear_hw_cntrs_ich8lan,
        .get_bus_info           = e1000_get_bus_info_ich8lan,
 +      .set_lan_id             = e1000_set_lan_id_single_port,
        .get_link_up_info       = e1000_get_link_up_info_ich8lan,
        /* led_on dependent on mac type */
        /* led_off dependent on mac type */
index 3d57ca5482f4b8ed4fe9eacb6bf25ea5c49c21c6,1ea395b6c992683c3bb4328548cc7da15e6a6223..5d7a760194d4b2d90e82c0ff530c7ee6fb398d27
@@@ -450,13 -450,23 +450,23 @@@ static bool e1000_clean_rx_irq(struct e
  
                length = le16_to_cpu(rx_desc->length);
  
-               /* !EOP means multiple descriptors were used to store a single
-                * packet, also make sure the frame isn't just CRC only */
-               if (!(status & E1000_RXD_STAT_EOP) || (length <= 4)) {
+               /*
+                * !EOP means multiple descriptors were used to store a single
+                * packet, if that's the case we need to toss it.  In fact, we
+                * need to toss every packet with the EOP bit clear and the
+                * next frame that _does_ have the EOP bit set, as it is by
+                * definition only a frame fragment
+                */
+               if (unlikely(!(status & E1000_RXD_STAT_EOP)))
+                       adapter->flags2 |= FLAG2_IS_DISCARDING;
+               if (adapter->flags2 & FLAG2_IS_DISCARDING) {
                        /* All receives must fit into a single buffer */
                        e_dbg("Receive packet consumed multiple buffers\n");
                        /* recycle */
                        buffer_info->skb = skb;
+                       if (status & E1000_RXD_STAT_EOP)
+                               adapter->flags2 &= ~FLAG2_IS_DISCARDING;
                        goto next_desc;
                }
  
@@@ -745,10 -755,16 +755,16 @@@ static bool e1000_clean_rx_irq_ps(struc
                                 PCI_DMA_FROMDEVICE);
                buffer_info->dma = 0;
  
-               if (!(staterr & E1000_RXD_STAT_EOP)) {
+               /* see !EOP comment in other rx routine */
+               if (!(staterr & E1000_RXD_STAT_EOP))
+                       adapter->flags2 |= FLAG2_IS_DISCARDING;
+               if (adapter->flags2 & FLAG2_IS_DISCARDING) {
                        e_dbg("Packet Split buffers didn't pick up the full "
                              "packet\n");
                        dev_kfree_skb_irq(skb);
+                       if (staterr & E1000_RXD_STAT_EOP)
+                               adapter->flags2 &= ~FLAG2_IS_DISCARDING;
                        goto next_desc;
                }
  
@@@ -1118,6 -1134,7 +1134,7 @@@ static void e1000_clean_rx_ring(struct 
  
        rx_ring->next_to_clean = 0;
        rx_ring->next_to_use = 0;
+       adapter->flags2 &= ~FLAG2_IS_DISCARDING;
  
        writel(0, adapter->hw.hw_addr + rx_ring->head);
        writel(0, adapter->hw.hw_addr + rx_ring->tail);
@@@ -2536,14 -2553,22 +2553,14 @@@ static void e1000_configure_rx(struct e
   *  @hw: pointer to the HW structure
   *  @mc_addr_list: array of multicast addresses to program
   *  @mc_addr_count: number of multicast addresses to program
 - *  @rar_used_count: the first RAR register free to program
 - *  @rar_count: total number of supported Receive Address Registers
   *
 - *  Updates the Receive Address Registers and Multicast Table Array.
 + *  Updates the Multicast Table Array.
   *  The caller must have a packed mc_addr_list of multicast addresses.
 - *  The parameter rar_count will usually be hw->mac.rar_entry_count
 - *  unless there are workarounds that change this.  Currently no func pointer
 - *  exists and all implementations are handled in the generic version of this
 - *  function.
   **/
  static void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list,
 -                                    u32 mc_addr_count, u32 rar_used_count,
 -                                    u32 rar_count)
 +                                    u32 mc_addr_count)
  {
 -      hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, mc_addr_count,
 -                                      rar_used_count, rar_count);
 +      hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, mc_addr_count);
  }
  
  /**
@@@ -2559,6 -2584,7 +2576,6 @@@ static void e1000_set_multi(struct net_
  {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
 -      struct e1000_mac_info *mac = &hw->mac;
        struct dev_mc_list *mc_ptr;
        u8  *mta_list;
        u32 rctl;
                        mc_ptr = mc_ptr->next;
                }
  
 -              e1000_update_mc_addr_list(hw, mta_list, i, 1,
 -                                        mac->rar_entry_count);
 +              e1000_update_mc_addr_list(hw, mta_list, i);
                kfree(mta_list);
        } else {
                /*
                 * if we're called from probe, we might not have
                 * anything to do here, so clear out the list
                 */
 -              e1000_update_mc_addr_list(hw, NULL, 0, 1, mac->rar_entry_count);
 +              e1000_update_mc_addr_list(hw, NULL, 0);
        }
  }
  
@@@ -3952,13 -3979,13 +3969,13 @@@ static int e1000_tx_map(struct e1000_ad
  dma_error:
        dev_err(&pdev->dev, "TX DMA map failed\n");
        buffer_info->dma = 0;
-       count--;
-       while (count >= 0) {
+       if (count)
                count--;
-               i--;
-               if (i < 0)
+       while (count--) {
+               if (i==0)
                        i += tx_ring->count;
+               i--;
                buffer_info = &tx_ring->buffer_info[i];
                e1000_put_txbuf(adapter, buffer_info);;
        }
@@@ -5125,7 -5152,7 +5142,7 @@@ static int __devinit e1000_probe(struc
  
        e1000_eeprom_checks(adapter);
  
 -      /* copy the MAC address out of the NVM */
 +      /* copy the MAC address */
        if (e1000e_read_mac_addr(&adapter->hw))
                e_err("NVM Read Error while reading MAC address\n");
  
@@@ -5317,7 -5344,7 +5334,7 @@@ static struct pci_error_handlers e1000_
        .resume = e1000_io_resume,
  };
  
 -static struct pci_device_id e1000_pci_tbl[] = {
 +static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_COPPER), board_82571 },
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_FIBER), board_82571 },
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER), board_82571 },
index a6c39209f66f086fb1c97ff329563bc79d3f7ccb,10e038adba0f5b245fc4ba77b63fac76168aa823..375194f4b97e36de06bdbd9984328ec99285505f
@@@ -2163,14 -2163,14 +2163,14 @@@ dma_error
        buffer_info->length = 0;
        buffer_info->next_to_watch = 0;
        buffer_info->mapped_as_page = false;
-       count--;
+       if (count)
+               count--;
  
        /* clear timestamp and dma mappings for remaining portion of packet */
-       while (count >= 0) {
-               count--;
-               i--;
-               if (i < 0)
+       while (count--) {
+               if (i==0)
                        i += tx_ring->count;
+               i--;
                buffer_info = &tx_ring->buffer_info[i];
                igbvf_put_txbuf(adapter, buffer_info);
        }
@@@ -2608,7 -2608,11 +2608,7 @@@ static void igbvf_print_device_info(str
        struct pci_dev *pdev = adapter->pdev;
  
        dev_info(&pdev->dev, "Intel(R) 82576 Virtual Function\n");
 -      dev_info(&pdev->dev, "Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
 -               /* MAC address */
 -               netdev->dev_addr[0], netdev->dev_addr[1],
 -               netdev->dev_addr[2], netdev->dev_addr[3],
 -               netdev->dev_addr[4], netdev->dev_addr[5]);
 +      dev_info(&pdev->dev, "Address: %pM\n", netdev->dev_addr);
        dev_info(&pdev->dev, "MAC: %d\n", hw->mac.type);
  }
  
@@@ -2774,8 -2778,11 +2774,8 @@@ static int __devinit igbvf_probe(struc
        memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len);
  
        if (!is_valid_ether_addr(netdev->perm_addr)) {
 -              dev_err(&pdev->dev, "Invalid MAC Address: "
 -                      "%02x:%02x:%02x:%02x:%02x:%02x\n",
 -                      netdev->dev_addr[0], netdev->dev_addr[1],
 -                      netdev->dev_addr[2], netdev->dev_addr[3],
 -                      netdev->dev_addr[4], netdev->dev_addr[5]);
 +              dev_err(&pdev->dev, "Invalid MAC Address: %pM\n",
 +                      netdev->dev_addr);
                err = -EIO;
                goto err_hw_init;
        }
@@@ -2877,7 -2884,7 +2877,7 @@@ static struct pci_error_handlers igbvf_
        .resume = igbvf_io_resume,
  };
  
 -static struct pci_device_id igbvf_pci_tbl[] = {
 +static DEFINE_PCI_DEVICE_TABLE(igbvf_pci_tbl) = {
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_VF), board_vf },
        { } /* terminate list */
  };
index 6c2d9366fe5e5c5e115b7c2066f7b089d37418bd,593d1a4f217c0fccbf439156825f2556316c624d..c56ea69762cdd9c233ad9846a6895b5f4f7f5a43
@@@ -50,7 -50,7 +50,7 @@@ MODULE_PARM_DESC(copybreak
   * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
   *   Class, Class Mask, private data (not used) }
   */
 -static struct pci_device_id ixgb_pci_tbl[] = {
 +static DEFINE_PCI_DEVICE_TABLE(ixgb_pci_tbl) = {
        {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX,
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_CX4,
@@@ -1363,13 -1363,13 +1363,13 @@@ ixgb_tx_map(struct ixgb_adapter *adapte
  dma_error:
        dev_err(&pdev->dev, "TX DMA map failed\n");
        buffer_info->dma = 0;
-       count--;
-       while (count >= 0) {
+       if (count)
                count--;
-               i--;
-               if (i < 0)
+       while (count--) {
+               if (i==0)
                        i += tx_ring->count;
+               i--;
                buffer_info = &tx_ring->buffer_info[i];
                ixgb_unmap_and_free_tx_resource(adapter, buffer_info);
        }
index 1dd867df2967c84c9c796e9fdb18dec2efe5d2d8,bfef0ebcba9ab343b36e4a7493cb36f42467b11c..8f81efb49169f150e3e45510117a904e6a7a7c82
@@@ -1,7 -1,7 +1,7 @@@
  ################################################################################
  #
  # Intel 10 Gigabit PCI Express Linux driver
- # Copyright(c) 1999 - 2009 Intel Corporation.
+ # Copyright(c) 1999 - 2010 Intel Corporation.
  #
  # This program is free software; you can redistribute it and/or modify it
  # under the terms and conditions of the GNU General Public License,
@@@ -33,8 -33,7 +33,8 @@@
  obj-$(CONFIG_IXGBE) += ixgbe.o
  
  ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \
 -              ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o
 +              ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \
 +              ixgbe_mbx.o
  
  ixgbe-$(CONFIG_IXGBE_DCB) +=  ixgbe_dcb.o ixgbe_dcb_82598.o \
                                ixgbe_dcb_82599.o ixgbe_dcb_nl.o
index ed735857695ca5ced49e6df506debbcbf826885c,303e7bd39b672fe4dbceff62ea91e96782e4211b..db64f139f173dbabc46161ada98e5c74c3422525
@@@ -1,7 -1,7 +1,7 @@@
  /*******************************************************************************
  
    Intel 10 Gigabit PCI Express Linux driver
-   Copyright(c) 1999 - 2009 Intel Corporation.
+   Copyright(c) 1999 - 2010 Intel Corporation.
  
    This program is free software; you can redistribute it and/or modify it
    under the terms and conditions of the GNU General Public License,
  
  #define IXGBE_MAX_RSC_INT_RATE          162760
  
 +#define IXGBE_MAX_VF_MC_ENTRIES         30
 +#define IXGBE_MAX_VF_FUNCTIONS          64
 +#define IXGBE_MAX_VFTA_ENTRIES          128
 +#define MAX_EMULATION_MAC_ADDRS         16
 +#define VMDQ_P(p)   ((p) + adapter->num_vfs)
 +
 +struct vf_data_storage {
 +      unsigned char vf_mac_addresses[ETH_ALEN];
 +      u16 vf_mc_hashes[IXGBE_MAX_VF_MC_ENTRIES];
 +      u16 num_vf_mc_hashes;
 +      u16 default_vf_vlan_id;
 +      u16 vlans_enabled;
 +      unsigned char em_mac_addresses[MAX_EMULATION_MAC_ADDRS * ETH_ALEN];
 +      bool clear_to_send;
 +      int rar;
 +};
 +
  /* wrapper around a pointer to a socket buffer,
   * so a DMA handle can be stored along with the buffer */
  struct ixgbe_tx_buffer {
@@@ -188,7 -171,7 +188,7 @@@ struct ixgbe_ring 
  enum ixgbe_ring_f_enum {
        RING_F_NONE = 0,
        RING_F_DCB,
 -      RING_F_VMDQ,
 +      RING_F_VMDQ,  /* SR-IOV uses the same ring feature */
        RING_F_RSS,
        RING_F_FDIR,
  #ifdef IXGBE_FCOE
  
  #define IXGBE_MAX_DCB_INDICES   8
  #define IXGBE_MAX_RSS_INDICES  16
 -#define IXGBE_MAX_VMDQ_INDICES 16
 +#define IXGBE_MAX_VMDQ_INDICES 64
  #define IXGBE_MAX_FDIR_INDICES 64
  #ifdef IXGBE_FCOE
  #define IXGBE_MAX_FCOE_INDICES  8
@@@ -305,8 -288,6 +305,8 @@@ struct ixgbe_adapter 
        /* RX */
        struct ixgbe_ring *rx_ring ____cacheline_aligned_in_smp; /* One per active queue */
        int num_rx_queues;
 +      int num_rx_pools;               /* == num_rx_queues in 82598 */
 +      int num_rx_queues_per_pool;     /* 1 if 82598, can be many if 82599 */
        u64 hw_csum_rx_error;
        u64 hw_rx_no_dma_resources;
        u64 non_eop_descs;
  #define IXGBE_FLAG_FDIR_PERFECT_CAPABLE         (u32)(1 << 27)
  #define IXGBE_FLAG_FCOE_CAPABLE                 (u32)(1 << 28)
  #define IXGBE_FLAG_FCOE_ENABLED                 (u32)(1 << 29)
 +#define IXGBE_FLAG_SRIOV_CAPABLE                (u32)(1 << 30)
 +#define IXGBE_FLAG_SRIOV_ENABLED                (u32)(1 << 31)
  
        u32 flags2;
  #define IXGBE_FLAG2_RSC_CAPABLE                 (u32)(1)
        u64 rsc_total_flush;
        u32 wol;
        u16 eeprom_version;
 +
 +      /* SR-IOV */
 +      DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS);
 +      unsigned int num_vfs;
 +      struct vf_data_storage *vfinfo;
  };
  
  enum ixbge_state_t {
@@@ -466,7 -440,6 +466,7 @@@ extern s32 ixgbe_atr_set_flex_byte_8259
                                           u16 flex_byte);
  extern s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input,
                                        u8 l4type);
 +extern void ixgbe_set_rx_mode(struct net_device *netdev);
  #ifdef IXGBE_FCOE
  extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter);
  extern int ixgbe_fso(struct ixgbe_adapter *adapter,
index 9ec296cf4c4009f8818136a2f561729e5ba3abc2,b49bd6b9feb724f7c5b93c69647d86e69a9a8ab0..c92b5b8b31813ec0fc05e67be081286be5870b2a
@@@ -1,7 -1,7 +1,7 @@@
  /*******************************************************************************
  
    Intel 10 Gigabit PCI Express Linux driver
-   Copyright(c) 1999 - 2009 Intel Corporation.
+   Copyright(c) 1999 - 2010 Intel Corporation.
  
    This program is free software; you can redistribute it and/or modify it
    under the terms and conditions of the GNU General Public License,
@@@ -31,7 -31,6 +31,7 @@@
  
  #include "ixgbe.h"
  #include "ixgbe_phy.h"
 +#include "ixgbe_mbx.h"
  
  #define IXGBE_82599_MAX_TX_QUEUES 128
  #define IXGBE_82599_MAX_RX_QUEUES 128
@@@ -952,6 -951,8 +952,6 @@@ static s32 ixgbe_reset_hw_82599(struct 
  
        msleep(50);
  
 -
 -
        /*
         * Store the original AUTOC/AUTOC2 values if they have not been
         * stored off yet.  Otherwise restore the stored original
@@@ -1094,11 -1095,9 +1094,11 @@@ static s32 ixgbe_set_vfta_82599(struct 
                                  bool vlan_on)
  {
        u32 regindex;
 +      u32 vlvf_index;
        u32 bitindex;
        u32 bits;
        u32 first_empty_slot;
 +      u32 vt_ctl;
  
        if (vlan > 4095)
                return IXGBE_ERR_PARAM;
  
  
        /* Part 2
 -       * If the vind is set
 +       * If VT mode is set
         *   Either vlan_on
         *     make sure the vlan is in VLVF
         *     set the vind bit in the matching VLVFB
         *   Or !vlan_on
         *     clear the pool bit and possibly the vind
         */
 -      if (vind) {
 -              /* find the vlanid or the first empty slot */
 -              first_empty_slot = 0;
 -
 -              for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) {
 -                      bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex));
 -                      if (!bits && !first_empty_slot)
 -                              first_empty_slot = regindex;
 -                      else if ((bits & 0x0FFF) == vlan)
 -                              break;
 -              }
 +      vt_ctl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
 +      if (!(vt_ctl & IXGBE_VT_CTL_VT_ENABLE))
 +              goto out;
  
 -              if (regindex >= IXGBE_VLVF_ENTRIES) {
 -                      if (first_empty_slot)
 -                              regindex = first_empty_slot;
 -                      else {
 -                              hw_dbg(hw, "No space in VLVF.\n");
 -                              goto out;
 -                      }
 +      /* find the vlanid or the first empty slot */
 +      first_empty_slot = 0;
 +
 +      for (vlvf_index = 1; vlvf_index < IXGBE_VLVF_ENTRIES; vlvf_index++) {
 +              bits = IXGBE_READ_REG(hw, IXGBE_VLVF(vlvf_index));
 +              if (!bits && !first_empty_slot)
 +                      first_empty_slot = vlvf_index;
 +              else if ((bits & 0x0FFF) == vlan)
 +                      break;
 +      }
 +
 +      if (vlvf_index >= IXGBE_VLVF_ENTRIES) {
 +              if (first_empty_slot)
 +                      vlvf_index = first_empty_slot;
 +              else {
 +                      hw_dbg(hw, "No space in VLVF.\n");
 +                      goto out;
                }
 +      }
  
 -              if (vlan_on) {
 -                      /* set the pool bit */
 -                      if (vind < 32) {
 -                              bits = IXGBE_READ_REG(hw,
 -                                                  IXGBE_VLVFB(regindex * 2));
 -                              bits |= (1 << vind);
 -                              IXGBE_WRITE_REG(hw,
 -                                            IXGBE_VLVFB(regindex * 2), bits);
 -                      } else {
 -                              bits = IXGBE_READ_REG(hw,
 -                                            IXGBE_VLVFB((regindex * 2) + 1));
 -                              bits |= (1 << vind);
 -                              IXGBE_WRITE_REG(hw,
 -                                      IXGBE_VLVFB((regindex * 2) + 1), bits);
 -                      }
 +      if (vlan_on) {
 +              /* set the pool bit */
 +              if (vind < 32) {
 +                      bits = IXGBE_READ_REG(hw,
 +                                            IXGBE_VLVFB(vlvf_index * 2));
 +                      bits |= (1 << vind);
 +                      IXGBE_WRITE_REG(hw,
 +                                      IXGBE_VLVFB(vlvf_index * 2), bits);
                } else {
 -                      /* clear the pool bit */
 -                      if (vind < 32) {
 -                              bits = IXGBE_READ_REG(hw,
 -                                   IXGBE_VLVFB(regindex * 2));
 +                      bits = IXGBE_READ_REG(hw,
 +                              IXGBE_VLVFB((vlvf_index * 2) + 1));
 +                      bits |= (1 << (vind - 32));
 +                      IXGBE_WRITE_REG(hw,
 +                              IXGBE_VLVFB((vlvf_index * 2) + 1), bits);
 +              }
 +      } else {
 +              /* clear the pool bit */
 +              if (vind < 32) {
 +                      bits = IXGBE_READ_REG(hw,
 +                                            IXGBE_VLVFB(vlvf_index * 2));
                        bits &= ~(1 << vind);
 -                              IXGBE_WRITE_REG(hw,
 -                                            IXGBE_VLVFB(regindex * 2), bits);
 -                              bits |= IXGBE_READ_REG(hw,
 -                                            IXGBE_VLVFB((regindex * 2) + 1));
 -                      } else {
 -                              bits = IXGBE_READ_REG(hw,
 -                                            IXGBE_VLVFB((regindex * 2) + 1));
 -                              bits &= ~(1 << vind);
 -                              IXGBE_WRITE_REG(hw,
 -                                      IXGBE_VLVFB((regindex * 2) + 1), bits);
 -                              bits |= IXGBE_READ_REG(hw,
 -                                                  IXGBE_VLVFB(regindex * 2));
 -                      }
 +                      IXGBE_WRITE_REG(hw,
 +                                      IXGBE_VLVFB(vlvf_index * 2), bits);
 +                      bits |= IXGBE_READ_REG(hw,
 +                                      IXGBE_VLVFB((vlvf_index * 2) + 1));
 +              } else {
 +                      bits = IXGBE_READ_REG(hw,
 +                              IXGBE_VLVFB((vlvf_index * 2) + 1));
 +                      bits &= ~(1 << (vind - 32));
 +                      IXGBE_WRITE_REG(hw,
 +                              IXGBE_VLVFB((vlvf_index * 2) + 1), bits);
 +                      bits |= IXGBE_READ_REG(hw,
 +                                             IXGBE_VLVFB(vlvf_index * 2));
                }
 +      }
  
 -              if (bits)
 -                      IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex),
 -                                      (IXGBE_VLVF_VIEN | vlan));
 -              else
 -                      IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), 0);
 +      if (bits) {
 +              IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index),
 +                              (IXGBE_VLVF_VIEN | vlan));
 +              /* if bits is non-zero then some pools/VFs are still
 +               * using this VLAN ID.  Force the VFTA entry to on */
 +              bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex));
 +              bits |= (1 << bitindex);
 +              IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits);
        }
 +      else
 +              IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0);
  
  out:
        return 0;
@@@ -2664,5 -2655,4 +2664,5 @@@ struct ixgbe_info ixgbe_82599_info = 
        .mac_ops                = &mac_ops_82599,
        .eeprom_ops             = &eeprom_ops_82599,
        .phy_ops                = &phy_ops_82599,
 +      .mbx_ops                = &mbx_ops_82599,
  };
index 1cedb9af63dc27db5aa1397588ceabb3d80d6d41,21f158f79dd01b10110866f1b1b0f2e80d236e36..276c2aaa800b57a0caed5676ccdbb1d4205cb7e7
@@@ -1,7 -1,7 +1,7 @@@
  /*******************************************************************************
  
    Intel 10 Gigabit PCI Express Linux driver
-   Copyright(c) 1999 - 2009 Intel Corporation.
+   Copyright(c) 1999 - 2010 Intel Corporation.
  
    This program is free software; you can redistribute it and/or modify it
    under the terms and conditions of the GNU General Public License,
@@@ -1278,11 -1278,19 +1278,11 @@@ s32 ixgbe_init_rx_addrs_generic(struct 
                /* Get the MAC address from the RAR0 for later reference */
                hw->mac.ops.get_mac_addr(hw, hw->mac.addr);
  
 -              hw_dbg(hw, " Keeping Current RAR0 Addr =%.2X %.2X %.2X ",
 -                     hw->mac.addr[0], hw->mac.addr[1],
 -                     hw->mac.addr[2]);
 -              hw_dbg(hw, "%.2X %.2X %.2X\n", hw->mac.addr[3],
 -                     hw->mac.addr[4], hw->mac.addr[5]);
 +              hw_dbg(hw, " Keeping Current RAR0 Addr =%pM\n", hw->mac.addr);
        } else {
                /* Setup the receive address. */
                hw_dbg(hw, "Overriding MAC Address in RAR[0]\n");
 -              hw_dbg(hw, " New MAC Addr =%.2X %.2X %.2X ",
 -                     hw->mac.addr[0], hw->mac.addr[1],
 -                     hw->mac.addr[2]);
 -              hw_dbg(hw, "%.2X %.2X %.2X\n", hw->mac.addr[3],
 -                     hw->mac.addr[4], hw->mac.addr[5]);
 +              hw_dbg(hw, " New MAC Addr =%pM\n", hw->mac.addr);
  
                hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
        }
index a0107b5a28e7937f1b2e27fb49068543662b21dc,d77961fc75f90c8eda86139f6885b5384fe47f56..1525c86cbccf15bfd874174840dc9bc770a4aa7f
@@@ -1,7 -1,7 +1,7 @@@
  /*******************************************************************************
  
    Intel 10 Gigabit PCI Express Linux driver
-   Copyright(c) 1999 - 2009 Intel Corporation.
+   Copyright(c) 1999 - 2010 Intel Corporation.
  
    This program is free software; you can redistribute it and/or modify it
    under the terms and conditions of the GNU General Public License,
@@@ -1867,22 -1867,11 +1867,22 @@@ static void ixgbe_diag_test(struct net_
                if (ixgbe_intr_test(adapter, &data[2]))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
  
 +              /* If SRIOV or VMDq is enabled then skip MAC
 +               * loopback diagnostic. */
 +              if (adapter->flags & (IXGBE_FLAG_SRIOV_ENABLED |
 +                                    IXGBE_FLAG_VMDQ_ENABLED)) {
 +                      DPRINTK(HW, INFO, "Skip MAC loopback diagnostic in VT "
 +                              "mode\n");
 +                      data[3] = 0;
 +                      goto skip_loopback;
 +              }
 +
                ixgbe_reset(adapter);
                DPRINTK(HW, INFO, "loopback testing starting\n");
                if (ixgbe_loopback_test(adapter, &data[3]))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
  
 +skip_loopback:
                ixgbe_reset(adapter);
  
                clear_bit(__IXGBE_TESTING, &adapter->state);
index 81971ed607ebaa6cb7bc1e6982d0f2c9c0c0cdb1,6d61add27a06ca871799e7be2f14a0a303f3f8a4..c46252520d7ac8a07c40a639c27515c46162d4ee
@@@ -1,7 -1,7 +1,7 @@@
  /*******************************************************************************
  
    Intel 10 Gigabit PCI Express Linux driver
-   Copyright(c) 1999 - 2009 Intel Corporation.
+   Copyright(c) 1999 - 2010 Intel Corporation.
  
    This program is free software; you can redistribute it and/or modify it
    under the terms and conditions of the GNU General Public License,
@@@ -45,7 -45,6 +45,7 @@@
  #include "ixgbe.h"
  #include "ixgbe_common.h"
  #include "ixgbe_dcb_82599.h"
 +#include "ixgbe_sriov.h"
  
  char ixgbe_driver_name[] = "ixgbe";
  static const char ixgbe_driver_string[] =
@@@ -53,7 -52,7 +53,7 @@@
  
  #define DRV_VERSION "2.0.44-k2"
  const char ixgbe_driver_version[] = DRV_VERSION;
- static char ixgbe_copyright[] = "Copyright (c) 1999-2009 Intel Corporation.";
+ static char ixgbe_copyright[] = "Copyright (c) 1999-2010 Intel Corporation.";
  
  static const struct ixgbe_info *ixgbe_info_tbl[] = {
        [board_82598] = &ixgbe_82598_info,
@@@ -68,7 -67,7 +68,7 @@@
   * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
   *   Class, Class Mask, private data (not used) }
   */
 -static struct pci_device_id ixgbe_pci_tbl[] = {
 +static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = {
        {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598),
         board_82598 },
        {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_DUAL_PORT),
@@@ -125,13 -124,6 +125,13 @@@ static struct notifier_block dca_notifi
  };
  #endif
  
 +#ifdef CONFIG_PCI_IOV
 +static unsigned int max_vfs;
 +module_param(max_vfs, uint, 0);
 +MODULE_PARM_DESC(max_vfs, "Maximum number of virtual functions to allocate "
 +                 "per physical function");
 +#endif /* CONFIG_PCI_IOV */
 +
  MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
  MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver");
  MODULE_LICENSE("GPL");
@@@ -139,41 -131,6 +139,41 @@@ MODULE_VERSION(DRV_VERSION)
  
  #define DEFAULT_DEBUG_LEVEL_SHIFT 3
  
 +static inline void ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
 +{
 +      struct ixgbe_hw *hw = &adapter->hw;
 +      u32 gcr;
 +      u32 gpie;
 +      u32 vmdctl;
 +
 +#ifdef CONFIG_PCI_IOV
 +      /* disable iov and allow time for transactions to clear */
 +      pci_disable_sriov(adapter->pdev);
 +#endif
 +
 +      /* turn off device IOV mode */
 +      gcr = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
 +      gcr &= ~(IXGBE_GCR_EXT_SRIOV);
 +      IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr);
 +      gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
 +      gpie &= ~IXGBE_GPIE_VTMODE_MASK;
 +      IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
 +
 +      /* set default pool back to 0 */
 +      vmdctl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
 +      vmdctl &= ~IXGBE_VT_CTL_POOL_MASK;
 +      IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vmdctl);
 +
 +      /* take a breather then clean up driver data */
 +      msleep(100);
 +      if (adapter->vfinfo)
 +              kfree(adapter->vfinfo);
 +      adapter->vfinfo = NULL;
 +
 +      adapter->num_vfs = 0;
 +      adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED;
 +}
 +
  static void ixgbe_release_hw_control(struct ixgbe_adapter *adapter)
  {
        u32 ctrl_ext;
@@@ -1068,12 -1025,7 +1068,12 @@@ static void ixgbe_configure_msix(struc
  
        /* set up to autoclear timer, and the vectors */
        mask = IXGBE_EIMS_ENABLE_MASK;
 -      mask &= ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC);
 +      if (adapter->num_vfs)
 +              mask &= ~(IXGBE_EIMS_OTHER |
 +                        IXGBE_EIMS_MAILBOX |
 +                        IXGBE_EIMS_LSC);
 +      else
 +              mask &= ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC);
        IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, mask);
  }
  
@@@ -1302,9 -1254,6 +1302,9 @@@ static irqreturn_t ixgbe_msix_lsc(int i
        if (eicr & IXGBE_EICR_LSC)
                ixgbe_check_lsc(adapter);
  
 +      if (eicr & IXGBE_EICR_MAILBOX)
 +              ixgbe_msg_task(adapter);
 +
        if (hw->mac.type == ixgbe_mac_82598EB)
                ixgbe_check_fan_failure(adapter, eicr);
  
@@@ -1819,8 -1768,6 +1819,8 @@@ static inline void ixgbe_irq_enable(str
                mask |= IXGBE_EIMS_ECC;
                mask |= IXGBE_EIMS_GPI_SDP1;
                mask |= IXGBE_EIMS_GPI_SDP2;
 +              if (adapter->num_vfs)
 +                      mask |= IXGBE_EIMS_MAILBOX;
        }
        if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
            adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
        IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
        ixgbe_irq_enable_queues(adapter, ~0);
        IXGBE_WRITE_FLUSH(&adapter->hw);
 +
 +      if (adapter->num_vfs > 32) {
 +              u32 eitrsel = (1 << (adapter->num_vfs - 32)) - 1;
 +              IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITRSEL, eitrsel);
 +      }
  }
  
  /**
@@@ -1963,8 -1905,6 +1963,8 @@@ static inline void ixgbe_irq_disable(st
                IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000);
                IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0);
                IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0);
 +              if (adapter->num_vfs > 32)
 +                      IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITRSEL, 0);
        }
        IXGBE_WRITE_FLUSH(&adapter->hw);
        if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
@@@ -2049,32 -1989,18 +2049,32 @@@ static void ixgbe_configure_tx(struct i
  
        if (hw->mac.type == ixgbe_mac_82599EB) {
                u32 rttdcs;
 +              u32 mask;
  
                /* disable the arbiter while setting MTQC */
                rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
                rttdcs |= IXGBE_RTTDCS_ARBDIS;
                IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
  
 -              /* We enable 8 traffic classes, DCB only */
 -              if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
 -                      IXGBE_WRITE_REG(hw, IXGBE_MTQC, (IXGBE_MTQC_RT_ENA |
 -                                      IXGBE_MTQC_8TC_8TQ));
 -              else
 +              /* set transmit pool layout */
 +              mask = (IXGBE_FLAG_SRIOV_ENABLED | IXGBE_FLAG_DCB_ENABLED);
 +              switch (adapter->flags & mask) {
 +
 +              case (IXGBE_FLAG_SRIOV_ENABLED):
 +                      IXGBE_WRITE_REG(hw, IXGBE_MTQC,
 +                                      (IXGBE_MTQC_VT_ENA | IXGBE_MTQC_64VF));
 +                      break;
 +
 +              case (IXGBE_FLAG_DCB_ENABLED):
 +                      /* We enable 8 traffic classes, DCB only */
 +                      IXGBE_WRITE_REG(hw, IXGBE_MTQC,
 +                                    (IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ));
 +                      break;
 +
 +              default:
                        IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB);
 +                      break;
 +              }
  
                /* re-eable the arbiter */
                rttdcs &= ~IXGBE_RTTDCS_ARBDIS;
@@@ -2133,16 -2059,12 +2133,16 @@@ static u32 ixgbe_setup_mrqc(struct ixgb
  #ifdef CONFIG_IXGBE_DCB
                                 | IXGBE_FLAG_DCB_ENABLED
  #endif
 +                               | IXGBE_FLAG_SRIOV_ENABLED
                                );
  
        switch (mask) {
        case (IXGBE_FLAG_RSS_ENABLED):
                mrqc = IXGBE_MRQC_RSSEN;
                break;
 +      case (IXGBE_FLAG_SRIOV_ENABLED):
 +              mrqc = IXGBE_MRQC_VMDQEN;
 +              break;
  #ifdef CONFIG_IXGBE_DCB
        case (IXGBE_FLAG_DCB_ENABLED):
                mrqc = IXGBE_MRQC_RT8TCEN;
@@@ -2223,9 -2145,7 +2223,9 @@@ static void ixgbe_configure_rx(struct i
        int rx_buf_len;
  
        /* Decide whether to use packet split mode or not */
 -      adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED;
 +      /* Do not use packet split if we're in SR-IOV Mode */
 +      if (!adapter->num_vfs)
 +              adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED;
  
        /* Set the RX buffer length according to the mode */
        if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
                                      IXGBE_PSRTYPE_IPV4HDR |
                                      IXGBE_PSRTYPE_IPV6HDR |
                                      IXGBE_PSRTYPE_L2HDR;
 -                      IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype);
 +                      IXGBE_WRITE_REG(hw,
 +                                      IXGBE_PSRTYPE(adapter->num_vfs),
 +                                      psrtype);
                }
        } else {
                if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) &&
                IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
        }
  
 +      if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
 +              u32 vt_reg_bits;
 +              u32 reg_offset, vf_shift;
 +              u32 vmdctl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
 +              vt_reg_bits = IXGBE_VMD_CTL_VMDQ_EN
 +                      | IXGBE_VT_CTL_REPLEN;
 +              vt_reg_bits |= (adapter->num_vfs <<
 +                              IXGBE_VT_CTL_POOL_SHIFT);
 +              IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vmdctl | vt_reg_bits);
 +              IXGBE_WRITE_REG(hw, IXGBE_MRQC, 0);
 +
 +              vf_shift = adapter->num_vfs % 32;
 +              reg_offset = adapter->num_vfs / 32;
 +              IXGBE_WRITE_REG(hw, IXGBE_VFRE(0), 0);
 +              IXGBE_WRITE_REG(hw, IXGBE_VFRE(1), 0);
 +              IXGBE_WRITE_REG(hw, IXGBE_VFTE(0), 0);
 +              IXGBE_WRITE_REG(hw, IXGBE_VFTE(1), 0);
 +              /* Enable only the PF's pool for Tx/Rx */
 +              IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), (1 << vf_shift));
 +              IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), (1 << vf_shift));
 +              IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
 +              ixgbe_set_vmolr(hw, adapter->num_vfs);
 +      }
 +
        /* Program MRQC for the distribution of queues */
        mrqc = ixgbe_setup_mrqc(adapter);
  
        }
        IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
  
 +      if (adapter->num_vfs) {
 +              u32 reg;
 +
 +              /* Map PF MAC address in RAR Entry 0 to first pool
 +               * following VFs */
 +              hw->mac.ops.set_vmdq(hw, 0, adapter->num_vfs);
 +
 +              /* Set up VF register offsets for selected VT Mode, i.e.
 +               * 64 VFs for SR-IOV */
 +              reg = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
 +              reg |= IXGBE_GCR_EXT_SRIOV;
 +              IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, reg);
 +      }
 +
        rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
  
        if (adapter->flags & IXGBE_FLAG_RSS_ENABLED ||
@@@ -2534,7 -2414,7 +2534,7 @@@ static u8 *ixgbe_addr_list_itr(struct i
   * responsible for configuring the hardware for proper unicast, multicast and
   * promiscuous mode.
   **/
 -static void ixgbe_set_rx_mode(struct net_device *netdev)
 +void ixgbe_set_rx_mode(struct net_device *netdev)
  {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
        struct ixgbe_hw *hw = &adapter->hw;
                addr_list = netdev->mc_list->dmi_addr;
        hw->mac.ops.update_mc_addr_list(hw, addr_list, addr_count,
                                        ixgbe_addr_list_itr);
 +      if (adapter->num_vfs)
 +              ixgbe_restore_vf_multicasts(adapter);
  }
  
  static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter)
@@@ -2836,10 -2714,6 +2836,10 @@@ static int ixgbe_up_complete(struct ixg
                        /* MSI only */
                        gpie = 0;
                }
 +              if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
 +                      gpie &= ~IXGBE_GPIE_VTMODE_MASK;
 +                      gpie |= IXGBE_GPIE_VTMODE_64;
 +              }
                /* XXX: to interrupt immediately for EICS writes, enable this */
                /* gpie |= IXGBE_GPIE_EIMEN; */
                IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
                txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
                txdctl |= IXGBE_TXDCTL_ENABLE;
                IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
 +              if (hw->mac.type == ixgbe_mac_82599EB) {
 +                      int wait_loop = 10;
 +                      /* poll for Tx Enable ready */
 +                      do {
 +                              msleep(1);
 +                              txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
 +                      } while (--wait_loop &&
 +                               !(txdctl & IXGBE_TXDCTL_ENABLE));
 +                      if (!wait_loop)
 +                              DPRINTK(DRV, ERR, "Could not enable "
 +                                      "Tx Queue %d\n", j);
 +              }
        }
  
        for (i = 0; i < num_rx_rings; i++) {
@@@ -3061,8 -2923,7 +3061,8 @@@ void ixgbe_reset(struct ixgbe_adapter *
        }
  
        /* reprogram the RAR[0] in case user changed it. */
 -      hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
 +      hw->mac.ops.set_rar(hw, 0, hw->mac.addr, adapter->num_vfs,
 +                          IXGBE_RAH_AV);
  }
  
  /**
@@@ -3430,19 -3291,6 +3430,19 @@@ static inline bool ixgbe_set_fcoe_queue
  }
  
  #endif /* IXGBE_FCOE */
 +/**
 + * ixgbe_set_sriov_queues: Allocate queues for IOV use
 + * @adapter: board private structure to initialize
 + *
 + * IOV doesn't actually use anything, so just NAK the
 + * request for now and let the other queue routines
 + * figure out what to do.
 + */
 +static inline bool ixgbe_set_sriov_queues(struct ixgbe_adapter *adapter)
 +{
 +      return false;
 +}
 +
  /*
   * ixgbe_set_num_queues: Allocate queues for device, feature dependant
   * @adapter: board private structure to initialize
   **/
  static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
  {
 +      /* Start with base case */
 +      adapter->num_rx_queues = 1;
 +      adapter->num_tx_queues = 1;
 +      adapter->num_rx_pools = adapter->num_rx_queues;
 +      adapter->num_rx_queues_per_pool = 1;
 +
 +      if (ixgbe_set_sriov_queues(adapter))
 +              return;
 +
  #ifdef IXGBE_FCOE
        if (ixgbe_set_fcoe_queues(adapter))
                goto done;
@@@ -3735,24 -3574,6 +3735,24 @@@ static inline bool ixgbe_cache_ring_fco
  }
  
  #endif /* IXGBE_FCOE */
 +/**
 + * ixgbe_cache_ring_sriov - Descriptor ring to register mapping for sriov
 + * @adapter: board private structure to initialize
 + *
 + * SR-IOV doesn't use any descriptor rings but changes the default if
 + * no other mapping is used.
 + *
 + */
 +static inline bool ixgbe_cache_ring_sriov(struct ixgbe_adapter *adapter)
 +{
 +      adapter->rx_ring[0].reg_idx = adapter->num_vfs * 2;
 +      adapter->tx_ring[0].reg_idx = adapter->num_vfs * 2;
 +      if (adapter->num_vfs)
 +              return true;
 +      else
 +              return false;
 +}
 +
  /**
   * ixgbe_cache_ring_register - Descriptor ring to register mapping
   * @adapter: board private structure to initialize
@@@ -3770,9 -3591,6 +3770,9 @@@ static void ixgbe_cache_ring_register(s
        adapter->rx_ring[0].reg_idx = 0;
        adapter->tx_ring[0].reg_idx = 0;
  
 +      if (ixgbe_cache_ring_sriov(adapter))
 +              return;
 +
  #ifdef IXGBE_FCOE
        if (ixgbe_cache_ring_fcoe(adapter))
                return;
@@@ -3882,9 -3700,6 +3882,9 @@@ static int ixgbe_set_interrupt_capabili
        adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
        adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
        adapter->atr_sample_rate = 0;
 +      if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
 +              ixgbe_disable_sriov(adapter);
 +
        ixgbe_set_num_queues(adapter);
  
        err = pci_enable_msi(adapter->pdev);
@@@ -5352,14 -5167,14 +5352,14 @@@ dma_error
        tx_buffer_info->dma = 0;
        tx_buffer_info->time_stamp = 0;
        tx_buffer_info->next_to_watch = 0;
-       count--;
+       if (count)
+               count--;
  
        /* clear timestamp and dma mappings for remaining portion of packet */
-       while (count >= 0) {
-               count--;
-               i--;
-               if (i < 0)
+       while (count--) {
+               if (i==0)
                        i += tx_ring->count;
+               i--;
                tx_buffer_info = &tx_ring->tx_buffer_info[i];
                ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info);
        }
@@@ -5669,8 -5484,7 +5669,8 @@@ static int ixgbe_set_mac(struct net_dev
        memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
        memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len);
  
 -      hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
 +      hw->mac.ops.set_rar(hw, 0, hw->mac.addr, adapter->num_vfs,
 +                          IXGBE_RAH_AV);
  
        return 0;
  }
@@@ -5762,6 -5576,10 +5762,10 @@@ static void ixgbe_netpoll(struct net_de
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
        int i;
  
+       /* if interface is down do nothing */
+       if (test_bit(__IXGBE_DOWN, &adapter->state))
+               return;
        adapter->flags |= IXGBE_FLAG_IN_NETPOLL;
        if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
                int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
@@@ -5803,61 -5621,6 +5807,61 @@@ static const struct net_device_ops ixgb
  #endif /* IXGBE_FCOE */
  };
  
 +static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter,
 +                         const struct ixgbe_info *ii)
 +{
 +#ifdef CONFIG_PCI_IOV
 +      struct ixgbe_hw *hw = &adapter->hw;
 +      int err;
 +
 +      if (hw->mac.type != ixgbe_mac_82599EB || !max_vfs)
 +              return;
 +
 +      /* The 82599 supports up to 64 VFs per physical function
 +       * but this implementation limits allocation to 63 so that
 +       * basic networking resources are still available to the
 +       * physical function
 +       */
 +      adapter->num_vfs = (max_vfs > 63) ? 63 : max_vfs;
 +      adapter->flags |= IXGBE_FLAG_SRIOV_ENABLED;
 +      err = pci_enable_sriov(adapter->pdev, adapter->num_vfs);
 +      if (err) {
 +              DPRINTK(PROBE, ERR,
 +                      "Failed to enable PCI sriov: %d\n", err);
 +              goto err_novfs;
 +      }
 +      /* If call to enable VFs succeeded then allocate memory
 +       * for per VF control structures.
 +       */
 +      adapter->vfinfo =
 +              kcalloc(adapter->num_vfs,
 +                      sizeof(struct vf_data_storage), GFP_KERNEL);
 +      if (adapter->vfinfo) {
 +              /* Now that we're sure SR-IOV is enabled
 +               * and memory allocated set up the mailbox parameters
 +               */
 +              ixgbe_init_mbx_params_pf(hw);
 +              memcpy(&hw->mbx.ops, ii->mbx_ops,
 +                     sizeof(hw->mbx.ops));
 +
 +              /* Disable RSC when in SR-IOV mode */
 +              adapter->flags2 &= ~(IXGBE_FLAG2_RSC_CAPABLE |
 +                                   IXGBE_FLAG2_RSC_ENABLED);
 +              return;
 +      }
 +
 +      /* Oh oh */
 +      DPRINTK(PROBE, ERR,
 +              "Unable to allocate memory for VF "
 +              "Data Storage - SRIOV disabled\n");
 +      pci_disable_sriov(adapter->pdev);
 +
 +err_novfs:
 +      adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED;
 +      adapter->num_vfs = 0;
 +#endif /* CONFIG_PCI_IOV */
 +}
 +
  /**
   * ixgbe_probe - Device Initialization Routine
   * @pdev: PCI device information struct
@@@ -6032,8 -5795,6 +6036,8 @@@ static int __devinit ixgbe_probe(struc
                goto err_sw_init;
        }
  
 +      ixgbe_probe_vf(adapter, ii);
 +
        netdev->features = NETIF_F_SG |
                           NETIF_F_IP_CSUM |
                           NETIF_F_HW_VLAN_TX |
        netdev->vlan_features |= NETIF_F_IPV6_CSUM;
        netdev->vlan_features |= NETIF_F_SG;
  
 +      if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
 +              adapter->flags &= ~(IXGBE_FLAG_RSS_ENABLED |
 +                                  IXGBE_FLAG_DCB_ENABLED);
        if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
                adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
  
                ixgbe_setup_dca(adapter);
        }
  #endif
 +      if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
 +              DPRINTK(PROBE, INFO, "IOV is enabled with %d VFs\n",
 +                      adapter->num_vfs);
 +              for (i = 0; i < adapter->num_vfs; i++)
 +                      ixgbe_vf_configuration(pdev, (i | 0x10000000));
 +      }
 +
        /* add san mac addr to netdev */
        ixgbe_add_sanmac_netdev(netdev);
  
@@@ -6202,8 -5953,6 +6206,8 @@@ err_register
        ixgbe_clear_interrupt_scheme(adapter);
  err_sw_init:
  err_eeprom:
 +      if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
 +              ixgbe_disable_sriov(adapter);
        clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
        del_timer_sync(&adapter->sfp_timer);
        cancel_work_sync(&adapter->sfp_task);
@@@ -6272,9 -6021,6 +6276,9 @@@ static void __devexit ixgbe_remove(stru
        if (netdev->reg_state == NETREG_REGISTERED)
                unregister_netdev(netdev);
  
 +      if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
 +              ixgbe_disable_sriov(adapter);
 +
        ixgbe_clear_interrupt_scheme(adapter);
  
        ixgbe_release_hw_control(adapter);
index ec8ad182e2f5a3e1b191fc80e1668d1c48e38f73,9eafddfa1b97f82810e735ef40f4c8c3d9d46f62..b4caa7011a2b1ed252dbe61763333fb3051194ab
@@@ -1,7 -1,7 +1,7 @@@
  /*******************************************************************************
  
    Intel 10 Gigabit PCI Express Linux driver
-   Copyright(c) 1999 - 2009 Intel Corporation.
+   Copyright(c) 1999 - 2010 Intel Corporation.
  
    This program is free software; you can redistribute it and/or modify it
    under the terms and conditions of the GNU General Public License,
  #define IXGBE_DTXCTL    0x07E00
  
  #define IXGBE_DMATXCTL  0x04A80
 +#define IXGBE_PFDTXGSWC     0x08220
  #define IXGBE_DTXMXSZRQ     0x08100
  #define IXGBE_DTXTCPFLGL    0x04A88
  #define IXGBE_DTXTCPFLGH    0x04A8C
  #define IXGBE_DMATXCTL_NS       0x2 /* No Snoop LSO hdr buffer */
  #define IXGBE_DMATXCTL_GDV      0x8 /* Global Double VLAN */
  #define IXGBE_DMATXCTL_VT_SHIFT 16  /* VLAN EtherType */
 +
 +#define IXGBE_PFDTXGSWC_VT_LBEN 0x1 /* Local L2 VT switch enable */
  #define IXGBE_DCA_TXCTRL(_i)    (0x07200 + ((_i) * 4)) /* 16 of these (0-15) */
  /* Tx DCA Control register : 128 of these (0-127) */
  #define IXGBE_DCA_TXCTRL_82599(_i)  (0x0600C + ((_i) * 0x40))
  /* DCB registers */
  #define IXGBE_RTRPCS      0x02430
  #define IXGBE_RTTDCS      0x04900
 +#define IXGBE_RTTDCS_ARBDIS     0x00000040 /* DCB arbiter disable */
  #define IXGBE_RTTPCS      0x0CD00
  #define IXGBE_RTRUP2TC    0x03020
  #define IXGBE_RTTUP2TC    0x0C800
  #define IXGBE_GCR_CMPL_TMOUT_RESEND     0x00010000
  #define IXGBE_GCR_CAP_VER2              0x00040000
  
 +#define IXGBE_GCR_EXT_MSIX_EN           0x80000000
 +#define IXGBE_GCR_EXT_VT_MODE_16        0x00000001
 +#define IXGBE_GCR_EXT_VT_MODE_32        0x00000002
 +#define IXGBE_GCR_EXT_VT_MODE_64        0x00000003
 +#define IXGBE_GCR_EXT_SRIOV             (IXGBE_GCR_EXT_MSIX_EN | \
 +                                         IXGBE_GCR_EXT_VT_MODE_64)
 +
  /* Time Sync Registers */
  #define IXGBE_TSYNCRXCTL 0x05188 /* Rx Time Sync Control register - RW */
  #define IXGBE_TSYNCTXCTL 0x08C00 /* Tx Time Sync Control register - RW */
  /* VFRE bitmask */
  #define IXGBE_VFRE_ENABLE_ALL   0xFFFFFFFF
  
 +#define IXGBE_VF_INIT_TIMEOUT   200 /* Number of retries to clear RSTI */
 +
  /* RDHMPN and TDHMPN bitmasks */
  #define IXGBE_RDHMPN_RDICADDR       0x007FF800
  #define IXGBE_RDHMPN_RDICRDREQ      0x00800000
  /* VLAN pool filtering masks */
  #define IXGBE_VLVF_VIEN         0x80000000  /* filter is valid */
  #define IXGBE_VLVF_ENTRIES      64
 +#define IXGBE_VLVF_VLANID_MASK  0x00000FFF
  
  #define IXGBE_ETHERNET_IEEE_VLAN_TYPE 0x8100  /* 802.1q protocol */
  
  #define IXGBE_RX_DESC_SPECIAL_PRI_SHIFT  0x000D /* Priority in upper 3 of 16 */
  #define IXGBE_TX_DESC_SPECIAL_PRI_SHIFT  IXGBE_RX_DESC_SPECIAL_PRI_SHIFT
  
 +/* SR-IOV specific macros */
 +#define IXGBE_MBVFICR_INDEX(vf_number)   (vf_number >> 4)
 +#define IXGBE_MBVFICR(_i)                (0x00710 + (_i * 4))
 +#define IXGBE_VFLRE(_i)                  (((_i & 1) ? 0x001C0 : 0x00600))
 +#define IXGBE_VFLREC(_i)                 (0x00700 + (_i * 4))
 +
  /* Little Endian defines */
  #ifndef __le32
  #define __le32  u32
@@@ -2483,37 -2463,6 +2483,37 @@@ struct ixgbe_phy_info 
        bool                            multispeed_fiber;
  };
  
 +#include "ixgbe_mbx.h"
 +
 +struct ixgbe_mbx_operations {
 +      s32 (*init_params)(struct ixgbe_hw *hw);
 +      s32 (*read)(struct ixgbe_hw *, u32 *, u16,  u16);
 +      s32 (*write)(struct ixgbe_hw *, u32 *, u16, u16);
 +      s32 (*read_posted)(struct ixgbe_hw *, u32 *, u16,  u16);
 +      s32 (*write_posted)(struct ixgbe_hw *, u32 *, u16, u16);
 +      s32 (*check_for_msg)(struct ixgbe_hw *, u16);
 +      s32 (*check_for_ack)(struct ixgbe_hw *, u16);
 +      s32 (*check_for_rst)(struct ixgbe_hw *, u16);
 +};
 +
 +struct ixgbe_mbx_stats {
 +      u32 msgs_tx;
 +      u32 msgs_rx;
 +
 +      u32 acks;
 +      u32 reqs;
 +      u32 rsts;
 +};
 +
 +struct ixgbe_mbx_info {
 +      struct ixgbe_mbx_operations ops;
 +      struct ixgbe_mbx_stats stats;
 +      u32 timeout;
 +      u32 usec_delay;
 +      u32 v2p_mailbox;
 +      u16 size;
 +};
 +
  struct ixgbe_hw {
        u8 __iomem                      *hw_addr;
        void                            *back;
        struct ixgbe_phy_info           phy;
        struct ixgbe_eeprom_info        eeprom;
        struct ixgbe_bus_info           bus;
 +      struct ixgbe_mbx_info           mbx;
        u16                             device_id;
        u16                             vendor_id;
        u16                             subsystem_device_id;
@@@ -2538,7 -2486,6 +2538,7 @@@ struct ixgbe_info 
        struct ixgbe_mac_operations     *mac_ops;
        struct ixgbe_eeprom_operations  *eeprom_ops;
        struct ixgbe_phy_operations     *phy_ops;
 +      struct ixgbe_mbx_operations     *mbx_ops;
  };
  
  
diff --combined drivers/net/mlx4/main.c
index 58f7f979cd2b9861b2b49b68dfe6865bb8ae2926,3cf56d90d85924551c86252ac1343226173a3630..8f6e816a7395f78dadfa12c7a64269ce820d0b7d
@@@ -1174,7 -1174,7 +1174,7 @@@ static int __mlx4_init_one(struct pci_d
        return 0;
  
  err_port:
-       for (port = 1; port <= dev->caps.num_ports; port++)
+       for (--port; port >= 1; --port)
                mlx4_cleanup_port_info(&priv->port[port]);
  
        mlx4_cleanup_mcg_table(dev);
@@@ -1271,7 -1271,7 +1271,7 @@@ int mlx4_restart_one(struct pci_dev *pd
        return __mlx4_init_one(pdev, NULL);
  }
  
 -static struct pci_device_id mlx4_pci_table[] = {
 +static DEFINE_PCI_DEVICE_TABLE(mlx4_pci_table) = {
        { PCI_VDEVICE(MELLANOX, 0x6340) }, /* MT25408 "Hermon" SDR */
        { PCI_VDEVICE(MELLANOX, 0x634a) }, /* MT25408 "Hermon" DDR */
        { PCI_VDEVICE(MELLANOX, 0x6354) }, /* MT25408 "Hermon" QDR */
diff --combined drivers/net/s2io.c
index ac6189005c797b80ca5f404f243c09a0ebdec81d,3c4836d0898f310403f9d44e714793a127514df0..d1664586e8ffce60c0b7eef01859e46c64622bd0
@@@ -523,7 -523,7 +523,7 @@@ module_param_array(rts_frm_len, uint, N
   * S2IO device table.
   * This table lists all the devices that this driver supports.
   */
 -static struct pci_device_id s2io_tbl[] __devinitdata = {
 +static DEFINE_PCI_DEVICE_TABLE(s2io_tbl) = {
        {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_WIN,
         PCI_ANY_ID, PCI_ANY_ID},
        {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_UNI,
@@@ -3421,7 -3421,7 +3421,7 @@@ static int wait_for_cmd_complete(void _
                                break;
                        }
                } else {
-                       if (!(val64 & busy_bit)) {
+                       if (val64 & busy_bit) {
                                ret = SUCCESS;
                                break;
                        }
diff --combined drivers/net/sky2.c
index 8ae8520baaf3b4dd2b375022cc2860403aed5121,37f486b65f630300b6d65ab6b839de7bbcb43112..f8f50f70bcd2f2175c3ef18b5b0e3582f76b9f11
@@@ -1844,7 -1844,8 +1844,8 @@@ static void sky2_tx_complete(struct sky
        sky2->tx_cons = idx;
        smp_mb();
  
-       if (tx_avail(sky2) > MAX_SKB_TX_LE + 4)
+       /* Wake unless it's detached, and called e.g. from sky2_down() */
+       if (tx_avail(sky2) > MAX_SKB_TX_LE + 4 && netif_device_present(dev))
                netif_wake_queue(dev);
  }
  
@@@ -3176,9 -3177,7 +3177,9 @@@ static void sky2_reset(struct sky2_hw *
  static void sky2_detach(struct net_device *dev)
  {
        if (netif_running(dev)) {
 +              netif_tx_lock(dev);
                netif_device_detach(dev);       /* stop txq */
 +              netif_tx_unlock(dev);
                sky2_down(dev);
        }
  }
@@@ -3839,50 -3838,6 +3840,50 @@@ static int sky2_get_regs_len(struct net
        return 0x4000;
  }
  
 +static int sky2_reg_access_ok(struct sky2_hw *hw, unsigned int b)
 +{
 +      /* This complicated switch statement is to make sure and
 +       * only access regions that are unreserved.
 +       * Some blocks are only valid on dual port cards.
 +       */
 +      switch (b) {
 +      /* second port */
 +      case 5:         /* Tx Arbiter 2 */
 +      case 9:         /* RX2 */
 +      case 14 ... 15: /* TX2 */
 +      case 17: case 19: /* Ram Buffer 2 */
 +      case 22 ... 23: /* Tx Ram Buffer 2 */
 +      case 25:        /* Rx MAC Fifo 1 */
 +      case 27:        /* Tx MAC Fifo 2 */
 +      case 31:        /* GPHY 2 */
 +      case 40 ... 47: /* Pattern Ram 2 */
 +      case 52: case 54: /* TCP Segmentation 2 */
 +      case 112 ... 116: /* GMAC 2 */
 +              return hw->ports > 1;
 +
 +      case 0:         /* Control */
 +      case 2:         /* Mac address */
 +      case 4:         /* Tx Arbiter 1 */
 +      case 7:         /* PCI express reg */
 +      case 8:         /* RX1 */
 +      case 12 ... 13: /* TX1 */
 +      case 16: case 18:/* Rx Ram Buffer 1 */
 +      case 20 ... 21: /* Tx Ram Buffer 1 */
 +      case 24:        /* Rx MAC Fifo 1 */
 +      case 26:        /* Tx MAC Fifo 1 */
 +      case 28 ... 29: /* Descriptor and status unit */
 +      case 30:        /* GPHY 1*/
 +      case 32 ... 39: /* Pattern Ram 1 */
 +      case 48: case 50: /* TCP Segmentation 1 */
 +      case 56 ... 60: /* PCI space */
 +      case 80 ... 84: /* GMAC 1 */
 +              return 1;
 +
 +      default:
 +              return 0;
 +      }
 +}
 +
  /*
   * Returns copy of control register region
   * Note: ethtool_get_regs always provides full size (16k) buffer
@@@ -3897,13 -3852,55 +3898,13 @@@ static void sky2_get_regs(struct net_de
        regs->version = 1;
  
        for (b = 0; b < 128; b++) {
 -              /* This complicated switch statement is to make sure and
 -               * only access regions that are unreserved.
 -               * Some blocks are only valid on dual port cards.
 -               * and block 3 has some special diagnostic registers that
 -               * are poison.
 -               */
 -              switch (b) {
 -              case 3:
 -                      /* skip diagnostic ram region */
 +              /* skip poisonous diagnostic ram region in block 3 */
 +              if (b == 3)
                        memcpy_fromio(p + 0x10, io + 0x10, 128 - 0x10);
 -                      break;
 -
 -              /* dual port cards only */
 -              case 5:         /* Tx Arbiter 2 */
 -              case 9:         /* RX2 */
 -              case 14 ... 15: /* TX2 */
 -              case 17: case 19: /* Ram Buffer 2 */
 -              case 22 ... 23: /* Tx Ram Buffer 2 */
 -              case 25:        /* Rx MAC Fifo 1 */
 -              case 27:        /* Tx MAC Fifo 2 */
 -              case 31:        /* GPHY 2 */
 -              case 40 ... 47: /* Pattern Ram 2 */
 -              case 52: case 54: /* TCP Segmentation 2 */
 -              case 112 ... 116: /* GMAC 2 */
 -                      if (sky2->hw->ports == 1)
 -                              goto reserved;
 -                      /* fall through */
 -              case 0:         /* Control */
 -              case 2:         /* Mac address */
 -              case 4:         /* Tx Arbiter 1 */
 -              case 7:         /* PCI express reg */
 -              case 8:         /* RX1 */
 -              case 12 ... 13: /* TX1 */
 -              case 16: case 18:/* Rx Ram Buffer 1 */
 -              case 20 ... 21: /* Tx Ram Buffer 1 */
 -              case 24:        /* Rx MAC Fifo 1 */
 -              case 26:        /* Tx MAC Fifo 1 */
 -              case 28 ... 29: /* Descriptor and status unit */
 -              case 30:        /* GPHY 1*/
 -              case 32 ... 39: /* Pattern Ram 1 */
 -              case 48: case 50: /* TCP Segmentation 1 */
 -              case 56 ... 60: /* PCI space */
 -              case 80 ... 84: /* GMAC 1 */
 +              else if (sky2_reg_access_ok(sky2->hw, b))
                        memcpy_fromio(p, io, 128);
 -                      break;
 -              default:
 -reserved:
 +              else
                        memset(p, 0, 128);
 -              }
  
                p += 128;
                io += 128;
@@@ -4688,6 -4685,7 +4689,7 @@@ static int __devinit sky2_probe(struct 
        INIT_WORK(&hw->restart_work, sky2_restart);
  
        pci_set_drvdata(pdev, hw);
+       pdev->d3_delay = 150;
  
        return 0;
  
diff --combined drivers/net/tg3.c
index eaed2aa09e1f4dc58084382816867d2faa8aa917,7f82b0238e08d3e2cc64892b4d317b58c2103270..7195bdec17f3efa33e63fe6a1a0f7ea34165cfac
@@@ -4,7 -4,7 +4,7 @@@
   * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
   * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
   * Copyright (C) 2004 Sun Microsystems Inc.
-  * Copyright (C) 2005-2009 Broadcom Corporation.
+  * Copyright (C) 2005-2010 Broadcom Corporation.
   *
   * Firmware is:
   *    Derived from proprietary unpublished source code,
@@@ -68,8 -68,8 +68,8 @@@
  
  #define DRV_MODULE_NAME               "tg3"
  #define PFX DRV_MODULE_NAME   ": "
- #define DRV_MODULE_VERSION    "3.105"
- #define DRV_MODULE_RELDATE    "December 2, 2009"
+ #define DRV_MODULE_VERSION    "3.106"
+ #define DRV_MODULE_RELDATE    "January 12, 2010"
  
  #define TG3_DEF_MAC_MODE      0
  #define TG3_DEF_RX_MODE               0
@@@ -174,7 -174,7 +174,7 @@@ static int tg3_debug = -1; /* -1 == us
  module_param(tg3_debug, int, 0);
  MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value");
  
 -static struct pci_device_id tg3_pci_tbl[] = {
 +static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5718)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5724)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57781)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57785)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57761)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57765)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)},
        {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
        {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)},
        {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)},
@@@ -1043,7 -1037,11 +1043,11 @@@ static void tg3_mdio_start(struct tg3 *
                else
                        tp->phy_addr = 1;
  
-               is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES;
+               if (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0)
+                       is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES;
+               else
+                       is_serdes = tr32(TG3_CPMU_PHY_STRAP) &
+                                   TG3_CPMU_PHY_STRAP_IS_SERDES;
                if (is_serdes)
                        tp->phy_addr += 7;
        } else
@@@ -1566,9 -1564,7 +1570,9 @@@ static void tg3_phy_toggle_apd(struct t
  {
        u32 reg;
  
 -      if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
 +      if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
 +              (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 &&
 +           (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)))
                return;
  
        if (tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) {
@@@ -1943,10 -1939,6 +1947,10 @@@ static int tg3_phy_reset(struct tg3 *tp
                }
        }
  
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 &&
 +          (tp->tg3_flags2 & TG3_FLG2_MII_SERDES))
 +              return 0;
 +
        tg3_phy_apply_otp(tp);
  
        if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD)
@@@ -2027,9 -2019,7 +2031,9 @@@ static void tg3_frob_aux_power(struct t
  {
        struct tg3 *tp_peer = tp;
  
 -      if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0)
 +      /* The GPIOs do something completely different on 57765. */
 +      if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0 ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
                return;
  
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
@@@ -4707,8 -4697,9 +4711,9 @@@ next_pkt
                (*post_ptr)++;
  
                if (unlikely(rx_std_posted >= tp->rx_std_max_post)) {
-                       u32 idx = *post_ptr % TG3_RX_RING_SIZE;
-                       tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, idx);
+                       tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE;
+                       tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG,
+                                    tpr->rx_std_prod_idx);
                        work_mask &= ~RXD_OPAQUE_RING_STD;
                        rx_std_posted = 0;
                }
@@@ -7448,13 -7439,10 +7453,13 @@@ static void tg3_rings_reset(struct tg3 
                for (i = 1; i < TG3_IRQ_MAX_VECS; i++) {
                        tp->napi[i].tx_prod = 0;
                        tp->napi[i].tx_cons = 0;
 -                      tw32_mailbox(tp->napi[i].prodmbox, 0);
 +                      if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS)
 +                              tw32_mailbox(tp->napi[i].prodmbox, 0);
                        tw32_rx_mbox(tp->napi[i].consmbox, 0);
                        tw32_mailbox_f(tp->napi[i].int_mbox, 1);
                }
 +              if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS))
 +                      tw32_mailbox(tp->napi[0].prodmbox, 0);
        } else {
                tp->napi[0].tx_prod = 0;
                tp->napi[0].tx_cons = 0;
@@@ -7586,20 -7574,6 +7591,20 @@@ static int tg3_reset_hw(struct tg3 *tp
                tw32(TG3_PCIE_LNKCTL, val | TG3_PCIE_LNKCTL_L1_PLL_PD_DIS);
        }
  
 +      if (tp->tg3_flags3 & TG3_FLG3_L1PLLPD_EN) {
 +              u32 grc_mode = tr32(GRC_MODE);
 +
 +              /* Access the lower 1K of PL PCIE block registers. */
 +              val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK;
 +              tw32(GRC_MODE, val | GRC_MODE_PCIE_PL_SEL);
 +
 +              val = tr32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL1);
 +              tw32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL1,
 +                   val | TG3_PCIE_PL_LO_PHYCTL1_L1PLLPD_EN);
 +
 +              tw32(GRC_MODE, grc_mode);
 +      }
 +
        /* This works around an issue with Athlon chipsets on
         * B3 tigon3 silicon.  This bit has no effect on any
         * other revision.  But do not set this on PCI Express
             ((u64) tpr->rx_std_mapping >> 32));
        tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW,
             ((u64) tpr->rx_std_mapping & 0xffffffff));
-       if (!(tp->tg3_flags3 & TG3_FLG3_5755_PLUS))
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717)
                tw32(RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR,
                     NIC_SRAM_RX_BUFFER_DESC);
  
                        tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS,
                             (RX_JUMBO_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT) |
                             BDINFO_FLAGS_USE_EXT_RECV);
 -                      if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
 +                      if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717)
                                tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_NIC_ADDR,
                                     NIC_SRAM_RX_JUMBO_BUFFER_DESC);
                } else {
        /* Prevent chip from dropping frames when flow control
         * is enabled.
         */
 -      tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
 +              val = 1;
 +      else
 +              val = 2;
 +      tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, val);
  
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
            (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
@@@ -10670,27 -10640,12 +10675,27 @@@ static int tg3_test_memory(struct tg3 *
                { 0x00008000, 0x01000},
                { 0x00010000, 0x01000},
                { 0xffffffff, 0x00000}
 +      }, mem_tbl_5717[] = {
 +              { 0x00000200, 0x00008},
 +              { 0x00010000, 0x0a000},
 +              { 0x00020000, 0x13c00},
 +              { 0xffffffff, 0x00000}
 +      }, mem_tbl_57765[] = {
 +              { 0x00000200, 0x00008},
 +              { 0x00004000, 0x00800},
 +              { 0x00006000, 0x09800},
 +              { 0x00010000, 0x0a000},
 +              { 0xffffffff, 0x00000}
        };
        struct mem_entry *mem_tbl;
        int err = 0;
        int i;
  
 -      if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
 +              mem_tbl = mem_tbl_5717;
 +      else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
 +              mem_tbl = mem_tbl_57765;
 +      else if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
                mem_tbl = mem_tbl_5755;
        else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
                mem_tbl = mem_tbl_5906;
@@@ -12172,7 -12127,8 +12177,8 @@@ static void __devinit tg3_get_eeprom_hw
  
                tp->phy_id = eeprom_phy_id;
                if (eeprom_phy_serdes) {
-                       if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
+                       if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) ||
+                           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
                                tp->tg3_flags2 |= TG3_FLG2_MII_SERDES;
                        else
                                tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
@@@ -13146,8 -13102,6 +13152,8 @@@ static int __devinit tg3_get_invariants
                            tp->pci_chip_rev_id == CHIPREV_ID_57780_A0 ||
                            tp->pci_chip_rev_id == CHIPREV_ID_57780_A1)
                                tp->tg3_flags3 |= TG3_FLG3_CLKREQ_BUG;
 +              } else if (tp->pci_chip_rev_id == CHIPREV_ID_5717_A0) {
 +                      tp->tg3_flags3 |= TG3_FLG3_L1PLLPD_EN;
                }
        } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
                tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
                tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3;
  
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
 -          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
                tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL;
  
        if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 ||
        if (err)
                return err;
  
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 &&
+           (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0 ||
+                (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)))
+               return -ENOTSUPP;
        /* Initialize data/descriptor byte/word swapping. */
        val = tr32(GRC_MODE);
        val &= GRC_MODE_HOST_STACKUP;
@@@ -14128,22 -14086,9 +14139,22 @@@ static void __devinit tg3_init_link_con
  
  static void __devinit tg3_init_bufmgr_config(struct tg3 *tp)
  {
 -      if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS &&
 -          GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
 -          GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765) {
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) {
 +              tp->bufmgr_config.mbuf_read_dma_low_water =
 +                      DEFAULT_MB_RDMA_LOW_WATER_5705;
 +              tp->bufmgr_config.mbuf_mac_rx_low_water =
 +                      DEFAULT_MB_MACRX_LOW_WATER_57765;
 +              tp->bufmgr_config.mbuf_high_water =
 +                      DEFAULT_MB_HIGH_WATER_57765;
 +
 +              tp->bufmgr_config.mbuf_read_dma_low_water_jumbo =
 +                      DEFAULT_MB_RDMA_LOW_WATER_5705;
 +              tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo =
 +                      DEFAULT_MB_MACRX_LOW_WATER_JUMBO_57765;
 +              tp->bufmgr_config.mbuf_high_water_jumbo =
 +                      DEFAULT_MB_HIGH_WATER_JUMBO_57765;
 +      } else if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
                tp->bufmgr_config.mbuf_read_dma_low_water =
                        DEFAULT_MB_RDMA_LOW_WATER_5705;
                tp->bufmgr_config.mbuf_mac_rx_low_water =
@@@ -14203,9 -14148,7 +14214,9 @@@ static char * __devinit tg3_phy_string(
        case PHY_ID_BCM5756:    return "5722/5756";
        case PHY_ID_BCM5906:    return "5906";
        case PHY_ID_BCM5761:    return "5761";
 -      case PHY_ID_BCM5717:    return "5717";
 +      case PHY_ID_BCM5718C:   return "5718C";
 +      case PHY_ID_BCM5718S:   return "5718S";
 +      case PHY_ID_BCM57765:   return "57765";
        case PHY_ID_BCM8002:    return "8002/serdes";
        case 0:                 return "serdes";
        default:                return "unknown";
diff --combined drivers/net/tg3.h
index 34c9ef4b74a3fece93676e66333c02b1a2a209e6,8a167912902b6e13449a18343b21ebf9939a91d8..e7f6214a168058f9a212fd955a94e5cdbc4bef88
@@@ -4,6 -4,7 +4,7 @@@
   * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
   * Copyright (C) 2001 Jeff Garzik (jgarzik@pobox.com)
   * Copyright (C) 2004 Sun Microsystems Inc.
+  * Copyright (C) 2007-2010 Broadcom Corporation.
   */
  
  #ifndef _T3_H
  #define  CPMU_MUTEX_REQ_DRIVER                 0x00001000
  #define TG3_CPMU_MUTEX_GNT            0x00003660
  #define  CPMU_MUTEX_GNT_DRIVER                 0x00001000
+ #define TG3_CPMU_PHY_STRAP            0x00003664
+ #define TG3_CPMU_PHY_STRAP_IS_SERDES   0x00000020
  /* 0x3664 --> 0x3800 unused */
  
  /* Mbuf cluster free registers */
  #define  DEFAULT_MB_MACRX_LOW_WATER     0x00000020
  #define  DEFAULT_MB_MACRX_LOW_WATER_5705  0x00000010
  #define  DEFAULT_MB_MACRX_LOW_WATER_5906  0x00000004
 +#define  DEFAULT_MB_MACRX_LOW_WATER_57765 0x0000002a
  #define  DEFAULT_MB_MACRX_LOW_WATER_JUMBO 0x00000098
  #define  DEFAULT_MB_MACRX_LOW_WATER_JUMBO_5780 0x0000004b
 +#define  DEFAULT_MB_MACRX_LOW_WATER_JUMBO_57765 0x0000007e
  #define BUFMGR_MB_HIGH_WATER          0x00004418
  #define  DEFAULT_MB_HIGH_WATER                 0x00000060
  #define  DEFAULT_MB_HIGH_WATER_5705    0x00000060
  #define  DEFAULT_MB_HIGH_WATER_5906    0x00000010
 +#define  DEFAULT_MB_HIGH_WATER_57765   0x000000a0
  #define  DEFAULT_MB_HIGH_WATER_JUMBO   0x0000017c
  #define  DEFAULT_MB_HIGH_WATER_JUMBO_5780 0x00000096
 +#define  DEFAULT_MB_HIGH_WATER_JUMBO_57765 0x000000ea
  #define BUFMGR_RX_MB_ALLOC_REQ                0x0000441c
  #define  BUFMGR_MB_ALLOC_BIT           0x10000000
  #define BUFMGR_RX_MB_ALLOC_RESP               0x00004420
  #define  GRC_MODE_HOST_SENDBDS                0x00020000
  #define  GRC_MODE_NO_TX_PHDR_CSUM     0x00100000
  #define  GRC_MODE_NVRAM_WR_ENABLE     0x00200000
 +#define  GRC_MODE_PCIE_TL_SEL         0x00000000
 +#define  GRC_MODE_PCIE_PL_SEL         0x00400000
  #define  GRC_MODE_NO_RX_PHDR_CSUM     0x00800000
  #define  GRC_MODE_IRQ_ON_TX_CPU_ATTN  0x01000000
  #define  GRC_MODE_IRQ_ON_RX_CPU_ATTN  0x02000000
  #define  GRC_MODE_IRQ_ON_DMA_ATTN     0x08000000
  #define  GRC_MODE_IRQ_ON_FLOW_ATTN    0x10000000
  #define  GRC_MODE_4X_NIC_SEND_RINGS   0x20000000
 +#define  GRC_MODE_PCIE_DL_SEL         0x20000000
  #define  GRC_MODE_MCAST_FRM_ENABLE    0x40000000
 +#define  GRC_MODE_PCIE_HI_1K_EN               0x80000000
 +#define  GRC_MODE_PCIE_PORT_MASK      (GRC_MODE_PCIE_TL_SEL | \
 +                                       GRC_MODE_PCIE_PL_SEL | \
 +                                       GRC_MODE_PCIE_DL_SEL | \
 +                                       GRC_MODE_PCIE_HI_1K_EN)
  #define GRC_MISC_CFG                  0x00006804
  #define  GRC_MISC_CFG_CORECLK_RESET   0x00000001
  #define  GRC_MISC_CFG_PRESCALAR_MASK  0x000000fe
  /* 0x7e74 --> 0x8000 unused */
  
  
 +/* Alternate PCIE definitions */
 +#define TG3_PCIE_TLDLPL_PORT          0x00007c00
 +#define TG3_PCIE_PL_LO_PHYCTL1                 0x00000004
 +#define TG3_PCIE_PL_LO_PHYCTL1_L1PLLPD_EN       0x00001000
 +
  /* OTP bit definitions */
  #define TG3_OTP_AGCTGT_MASK           0x000000e0
  #define TG3_OTP_AGCTGT_SHIFT          1
@@@ -2826,7 -2812,6 +2829,7 @@@ struct tg3 
  #define TG3_FLG3_40BIT_DMA_LIMIT_BUG  0x00100000
  #define TG3_FLG3_SHORT_DMA_BUG                0x00200000
  #define TG3_FLG3_USE_JUMBO_BDFLAG     0x00400000
 +#define TG3_FLG3_L1PLLPD_EN           0x00800000
  
        struct timer_list               timer;
        u16                             timer_counter;
  #define PHY_ID_BCM5756                        0xbc050ed0
  #define PHY_ID_BCM5784                        0xbc050fa0
  #define PHY_ID_BCM5761                        0xbc050fd0
 -#define PHY_ID_BCM5717                        0x5c0d8a00
 +#define PHY_ID_BCM5718C                       0x5c0d8a00
 +#define PHY_ID_BCM5718S                       0xbc050ff0
 +#define PHY_ID_BCM57765                       0x5c0d8a40
  #define PHY_ID_BCM5906                        0xdc00ac40
  #define PHY_ID_BCM8002                        0x60010140
  #define PHY_ID_INVALID                        0xffffffff
         (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \
         (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM5756 || \
         (X) == PHY_ID_BCM5906 || (X) == PHY_ID_BCM5761 || \
 -       (X) == PHY_ID_BCM5717 || (X) == PHY_ID_BCM8002)
 +       (X) == PHY_ID_BCM5718C || (X) == PHY_ID_BCM5718S || \
 +       (X) == PHY_ID_BCM57765 || (X) == PHY_ID_BCM8002)
  
        struct tg3_hw_stats             *hw_stats;
        dma_addr_t                      stats_mapping;
diff --combined drivers/net/ucc_geth.c
index 6750de10a087de4dcc76099868028e0786a51a88,eb8fe7e16c6cdd27319ec1e3a024328bd0d4c99b..225f65812f2ebaa82329530c235d2baa3f357572
@@@ -37,7 -37,6 +37,7 @@@
  #include <asm/qe.h>
  #include <asm/ucc.h>
  #include <asm/ucc_fast.h>
 +#include <asm/machdep.h>
  
  #include "ucc_geth.h"
  #include "fsl_pq_mdio.h"
@@@ -1335,7 -1334,7 +1335,7 @@@ static int adjust_enet_interface(struc
        struct ucc_geth __iomem *ug_regs;
        struct ucc_fast __iomem *uf_regs;
        int ret_val;
 -      u32 upsmr, maccfg2, tbiBaseAddress;
 +      u32 upsmr, maccfg2;
        u16 value;
  
        ugeth_vdbg("%s: IN", __func__);
        /* Note that this depends on proper setting in utbipar register. */
        if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) ||
            (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
 -              tbiBaseAddress = in_be32(&ug_regs->utbipar);
 -              tbiBaseAddress &= UTBIPAR_PHY_ADDRESS_MASK;
 -              tbiBaseAddress >>= UTBIPAR_PHY_ADDRESS_SHIFT;
 -              value = ugeth->phydev->bus->read(ugeth->phydev->bus,
 -                              (u8) tbiBaseAddress, ENET_TBI_MII_CR);
 +              struct ucc_geth_info *ug_info = ugeth->ug_info;
 +              struct phy_device *tbiphy;
 +
 +              if (!ug_info->tbi_node)
 +                      ugeth_warn("TBI mode requires that the device "
 +                              "tree specify a tbi-handle\n");
 +
 +              tbiphy = of_phy_find_device(ug_info->tbi_node);
 +              if (!tbiphy)
 +                      ugeth_warn("Could not get TBI device\n");
 +
 +              value = phy_read(tbiphy, ENET_TBI_MII_CR);
                value &= ~0x1000;       /* Turn off autonegotiation */
 -              ugeth->phydev->bus->write(ugeth->phydev->bus,
 -                              (u8) tbiBaseAddress, ENET_TBI_MII_CR, value);
 +              phy_write(tbiphy, ENET_TBI_MII_CR, value);
        }
  
        init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2);
@@@ -3286,13 -3279,12 +3286,12 @@@ static int ucc_geth_tx(struct net_devic
                /* Handle the transmitted buffer and release */
                /* the BD to be used with the current frame  */
  
-               if (bd == ugeth->txBd[txQ]) /* queue empty? */
+               skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
+               if (!skb)
                        break;
  
                dev->stats.tx_packets++;
  
-               skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
                if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN &&
                             skb_recycle_check(skb,
                                    ugeth->ug_info->uf_info.max_rx_buf_length +
index cee368d4859f06f45ecda81777e11d3351621178,9b4b8b5c757464f0f48e9455ed1ea23f0a418a4f..6a004abb5973205d241b8a8ca47d6979aca9402b
@@@ -1961,7 -1961,7 +1961,7 @@@ static void iwl4965_rx_reply_tx(struct 
        struct ieee80211_tx_info *info;
        struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
        u32  status = le32_to_cpu(tx_resp->u.status);
-       int tid = MAX_TID_COUNT - 1;
+       int uninitialized_var(tid);
        int sta_id;
        int freed;
        u8 *qc = NULL;
@@@ -2208,7 -2208,7 +2208,7 @@@ static struct iwl_lib_ops iwl4965_lib 
        },
  };
  
 -static struct iwl_ops iwl4965_ops = {
 +static const struct iwl_ops iwl4965_ops = {
        .ucode = &iwl4965_ucode,
        .lib = &iwl4965_lib,
        .hcmd = &iwl4965_hcmd,
@@@ -2239,6 -2239,7 +2239,6 @@@ struct iwl_cfg iwl4965_agn_cfg = 
        .broken_powersave = true,
        .led_compensation = 61,
        .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
 -      .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
  };
  
  /* Module firmware */
index c3f8ec0a38b1b55fe7f30edd8a7476491a56679b,de45f308b7440a56024ea5b54491633c4628398f..c6120f0b8f98d0aabf48e4439501e099938e7c5f
@@@ -781,7 -781,7 +781,7 @@@ void iwl5000_txq_update_byte_cnt_tbl(st
  
        scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
  
 -      if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP)
 +      if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
                scd_bc_tbl[txq_id].
                        tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
  }
@@@ -800,12 -800,12 +800,12 @@@ void iwl5000_txq_inval_byte_cnt_tbl(str
        if (txq_id != IWL_CMD_QUEUE_NUM)
                sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
  
 -      bc_ent =  cpu_to_le16(1 | (sta_id << 12));
 +      bc_ent = cpu_to_le16(1 | (sta_id << 12));
        scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
  
 -      if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP)
 +      if (read_ptr < TFD_QUEUE_SIZE_BC_DUP)
                scd_bc_tbl[txq_id].
 -                      tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] =  bc_ent;
 +                      tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
  }
  
  static int iwl5000_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
@@@ -1466,7 -1466,6 +1466,7 @@@ struct iwl_lib_ops iwl5000_lib = 
        .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
        .dump_nic_event_log = iwl_dump_nic_event_log,
        .dump_nic_error_log = iwl_dump_nic_error_log,
 +      .dump_csr = iwl_dump_csr,
        .load_ucode = iwl5000_load_ucode,
        .init_alive_start = iwl5000_init_alive_start,
        .alive_notify = iwl5000_alive_notify,
@@@ -1519,7 -1518,6 +1519,7 @@@ static struct iwl_lib_ops iwl5150_lib 
        .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
        .dump_nic_event_log = iwl_dump_nic_event_log,
        .dump_nic_error_log = iwl_dump_nic_error_log,
 +      .dump_csr = iwl_dump_csr,
        .load_ucode = iwl5000_load_ucode,
        .init_alive_start = iwl5000_init_alive_start,
        .alive_notify = iwl5000_alive_notify,
         },
  };
  
 -static struct iwl_ops iwl5000_ops = {
 +static const struct iwl_ops iwl5000_ops = {
        .ucode = &iwl5000_ucode,
        .lib = &iwl5000_lib,
        .hcmd = &iwl5000_hcmd,
        .led = &iwlagn_led_ops,
  };
  
 -static struct iwl_ops iwl5150_ops = {
 +static const struct iwl_ops iwl5150_ops = {
        .ucode = &iwl5000_ucode,
        .lib = &iwl5150_lib,
        .hcmd = &iwl5000_hcmd,
@@@ -1600,7 -1598,9 +1600,8 @@@ struct iwl_cfg iwl5300_agn_cfg = 
        .use_bsm = false,
        .ht_greenfield_support = true,
        .led_compensation = 51,
+       .use_rts_for_ht = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 -      .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
  };
  
  struct iwl_cfg iwl5100_bgn_cfg = {
        .use_bsm = false,
        .ht_greenfield_support = true,
        .led_compensation = 51,
+       .use_rts_for_ht = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
  };
  
@@@ -1668,7 -1669,9 +1670,8 @@@ struct iwl_cfg iwl5100_agn_cfg = 
        .use_bsm = false,
        .ht_greenfield_support = true,
        .led_compensation = 51,
+       .use_rts_for_ht = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 -      .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
  };
  
  struct iwl_cfg iwl5350_agn_cfg = {
        .use_bsm = false,
        .ht_greenfield_support = true,
        .led_compensation = 51,
+       .use_rts_for_ht = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 -      .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
  };
  
  struct iwl_cfg iwl5150_agn_cfg = {
        .use_bsm = false,
        .ht_greenfield_support = true,
        .led_compensation = 51,
+       .use_rts_for_ht = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 -      .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
  };
  
  struct iwl_cfg iwl5150_abg_cfg = {
index 14f482960d7faeda385162a58fafaf484e274cad,5461f105bd2dcb61971d17c64ef17c640c553c8b..5b56307a3812f6bc92a66935b2e427c0404bd5ac
@@@ -450,6 -450,8 +450,6 @@@ static void iwlcore_init_ht_hw_capab(co
        if (priv->cfg->ht_greenfield_support)
                ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
        ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
 -      ht_info->cap |= (IEEE80211_HT_CAP_SM_PS &
 -                           (priv->cfg->sm_ps_mode << 2));
        max_bit_rate = MAX_BIT_RATE_20_MHZ;
        if (priv->hw_params.ht40_channel & BIT(band)) {
                ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
@@@ -634,7 -636,7 +634,7 @@@ EXPORT_SYMBOL(iwlcore_rts_tx_cmd_flag)
  
  static bool is_single_rx_stream(struct iwl_priv *priv)
  {
 -      return !priv->current_ht_config.is_ht ||
 +      return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
               priv->current_ht_config.single_chain_sufficient;
  }
  
@@@ -1001,18 -1003,28 +1001,18 @@@ static int iwl_get_active_rx_chain_coun
   */
  static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
  {
 -      int idle_cnt = active_cnt;
 -      bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
 -
 -      /* # Rx chains when idling and maybe trying to save power */
 -      switch (priv->cfg->sm_ps_mode) {
 -      case WLAN_HT_CAP_SM_PS_STATIC:
 -              idle_cnt = (is_cam) ? active_cnt : IWL_NUM_IDLE_CHAINS_SINGLE;
 -              break;
 -      case WLAN_HT_CAP_SM_PS_DYNAMIC:
 -              idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL :
 -                      IWL_NUM_IDLE_CHAINS_SINGLE;
 -              break;
 -      case WLAN_HT_CAP_SM_PS_DISABLED:
 -              break;
 -      case WLAN_HT_CAP_SM_PS_INVALID:
 +      /* # Rx chains when idling, depending on SMPS mode */
 +      switch (priv->current_ht_config.smps) {
 +      case IEEE80211_SMPS_STATIC:
 +      case IEEE80211_SMPS_DYNAMIC:
 +              return IWL_NUM_IDLE_CHAINS_SINGLE;
 +      case IEEE80211_SMPS_OFF:
 +              return active_cnt;
        default:
 -              IWL_ERR(priv, "invalid sm_ps mode %u\n",
 -                      priv->cfg->sm_ps_mode);
 -              WARN_ON(1);
 -              break;
 +              WARN(1, "invalid SMPS mode %d",
 +                   priv->current_ht_config.smps);
 +              return active_cnt;
        }
 -      return idle_cnt;
  }
  
  /* up to 4 chains */
@@@ -1351,9 -1363,7 +1351,9 @@@ void iwl_irq_handle_error(struct iwl_pr
        clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
  
        priv->cfg->ops->lib->dump_nic_error_log(priv);
 -      priv->cfg->ops->lib->dump_nic_event_log(priv, false);
 +      if (priv->cfg->ops->lib->dump_csr)
 +              priv->cfg->ops->lib->dump_csr(priv);
 +      priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false);
  #ifdef CONFIG_IWLWIFI_DEBUG
        if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)
                iwl_print_rx_config_cmd(priv);
@@@ -2334,6 -2344,21 +2334,21 @@@ static void iwl_ht_conf(struct iwl_pri
        IWL_DEBUG_MAC80211(priv, "leave\n");
  }
  
+ static inline void iwl_set_no_assoc(struct iwl_priv *priv)
+ {
+       priv->assoc_id = 0;
+       iwl_led_disassociate(priv);
+       /*
+        * inform the ucode that there is no longer an
+        * association and that no more packets should be
+        * sent
+        */
+       priv->staging_rxon.filter_flags &=
+               ~RXON_FILTER_ASSOC_MSK;
+       priv->staging_rxon.assoc_id = 0;
+       iwlcore_commit_rxon(priv);
+ }
  #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
  void iwl_bss_info_changed(struct ieee80211_hw *hw,
                          struct ieee80211_vif *vif,
                                        IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
                        if (!iwl_is_rfkill(priv))
                                priv->cfg->ops->lib->post_associate(priv);
-               } else {
-                       priv->assoc_id = 0;
-                       iwl_led_disassociate(priv);
-                       /*
-                        * inform the ucode that there is no longer an
-                        * association and that no more packets should be
-                        * send
-                        */
-                       priv->staging_rxon.filter_flags &=
-                               ~RXON_FILTER_ASSOC_MSK;
-                       priv->staging_rxon.assoc_id = 0;
-                       iwlcore_commit_rxon(priv);
-               }
+               } else
+                       iwl_set_no_assoc(priv);
        }
  
        if (changes && iwl_is_associated(priv) && priv->assoc_id) {
                }
        }
  
-       if ((changes & BSS_CHANGED_BEACON_ENABLED) &&
-           vif->bss_conf.enable_beacon) {
-               memcpy(priv->staging_rxon.bssid_addr,
-                      bss_conf->bssid, ETH_ALEN);
-               memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
-               iwlcore_config_ap(priv);
+       if (changes & BSS_CHANGED_BEACON_ENABLED) {
+               if (vif->bss_conf.enable_beacon) {
+                       memcpy(priv->staging_rxon.bssid_addr,
+                              bss_conf->bssid, ETH_ALEN);
+                       memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
+                       iwlcore_config_ap(priv);
+               } else
+                       iwl_set_no_assoc(priv);
        }
  
        mutex_unlock(&priv->mutex);
@@@ -2584,12 -2599,12 +2589,12 @@@ int iwl_set_mode(struct iwl_priv *priv
  EXPORT_SYMBOL(iwl_set_mode);
  
  int iwl_mac_add_interface(struct ieee80211_hw *hw,
 -                               struct ieee80211_if_init_conf *conf)
 +                               struct ieee80211_vif *vif)
  {
        struct iwl_priv *priv = hw->priv;
        unsigned long flags;
  
 -      IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type);
 +      IWL_DEBUG_MAC80211(priv, "enter: type %d\n", vif->type);
  
        if (priv->vif) {
                IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n");
        }
  
        spin_lock_irqsave(&priv->lock, flags);
 -      priv->vif = conf->vif;
 -      priv->iw_mode = conf->type;
 +      priv->vif = vif;
 +      priv->iw_mode = vif->type;
  
        spin_unlock_irqrestore(&priv->lock, flags);
  
        mutex_lock(&priv->mutex);
  
 -      if (conf->mac_addr) {
 -              IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr);
 -              memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
 +      if (vif->addr) {
 +              IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr);
 +              memcpy(priv->mac_addr, vif->addr, ETH_ALEN);
        }
  
 -      if (iwl_set_mode(priv, conf->type) == -EAGAIN)
 +      if (iwl_set_mode(priv, vif->type) == -EAGAIN)
                /* we are not ready, will run again when ready */
                set_bit(STATUS_MODE_PENDING, &priv->status);
  
  EXPORT_SYMBOL(iwl_mac_add_interface);
  
  void iwl_mac_remove_interface(struct ieee80211_hw *hw,
 -                                   struct ieee80211_if_init_conf *conf)
 +                                   struct ieee80211_vif *vif)
  {
        struct iwl_priv *priv = hw->priv;
  
                priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
                iwlcore_commit_rxon(priv);
        }
 -      if (priv->vif == conf->vif) {
 +      if (priv->vif == vif) {
                priv->vif = NULL;
                memset(priv->bssid, 0, ETH_ALEN);
        }
@@@ -2674,21 -2689,6 +2679,21 @@@ int iwl_mac_config(struct ieee80211_hw 
                IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
        }
  
 +      if (changed & (IEEE80211_CONF_CHANGE_SMPS |
 +                     IEEE80211_CONF_CHANGE_CHANNEL)) {
 +              /* mac80211 uses static for non-HT which is what we want */
 +              priv->current_ht_config.smps = conf->smps_mode;
 +
 +              /*
 +               * Recalculate chain counts.
 +               *
 +               * If monitor mode is enabled then mac80211 will
 +               * set up the SM PS mode to OFF if an HT channel is
 +               * configured.
 +               */
 +              if (priv->cfg->ops->hcmd->set_rxon_chain)
 +                      priv->cfg->ops->hcmd->set_rxon_chain(priv);
 +      }
  
        /* during scanning mac80211 will delay channel setting until
         * scan finish with changed = 0
                iwl_set_tx_power(priv, conf->power_level, false);
        }
  
 -      /* call to ensure that 4965 rx_chain is set properly in monitor mode */
 -      if (priv->cfg->ops->hcmd->set_rxon_chain)
 -              priv->cfg->ops->hcmd->set_rxon_chain(priv);
 -
        if (!iwl_is_ready(priv)) {
                IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
                goto out;
@@@ -3192,77 -3196,6 +3197,77 @@@ void iwl_update_stats(struct iwl_priv *
  EXPORT_SYMBOL(iwl_update_stats);
  #endif
  
 +const static char *get_csr_string(int cmd)
 +{
 +      switch (cmd) {
 +              IWL_CMD(CSR_HW_IF_CONFIG_REG);
 +              IWL_CMD(CSR_INT_COALESCING);
 +              IWL_CMD(CSR_INT);
 +              IWL_CMD(CSR_INT_MASK);
 +              IWL_CMD(CSR_FH_INT_STATUS);
 +              IWL_CMD(CSR_GPIO_IN);
 +              IWL_CMD(CSR_RESET);
 +              IWL_CMD(CSR_GP_CNTRL);
 +              IWL_CMD(CSR_HW_REV);
 +              IWL_CMD(CSR_EEPROM_REG);
 +              IWL_CMD(CSR_EEPROM_GP);
 +              IWL_CMD(CSR_OTP_GP_REG);
 +              IWL_CMD(CSR_GIO_REG);
 +              IWL_CMD(CSR_GP_UCODE_REG);
 +              IWL_CMD(CSR_GP_DRIVER_REG);
 +              IWL_CMD(CSR_UCODE_DRV_GP1);
 +              IWL_CMD(CSR_UCODE_DRV_GP2);
 +              IWL_CMD(CSR_LED_REG);
 +              IWL_CMD(CSR_DRAM_INT_TBL_REG);
 +              IWL_CMD(CSR_GIO_CHICKEN_BITS);
 +              IWL_CMD(CSR_ANA_PLL_CFG);
 +              IWL_CMD(CSR_HW_REV_WA_REG);
 +              IWL_CMD(CSR_DBG_HPET_MEM_REG);
 +      default:
 +              return "UNKNOWN";
 +
 +      }
 +}
 +
 +void iwl_dump_csr(struct iwl_priv *priv)
 +{
 +      int i;
 +      u32 csr_tbl[] = {
 +              CSR_HW_IF_CONFIG_REG,
 +              CSR_INT_COALESCING,
 +              CSR_INT,
 +              CSR_INT_MASK,
 +              CSR_FH_INT_STATUS,
 +              CSR_GPIO_IN,
 +              CSR_RESET,
 +              CSR_GP_CNTRL,
 +              CSR_HW_REV,
 +              CSR_EEPROM_REG,
 +              CSR_EEPROM_GP,
 +              CSR_OTP_GP_REG,
 +              CSR_GIO_REG,
 +              CSR_GP_UCODE_REG,
 +              CSR_GP_DRIVER_REG,
 +              CSR_UCODE_DRV_GP1,
 +              CSR_UCODE_DRV_GP2,
 +              CSR_LED_REG,
 +              CSR_DRAM_INT_TBL_REG,
 +              CSR_GIO_CHICKEN_BITS,
 +              CSR_ANA_PLL_CFG,
 +              CSR_HW_REV_WA_REG,
 +              CSR_DBG_HPET_MEM_REG
 +      };
 +      IWL_ERR(priv, "CSR values:\n");
 +      IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is "
 +              "CSR_INT_PERIODIC_REG)\n");
 +      for (i = 0; i <  ARRAY_SIZE(csr_tbl); i++) {
 +              IWL_ERR(priv, "  %25s: 0X%08x\n",
 +                      get_csr_string(csr_tbl[i]),
 +                      iwl_read32(priv, csr_tbl[i]));
 +      }
 +}
 +EXPORT_SYMBOL(iwl_dump_csr);
 +
  #ifdef CONFIG_PM
  
  int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
index 42f9b17327c34040fd3e976a442fb23c0a108055,3822cf53e36850003b1c636a20bbde21d2846e43..70f0e79c8e4a8226bd0e4b834af5c4a592db0789
@@@ -512,7 -512,6 +512,7 @@@ struct iwl_ht_config 
        bool is_ht;
        bool is_40mhz;
        bool single_chain_sufficient;
 +      enum ieee80211_smps_mode smps; /* current smps mode */
        /* BSS related data */
        u8 extension_chan_offset;
        u8 ht_protection;
@@@ -712,7 -711,7 +712,7 @@@ extern void iwl_txq_ctx_stop(struct iwl
  extern int iwl_queue_space(const struct iwl_queue *q);
  static inline int iwl_queue_used(const struct iwl_queue *q, int i)
  {
-       return q->write_ptr > q->read_ptr ?
+       return q->write_ptr >= q->read_ptr ?
                (i >= q->read_ptr && i < q->write_ptr) :
                !(i < q->read_ptr && i >= q->write_ptr);
  }
@@@ -985,32 -984,6 +985,32 @@@ struct iwl_switch_rxon 
        __le16 channel;
  };
  
 +/*
 + * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds
 + * to perform continuous uCode event logging operation if enabled
 + */
 +#define UCODE_TRACE_PERIOD (100)
 +
 +/*
 + * iwl_event_log: current uCode event log position
 + *
 + * @ucode_trace: enable/disable ucode continuous trace timer
 + * @num_wraps: how many times the event buffer wraps
 + * @next_entry:  the entry just before the next one that uCode would fill
 + * @non_wraps_count: counter for no wrap detected when dump ucode events
 + * @wraps_once_count: counter for wrap once detected when dump ucode events
 + * @wraps_more_count: counter for wrap more than once detected
 + *                  when dump ucode events
 + */
 +struct iwl_event_log {
 +      bool ucode_trace;
 +      u32 num_wraps;
 +      u32 next_entry;
 +      int non_wraps_count;
 +      int wraps_once_count;
 +      int wraps_more_count;
 +};
 +
  struct iwl_priv {
  
        /* ieee device used by generic ieee processing code */
        u32 disable_tx_power_cal;
        struct work_struct run_time_calib_work;
        struct timer_list statistics_periodic;
 +      struct timer_list ucode_trace;
        bool hw_ready;
        /*For 3945*/
  #define IWL_DEFAULT_TX_POWER 0x0F
        struct iwl3945_notif_statistics statistics_39;
  
        u32 sta_supp_rates;
 +
 +      struct iwl_event_log event_log;
  }; /*iwl_priv */
  
  static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
index bf46308b17fad9535dbd53b5ebedebdc0b66dbfa,83cc4e500a96516ec3c0d4c3b65d60e54ca97a27..36580d8d8b8db4cbb6e5b38b2242d69ec8153045
@@@ -1,3 -1,29 +1,29 @@@
+ /******************************************************************************
+  *
+  * Copyright(c) 2009 - 2010 Intel Corporation. All rights reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License as
+  * published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  * more details.
+  *
+  * You should have received a copy of the GNU General Public License along with
+  * this program; if not, write to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+  *
+  * The full GNU General Public License is included in this distribution in the
+  * file called LICENSE.
+  *
+  * Contact Information:
+  *  Intel Linux Wireless <ilw@linux.intel.com>
+  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+  *
+  *****************************************************************************/
  #include <linux/module.h>
  
  /* sparse doesn't like tracepoint macros */
@@@ -11,6 -37,4 +37,6 @@@ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_io
  EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx);
  EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event);
  EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error);
 +EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event);
 +EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_wrap_event);
  #endif
index 0819f990be6ccaadcf37971ccf25483c5eb171d2,d9c7363b1bbb0ec4d0f7e971c49eb7f625c40e5d..ff4d012ce2600dfbaf5ac7317138daa628e15880
@@@ -1,3 -1,29 +1,29 @@@
+ /******************************************************************************
+  *
+  * Copyright(c) 2009 - 2010 Intel Corporation. All rights reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License as
+  * published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  * more details.
+  *
+  * You should have received a copy of the GNU General Public License along with
+  * this program; if not, write to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+  *
+  * The full GNU General Public License is included in this distribution in the
+  * file called LICENSE.
+  *
+  * Contact Information:
+  *  Intel Linux Wireless <ilw@linux.intel.com>
+  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+  *
+  *****************************************************************************/
  #if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ)
  #define __IWLWIFI_DEVICE_TRACE
  
@@@ -64,50 -90,6 +90,50 @@@ TRACE_EVENT(iwlwifi_dev_iowrite32
        TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val)
  );
  
 +#undef TRACE_SYSTEM
 +#define TRACE_SYSTEM iwlwifi_ucode
 +
 +TRACE_EVENT(iwlwifi_dev_ucode_cont_event,
 +      TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
 +      TP_ARGS(priv, time, data, ev),
 +      TP_STRUCT__entry(
 +              PRIV_ENTRY
 +
 +              __field(u32, time)
 +              __field(u32, data)
 +              __field(u32, ev)
 +      ),
 +      TP_fast_assign(
 +              PRIV_ASSIGN;
 +              __entry->time = time;
 +              __entry->data = data;
 +              __entry->ev = ev;
 +      ),
 +      TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
 +                __entry->priv, __entry->time, __entry->data, __entry->ev)
 +);
 +
 +TRACE_EVENT(iwlwifi_dev_ucode_wrap_event,
 +      TP_PROTO(struct iwl_priv *priv, u32 wraps, u32 n_entry, u32 p_entry),
 +      TP_ARGS(priv, wraps, n_entry, p_entry),
 +      TP_STRUCT__entry(
 +              PRIV_ENTRY
 +
 +              __field(u32, wraps)
 +              __field(u32, n_entry)
 +              __field(u32, p_entry)
 +      ),
 +      TP_fast_assign(
 +              PRIV_ASSIGN;
 +              __entry->wraps = wraps;
 +              __entry->n_entry = n_entry;
 +              __entry->p_entry = p_entry;
 +      ),
 +      TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X",
 +                __entry->priv, __entry->wraps, __entry->n_entry,
 +                __entry->p_entry)
 +);
 +
  #undef TRACE_SYSTEM
  #define TRACE_SYSTEM iwlwifi
  
index fab41f507bd3a93af62e30563b82b0206ad0e586,a72f7c2577de93222b50395fac0249ccdd3d33de..57c646598062c28e3b04aeef970192b780cde530
@@@ -31,7 -31,7 +31,7 @@@ MODULE_LICENSE("GPL")
  MODULE_ALIAS("prism54pci");
  MODULE_FIRMWARE("isl3886pci");
  
 -static struct pci_device_id p54p_table[] __devinitdata = {
 +static DEFINE_PCI_DEVICE_TABLE(p54p_table) = {
        /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
        { PCI_DEVICE(0x1260, 0x3890) },
        /* 3COM 3CRWE154G72 Wireless LAN adapter */
@@@ -197,6 -197,14 +197,14 @@@ static void p54p_check_rx_ring(struct i
                        i %= ring_limit;
                        continue;
                }
+               if (unlikely(len > priv->common.rx_mtu)) {
+                       if (net_ratelimit())
+                               dev_err(&priv->pdev->dev, "rx'd frame size "
+                                       "exceeds length threshold.\n");
+                       len = priv->common.rx_mtu;
+               }
                skb_put(skb, len);
  
                if (p54_rx(dev, skb)) {
index 4daf1c94ec04ee5b5b48495d57e5d7563081faad,72d3e437e1905f674548099f6d9bf22dcb8d1bff..442fc1117326bbaefdb11975c7166d8cf8387987
@@@ -62,6 -62,7 +62,7 @@@ static struct usb_device_id usb_ids[] 
        { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 },
        /* ZD1211B */
        { USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0409, 0x0248), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x0411, 0x00da), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B },
@@@ -1078,15 -1079,11 +1079,15 @@@ static int eject_installer(struct usb_i
        int r;
  
        /* Find bulk out endpoint */
 -      endpoint = &iface_desc->endpoint[1].desc;
 -      if (usb_endpoint_dir_out(endpoint) &&
 -          usb_endpoint_xfer_bulk(endpoint)) {
 -              bulk_out_ep = endpoint->bEndpointAddress;
 -      } else {
 +      for (r = 1; r >= 0; r--) {
 +              endpoint = &iface_desc->endpoint[r].desc;
 +              if (usb_endpoint_dir_out(endpoint) &&
 +                  usb_endpoint_xfer_bulk(endpoint)) {
 +                      bulk_out_ep = endpoint->bEndpointAddress;
 +                      break;
 +              }
 +      }
 +      if (r == -1) {
                dev_err(&udev->dev,
                        "zd1211rw: Could not find bulk out endpoint\n");
                return -ENODEV;
diff --combined lib/vsprintf.c
index add0446dd921d824f174d975f2e62e0374a34f18,3b8aeec4e32762c3066f8ec633ec0baed99e746e..af4aaa6c36f36c924d9a63da70f84e2b3459fca1
@@@ -681,55 -681,24 +681,55 @@@ static char *mac_address_string(char *b
        char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
        char *p = mac_addr;
        int i;
 +      char separator;
 +
 +      if (fmt[1] == 'F') {            /* FDDI canonical format */
 +              separator = '-';
 +      } else {
 +              separator = ':';
 +      }
  
        for (i = 0; i < 6; i++) {
                p = pack_hex_byte(p, addr[i]);
                if (fmt[0] == 'M' && i != 5)
 -                      *p++ = ':';
 +                      *p++ = separator;
        }
        *p = '\0';
  
        return string(buf, end, mac_addr, spec);
  }
  
 -static char *ip4_string(char *p, const u8 *addr, bool leading_zeros)
 +static char *ip4_string(char *p, const u8 *addr, const char *fmt)
  {
        int i;
 -
 +      bool leading_zeros = (fmt[0] == 'i');
 +      int index;
 +      int step;
 +
 +      switch (fmt[2]) {
 +      case 'h':
 +#ifdef __BIG_ENDIAN
 +              index = 0;
 +              step = 1;
 +#else
 +              index = 3;
 +              step = -1;
 +#endif
 +              break;
 +      case 'l':
 +              index = 3;
 +              step = -1;
 +              break;
 +      case 'n':
 +      case 'b':
 +      default:
 +              index = 0;
 +              step = 1;
 +              break;
 +      }
        for (i = 0; i < 4; i++) {
                char temp[3];   /* hold each IP quad in reverse order */
 -              int digits = put_dec_trunc(temp, addr[i]) - temp;
 +              int digits = put_dec_trunc(temp, addr[index]) - temp;
                if (leading_zeros) {
                        if (digits < 3)
                                *p++ = '0';
                        *p++ = temp[digits];
                if (i < 3)
                        *p++ = '.';
 +              index += step;
        }
        *p = '\0';
  
@@@ -821,7 -789,7 +821,7 @@@ static char *ip6_compressed_string(cha
        if (useIPv4) {
                if (needcolon)
                        *p++ = ':';
 -              p = ip4_string(p, &in6.s6_addr[12], false);
 +              p = ip4_string(p, &in6.s6_addr[12], "I4");
        }
        *p = '\0';
  
@@@ -861,7 -829,7 +861,7 @@@ static char *ip4_addr_string(char *buf
  {
        char ip4_addr[sizeof("255.255.255.255")];
  
 -      ip4_string(ip4_addr, addr, fmt[0] == 'i');
 +      ip4_string(ip4_addr, addr, fmt);
  
        return string(buf, end, ip4_addr, spec);
  }
@@@ -928,17 -896,14 +928,17 @@@ static char *uuid_string(char *buf, cha
   * - 'M' For a 6-byte MAC address, it prints the address in the
   *       usual colon-separated hex notation
   * - 'm' For a 6-byte MAC address, it prints the hex address without colons
 + * - 'MF' For a 6-byte MAC FDDI address, it prints the address
 + *       with a dash-separated hex notation
   * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way
   *       IPv4 uses dot-separated decimal without leading 0's (1.2.3.4)
   *       IPv6 uses colon separated network-order 16 bit hex with leading 0's
   * - 'i' [46] for 'raw' IPv4/IPv6 addresses
   *       IPv6 omits the colons (01020304...0f)
   *       IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
 + * - '[Ii]4[hnbl]' IPv4 addresses in host, network, big or little endian order
   * - 'I6c' for IPv6 addresses printed as specified by
-  *       http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt
+  *       http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00
   * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form
   *       "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
   *       Options for %pU are:
@@@ -974,7 -939,6 +974,7 @@@ static char *pointer(const char *fmt, c
                return resource_string(buf, end, ptr, spec, fmt);
        case 'M':                       /* Colon separated: 00:01:02:03:04:05 */
        case 'm':                       /* Contiguous: 000102030405 */
 +                                      /* [mM]F (FDDI, bit reversed) */
                return mac_address_string(buf, end, ptr, spec, fmt);
        case 'I':                       /* Formatted IP supported
                                         * 4:   1.2.3.4
@@@ -1224,7 -1188,7 +1224,7 @@@ qualifier
   * %pI6 print an IPv6 address with colons
   * %pi6 print an IPv6 address without colons
   * %pI6c print an IPv6 address as specified by
-  *   http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt
+  *   http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00
   * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
   *   case.
   * %n is ignored
diff --combined net/ipv4/route.c
index 1cc339441e7d2698f8bd2eacce4b7ce0a9481437,d62b05d33384081b2a5e696f3e68f96967cf5595..b16dfadbe6d66946a736be5ca02a4c12c20dc3ab
@@@ -586,7 -586,9 +586,9 @@@ static void __net_exit ip_rt_do_proc_ex
  {
        remove_proc_entry("rt_cache", net->proc_net_stat);
        remove_proc_entry("rt_cache", net->proc_net);
+ #ifdef CONFIG_NET_CLS_ROUTE
        remove_proc_entry("rt_acct", net->proc_net);
+ #endif
  }
  
  static struct pernet_operations ip_rt_proc_ops __net_initdata =  {
@@@ -1988,13 -1990,8 +1990,13 @@@ static int __mkroute_input(struct sk_bu
        if (skb->protocol != htons(ETH_P_IP)) {
                /* Not IP (i.e. ARP). Do not create route, if it is
                 * invalid for proxy arp. DNAT routes are always valid.
 +               *
 +               * Proxy arp feature have been extended to allow, ARP
 +               * replies back to the same interface, to support
 +               * Private VLAN switch technologies. See arp.c.
                 */
 -              if (out_dev == in_dev) {
 +              if (out_dev == in_dev &&
 +                  IN_DEV_PROXY_ARP_PVLAN(in_dev) == 0) {
                        err = -EINVAL;
                        goto cleanup;
                }
diff --combined net/mac80211/cfg.c
index b0102c538b309c44138fe047460b88668706a60f,9ae1a4760b58b76ffa991031329b10e23cb51778..facf233843e0ed8dddd3577b6716ef15b1831a7c
@@@ -78,15 -78,17 +78,15 @@@ static int ieee80211_change_iface(struc
                                  enum nl80211_iftype type, u32 *flags,
                                  struct vif_params *params)
  {
 -      struct ieee80211_sub_if_data *sdata;
 +      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        int ret;
  
 -      if (netif_running(dev))
 +      if (ieee80211_sdata_running(sdata))
                return -EBUSY;
  
        if (!nl80211_params_check(type, params))
                return -EINVAL;
  
 -      sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 -
        ret = ieee80211_if_change_type(sdata, type);
        if (ret)
                return ret;
@@@ -148,7 -150,7 +148,7 @@@ static int ieee80211_add_key(struct wip
        rcu_read_lock();
  
        if (mac_addr) {
 -              sta = sta_info_get(sdata->local, mac_addr);
 +              sta = sta_info_get_bss(sdata, mac_addr);
                if (!sta) {
                        ieee80211_key_free(key);
                        err = -ENOENT;
@@@ -179,7 -181,7 +179,7 @@@ static int ieee80211_del_key(struct wip
        if (mac_addr) {
                ret = -ENOENT;
  
 -              sta = sta_info_get(sdata->local, mac_addr);
 +              sta = sta_info_get_bss(sdata, mac_addr);
                if (!sta)
                        goto out_unlock;
  
@@@ -226,7 -228,7 +226,7 @@@ static int ieee80211_get_key(struct wip
        rcu_read_lock();
  
        if (mac_addr) {
 -              sta = sta_info_get(sdata->local, mac_addr);
 +              sta = sta_info_get_bss(sdata, mac_addr);
                if (!sta)
                        goto out;
  
@@@ -413,13 -415,15 +413,13 @@@ static int ieee80211_dump_station(struc
  static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
                                 u8 *mac, struct station_info *sinfo)
  {
 -      struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 +      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct sta_info *sta;
        int ret = -ENOENT;
  
        rcu_read_lock();
  
 -      /* XXX: verify sta->dev == dev */
 -
 -      sta = sta_info_get(local, mac);
 +      sta = sta_info_get_bss(sdata, mac);
        if (sta) {
                ret = 0;
                sta_set_sinfo(sta, sinfo);
@@@ -728,7 -732,7 +728,7 @@@ static int ieee80211_add_station(struc
        } else
                sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  
 -      if (compare_ether_addr(mac, dev->dev_addr) == 0)
 +      if (compare_ether_addr(mac, sdata->vif.addr) == 0)
                return -EINVAL;
  
        if (is_multicast_ether_addr(mac))
@@@ -775,7 -779,8 +775,7 @@@ static int ieee80211_del_station(struc
        if (mac) {
                rcu_read_lock();
  
 -              /* XXX: get sta belonging to dev */
 -              sta = sta_info_get(local, mac);
 +              sta = sta_info_get_bss(sdata, mac);
                if (!sta) {
                        rcu_read_unlock();
                        return -ENOENT;
@@@ -796,14 -801,14 +796,14 @@@ static int ieee80211_change_station(str
                                    u8 *mac,
                                    struct station_parameters *params)
  {
 +      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = wiphy_priv(wiphy);
        struct sta_info *sta;
        struct ieee80211_sub_if_data *vlansdata;
  
        rcu_read_lock();
  
 -      /* XXX: get sta belonging to dev */
 -      sta = sta_info_get(local, mac);
 +      sta = sta_info_get_bss(sdata, mac);
        if (!sta) {
                rcu_read_unlock();
                return -ENOENT;
  static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
                                 u8 *dst, u8 *next_hop)
  {
 -      struct ieee80211_local *local = wiphy_priv(wiphy);
        struct ieee80211_sub_if_data *sdata;
        struct mesh_path *mpath;
        struct sta_info *sta;
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  
        rcu_read_lock();
 -      sta = sta_info_get(local, next_hop);
 +      sta = sta_info_get(sdata, next_hop);
        if (!sta) {
                rcu_read_unlock();
                return -ENOENT;
@@@ -889,6 -895,7 +889,6 @@@ static int ieee80211_change_mpath(struc
                                    struct net_device *dev,
                                    u8 *dst, u8 *next_hop)
  {
 -      struct ieee80211_local *local = wiphy_priv(wiphy);
        struct ieee80211_sub_if_data *sdata;
        struct mesh_path *mpath;
        struct sta_info *sta;
  
        rcu_read_lock();
  
 -      sta = sta_info_get(local, next_hop);
 +      sta = sta_info_get(sdata, next_hop);
        if (!sta) {
                rcu_read_unlock();
                return -ENOENT;
@@@ -1085,13 -1092,6 +1085,13 @@@ static int ieee80211_change_bss(struct 
                        params->use_short_preamble;
                changed |= BSS_CHANGED_ERP_PREAMBLE;
        }
 +
 +      if (!sdata->vif.bss_conf.use_short_slot &&
 +          sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) {
 +              sdata->vif.bss_conf.use_short_slot = true;
 +              changed |= BSS_CHANGED_ERP_SLOT;
 +      }
 +
        if (params->use_short_slot_time >= 0) {
                sdata->vif.bss_conf.use_short_slot =
                        params->use_short_slot_time;
@@@ -1135,13 -1135,6 +1135,13 @@@ static int ieee80211_set_txq_params(str
        p.cw_max = params->cwmax;
        p.cw_min = params->cwmin;
        p.txop = params->txop;
 +
 +      /*
 +       * Setting tx queue params disables u-apsd because it's only
 +       * called in master mode.
 +       */
 +      p.uapsd = false;
 +
        if (drv_conf_tx(local, params->queue, &p)) {
                printk(KERN_DEBUG "%s: failed to set TX queue "
                       "parameters for queue %d\n",
@@@ -1244,13 -1237,6 +1244,13 @@@ static int ieee80211_set_wiphy_params(s
        struct ieee80211_local *local = wiphy_priv(wiphy);
        int err;
  
 +      if (changed & WIPHY_PARAM_COVERAGE_CLASS) {
 +              err = drv_set_coverage_class(local, wiphy->coverage_class);
 +
 +              if (err)
 +                      return err;
 +      }
 +
        if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
                err = drv_set_rts_threshold(local, wiphy->rts_threshold);
  
@@@ -1338,50 -1324,6 +1338,50 @@@ static int ieee80211_testmode_cmd(struc
  }
  #endif
  
 +int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
 +                           enum ieee80211_smps_mode smps_mode)
 +{
 +      const u8 *ap;
 +      enum ieee80211_smps_mode old_req;
 +      int err;
 +
 +      old_req = sdata->u.mgd.req_smps;
 +      sdata->u.mgd.req_smps = smps_mode;
 +
 +      if (old_req == smps_mode &&
 +          smps_mode != IEEE80211_SMPS_AUTOMATIC)
 +              return 0;
 +
 +      /*
 +       * If not associated, or current association is not an HT
 +       * association, there's no need to send an action frame.
 +       */
 +      if (!sdata->u.mgd.associated ||
 +          sdata->local->oper_channel_type == NL80211_CHAN_NO_HT) {
 +              mutex_lock(&sdata->local->iflist_mtx);
 +              ieee80211_recalc_smps(sdata->local, sdata);
 +              mutex_unlock(&sdata->local->iflist_mtx);
 +              return 0;
 +      }
 +
 +      ap = sdata->u.mgd.associated->bssid;
 +
 +      if (smps_mode == IEEE80211_SMPS_AUTOMATIC) {
 +              if (sdata->u.mgd.powersave)
 +                      smps_mode = IEEE80211_SMPS_DYNAMIC;
 +              else
 +                      smps_mode = IEEE80211_SMPS_OFF;
 +      }
 +
 +      /* send SM PS frame to AP */
 +      err = ieee80211_send_smps_action(sdata, smps_mode,
 +                                       ap, ap);
 +      if (err)
 +              sdata->u.mgd.req_smps = old_req;
 +
 +      return err;
 +}
 +
  static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
                                    bool enabled, int timeout)
  {
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
        struct ieee80211_conf *conf = &local->hw.conf;
  
+       if (sdata->vif.type != NL80211_IFTYPE_STATION)
+               return -EOPNOTSUPP;
        if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
                return -EOPNOTSUPP;
  
        sdata->u.mgd.powersave = enabled;
        conf->dynamic_ps_timeout = timeout;
  
 +      /* no change, but if automatic follow powersave */
 +      mutex_lock(&sdata->u.mgd.mtx);
 +      __ieee80211_request_smps(sdata, sdata->u.mgd.req_smps);
 +      mutex_unlock(&sdata->u.mgd.mtx);
 +
        if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
                ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
  
@@@ -1419,43 -1359,39 +1422,43 @@@ static int ieee80211_set_bitrate_mask(s
  {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 -      int i, err = -EINVAL;
 -      u32 target_rate;
 -      struct ieee80211_supported_band *sband;
 +      int i;
  
 -      sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
 +      /*
 +       * This _could_ be supported by providing a hook for
 +       * drivers for this function, but at this point it
 +       * doesn't seem worth bothering.
 +       */
 +      if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)
 +              return -EOPNOTSUPP;
  
 -      /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
 -       * target_rate = X, rate->fixed = 1 means only rate X
 -       * target_rate = X, rate->fixed = 0 means all rates <= X */
 -      sdata->max_ratectrl_rateidx = -1;
 -      sdata->force_unicast_rateidx = -1;
  
 -      if (mask->fixed)
 -              target_rate = mask->fixed / 100;
 -      else if (mask->maxrate)
 -              target_rate = mask->maxrate / 100;
 -      else
 -              return 0;
 +      for (i = 0; i < IEEE80211_NUM_BANDS; i++)
 +              sdata->rc_rateidx_mask[i] = mask->control[i].legacy;
  
 -      for (i=0; i< sband->n_bitrates; i++) {
 -              struct ieee80211_rate *brate = &sband->bitrates[i];
 -              int this_rate = brate->bitrate;
 +      return 0;
 +}
  
 -              if (target_rate == this_rate) {
 -                      sdata->max_ratectrl_rateidx = i;
 -                      if (mask->fixed)
 -                              sdata->force_unicast_rateidx = i;
 -                      err = 0;
 -                      break;
 -              }
 -      }
 +static int ieee80211_remain_on_channel(struct wiphy *wiphy,
 +                                     struct net_device *dev,
 +                                     struct ieee80211_channel *chan,
 +                                     enum nl80211_channel_type channel_type,
 +                                     unsigned int duration,
 +                                     u64 *cookie)
 +{
 +      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  
 -      return err;
 +      return ieee80211_wk_remain_on_channel(sdata, chan, channel_type,
 +                                            duration, cookie);
 +}
 +
 +static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
 +                                            struct net_device *dev,
 +                                            u64 cookie)
 +{
 +      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 +
 +      return ieee80211_wk_cancel_remain_on_channel(sdata, cookie);
  }
  
  struct cfg80211_ops mac80211_config_ops = {
        CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
        .set_power_mgmt = ieee80211_set_power_mgmt,
        .set_bitrate_mask = ieee80211_set_bitrate_mask,
 +      .remain_on_channel = ieee80211_remain_on_channel,
 +      .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel,
  };
diff --combined net/mac80211/iface.c
index fe140bf033f9d9a95235c2e4daf953afac3072d7,32abae3ce32a52a4b126a8a26368b327d0771a21..edf21cebeee8984b5b5f1852520fea2065a51e21
@@@ -62,23 -62,6 +62,23 @@@ static int ieee80211_change_mtu(struct 
        return 0;
  }
  
 +static int ieee80211_change_mac(struct net_device *dev, void *addr)
 +{
 +      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 +      struct sockaddr *sa = addr;
 +      int ret;
 +
 +      if (ieee80211_sdata_running(sdata))
 +              return -EBUSY;
 +
 +      ret = eth_mac_addr(dev, sa);
 +
 +      if (ret == 0)
 +              memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
 +
 +      return ret;
 +}
 +
  static inline int identical_mac_addr_allowed(int type1, int type2)
  {
        return type1 == NL80211_IFTYPE_MONITOR ||
@@@ -99,6 -82,7 +99,6 @@@ static int ieee80211_open(struct net_de
        struct ieee80211_sub_if_data *nsdata;
        struct ieee80211_local *local = sdata->local;
        struct sta_info *sta;
 -      struct ieee80211_if_init_conf conf;
        u32 changed = 0;
        int res;
        u32 hw_reconf_flags = 0;
        list_for_each_entry(nsdata, &local->interfaces, list) {
                struct net_device *ndev = nsdata->dev;
  
 -              if (ndev != dev && netif_running(ndev)) {
 +              if (ndev != dev && ieee80211_sdata_running(nsdata)) {
                        /*
                         * Allow only a single IBSS interface to be up at any
                         * time. This is restricted because beacon distribution
                struct net_device *ndev = nsdata->dev;
  
                /*
 -               * No need to check netif_running since we do not allow
 +               * No need to check running since we do not allow
                 * it to start up with this invalid address.
                 */
                if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) {
                ieee80211_configure_filter(local);
                break;
        default:
 -              conf.vif = &sdata->vif;
 -              conf.type = sdata->vif.type;
 -              conf.mac_addr = dev->dev_addr;
 -              res = drv_add_interface(local, &conf);
 +              res = drv_add_interface(local, &sdata->vif);
                if (res)
                        goto err_stop;
  
  
        return 0;
   err_del_interface:
 -      drv_remove_interface(local, &conf);
 +      drv_remove_interface(local, &sdata->vif);
   err_stop:
        if (!local->open_count)
                drv_stop(local);
@@@ -348,6 -335,7 +348,6 @@@ static int ieee80211_stop(struct net_de
  {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
 -      struct ieee80211_if_init_conf conf;
        struct sta_info *sta;
        unsigned long flags;
        struct sk_buff *skb, *tmp;
         */
        netif_tx_stop_all_queues(dev);
  
 +      /*
 +       * Purge work for this interface.
 +       */
 +      ieee80211_work_purge(sdata);
 +
        /*
         * Now delete all active aggregation sessions.
         */
                                BSS_CHANGED_BEACON_ENABLED);
                }
  
 -              conf.vif = &sdata->vif;
 -              conf.type = sdata->vif.type;
 -              conf.mac_addr = dev->dev_addr;
                /* disable all keys for as long as this netdev is down */
                ieee80211_disable_keys(sdata);
 -              drv_remove_interface(local, &conf);
 +              drv_remove_interface(local, &sdata->vif);
        }
  
        sdata->bss = NULL;
@@@ -673,7 -659,7 +673,7 @@@ static const struct net_device_ops ieee
        .ndo_start_xmit         = ieee80211_subif_start_xmit,
        .ndo_set_multicast_list = ieee80211_set_multicast_list,
        .ndo_change_mtu         = ieee80211_change_mtu,
 -      .ndo_set_mac_address    = eth_mac_addr,
 +      .ndo_set_mac_address    = ieee80211_change_mac,
        .ndo_select_queue       = ieee80211_netdev_select_queue,
  };
  
@@@ -684,21 -670,25 +684,25 @@@ static u16 ieee80211_monitor_select_que
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_hdr *hdr;
        struct ieee80211_radiotap_header *rtap = (void *)skb->data;
+       u8 *p;
  
        if (local->hw.queues < 4)
                return 0;
  
        if (skb->len < 4 ||
-           skb->len < rtap->it_len + 2 /* frame control */)
+           skb->len < le16_to_cpu(rtap->it_len) + 2 /* frame control */)
                return 0; /* doesn't matter, frame will be dropped */
  
-       hdr = (void *)((u8 *)skb->data + rtap->it_len);
+       hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
  
-       if (!ieee80211_is_data(hdr->frame_control)) {
+       if (!ieee80211_is_data_qos(hdr->frame_control)) {
                skb->priority = 7;
                return ieee802_1d_to_ac[skb->priority];
        }
  
+       p = ieee80211_get_qos_ctl(hdr);
+       skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
        return ieee80211_downgrade_queue(local, skb);
  }
  
@@@ -789,7 -779,7 +793,7 @@@ int ieee80211_if_change_type(struct iee
         * and goes into the requested mode.
         */
  
 -      if (netif_running(sdata->dev))
 +      if (ieee80211_sdata_running(sdata))
                return -EBUSY;
  
        /* Purge and reset type-dependent state. */
@@@ -843,8 -833,6 +847,8 @@@ int ieee80211_if_add(struct ieee80211_l
        /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */
        sdata = netdev_priv(ndev);
        ndev->ieee80211_ptr = &sdata->wdev;
 +      memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN);
 +      memcpy(sdata->name, ndev->name, IFNAMSIZ);
  
        /* initialise type-independent data */
        sdata->wdev.wiphy = local->hw.wiphy;
  
        INIT_LIST_HEAD(&sdata->key_list);
  
 -      sdata->force_unicast_rateidx = -1;
 -      sdata->max_ratectrl_rateidx = -1;
 +      for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
 +              struct ieee80211_supported_band *sband;
 +              sband = local->hw.wiphy->bands[i];
 +              sdata->rc_rateidx_mask[i] =
 +                      sband ? (1 << sband->n_bitrates) - 1 : 0;
 +      }
  
        /* setup type-dependent data */
        ieee80211_setup_sdata(sdata, type);
@@@ -954,8 -938,6 +958,8 @@@ static u32 ieee80211_idle_on(struct iee
               wiphy_name(local->hw.wiphy));
  #endif
  
 +      drv_flush(local, false);
 +
        local->hw.conf.flags |= IEEE80211_CONF_IDLE;
        return IEEE80211_CONF_CHANGE_IDLE;
  }
@@@ -965,18 -947,16 +969,18 @@@ u32 __ieee80211_recalc_idle(struct ieee
        struct ieee80211_sub_if_data *sdata;
        int count = 0;
  
 +      if (!list_empty(&local->work_list))
 +              return ieee80211_idle_off(local, "working");
 +
        if (local->scanning)
                return ieee80211_idle_off(local, "scanning");
  
        list_for_each_entry(sdata, &local->interfaces, list) {
 -              if (!netif_running(sdata->dev))
 +              if (!ieee80211_sdata_running(sdata))
                        continue;
                /* do not count disabled managed interfaces */
                if (sdata->vif.type == NL80211_IFTYPE_STATION &&
 -                  !sdata->u.mgd.associated &&
 -                  list_empty(&sdata->u.mgd.work_list))
 +                  !sdata->u.mgd.associated)
                        continue;
                /* do not count unused IBSS interfaces */
                if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
@@@ -1004,41 -984,3 +1008,41 @@@ void ieee80211_recalc_idle(struct ieee8
        if (chg)
                ieee80211_hw_config(local, chg);
  }
 +
 +static int netdev_notify(struct notifier_block *nb,
 +                       unsigned long state,
 +                       void *ndev)
 +{
 +      struct net_device *dev = ndev;
 +      struct ieee80211_sub_if_data *sdata;
 +
 +      if (state != NETDEV_CHANGENAME)
 +              return 0;
 +
 +      if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
 +              return 0;
 +
 +      if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
 +              return 0;
 +
 +      sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 +
 +      memcpy(sdata->name, sdata->name, IFNAMSIZ);
 +
 +      ieee80211_debugfs_rename_netdev(sdata);
 +      return 0;
 +}
 +
 +static struct notifier_block mac80211_netdev_notifier = {
 +      .notifier_call = netdev_notify,
 +};
 +
 +int ieee80211_iface_init(void)
 +{
 +      return register_netdevice_notifier(&mac80211_netdev_notifier);
 +}
 +
 +void ieee80211_iface_exit(void)
 +{
 +      unregister_netdevice_notifier(&mac80211_netdev_notifier);
 +}
diff --combined net/mac80211/mlme.c
index a82564e73d91799d973b3b3a68c19d8ec5ac1d58,05a18f43e1bf73fd34f029b1e35aa0a0193f7162..1e1d16c55ee57be5e9c4366d7c8094454e943e5d
@@@ -75,8 -75,11 +75,8 @@@ enum rx_mgmt_action 
        /* caller must call cfg80211_send_disassoc() */
        RX_MGMT_CFG80211_DISASSOC,
  
 -      /* caller must call cfg80211_auth_timeout() & free work */
 -      RX_MGMT_CFG80211_AUTH_TO,
 -
 -      /* caller must call cfg80211_assoc_timeout() & free work */
 -      RX_MGMT_CFG80211_ASSOC_TO,
 +      /* caller must tell cfg80211 about internal error */
 +      RX_MGMT_CFG80211_ASSOC_ERROR,
  };
  
  /* utils */
@@@ -119,6 -122,27 +119,6 @@@ static int ecw2cw(int ecw
        return (1 << ecw) - 1;
  }
  
 -static int ieee80211_compatible_rates(struct ieee80211_bss *bss,
 -                                    struct ieee80211_supported_band *sband,
 -                                    u32 *rates)
 -{
 -      int i, j, count;
 -      *rates = 0;
 -      count = 0;
 -      for (i = 0; i < bss->supp_rates_len; i++) {
 -              int rate = (bss->supp_rates[i] & 0x7F) * 5;
 -
 -              for (j = 0; j < sband->n_bitrates; j++)
 -                      if (sband->bitrates[j].bitrate == rate) {
 -                              *rates |= BIT(j);
 -                              count++;
 -                              break;
 -                      }
 -      }
 -
 -      return count;
 -}
 -
  /*
   * ieee80211_enable_ht should be called only after the operating band
   * has been determined as ht configuration depends on the hw's
@@@ -178,7 -202,7 +178,7 @@@ static u32 ieee80211_enable_ht(struct i
                ieee80211_hw_config(local, 0);
  
                rcu_read_lock();
 -              sta = sta_info_get(local, bssid);
 +              sta = sta_info_get(sdata, bssid);
                if (sta)
                        rate_control_rate_update(local, sband, sta,
                                                 IEEE80211_RC_HT_CHANGED);
  
  /* frame sending functions */
  
 -static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
 -                               struct ieee80211_mgd_work *wk)
 -{
 -      struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 -      struct ieee80211_local *local = sdata->local;
 -      struct sk_buff *skb;
 -      struct ieee80211_mgmt *mgmt;
 -      u8 *pos;
 -      const u8 *ies, *ht_ie;
 -      int i, len, count, rates_len, supp_rates_len;
 -      u16 capab;
 -      int wmm = 0;
 -      struct ieee80211_supported_band *sband;
 -      u32 rates = 0;
 -
 -      skb = dev_alloc_skb(local->hw.extra_tx_headroom +
 -                          sizeof(*mgmt) + 200 + wk->ie_len +
 -                          wk->ssid_len);
 -      if (!skb) {
 -              printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
 -                     "frame\n", sdata->dev->name);
 -              return;
 -      }
 -      skb_reserve(skb, local->hw.extra_tx_headroom);
 -
 -      sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
 -
 -      capab = ifmgd->capab;
 -
 -      if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) {
 -              if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
 -                      capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
 -              if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
 -                      capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
 -      }
 -
 -      if (wk->bss->cbss.capability & WLAN_CAPABILITY_PRIVACY)
 -              capab |= WLAN_CAPABILITY_PRIVACY;
 -      if (wk->bss->wmm_used)
 -              wmm = 1;
 -
 -      /* get all rates supported by the device and the AP as
 -       * some APs don't like getting a superset of their rates
 -       * in the association request (e.g. D-Link DAP 1353 in
 -       * b-only mode) */
 -      rates_len = ieee80211_compatible_rates(wk->bss, sband, &rates);
 -
 -      if ((wk->bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
 -          (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
 -              capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
 -
 -      mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
 -      memset(mgmt, 0, 24);
 -      memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN);
 -      memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
 -      memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN);
 -
 -      if (!is_zero_ether_addr(wk->prev_bssid)) {
 -              skb_put(skb, 10);
 -              mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 -                                                IEEE80211_STYPE_REASSOC_REQ);
 -              mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
 -              mgmt->u.reassoc_req.listen_interval =
 -                              cpu_to_le16(local->hw.conf.listen_interval);
 -              memcpy(mgmt->u.reassoc_req.current_ap, wk->prev_bssid,
 -                     ETH_ALEN);
 -      } else {
 -              skb_put(skb, 4);
 -              mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 -                                                IEEE80211_STYPE_ASSOC_REQ);
 -              mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
 -              mgmt->u.assoc_req.listen_interval =
 -                              cpu_to_le16(local->hw.conf.listen_interval);
 -      }
 -
 -      /* SSID */
 -      ies = pos = skb_put(skb, 2 + wk->ssid_len);
 -      *pos++ = WLAN_EID_SSID;
 -      *pos++ = wk->ssid_len;
 -      memcpy(pos, wk->ssid, wk->ssid_len);
 -
 -      /* add all rates which were marked to be used above */
 -      supp_rates_len = rates_len;
 -      if (supp_rates_len > 8)
 -              supp_rates_len = 8;
 -
 -      len = sband->n_bitrates;
 -      pos = skb_put(skb, supp_rates_len + 2);
 -      *pos++ = WLAN_EID_SUPP_RATES;
 -      *pos++ = supp_rates_len;
 -
 -      count = 0;
 -      for (i = 0; i < sband->n_bitrates; i++) {
 -              if (BIT(i) & rates) {
 -                      int rate = sband->bitrates[i].bitrate;
 -                      *pos++ = (u8) (rate / 5);
 -                      if (++count == 8)
 -                              break;
 -              }
 -      }
 -
 -      if (rates_len > count) {
 -              pos = skb_put(skb, rates_len - count + 2);
 -              *pos++ = WLAN_EID_EXT_SUPP_RATES;
 -              *pos++ = rates_len - count;
 -
 -              for (i++; i < sband->n_bitrates; i++) {
 -                      if (BIT(i) & rates) {
 -                              int rate = sband->bitrates[i].bitrate;
 -                              *pos++ = (u8) (rate / 5);
 -                      }
 -              }
 -      }
 -
 -      if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) {
 -              /* 1. power capabilities */
 -              pos = skb_put(skb, 4);
 -              *pos++ = WLAN_EID_PWR_CAPABILITY;
 -              *pos++ = 2;
 -              *pos++ = 0; /* min tx power */
 -              *pos++ = local->hw.conf.channel->max_power; /* max tx power */
 -
 -              /* 2. supported channels */
 -              /* TODO: get this in reg domain format */
 -              pos = skb_put(skb, 2 * sband->n_channels + 2);
 -              *pos++ = WLAN_EID_SUPPORTED_CHANNELS;
 -              *pos++ = 2 * sband->n_channels;
 -              for (i = 0; i < sband->n_channels; i++) {
 -                      *pos++ = ieee80211_frequency_to_channel(
 -                                      sband->channels[i].center_freq);
 -                      *pos++ = 1; /* one channel in the subband*/
 -              }
 -      }
 -
 -      if (wk->ie_len && wk->ie) {
 -              pos = skb_put(skb, wk->ie_len);
 -              memcpy(pos, wk->ie, wk->ie_len);
 -      }
 -
 -      if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) {
 -              pos = skb_put(skb, 9);
 -              *pos++ = WLAN_EID_VENDOR_SPECIFIC;
 -              *pos++ = 7; /* len */
 -              *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
 -              *pos++ = 0x50;
 -              *pos++ = 0xf2;
 -              *pos++ = 2; /* WME */
 -              *pos++ = 0; /* WME info */
 -              *pos++ = 1; /* WME ver */
 -              *pos++ = 0;
 -      }
 -
 -      /* wmm support is a must to HT */
 -      /*
 -       * IEEE802.11n does not allow TKIP/WEP as pairwise
 -       * ciphers in HT mode. We still associate in non-ht
 -       * mode (11a/b/g) if any one of these ciphers is
 -       * configured as pairwise.
 -       */
 -      if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
 -          sband->ht_cap.ht_supported &&
 -          (ht_ie = ieee80211_bss_get_ie(&wk->bss->cbss, WLAN_EID_HT_INFORMATION)) &&
 -          ht_ie[1] >= sizeof(struct ieee80211_ht_info) &&
 -          (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))) {
 -              struct ieee80211_ht_info *ht_info =
 -                      (struct ieee80211_ht_info *)(ht_ie + 2);
 -              u16 cap = sband->ht_cap.cap;
 -              __le16 tmp;
 -              u32 flags = local->hw.conf.channel->flags;
 -
 -              switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
 -              case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
 -                      if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
 -                              cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
 -                              cap &= ~IEEE80211_HT_CAP_SGI_40;
 -                      }
 -                      break;
 -              case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
 -                      if (flags & IEEE80211_CHAN_NO_HT40MINUS) {
 -                              cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
 -                              cap &= ~IEEE80211_HT_CAP_SGI_40;
 -                      }
 -                      break;
 -              }
 -
 -              tmp = cpu_to_le16(cap);
 -              pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2);
 -              *pos++ = WLAN_EID_HT_CAPABILITY;
 -              *pos++ = sizeof(struct ieee80211_ht_cap);
 -              memset(pos, 0, sizeof(struct ieee80211_ht_cap));
 -              memcpy(pos, &tmp, sizeof(u16));
 -              pos += sizeof(u16);
 -              /* TODO: needs a define here for << 2 */
 -              *pos++ = sband->ht_cap.ampdu_factor |
 -                       (sband->ht_cap.ampdu_density << 2);
 -              memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
 -      }
 -
 -      IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
 -      ieee80211_tx_skb(sdata, skb);
 -}
 -
 -
  static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
                                           const u8 *bssid, u16 stype, u16 reason,
                                           void *cookie)
        skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
        if (!skb) {
                printk(KERN_DEBUG "%s: failed to allocate buffer for "
 -                     "deauth/disassoc frame\n", sdata->dev->name);
 +                     "deauth/disassoc frame\n", sdata->name);
                return;
        }
        skb_reserve(skb, local->hw.extra_tx_headroom);
        mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
        memset(mgmt, 0, 24);
        memcpy(mgmt->da, bssid, ETH_ALEN);
 -      memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
 +      memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
        memcpy(mgmt->bssid, bssid, ETH_ALEN);
        mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
        skb_put(skb, 2);
  void ieee80211_send_pspoll(struct ieee80211_local *local,
                           struct ieee80211_sub_if_data *sdata)
  {
 -      struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct ieee80211_pspoll *pspoll;
        struct sk_buff *skb;
 -      u16 fc;
  
 -      skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll));
 -      if (!skb) {
 -              printk(KERN_DEBUG "%s: failed to allocate buffer for "
 -                     "pspoll frame\n", sdata->dev->name);
 +      skb = ieee80211_pspoll_get(&local->hw, &sdata->vif);
 +      if (!skb)
                return;
 -      }
 -      skb_reserve(skb, local->hw.extra_tx_headroom);
  
 -      pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll));
 -      memset(pspoll, 0, sizeof(*pspoll));
 -      fc = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL | IEEE80211_FCTL_PM;
 -      pspoll->frame_control = cpu_to_le16(fc);
 -      pspoll->aid = cpu_to_le16(ifmgd->aid);
 -
 -      /* aid in PS-Poll has its two MSBs each set to 1 */
 -      pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14);
 -
 -      memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN);
 -      memcpy(pspoll->ta, sdata->dev->dev_addr, ETH_ALEN);
 +      pspoll = (struct ieee80211_pspoll *) skb->data;
 +      pspoll->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
  
        IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
        ieee80211_tx_skb(sdata, skb);
  void ieee80211_send_nullfunc(struct ieee80211_local *local,
                             struct ieee80211_sub_if_data *sdata,
                             int powersave)
 +{
 +      struct sk_buff *skb;
 +      struct ieee80211_hdr_3addr *nullfunc;
 +
 +      skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif);
 +      if (!skb)
 +              return;
 +
 +      nullfunc = (struct ieee80211_hdr_3addr *) skb->data;
 +      if (powersave)
 +              nullfunc->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
 +
 +      IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
 +      ieee80211_tx_skb(sdata, skb);
 +}
 +
 +static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
 +                                        struct ieee80211_sub_if_data *sdata)
  {
        struct sk_buff *skb;
        struct ieee80211_hdr *nullfunc;
        if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
                return;
  
 -      skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24);
 +      skb = dev_alloc_skb(local->hw.extra_tx_headroom + 30);
        if (!skb) {
 -              printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
 -                     "frame\n", sdata->dev->name);
 +              printk(KERN_DEBUG "%s: failed to allocate buffer for 4addr "
 +                     "nullfunc frame\n", sdata->name);
                return;
        }
        skb_reserve(skb, local->hw.extra_tx_headroom);
  
 -      nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24);
 -      memset(nullfunc, 0, 24);
 +      nullfunc = (struct ieee80211_hdr *) skb_put(skb, 30);
 +      memset(nullfunc, 0, 30);
        fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
 -                       IEEE80211_FCTL_TODS);
 -      if (powersave)
 -              fc |= cpu_to_le16(IEEE80211_FCTL_PM);
 +                       IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
        nullfunc->frame_control = fc;
        memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN);
 -      memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN);
 +      memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
        memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN);
 +      memcpy(nullfunc->addr4, sdata->vif.addr, ETH_ALEN);
  
        IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
        ieee80211_tx_skb(sdata, skb);
@@@ -321,7 -546,7 +321,7 @@@ static void ieee80211_chswitch_work(str
                container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work);
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
  
 -      if (!netif_running(sdata->dev))
 +      if (!ieee80211_sdata_running(sdata))
                return;
  
        mutex_lock(&ifmgd->mtx);
        ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL);
  
        /* XXX: shouldn't really modify cfg80211-owned data! */
 -      ifmgd->associated->cbss.channel = sdata->local->oper_channel;
 +      ifmgd->associated->channel = sdata->local->oper_channel;
  
        ieee80211_wake_queues_by_reason(&sdata->local->hw,
                                        IEEE80211_QUEUE_STOP_REASON_CSA);
@@@ -359,8 -584,6 +359,8 @@@ void ieee80211_sta_process_chanswitch(s
                                      struct ieee80211_channel_sw_ie *sw_elem,
                                      struct ieee80211_bss *bss)
  {
 +      struct cfg80211_bss *cbss =
 +              container_of((void *)bss, struct cfg80211_bss, priv);
        struct ieee80211_channel *new_ch;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num);
                mod_timer(&ifmgd->chswitch_timer,
                          jiffies +
                          msecs_to_jiffies(sw_elem->count *
 -                                         bss->cbss.beacon_interval));
 +                                         cbss->beacon_interval));
        }
  }
  
@@@ -468,13 -691,8 +468,13 @@@ void ieee80211_recalc_ps(struct ieee802
                return;
        }
  
 +      if (!list_empty(&local->work_list)) {
 +              local->ps_sdata = NULL;
 +              goto change;
 +      }
 +
        list_for_each_entry(sdata, &local->interfaces, list) {
 -              if (!netif_running(sdata->dev))
 +              if (!ieee80211_sdata_running(sdata))
                        continue;
                if (sdata->vif.type != NL80211_IFTYPE_STATION)
                        continue;
        }
  
        if (count == 1 && found->u.mgd.powersave &&
 -          found->u.mgd.associated && list_empty(&found->u.mgd.work_list) &&
 +          found->u.mgd.associated &&
            !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL |
                                    IEEE80211_STA_CONNECTION_POLL))) {
                s32 beaconint_us;
                local->ps_sdata = NULL;
        }
  
 + change:
        ieee80211_change_ps(local);
  }
  
@@@ -569,9 -786,9 +569,9 @@@ static void ieee80211_sta_wmm_params(st
        struct ieee80211_tx_queue_params params;
        size_t left;
        int count;
 -      u8 *pos;
 +      u8 *pos, uapsd_queues = 0;
  
 -      if (!(ifmgd->flags & IEEE80211_STA_WMM_ENABLED))
 +      if (local->hw.queues < 4)
                return;
  
        if (!wmm_param)
  
        if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
                return;
 +
 +      if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED)
 +              uapsd_queues = local->uapsd_queues;
 +
        count = wmm_param[6] & 0x0f;
        if (count == ifmgd->wmm_last_param_set)
                return;
        for (; left >= 4; left -= 4, pos += 4) {
                int aci = (pos[0] >> 5) & 0x03;
                int acm = (pos[0] >> 4) & 0x01;
 +              bool uapsd = false;
                int queue;
  
                switch (aci) {
                        queue = 3;
                        if (acm)
                                local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */
 +                      if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
 +                              uapsd = true;
                        break;
                case 2: /* AC_VI */
                        queue = 1;
                        if (acm)
                                local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
 +                      if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
 +                              uapsd = true;
                        break;
                case 3: /* AC_VO */
                        queue = 0;
                        if (acm)
                                local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
 +                      if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
 +                              uapsd = true;
                        break;
                case 0: /* AC_BE */
                default:
                        queue = 2;
                        if (acm)
                                local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
 +                      if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
 +                              uapsd = true;
                        break;
                }
  
                params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
                params.cw_min = ecw2cw(pos[1] & 0x0f);
                params.txop = get_unaligned_le16(pos + 2);
 +              params.uapsd = uapsd;
 +
  #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
                printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
 -                     "cWmin=%d cWmax=%d txop=%d\n",
 +                     "cWmin=%d cWmax=%d txop=%d uapsd=%d\n",
                       wiphy_name(local->hw.wiphy), queue, aci, acm,
 -                     params.aifs, params.cw_min, params.cw_max, params.txop);
 +                     params.aifs, params.cw_min, params.cw_max, params.txop,
 +                     params.uapsd);
  #endif
                if (drv_conf_tx(local, queue, &params) && local->ops->conf_tx)
                        printk(KERN_DEBUG "%s: failed to set TX queue "
@@@ -670,8 -871,6 +670,8 @@@ static u32 ieee80211_handle_bss_capabil
        }
  
        use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME);
 +      if (sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
 +              use_short_slot = true;
  
        if (use_protection != bss_conf->use_cts_prot) {
                bss_conf->use_cts_prot = use_protection;
  }
  
  static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
 -                                   struct ieee80211_mgd_work *wk,
 +                                   struct cfg80211_bss *cbss,
                                     u32 bss_info_changed)
  {
 +      struct ieee80211_bss *bss = (void *)cbss->priv;
        struct ieee80211_local *local = sdata->local;
 -      struct ieee80211_bss *bss = wk->bss;
  
        bss_info_changed |= BSS_CHANGED_ASSOC;
        /* set timing information */
 -      sdata->vif.bss_conf.beacon_int = bss->cbss.beacon_interval;
 -      sdata->vif.bss_conf.timestamp = bss->cbss.tsf;
 +      sdata->vif.bss_conf.beacon_int = cbss->beacon_interval;
 +      sdata->vif.bss_conf.timestamp = cbss->tsf;
        sdata->vif.bss_conf.dtim_period = bss->dtim_period;
  
        bss_info_changed |= BSS_CHANGED_BEACON_INT;
        bss_info_changed |= ieee80211_handle_bss_capability(sdata,
 -              bss->cbss.capability, bss->has_erp_value, bss->erp_value);
 +              cbss->capability, bss->has_erp_value, bss->erp_value);
  
 -      sdata->u.mgd.associated = bss;
 -      sdata->u.mgd.old_associate_work = wk;
 -      memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN);
 +      sdata->u.mgd.associated = cbss;
 +      memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN);
  
        /* just to be sure */
        sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL |
  
        mutex_lock(&local->iflist_mtx);
        ieee80211_recalc_ps(local, -1);
 +      ieee80211_recalc_smps(local, sdata);
        mutex_unlock(&local->iflist_mtx);
  
        netif_tx_start_all_queues(sdata->dev);
        netif_carrier_on(sdata->dev);
  }
  
 -static enum rx_mgmt_action __must_check
 -ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
 -                     struct ieee80211_mgd_work *wk)
 -{
 -      struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 -      struct ieee80211_local *local = sdata->local;
 -
 -      wk->tries++;
 -      if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
 -              printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n",
 -                     sdata->dev->name, wk->bss->cbss.bssid);
 -
 -              /*
 -               * Most likely AP is not in the range so remove the
 -               * bss struct for that AP.
 -               */
 -              cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss);
 -
 -              /*
 -               * We might have a pending scan which had no chance to run yet
 -               * due to work needing to be done. Hence, queue the STAs work
 -               * again for that.
 -               */
 -              ieee80211_queue_work(&local->hw, &ifmgd->work);
 -              return RX_MGMT_CFG80211_AUTH_TO;
 -      }
 -
 -      printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n",
 -                      sdata->dev->name, wk->bss->cbss.bssid,
 -                      wk->tries);
 -
 -      /*
 -       * Direct probe is sent to broadcast address as some APs
 -       * will not answer to direct packet in unassociated state.
 -       */
 -      ieee80211_send_probe_req(sdata, NULL, wk->ssid, wk->ssid_len, NULL, 0);
 -
 -      wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
 -      run_again(ifmgd, wk->timeout);
 -
 -      return RX_MGMT_NONE;
 -}
 -
 -
 -static enum rx_mgmt_action __must_check
 -ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
 -                     struct ieee80211_mgd_work *wk)
 -{
 -      struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 -      struct ieee80211_local *local = sdata->local;
 -
 -      wk->tries++;
 -      if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
 -              printk(KERN_DEBUG "%s: authentication with AP %pM"
 -                     " timed out\n",
 -                     sdata->dev->name, wk->bss->cbss.bssid);
 -
 -              /*
 -               * Most likely AP is not in the range so remove the
 -               * bss struct for that AP.
 -               */
 -              cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss);
 -
 -              /*
 -               * We might have a pending scan which had no chance to run yet
 -               * due to work needing to be done. Hence, queue the STAs work
 -               * again for that.
 -               */
 -              ieee80211_queue_work(&local->hw, &ifmgd->work);
 -              return RX_MGMT_CFG80211_AUTH_TO;
 -      }
 -
 -      printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n",
 -             sdata->dev->name, wk->bss->cbss.bssid, wk->tries);
 -
 -      ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len,
 -                          wk->bss->cbss.bssid, NULL, 0, 0);
 -      wk->auth_transaction = 2;
 -
 -      wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
 -      run_again(ifmgd, wk->timeout);
 -
 -      return RX_MGMT_NONE;
 -}
 -
 -static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 -                                 bool deauth)
 +static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata)
  {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct ieee80211_local *local = sdata->local;
        if (WARN_ON(!ifmgd->associated))
                return;
  
 -      memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN);
 +      memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
  
        ifmgd->associated = NULL;
        memset(ifmgd->bssid, 0, ETH_ALEN);
  
 -      if (deauth) {
 -              kfree(ifmgd->old_associate_work);
 -              ifmgd->old_associate_work = NULL;
 -      } else {
 -              struct ieee80211_mgd_work *wk = ifmgd->old_associate_work;
 -
 -              wk->state = IEEE80211_MGD_STATE_IDLE;
 -              list_add(&wk->list, &ifmgd->work_list);
 -      }
 -
        /*
         * we need to commit the associated = NULL change because the
         * scan code uses that to determine whether this iface should
        netif_carrier_off(sdata->dev);
  
        rcu_read_lock();
 -      sta = sta_info_get(local, bssid);
 +      sta = sta_info_get(sdata, bssid);
        if (sta)
                ieee80211_sta_tear_down_BA_sessions(sta);
        rcu_read_unlock();
  
        rcu_read_lock();
  
 -      sta = sta_info_get(local, bssid);
 +      sta = sta_info_get(sdata, bssid);
        if (!sta) {
                rcu_read_unlock();
                return;
        sta_info_destroy(sta);
  }
  
 -static enum rx_mgmt_action __must_check
 -ieee80211_associate(struct ieee80211_sub_if_data *sdata,
 -                  struct ieee80211_mgd_work *wk)
 -{
 -      struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 -      struct ieee80211_local *local = sdata->local;
 -
 -      wk->tries++;
 -      if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) {
 -              printk(KERN_DEBUG "%s: association with AP %pM"
 -                     " timed out\n",
 -                     sdata->dev->name, wk->bss->cbss.bssid);
 -
 -              /*
 -               * Most likely AP is not in the range so remove the
 -               * bss struct for that AP.
 -               */
 -              cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss);
 -
 -              /*
 -               * We might have a pending scan which had no chance to run yet
 -               * due to work needing to be done. Hence, queue the STAs work
 -               * again for that.
 -               */
 -              ieee80211_queue_work(&local->hw, &ifmgd->work);
 -              return RX_MGMT_CFG80211_ASSOC_TO;
 -      }
 -
 -      printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n",
 -             sdata->dev->name, wk->bss->cbss.bssid, wk->tries);
 -      ieee80211_send_assoc(sdata, wk);
 -
 -      wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
 -      run_again(ifmgd, wk->timeout);
 -
 -      return RX_MGMT_NONE;
 -}
 -
  void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
                             struct ieee80211_hdr *hdr)
  {
@@@ -856,8 -1189,8 +856,8 @@@ static void ieee80211_mgd_probe_ap_send
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        const u8 *ssid;
  
 -      ssid = ieee80211_bss_get_ie(&ifmgd->associated->cbss, WLAN_EID_SSID);
 -      ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid,
 +      ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
 +      ieee80211_send_probe_req(sdata, ifmgd->associated->bssid,
                                 ssid + 2, ssid[1], NULL, 0);
  
        ifmgd->probe_send_count++;
@@@ -871,15 -1204,12 +871,15 @@@ static void ieee80211_mgd_probe_ap(stru
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        bool already = false;
  
 -      if (!netif_running(sdata->dev))
 +      if (!ieee80211_sdata_running(sdata))
                return;
  
        if (sdata->local->scanning)
                return;
  
 +      if (sdata->local->tmp_channel)
 +              return;
 +
        mutex_lock(&ifmgd->mtx);
  
        if (!ifmgd->associated)
  #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
        if (beacon && net_ratelimit())
                printk(KERN_DEBUG "%s: detected beacon loss from AP "
 -                     "- sending probe request\n", sdata->dev->name);
 +                     "- sending probe request\n", sdata->name);
  #endif
  
        /*
@@@ -941,8 -1271,88 +941,8 @@@ void ieee80211_beacon_loss(struct ieee8
  }
  EXPORT_SYMBOL(ieee80211_beacon_loss);
  
 -static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata,
 -                                   struct ieee80211_mgd_work *wk)
 -{
 -      wk->state = IEEE80211_MGD_STATE_IDLE;
 -      printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name);
 -}
 -
 -
 -static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
 -                                   struct ieee80211_mgd_work *wk,
 -                                   struct ieee80211_mgmt *mgmt,
 -                                   size_t len)
 -{
 -      u8 *pos;
 -      struct ieee802_11_elems elems;
 -
 -      pos = mgmt->u.auth.variable;
 -      ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
 -      if (!elems.challenge)
 -              return;
 -      ieee80211_send_auth(sdata, 3, wk->auth_alg,
 -                          elems.challenge - 2, elems.challenge_len + 2,
 -                          wk->bss->cbss.bssid,
 -                          wk->key, wk->key_len, wk->key_idx);
 -      wk->auth_transaction = 4;
 -}
 -
 -static enum rx_mgmt_action __must_check
 -ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
 -                     struct ieee80211_mgd_work *wk,
 -                     struct ieee80211_mgmt *mgmt, size_t len)
 -{
 -      u16 auth_alg, auth_transaction, status_code;
 -
 -      if (wk->state != IEEE80211_MGD_STATE_AUTH)
 -              return RX_MGMT_NONE;
 -
 -      if (len < 24 + 6)
 -              return RX_MGMT_NONE;
 -
 -      if (memcmp(wk->bss->cbss.bssid, mgmt->sa, ETH_ALEN) != 0)
 -              return RX_MGMT_NONE;
 -
 -      if (memcmp(wk->bss->cbss.bssid, mgmt->bssid, ETH_ALEN) != 0)
 -              return RX_MGMT_NONE;
 -
 -      auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
 -      auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
 -      status_code = le16_to_cpu(mgmt->u.auth.status_code);
 -
 -      if (auth_alg != wk->auth_alg ||
 -          auth_transaction != wk->auth_transaction)
 -              return RX_MGMT_NONE;
 -
 -      if (status_code != WLAN_STATUS_SUCCESS) {
 -              list_del(&wk->list);
 -              kfree(wk);
 -              return RX_MGMT_CFG80211_AUTH;
 -      }
 -
 -      switch (wk->auth_alg) {
 -      case WLAN_AUTH_OPEN:
 -      case WLAN_AUTH_LEAP:
 -      case WLAN_AUTH_FT:
 -              ieee80211_auth_completed(sdata, wk);
 -              return RX_MGMT_CFG80211_AUTH;
 -      case WLAN_AUTH_SHARED_KEY:
 -              if (wk->auth_transaction == 4) {
 -                      ieee80211_auth_completed(sdata, wk);
 -                      return RX_MGMT_CFG80211_AUTH;
 -              } else
 -                      ieee80211_auth_challenge(sdata, wk, mgmt, len);
 -              break;
 -      }
 -
 -      return RX_MGMT_NONE;
 -}
 -
 -
  static enum rx_mgmt_action __must_check
  ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
 -                       struct ieee80211_mgd_work *wk,
                         struct ieee80211_mgmt *mgmt, size_t len)
  {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
  
        ASSERT_MGD_MTX(ifmgd);
  
 -      if (wk)
 -              bssid = wk->bss->cbss.bssid;
 -      else
 -              bssid = ifmgd->associated->cbss.bssid;
 +      bssid = ifmgd->associated->bssid;
  
        reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
  
        printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n",
 -                      sdata->dev->name, bssid, reason_code);
 +                      sdata->name, bssid, reason_code);
  
 -      if (!wk) {
 -              ieee80211_set_disassoc(sdata, true);
 -              ieee80211_recalc_idle(sdata->local);
 -      } else {
 -              list_del(&wk->list);
 -              kfree(wk);
 -      }
 +      ieee80211_set_disassoc(sdata);
 +      ieee80211_recalc_idle(sdata->local);
  
        return RX_MGMT_CFG80211_DEAUTH;
  }
@@@ -983,72 -1401,123 +983,72 @@@ ieee80211_rx_mgmt_disassoc(struct ieee8
        if (WARN_ON(!ifmgd->associated))
                return RX_MGMT_NONE;
  
 -      if (WARN_ON(memcmp(ifmgd->associated->cbss.bssid, mgmt->sa, ETH_ALEN)))
 +      if (WARN_ON(memcmp(ifmgd->associated->bssid, mgmt->sa, ETH_ALEN)))
                return RX_MGMT_NONE;
  
        reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
  
        printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n",
 -                      sdata->dev->name, mgmt->sa, reason_code);
 +                      sdata->name, mgmt->sa, reason_code);
  
 -      ieee80211_set_disassoc(sdata, false);
 +      ieee80211_set_disassoc(sdata);
        ieee80211_recalc_idle(sdata->local);
        return RX_MGMT_CFG80211_DISASSOC;
  }
  
  
 -static enum rx_mgmt_action __must_check
 -ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
 -                           struct ieee80211_mgd_work *wk,
 -                           struct ieee80211_mgmt *mgmt, size_t len,
 -                           bool reassoc)
 +static bool ieee80211_assoc_success(struct ieee80211_work *wk,
 +                                  struct ieee80211_mgmt *mgmt, size_t len)
  {
 +      struct ieee80211_sub_if_data *sdata = wk->sdata;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_supported_band *sband;
        struct sta_info *sta;
 +      struct cfg80211_bss *cbss = wk->assoc.bss;
 +      u8 *pos;
        u32 rates, basic_rates;
 -      u16 capab_info, status_code, aid;
 +      u16 capab_info, aid;
        struct ieee802_11_elems elems;
        struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
 -      u8 *pos;
        u32 changed = 0;
 -      int i, j;
 -      bool have_higher_than_11mbit = false, newsta = false;
 +      int i, j, err;
 +      bool have_higher_than_11mbit = false;
        u16 ap_ht_cap_flags;
  
 -      /*
 -       * AssocResp and ReassocResp have identical structure, so process both
 -       * of them in this function.
 -       */
 -
 -      if (len < 24 + 6)
 -              return RX_MGMT_NONE;
 -
 -      if (memcmp(wk->bss->cbss.bssid, mgmt->sa, ETH_ALEN) != 0)
 -              return RX_MGMT_NONE;
 +      /* AssocResp and ReassocResp have identical structure */
  
 -      capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
 -      status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
        aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
 -
 -      printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x "
 -             "status=%d aid=%d)\n",
 -             sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa,
 -             capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
 -
 -      pos = mgmt->u.assoc_resp.variable;
 -      ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
 -
 -      if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
 -          elems.timeout_int && elems.timeout_int_len == 5 &&
 -          elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) {
 -              u32 tu, ms;
 -              tu = get_unaligned_le32(elems.timeout_int + 1);
 -              ms = tu * 1024 / 1000;
 -              printk(KERN_DEBUG "%s: AP rejected association temporarily; "
 -                     "comeback duration %u TU (%u ms)\n",
 -                     sdata->dev->name, tu, ms);
 -              wk->timeout = jiffies + msecs_to_jiffies(ms);
 -              if (ms > IEEE80211_ASSOC_TIMEOUT)
 -                      run_again(ifmgd, jiffies + msecs_to_jiffies(ms));
 -              return RX_MGMT_NONE;
 -      }
 -
 -      if (status_code != WLAN_STATUS_SUCCESS) {
 -              printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
 -                     sdata->dev->name, status_code);
 -              wk->state = IEEE80211_MGD_STATE_IDLE;
 -              return RX_MGMT_CFG80211_ASSOC;
 -      }
 +      capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
  
        if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
                printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
 -                     "set\n", sdata->dev->name, aid);
 +                     "set\n", sdata->name, aid);
        aid &= ~(BIT(15) | BIT(14));
  
 +      pos = mgmt->u.assoc_resp.variable;
 +      ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
 +
        if (!elems.supp_rates) {
                printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
 -                     sdata->dev->name);
 -              return RX_MGMT_NONE;
 +                     sdata->name);
 +              return false;
        }
  
 -      printk(KERN_DEBUG "%s: associated\n", sdata->dev->name);
        ifmgd->aid = aid;
  
 -      rcu_read_lock();
 -
 -      /* Add STA entry for the AP */
 -      sta = sta_info_get(local, wk->bss->cbss.bssid);
 +      sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL);
        if (!sta) {
 -              newsta = true;
 -
 -              rcu_read_unlock();
 -
 -              sta = sta_info_alloc(sdata, wk->bss->cbss.bssid, GFP_KERNEL);
 -              if (!sta) {
 -                      printk(KERN_DEBUG "%s: failed to alloc STA entry for"
 -                             " the AP\n", sdata->dev->name);
 -                      return RX_MGMT_NONE;
 -              }
 -
 -              set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC |
 -                                 WLAN_STA_ASSOC_AP);
 -              if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
 -                      set_sta_flags(sta, WLAN_STA_AUTHORIZED);
 -
 -              rcu_read_lock();
 +              printk(KERN_DEBUG "%s: failed to alloc STA entry for"
 +                     " the AP\n", sdata->name);
 +              return false;
        }
  
 +      set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC |
 +                         WLAN_STA_ASSOC_AP);
 +      if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
 +              set_sta_flags(sta, WLAN_STA_AUTHORIZED);
 +
        rates = 0;
        basic_rates = 0;
        sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
        if (elems.wmm_param)
                set_sta_flags(sta, WLAN_STA_WME);
  
 -      if (newsta) {
 -              int err = sta_info_insert(sta);
 -              if (err) {
 -                      printk(KERN_DEBUG "%s: failed to insert STA entry for"
 -                             " the AP (error %d)\n", sdata->dev->name, err);
 -                      rcu_read_unlock();
 -                      return RX_MGMT_NONE;
 -              }
 +      err = sta_info_insert(sta);
 +      sta = NULL;
 +      if (err) {
 +              printk(KERN_DEBUG "%s: failed to insert STA entry for"
 +                     " the AP (error %d)\n", sdata->name, err);
 +              return false;
        }
  
 -      rcu_read_unlock();
 -
        if (elems.wmm_param)
                ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param,
                                         elems.wmm_param_len);
        else
                ieee80211_set_wmm_default(sdata);
  
 +      local->oper_channel = wk->chan;
 +
        if (elems.ht_info_elem && elems.wmm_param &&
 -          (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
 +          (sdata->local->hw.queues >= 4) &&
            !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
                changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
 -                                             wk->bss->cbss.bssid,
 -                                             ap_ht_cap_flags);
 -
 -        /* delete work item -- must be before set_associated for PS */
 -      list_del(&wk->list);
 +                                             cbss->bssid, ap_ht_cap_flags);
  
        /* set AID and assoc capability,
         * ieee80211_set_associated() will tell the driver */
        bss_conf->aid = aid;
        bss_conf->assoc_capability = capab_info;
 -      /* this will take ownership of wk */
 -      ieee80211_set_associated(sdata, wk, changed);
 +      ieee80211_set_associated(sdata, cbss, changed);
 +
 +      /*
 +       * If we're using 4-addr mode, let the AP know that we're
 +       * doing so, so that it can create the STA VLAN on its side
 +       */
 +      if (ifmgd->use_4addr)
 +              ieee80211_send_4addr_nullfunc(local, sdata);
  
        /*
         * Start timer to probe the connection to the AP now.
        ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
        mod_beacon_timer(sdata);
  
 -      return RX_MGMT_CFG80211_ASSOC;
 +      return true;
  }
  
  
@@@ -1188,7 -1657,7 +1188,7 @@@ static void ieee80211_rx_bss_info(struc
                return;
  
        if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) &&
 -          (memcmp(mgmt->bssid, sdata->u.mgd.associated->cbss.bssid,
 +          (memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid,
                                                        ETH_ALEN) == 0)) {
                struct ieee80211_channel_sw_ie *sw_elem =
                        (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem;
  
  
  static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
 -                                       struct ieee80211_mgd_work *wk,
 -                                       struct ieee80211_mgmt *mgmt, size_t len,
 -                                       struct ieee80211_rx_status *rx_status)
 +                                       struct sk_buff *skb)
  {
 +      struct ieee80211_mgmt *mgmt = (void *)skb->data;
        struct ieee80211_if_managed *ifmgd;
 -      size_t baselen;
 +      struct ieee80211_rx_status *rx_status = (void *) skb->cb;
 +      size_t baselen, len = skb->len;
        struct ieee802_11_elems elems;
  
        ifmgd = &sdata->u.mgd;
  
        ASSERT_MGD_MTX(ifmgd);
  
 -      if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
 +      if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN))
                return; /* ignore ProbeResp to foreign address */
  
        baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
  
        ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false);
  
 -      /* direct probe may be part of the association flow */
 -      if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) {
 -              printk(KERN_DEBUG "%s: direct probe responded\n",
 -                     sdata->dev->name);
 -              wk->tries = 0;
 -              wk->state = IEEE80211_MGD_STATE_AUTH;
 -              WARN_ON(ieee80211_authenticate(sdata, wk) != RX_MGMT_NONE);
 -      }
 -
        if (ifmgd->associated &&
 -          memcmp(mgmt->bssid, ifmgd->associated->cbss.bssid, ETH_ALEN) == 0 &&
 +          memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0 &&
            ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
                            IEEE80211_STA_CONNECTION_POLL)) {
                ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
@@@ -1296,7 -1774,7 +1296,7 @@@ static void ieee80211_rx_mgmt_beacon(st
        if (!ifmgd->associated)
                return;
  
 -      bssid = ifmgd->associated->cbss.bssid;
 +      bssid = ifmgd->associated->bssid;
  
        /*
         * And in theory even frames from a different AP we were just
  #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
                if (net_ratelimit()) {
                        printk(KERN_DEBUG "%s: cancelling probereq poll due "
 -                             "to a received beacon\n", sdata->dev->name);
 +                             "to a received beacon\n", sdata->name);
                }
  #endif
                ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL;
  
                rcu_read_lock();
  
 -              sta = sta_info_get(local, bssid);
 +              sta = sta_info_get(sdata, bssid);
                if (WARN_ON(!sta)) {
                        rcu_read_unlock();
                        return;
@@@ -1435,6 -1913,9 +1435,6 @@@ ieee80211_rx_result ieee80211_sta_rx_mg
        switch (fc & IEEE80211_FCTL_STYPE) {
        case IEEE80211_STYPE_PROBE_RESP:
        case IEEE80211_STYPE_BEACON:
 -      case IEEE80211_STYPE_AUTH:
 -      case IEEE80211_STYPE_ASSOC_RESP:
 -      case IEEE80211_STYPE_REASSOC_RESP:
        case IEEE80211_STYPE_DEAUTH:
        case IEEE80211_STYPE_DISASSOC:
        case IEEE80211_STYPE_ACTION:
@@@ -1452,6 -1933,7 +1452,6 @@@ static void ieee80211_sta_rx_queued_mgm
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct ieee80211_rx_status *rx_status;
        struct ieee80211_mgmt *mgmt;
 -      struct ieee80211_mgd_work *wk;
        enum rx_mgmt_action rma = RX_MGMT_NONE;
        u16 fc;
  
        mutex_lock(&ifmgd->mtx);
  
        if (ifmgd->associated &&
 -          memcmp(ifmgd->associated->cbss.bssid, mgmt->bssid,
 -                                                      ETH_ALEN) == 0) {
 +          memcmp(ifmgd->associated->bssid, mgmt->bssid, ETH_ALEN) == 0) {
                switch (fc & IEEE80211_FCTL_STYPE) {
                case IEEE80211_STYPE_BEACON:
                        ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len,
                                                 rx_status);
                        break;
                case IEEE80211_STYPE_PROBE_RESP:
 -                      ieee80211_rx_mgmt_probe_resp(sdata, NULL, mgmt,
 -                                                   skb->len, rx_status);
 +                      ieee80211_rx_mgmt_probe_resp(sdata, skb);
                        break;
                case IEEE80211_STYPE_DEAUTH:
 -                      rma = ieee80211_rx_mgmt_deauth(sdata, NULL,
 -                                                     mgmt, skb->len);
 +                      rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);
                        break;
                case IEEE80211_STYPE_DISASSOC:
                        rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
                        break;
                case IEEE80211_STYPE_ACTION:
-                       /* XXX: differentiate, can only happen for CSA now! */
+                       if (mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT)
+                               break;
                        ieee80211_sta_process_chanswitch(sdata,
                                        &mgmt->u.action.u.chan_switch.sw_elem,
 -                                      ifmgd->associated);
 +                                      (void *)ifmgd->associated->priv);
                        break;
                }
                mutex_unlock(&ifmgd->mtx);
                goto out;
        }
  
 -      list_for_each_entry(wk, &ifmgd->work_list, list) {
 -              if (memcmp(wk->bss->cbss.bssid, mgmt->bssid, ETH_ALEN) != 0)
 -                      continue;
 -
 -              switch (fc & IEEE80211_FCTL_STYPE) {
 -              case IEEE80211_STYPE_PROBE_RESP:
 -                      ieee80211_rx_mgmt_probe_resp(sdata, wk, mgmt, skb->len,
 -                                                   rx_status);
 -                      break;
 -              case IEEE80211_STYPE_AUTH:
 -                      rma = ieee80211_rx_mgmt_auth(sdata, wk, mgmt, skb->len);
 -                      break;
 -              case IEEE80211_STYPE_ASSOC_RESP:
 -                      rma = ieee80211_rx_mgmt_assoc_resp(sdata, wk, mgmt,
 -                                                         skb->len, false);
 -                      break;
 -              case IEEE80211_STYPE_REASSOC_RESP:
 -                      rma = ieee80211_rx_mgmt_assoc_resp(sdata, wk, mgmt,
 -                                                         skb->len, true);
 -                      break;
 -              case IEEE80211_STYPE_DEAUTH:
 -                      rma = ieee80211_rx_mgmt_deauth(sdata, wk, mgmt,
 -                                                     skb->len);
 -                      break;
 -              }
 -              /*
 -               * We've processed this frame for that work, so it can't
 -               * belong to another work struct.
 -               * NB: this is also required for correctness because the
 -               * called functions can free 'wk', and for 'rma'!
 -               */
 -              break;
 -      }
 -
        mutex_unlock(&ifmgd->mtx);
  
 -      switch (rma) {
 -      case RX_MGMT_NONE:
 -              /* no action */
 -              break;
 -      case RX_MGMT_CFG80211_AUTH:
 -              cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, skb->len);
 -              break;
 -      case RX_MGMT_CFG80211_ASSOC:
 -              cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, skb->len);
 -              break;
 -      case RX_MGMT_CFG80211_DEAUTH:
 +      if (skb->len >= 24 + 2 /* mgmt + deauth reason */ &&
 +          (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH)
                cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
 -              break;
 -      default:
 -              WARN(1, "unexpected: %d", rma);
 -      }
  
   out:
        kfree_skb(skb);
@@@ -1534,8 -2068,12 +1536,8 @@@ static void ieee80211_sta_work(struct w
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_managed *ifmgd;
        struct sk_buff *skb;
 -      struct ieee80211_mgd_work *wk, *tmp;
 -      LIST_HEAD(free_work);
 -      enum rx_mgmt_action rma;
 -      bool anybusy = false;
  
 -      if (!netif_running(sdata->dev))
 +      if (!ieee80211_sdata_running(sdata))
                return;
  
        if (local->scanning)
            ifmgd->associated) {
                u8 bssid[ETH_ALEN];
  
 -              memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN);
 +              memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
                if (time_is_after_jiffies(ifmgd->probe_timeout))
                        run_again(ifmgd, ifmgd->probe_timeout);
  
                        printk(KERN_DEBUG "No probe response from AP %pM"
                                " after %dms, disconnecting.\n",
                                bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
 -                      ieee80211_set_disassoc(sdata, true);
 +                      ieee80211_set_disassoc(sdata);
                        ieee80211_recalc_idle(local);
                        mutex_unlock(&ifmgd->mtx);
                        /*
                }
        }
  
 -
 -      ieee80211_recalc_idle(local);
 -
 -      list_for_each_entry_safe(wk, tmp, &ifmgd->work_list, list) {
 -              if (time_is_after_jiffies(wk->timeout)) {
 -                      /*
 -                       * This work item isn't supposed to be worked on
 -                       * right now, but take care to adjust the timer
 -                       * properly.
 -                       */
 -                      run_again(ifmgd, wk->timeout);
 -                      continue;
 -              }
 -
 -              switch (wk->state) {
 -              default:
 -                      WARN_ON(1);
 -                      /* fall through */
 -              case IEEE80211_MGD_STATE_IDLE:
 -                      /* nothing */
 -                      rma = RX_MGMT_NONE;
 -                      break;
 -              case IEEE80211_MGD_STATE_PROBE:
 -                      rma = ieee80211_direct_probe(sdata, wk);
 -                      break;
 -              case IEEE80211_MGD_STATE_AUTH:
 -                      rma = ieee80211_authenticate(sdata, wk);
 -                      break;
 -              case IEEE80211_MGD_STATE_ASSOC:
 -                      rma = ieee80211_associate(sdata, wk);
 -                      break;
 -              }
 -
 -              switch (rma) {
 -              case RX_MGMT_NONE:
 -                      /* no action required */
 -                      break;
 -              case RX_MGMT_CFG80211_AUTH_TO:
 -              case RX_MGMT_CFG80211_ASSOC_TO:
 -                      list_del(&wk->list);
 -                      list_add(&wk->list, &free_work);
 -                      wk->tries = rma; /* small abuse but only local */
 -                      break;
 -              default:
 -                      WARN(1, "unexpected: %d", rma);
 -              }
 -      }
 -
 -      list_for_each_entry(wk, &ifmgd->work_list, list) {
 -              if (wk->state != IEEE80211_MGD_STATE_IDLE) {
 -                      anybusy = true;
 -                      break;
 -              }
 -      }
 -      if (!anybusy &&
 -          test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request))
 -              ieee80211_queue_delayed_work(&local->hw,
 -                                           &local->scan_work,
 -                                           round_jiffies_relative(0));
 -
        mutex_unlock(&ifmgd->mtx);
 -
 -      list_for_each_entry_safe(wk, tmp, &free_work, list) {
 -              switch (wk->tries) {
 -              case RX_MGMT_CFG80211_AUTH_TO:
 -                      cfg80211_send_auth_timeout(sdata->dev,
 -                                                 wk->bss->cbss.bssid);
 -                      break;
 -              case RX_MGMT_CFG80211_ASSOC_TO:
 -                      cfg80211_send_assoc_timeout(sdata->dev,
 -                                                  wk->bss->cbss.bssid);
 -                      break;
 -              default:
 -                      WARN(1, "unexpected: %d", wk->tries);
 -              }
 -
 -              list_del(&wk->list);
 -              kfree(wk);
 -      }
 -
 -      ieee80211_recalc_idle(local);
  }
  
  static void ieee80211_sta_bcn_mon_timer(unsigned long data)
@@@ -1712,14 -2330,14 +1714,14 @@@ void ieee80211_sta_setup_sdata(struct i
                    (unsigned long) sdata);
        skb_queue_head_init(&ifmgd->skb_queue);
  
 -      INIT_LIST_HEAD(&ifmgd->work_list);
 -
 -      ifmgd->capab = WLAN_CAPABILITY_ESS;
        ifmgd->flags = 0;
 -      if (sdata->local->hw.queues >= 4)
 -              ifmgd->flags |= IEEE80211_STA_WMM_ENABLED;
  
        mutex_init(&ifmgd->mtx);
 +
 +      if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS)
 +              ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC;
 +      else
 +              ifmgd->req_smps = IEEE80211_SMPS_OFF;
  }
  
  /* scan finished notification */
@@@ -1750,34 -2368,12 +1752,34 @@@ int ieee80211_max_network_latency(struc
  }
  
  /* config hooks */
 +static enum work_done_result
 +ieee80211_probe_auth_done(struct ieee80211_work *wk,
 +                        struct sk_buff *skb)
 +{
 +      if (!skb) {
 +              cfg80211_send_auth_timeout(wk->sdata->dev, wk->filter_ta);
 +              return WORK_DONE_DESTROY;
 +      }
 +
 +      if (wk->type == IEEE80211_WORK_AUTH) {
 +              cfg80211_send_rx_auth(wk->sdata->dev, skb->data, skb->len);
 +              return WORK_DONE_DESTROY;
 +      }
 +
 +      mutex_lock(&wk->sdata->u.mgd.mtx);
 +      ieee80211_rx_mgmt_probe_resp(wk->sdata, skb);
 +      mutex_unlock(&wk->sdata->u.mgd.mtx);
 +
 +      wk->type = IEEE80211_WORK_AUTH;
 +      wk->probe_auth.tries = 0;
 +      return WORK_DONE_REQUEUE;
 +}
 +
  int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
                       struct cfg80211_auth_request *req)
  {
 -      struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        const u8 *ssid;
 -      struct ieee80211_mgd_work *wk;
 +      struct ieee80211_work *wk;
        u16 auth_alg;
  
        switch (req->auth_type) {
        if (!wk)
                return -ENOMEM;
  
 -      wk->bss = (void *)req->bss;
 +      memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN);
  
        if (req->ie && req->ie_len) {
                memcpy(wk->ie, req->ie, req->ie_len);
        }
  
        if (req->key && req->key_len) {
 -              wk->key_len = req->key_len;
 -              wk->key_idx = req->key_idx;
 -              memcpy(wk->key, req->key, req->key_len);
 +              wk->probe_auth.key_len = req->key_len;
 +              wk->probe_auth.key_idx = req->key_idx;
 +              memcpy(wk->probe_auth.key, req->key, req->key_len);
        }
  
        ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
 -      memcpy(wk->ssid, ssid + 2, ssid[1]);
 -      wk->ssid_len = ssid[1];
 +      memcpy(wk->probe_auth.ssid, ssid + 2, ssid[1]);
 +      wk->probe_auth.ssid_len = ssid[1];
  
 -      wk->state = IEEE80211_MGD_STATE_PROBE;
 -      wk->auth_alg = auth_alg;
 -      wk->timeout = jiffies; /* run right away */
 +      wk->probe_auth.algorithm = auth_alg;
 +      wk->probe_auth.privacy = req->bss->capability & WLAN_CAPABILITY_PRIVACY;
  
 -      /*
 -       * XXX: if still associated need to tell AP that we're going
 -       *      to sleep and then change channel etc.
 -       */
 -      sdata->local->oper_channel = req->bss->channel;
 -      ieee80211_hw_config(sdata->local, 0);
 -
 -      mutex_lock(&ifmgd->mtx);
 -      list_add(&wk->list, &sdata->u.mgd.work_list);
 -      mutex_unlock(&ifmgd->mtx);
 +      wk->type = IEEE80211_WORK_DIRECT_PROBE;
 +      wk->chan = req->bss->channel;
 +      wk->sdata = sdata;
 +      wk->done = ieee80211_probe_auth_done;
  
 -      ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work);
 +      ieee80211_add_work(wk);
        return 0;
  }
  
 -int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 -                      struct cfg80211_assoc_request *req)
 +static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
 +                                                struct sk_buff *skb)
  {
 -      struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 -      struct ieee80211_mgd_work *wk, *found = NULL;
 -      int i, err;
 +      struct ieee80211_mgmt *mgmt;
 +      u16 status;
  
 -      mutex_lock(&ifmgd->mtx);
 +      if (!skb) {
 +              cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta);
 +              return WORK_DONE_DESTROY;
 +      }
  
 -      list_for_each_entry(wk, &ifmgd->work_list, list) {
 -              if (&wk->bss->cbss == req->bss &&
 -                  wk->state == IEEE80211_MGD_STATE_IDLE) {
 -                      found = wk;
 -                      break;
 +      mgmt = (void *)skb->data;
 +      status = le16_to_cpu(mgmt->u.assoc_resp.status_code);
 +
 +      if (status == WLAN_STATUS_SUCCESS) {
 +              mutex_lock(&wk->sdata->u.mgd.mtx);
 +              if (!ieee80211_assoc_success(wk, mgmt, skb->len)) {
 +                      mutex_unlock(&wk->sdata->u.mgd.mtx);
 +                      /* oops -- internal error -- send timeout for now */
 +                      cfg80211_send_assoc_timeout(wk->sdata->dev,
 +                                                  wk->filter_ta);
 +                      return WORK_DONE_DESTROY;
                }
 +              mutex_unlock(&wk->sdata->u.mgd.mtx);
        }
  
 -      if (!found) {
 -              err = -ENOLINK;
 -              goto out;
 -      }
 +      cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len);
 +      return WORK_DONE_DESTROY;
 +}
  
 -      list_del(&found->list);
 +int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 +                      struct cfg80211_assoc_request *req)
 +{
 +      struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 +      struct ieee80211_bss *bss = (void *)req->bss->priv;
 +      struct ieee80211_work *wk;
 +      const u8 *ssid;
 +      int i;
  
 -      wk = krealloc(found, sizeof(*wk) + req->ie_len, GFP_KERNEL);
 -      if (!wk) {
 -              list_add(&found->list, &ifmgd->work_list);
 -              err = -ENOMEM;
 -              goto out;
 +      mutex_lock(&ifmgd->mtx);
 +      if (ifmgd->associated) {
 +              mutex_unlock(&ifmgd->mtx);
 +              return -EALREADY;
        }
 +      mutex_unlock(&ifmgd->mtx);
  
 -      list_add(&wk->list, &ifmgd->work_list);
 +      wk = kzalloc(sizeof(*wk) + req->ie_len, GFP_KERNEL);
 +      if (!wk)
 +              return -ENOMEM;
  
        ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N;
  
                    req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104)
                        ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
  
 -      sdata->local->oper_channel = req->bss->channel;
 -      ieee80211_hw_config(sdata->local, 0);
  
        if (req->ie && req->ie_len) {
                memcpy(wk->ie, req->ie, req->ie_len);
        } else
                wk->ie_len = 0;
  
 +      wk->assoc.bss = req->bss;
 +
 +      memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN);
 +
 +      /* new association always uses requested smps mode */
 +      if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) {
 +              if (ifmgd->powersave)
 +                      ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC;
 +              else
 +                      ifmgd->ap_smps = IEEE80211_SMPS_OFF;
 +      } else
 +              ifmgd->ap_smps = ifmgd->req_smps;
 +
 +      wk->assoc.smps = ifmgd->ap_smps;
 +      /*
 +       * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode.
 +       * We still associate in non-HT mode (11a/b/g) if any one of these
 +       * ciphers is configured as pairwise.
 +       * We can set this to true for non-11n hardware, that'll be checked
 +       * separately along with the peer capabilities.
 +       */
 +      wk->assoc.use_11n = !(ifmgd->flags & IEEE80211_STA_DISABLE_11N);
 +      wk->assoc.capability = req->bss->capability;
 +      wk->assoc.wmm_used = bss->wmm_used;
 +      wk->assoc.supp_rates = bss->supp_rates;
 +      wk->assoc.supp_rates_len = bss->supp_rates_len;
 +      wk->assoc.ht_information_ie =
 +              ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_INFORMATION);
 +
 +      if (bss->wmm_used && bss->uapsd_supported &&
 +          (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) {
 +              wk->assoc.uapsd_used = true;
 +              ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED;
 +      } else {
 +              wk->assoc.uapsd_used = false;
 +              ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED;
 +      }
 +
 +      ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
 +      memcpy(wk->assoc.ssid, ssid + 2, ssid[1]);
 +      wk->assoc.ssid_len = ssid[1];
 +
        if (req->prev_bssid)
 -              memcpy(wk->prev_bssid, req->prev_bssid, ETH_ALEN);
 +              memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN);
  
 -      wk->state = IEEE80211_MGD_STATE_ASSOC;
 -      wk->tries = 0;
 -      wk->timeout = jiffies; /* run right away */
 +      wk->type = IEEE80211_WORK_ASSOC;
 +      wk->chan = req->bss->channel;
 +      wk->sdata = sdata;
 +      wk->done = ieee80211_assoc_done;
  
        if (req->use_mfp) {
                ifmgd->mfp = IEEE80211_MFP_REQUIRED;
        else
                ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT;
  
 -      ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work);
 -
 -      err = 0;
 -
 - out:
 -      mutex_unlock(&ifmgd->mtx);
 -      return err;
 +      ieee80211_add_work(wk);
 +      return 0;
  }
  
  int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
                         struct cfg80211_deauth_request *req,
                         void *cookie)
  {
 +      struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 -      struct ieee80211_mgd_work *wk;
 -      const u8 *bssid = NULL;
 -      bool not_auth_yet = false;
 +      struct ieee80211_work *wk;
 +      const u8 *bssid = req->bss->bssid;
  
        mutex_lock(&ifmgd->mtx);
  
 -      if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) {
 +      if (ifmgd->associated == req->bss) {
                bssid = req->bss->bssid;
 -              ieee80211_set_disassoc(sdata, true);
 -      } else list_for_each_entry(wk, &ifmgd->work_list, list) {
 -              if (&wk->bss->cbss == req->bss) {
 -                      bssid = req->bss->bssid;
 -                      if (wk->state == IEEE80211_MGD_STATE_PROBE)
 -                              not_auth_yet = true;
 +              ieee80211_set_disassoc(sdata);
 +              mutex_unlock(&ifmgd->mtx);
 +      } else {
 +              bool not_auth_yet = false;
 +
 +              mutex_unlock(&ifmgd->mtx);
 +
 +              mutex_lock(&local->work_mtx);
 +              list_for_each_entry(wk, &local->work_list, list) {
 +                      if (wk->type != IEEE80211_WORK_DIRECT_PROBE)
 +                              continue;
 +                      if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN))
 +                              continue;
 +                      not_auth_yet = true;
                        list_del(&wk->list);
 -                      kfree(wk);
 +                      free_work(wk);
                        break;
                }
 -      }
 -
 -      /*
 -       * If somebody requests authentication and we haven't
 -       * sent out an auth frame yet there's no need to send
 -       * out a deauth frame either. If the state was PROBE,
 -       * then this is the case. If it's AUTH we have sent a
 -       * frame, and if it's IDLE we have completed the auth
 -       * process already.
 -       */
 -      if (not_auth_yet) {
 -              mutex_unlock(&ifmgd->mtx);
 -              __cfg80211_auth_canceled(sdata->dev, bssid);
 -              return 0;
 -      }
 +              mutex_unlock(&local->work_mtx);
  
 -      /*
 -       * cfg80211 should catch this ... but it's racy since
 -       * we can receive a deauth frame, process it, hand it
 -       * to cfg80211 while that's in a locked section already
 -       * trying to tell us that the user wants to disconnect.
 -       */
 -      if (!bssid) {
 -              mutex_unlock(&ifmgd->mtx);
 -              return -ENOLINK;
 +              /*
 +               * If somebody requests authentication and we haven't
 +               * sent out an auth frame yet there's no need to send
 +               * out a deauth frame either. If the state was PROBE,
 +               * then this is the case. If it's AUTH we have sent a
 +               * frame, and if it's IDLE we have completed the auth
 +               * process already.
 +               */
 +              if (not_auth_yet) {
 +                      __cfg80211_auth_canceled(sdata->dev, bssid);
 +                      return 0;
 +              }
        }
  
 -      mutex_unlock(&ifmgd->mtx);
 -
        printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n",
 -             sdata->dev->name, bssid, req->reason_code);
 +             sdata->name, bssid, req->reason_code);
  
        ieee80211_send_deauth_disassoc(sdata, bssid,
                        IEEE80211_STYPE_DEAUTH, req->reason_code,
@@@ -2035,15 -2590,15 +2037,15 @@@ int ieee80211_mgd_disassoc(struct ieee8
         * to cfg80211 while that's in a locked section already
         * trying to tell us that the user wants to disconnect.
         */
 -      if (&ifmgd->associated->cbss != req->bss) {
 +      if (ifmgd->associated != req->bss) {
                mutex_unlock(&ifmgd->mtx);
                return -ENOLINK;
        }
  
        printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n",
 -             sdata->dev->name, req->bss->bssid, req->reason_code);
 +             sdata->name, req->bss->bssid, req->reason_code);
  
 -      ieee80211_set_disassoc(sdata, false);
 +      ieee80211_set_disassoc(sdata);
  
        mutex_unlock(&ifmgd->mtx);
  
diff --combined net/mac80211/rx.c
index efa6d3689c5e0856d0f340f2c71a764d59c8ba20,82a30c1bf3abf6c2874b9aff0088bf250e4a8f64..a8e15b84c05ba7c88cca76a25f4370a95ba9765d
@@@ -283,15 -283,15 +283,15 @@@ ieee80211_rx_monitor(struct ieee80211_l
        skb->protocol = htons(ETH_P_802_2);
  
        list_for_each_entry_rcu(sdata, &local->interfaces, list) {
 -              if (!netif_running(sdata->dev))
 -                      continue;
 -
                if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
                        continue;
  
                if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)
                        continue;
  
 +              if (!ieee80211_sdata_running(sdata))
 +                      continue;
 +
                if (prev_dev) {
                        skb2 = skb_clone(skb, GFP_ATOMIC);
                        if (skb2) {
@@@ -361,9 -361,7 +361,9 @@@ static void ieee80211_parse_qos(struct 
   * boundary. In the case of regular frames, this simply means aligning the
   * payload to a four-byte boundary (because either the IP header is directly
   * contained, or IV/RFC1042 headers that have a length divisible by four are
 - * in front of it).
 + * in front of it).  If the payload data is not properly aligned and the
 + * architecture doesn't support efficient unaligned operations, mac80211
 + * will align the data.
   *
   * With A-MSDU frames, however, the payload data address must yield two modulo
   * four because there are 14-byte 802.3 headers within the A-MSDU frames that
   */
  static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx)
  {
 -      struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
 -      int hdrlen;
 -
 -#ifndef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT
 -      return;
 +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 +      WARN_ONCE((unsigned long)rx->skb->data & 1,
 +                "unaligned packet at 0x%p\n", rx->skb->data);
  #endif
 -
 -      if (WARN_ONCE((unsigned long)rx->skb->data & 1,
 -                    "unaligned packet at 0x%p\n", rx->skb->data))
 -              return;
 -
 -      if (!ieee80211_is_data_present(hdr->frame_control))
 -              return;
 -
 -      hdrlen = ieee80211_hdrlen(hdr->frame_control);
 -      if (rx->flags & IEEE80211_RX_AMSDU)
 -              hdrlen += ETH_HLEN;
 -      WARN_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3,
 -                "unaligned IP payload at 0x%p\n", rx->skb->data + hdrlen);
  }
  
  
@@@ -463,7 -476,7 +463,7 @@@ ieee80211_rx_mesh_check(struct ieee8021
  {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
        unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
 -      char *dev_addr = rx->sdata->dev->dev_addr;
 +      char *dev_addr = rx->sdata->vif.addr;
  
        if (ieee80211_is_data(hdr->frame_control)) {
                if (is_multicast_ether_addr(hdr->addr1)) {
@@@ -1008,10 -1021,10 +1008,10 @@@ static void ap_sta_ps_start(struct sta_
  
        atomic_inc(&sdata->bss->num_sta_ps);
        set_sta_flags(sta, WLAN_STA_PS_STA);
 -      drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta);
 +      drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
  #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
        printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n",
 -             sdata->dev->name, sta->sta.addr, sta->sta.aid);
 +             sdata->name, sta->sta.addr, sta->sta.aid);
  #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
  }
  
@@@ -1025,13 -1038,13 +1025,13 @@@ static void ap_sta_ps_end(struct sta_in
  
  #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
        printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n",
 -             sdata->dev->name, sta->sta.addr, sta->sta.aid);
 +             sdata->name, sta->sta.addr, sta->sta.aid);
  #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
  
        if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) {
  #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
                printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n",
 -                     sdata->dev->name, sta->sta.addr, sta->sta.aid);
 +                     sdata->name, sta->sta.addr, sta->sta.aid);
  #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
                return;
        }
@@@ -1111,18 -1124,6 +1111,18 @@@ ieee80211_rx_h_sta_process(struct ieee8
        if (ieee80211_is_nullfunc(hdr->frame_control) ||
            ieee80211_is_qos_nullfunc(hdr->frame_control)) {
                I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc);
 +
 +              /*
 +               * If we receive a 4-addr nullfunc frame from a STA
 +               * that was not moved to a 4-addr STA vlan yet, drop
 +               * the frame to the monitor interface, to make sure
 +               * that hostapd sees it
 +               */
 +              if (ieee80211_has_a4(hdr->frame_control) &&
 +                  (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
 +                   (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
 +                    !rx->sdata->u.vlan.sta)))
 +                      return RX_DROP_MONITOR;
                /*
                 * Update counter and free packet here to avoid
                 * counting this as a dropped packed.
@@@ -1155,7 -1156,7 +1155,7 @@@ ieee80211_reassemble_add(struct ieee802
                printk(KERN_DEBUG "%s: RX reassembly removed oldest "
                       "fragment entry (idx=%d age=%lu seq=%d last_frag=%d "
                       "addr1=%pM addr2=%pM\n",
 -                     sdata->dev->name, idx,
 +                     sdata->name, idx,
                       jiffies - entry->first_frag_time, entry->seq,
                       entry->last_frag, hdr->addr1, hdr->addr2);
  #endif
@@@ -1423,6 -1424,7 +1423,6 @@@ static in
  __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
  {
        struct ieee80211_sub_if_data *sdata = rx->sdata;
 -      struct net_device *dev = sdata->dev;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
  
        if (ieee80211_has_a4(hdr->frame_control) &&
             (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.use_4addr)))
                return -1;
  
 -      return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type);
 +      return ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type);
  }
  
  /*
@@@ -1451,7 -1453,7 +1451,7 @@@ static bool ieee80211_frame_allowed(str
         * of whether the frame was encrypted or not.
         */
        if (ehdr->h_proto == htons(ETH_P_PAE) &&
 -          (compare_ether_addr(ehdr->h_dest, rx->sdata->dev->dev_addr) == 0 ||
 +          (compare_ether_addr(ehdr->h_dest, rx->sdata->vif.addr) == 0 ||
             compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0))
                return true;
  
@@@ -1470,6 -1472,7 +1470,6 @@@ ieee80211_deliver_skb(struct ieee80211_
  {
        struct ieee80211_sub_if_data *sdata = rx->sdata;
        struct net_device *dev = sdata->dev;
 -      struct ieee80211_local *local = rx->local;
        struct sk_buff *skb, *xmit_skb;
        struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
        struct sta_info *dsta;
                                printk(KERN_DEBUG "%s: failed to clone "
                                       "multicast frame\n", dev->name);
                } else {
 -                      dsta = sta_info_get(local, skb->data);
 -                      if (dsta && dsta->sdata->dev == dev) {
 +                      dsta = sta_info_get(sdata, skb->data);
 +                      if (dsta) {
                                /*
                                 * The destination station is associated to
                                 * this AP (in this VLAN), so send the frame
        if (skb) {
                int align __maybe_unused;
  
 -#if defined(CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT) || !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
 +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
                /*
                 * 'align' will only take the values 0 or 2 here
                 * since all frames are required to be aligned
@@@ -1553,10 -1556,16 +1553,10 @@@ static ieee80211_rx_result debug_noinli
  ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
  {
        struct net_device *dev = rx->sdata->dev;
 -      struct ieee80211_local *local = rx->local;
 -      u16 ethertype;
 -      u8 *payload;
 -      struct sk_buff *skb = rx->skb, *frame = NULL;
 +      struct sk_buff *skb = rx->skb;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        __le16 fc = hdr->frame_control;
 -      const struct ethhdr *eth;
 -      int remaining, err;
 -      u8 dst[ETH_ALEN];
 -      u8 src[ETH_ALEN];
 +      struct sk_buff_head frame_list;
  
        if (unlikely(!ieee80211_is_data(fc)))
                return RX_CONTINUE;
        if (!(rx->flags & IEEE80211_RX_AMSDU))
                return RX_CONTINUE;
  
 -      err = __ieee80211_data_to_8023(rx);
 -      if (unlikely(err))
 +      if (ieee80211_has_a4(hdr->frame_control) &&
 +          rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
 +          !rx->sdata->u.vlan.sta)
                return RX_DROP_UNUSABLE;
  
 -      skb->dev = dev;
 -
 -      dev->stats.rx_packets++;
 -      dev->stats.rx_bytes += skb->len;
 -
 -      /* skip the wrapping header */
 -      eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr));
 -      if (!eth)
 +      if (is_multicast_ether_addr(hdr->addr1) &&
 +          ((rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
 +            rx->sdata->u.vlan.sta) ||
 +           (rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
 +            rx->sdata->u.mgd.use_4addr)))
                return RX_DROP_UNUSABLE;
  
 -      while (skb != frame) {
 -              u8 padding;
 -              __be16 len = eth->h_proto;
 -              unsigned int subframe_len = sizeof(struct ethhdr) + ntohs(len);
 -
 -              remaining = skb->len;
 -              memcpy(dst, eth->h_dest, ETH_ALEN);
 -              memcpy(src, eth->h_source, ETH_ALEN);
 +      skb->dev = dev;
 +      __skb_queue_head_init(&frame_list);
  
 -              padding = ((4 - subframe_len) & 0x3);
 -              /* the last MSDU has no padding */
 -              if (subframe_len > remaining)
 -                      return RX_DROP_UNUSABLE;
 +      ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
 +                               rx->sdata->vif.type,
 +                               rx->local->hw.extra_tx_headroom);
  
 -              skb_pull(skb, sizeof(struct ethhdr));
 -              /* if last subframe reuse skb */
 -              if (remaining <= subframe_len + padding)
 -                      frame = skb;
 -              else {
 -                      /*
 -                       * Allocate and reserve two bytes more for payload
 -                       * alignment since sizeof(struct ethhdr) is 14.
 -                       */
 -                      frame = dev_alloc_skb(
 -                              ALIGN(local->hw.extra_tx_headroom, 4) +
 -                              subframe_len + 2);
 -
 -                      if (frame == NULL)
 -                              return RX_DROP_UNUSABLE;
 -
 -                      skb_reserve(frame,
 -                                  ALIGN(local->hw.extra_tx_headroom, 4) +
 -                                  sizeof(struct ethhdr) + 2);
 -                      memcpy(skb_put(frame, ntohs(len)), skb->data,
 -                              ntohs(len));
 -
 -                      eth = (struct ethhdr *) skb_pull(skb, ntohs(len) +
 -                                                      padding);
 -                      if (!eth) {
 -                              dev_kfree_skb(frame);
 -                              return RX_DROP_UNUSABLE;
 -                      }
 -              }
 -
 -              skb_reset_network_header(frame);
 -              frame->dev = dev;
 -              frame->priority = skb->priority;
 -              rx->skb = frame;
 -
 -              payload = frame->data;
 -              ethertype = (payload[6] << 8) | payload[7];
 -
 -              if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&
 -                          ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
 -                         compare_ether_addr(payload,
 -                                            bridge_tunnel_header) == 0)) {
 -                      /* remove RFC1042 or Bridge-Tunnel
 -                       * encapsulation and replace EtherType */
 -                      skb_pull(frame, 6);
 -                      memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
 -                      memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
 -              } else {
 -                      memcpy(skb_push(frame, sizeof(__be16)),
 -                             &len, sizeof(__be16));
 -                      memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
 -                      memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
 -              }
 +      while (!skb_queue_empty(&frame_list)) {
 +              rx->skb = __skb_dequeue(&frame_list);
  
                if (!ieee80211_frame_allowed(rx, fc)) {
 -                      if (skb == frame) /* last frame */
 -                              return RX_DROP_UNUSABLE;
 -                      dev_kfree_skb(frame);
 +                      dev_kfree_skb(rx->skb);
                        continue;
                }
 +              dev->stats.rx_packets++;
 +              dev->stats.rx_bytes += rx->skb->len;
  
                ieee80211_deliver_skb(rx);
        }
@@@ -1652,7 -1721,7 +1652,7 @@@ ieee80211_rx_h_mesh_fwding(struct ieee8
  
        /* Frame has reached destination.  Don't forward */
        if (!is_multicast_ether_addr(hdr->addr1) &&
 -          compare_ether_addr(sdata->dev->dev_addr, hdr->addr3) == 0)
 +          compare_ether_addr(sdata->vif.addr, hdr->addr3) == 0)
                return RX_CONTINUE;
  
        mesh_hdr->ttl--;
  
                        if (!fwd_skb && net_ratelimit())
                                printk(KERN_DEBUG "%s: failed to clone mesh frame\n",
 -                                                 sdata->dev->name);
 +                                                 sdata->name);
  
                        fwd_hdr =  (struct ieee80211_hdr *) fwd_skb->data;
 -                      memcpy(fwd_hdr->addr2, sdata->dev->dev_addr, ETH_ALEN);
 +                      memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
                        info = IEEE80211_SKB_CB(fwd_skb);
                        memset(info, 0, sizeof(*info));
                        info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
@@@ -1803,7 -1872,7 +1803,7 @@@ static void ieee80211_process_sa_query_
        struct sk_buff *skb;
        struct ieee80211_mgmt *resp;
  
 -      if (compare_ether_addr(mgmt->da, sdata->dev->dev_addr) != 0) {
 +      if (compare_ether_addr(mgmt->da, sdata->vif.addr) != 0) {
                /* Not to own unicast address */
                return;
        }
        resp = (struct ieee80211_mgmt *) skb_put(skb, 24);
        memset(resp, 0, 24);
        memcpy(resp->da, mgmt->sa, ETH_ALEN);
 -      memcpy(resp->sa, sdata->dev->dev_addr, ETH_ALEN);
 +      memcpy(resp->sa, sdata->vif.addr, ETH_ALEN);
        memcpy(resp->bssid, sdata->u.mgd.bssid, ETH_ALEN);
        resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
                                          IEEE80211_STYPE_ACTION);
@@@ -1946,6 -2015,10 +1946,10 @@@ ieee80211_rx_h_action(struct ieee80211_
                }
                break;
        default:
+               /* do not process rejected action frames */
+               if (mgmt->u.action.category & 0x80)
+                       return RX_DROP_MONITOR;
                return RX_CONTINUE;
        }
  
@@@ -1959,7 -2032,6 +1963,7 @@@ ieee80211_rx_h_mgmt(struct ieee80211_rx
  {
        struct ieee80211_sub_if_data *sdata = rx->sdata;
        struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
 +      ieee80211_rx_result rxs;
  
        if (!(rx->flags & IEEE80211_RX_RA_MATCH))
                return RX_DROP_MONITOR;
        if (ieee80211_drop_unencrypted(rx, mgmt->frame_control))
                return RX_DROP_MONITOR;
  
 +      rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb);
 +      if (rxs != RX_CONTINUE)
 +              return rxs;
 +
        if (ieee80211_vif_is_mesh(&sdata->vif))
                return ieee80211_mesh_rx_mgmt(sdata, rx->skb);
  
@@@ -2075,7 -2143,7 +2079,7 @@@ static void ieee80211_rx_cooked_monitor
        skb->protocol = htons(ETH_P_802_2);
  
        list_for_each_entry_rcu(sdata, &local->interfaces, list) {
 -              if (!netif_running(sdata->dev))
 +              if (!ieee80211_sdata_running(sdata))
                        continue;
  
                if (sdata->vif.type != NL80211_IFTYPE_MONITOR ||
@@@ -2212,7 -2280,7 +2216,7 @@@ static int prepare_for_handlers(struct 
                if (!bssid && !sdata->u.mgd.use_4addr)
                        return 0;
                if (!multicast &&
 -                  compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) {
 +                  compare_ether_addr(sdata->vif.addr, hdr->addr1) != 0) {
                        if (!(sdata->dev->flags & IFF_PROMISC))
                                return 0;
                        rx->flags &= ~IEEE80211_RX_RA_MATCH;
                                return 0;
                        rx->flags &= ~IEEE80211_RX_RA_MATCH;
                } else if (!multicast &&
 -                         compare_ether_addr(sdata->dev->dev_addr,
 +                         compare_ether_addr(sdata->vif.addr,
                                              hdr->addr1) != 0) {
                        if (!(sdata->dev->flags & IFF_PROMISC))
                                return 0;
                break;
        case NL80211_IFTYPE_MESH_POINT:
                if (!multicast &&
 -                  compare_ether_addr(sdata->dev->dev_addr,
 +                  compare_ether_addr(sdata->vif.addr,
                                       hdr->addr1) != 0) {
                        if (!(sdata->dev->flags & IFF_PROMISC))
                                return 0;
        case NL80211_IFTYPE_AP_VLAN:
        case NL80211_IFTYPE_AP:
                if (!bssid) {
 -                      if (compare_ether_addr(sdata->dev->dev_addr,
 +                      if (compare_ether_addr(sdata->vif.addr,
                                               hdr->addr1))
                                return 0;
                } else if (!ieee80211_bssid_match(bssid,
 -                                      sdata->dev->dev_addr)) {
 +                                      sdata->vif.addr)) {
                        if (!(rx->flags & IEEE80211_RX_IN_SCAN))
                                return 0;
                        rx->flags &= ~IEEE80211_RX_RA_MATCH;
@@@ -2300,8 -2368,6 +2304,8 @@@ static void __ieee80211_rx_handle_packe
        int prepares;
        struct ieee80211_sub_if_data *prev = NULL;
        struct sk_buff *skb_new;
 +      struct sta_info *sta, *tmp;
 +      bool found_sta = false;
  
        hdr = (struct ieee80211_hdr *)skb->data;
        memset(&rx, 0, sizeof(rx));
        ieee80211_parse_qos(&rx);
        ieee80211_verify_alignment(&rx);
  
 -      rx.sta = sta_info_get(local, hdr->addr2);
 -      if (rx.sta)
 -              rx.sdata = rx.sta->sdata;
 -
 -      if (rx.sdata && ieee80211_is_data(hdr->frame_control)) {
 -              rx.flags |= IEEE80211_RX_RA_MATCH;
 -              prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
 -              if (prepares) {
 -                      if (status->flag & RX_FLAG_MMIC_ERROR) {
 -                              if (rx.flags & IEEE80211_RX_RA_MATCH)
 -                                      ieee80211_rx_michael_mic_report(hdr, &rx);
 -                      } else
 -                              prev = rx.sdata;
 +      if (ieee80211_is_data(hdr->frame_control)) {
 +              for_each_sta_info(local, hdr->addr2, sta, tmp) {
 +                      rx.sta = sta;
 +                      found_sta = true;
 +                      rx.sdata = sta->sdata;
 +
 +                      rx.flags |= IEEE80211_RX_RA_MATCH;
 +                      prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
 +                      if (prepares) {
 +                              if (status->flag & RX_FLAG_MMIC_ERROR) {
 +                                      if (rx.flags & IEEE80211_RX_RA_MATCH)
 +                                              ieee80211_rx_michael_mic_report(hdr, &rx);
 +                              } else
 +                                      prev = rx.sdata;
 +                      }
                }
 -      } else list_for_each_entry_rcu(sdata, &local->interfaces, list) {
 -              if (!netif_running(sdata->dev))
 -                      continue;
 +      }
 +      if (!found_sta) {
 +              list_for_each_entry_rcu(sdata, &local->interfaces, list) {
 +                      if (!ieee80211_sdata_running(sdata))
 +                              continue;
  
 -              if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
 -                  sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 -                      continue;
 +                      if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
 +                          sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 +                              continue;
  
 -              rx.flags |= IEEE80211_RX_RA_MATCH;
 -              prepares = prepare_for_handlers(sdata, &rx, hdr);
 +                      rx.sta = sta_info_get(sdata, hdr->addr2);
  
 -              if (!prepares)
 -                      continue;
 +                      rx.flags |= IEEE80211_RX_RA_MATCH;
 +                      prepares = prepare_for_handlers(sdata, &rx, hdr);
  
 -              if (status->flag & RX_FLAG_MMIC_ERROR) {
 -                      rx.sdata = sdata;
 -                      if (rx.flags & IEEE80211_RX_RA_MATCH)
 -                              ieee80211_rx_michael_mic_report(hdr, &rx);
 -                      continue;
 -              }
 +                      if (!prepares)
 +                              continue;
  
 -              /*
 -               * frame is destined for this interface, but if it's not
 -               * also for the previous one we handle that after the
 -               * loop to avoid copying the SKB once too much
 -               */
 +                      if (status->flag & RX_FLAG_MMIC_ERROR) {
 +                              rx.sdata = sdata;
 +                              if (rx.flags & IEEE80211_RX_RA_MATCH)
 +                                      ieee80211_rx_michael_mic_report(hdr,
 +                                                                      &rx);
 +                              continue;
 +                      }
  
 -              if (!prev) {
 -                      prev = sdata;
 -                      continue;
 -              }
 +                      /*
 +                       * frame is destined for this interface, but if it's
 +                       * not also for the previous one we handle that after
 +                       * the loop to avoid copying the SKB once too much
 +                       */
  
 -              /*
 -               * frame was destined for the previous interface
 -               * so invoke RX handlers for it
 -               */
 +                      if (!prev) {
 +                              prev = sdata;
 +                              continue;
 +                      }
  
 -              skb_new = skb_copy(skb, GFP_ATOMIC);
 -              if (!skb_new) {
 -                      if (net_ratelimit())
 -                              printk(KERN_DEBUG "%s: failed to copy "
 -                                     "multicast frame for %s\n",
 -                                     wiphy_name(local->hw.wiphy),
 -                                     prev->dev->name);
 -                      continue;
 +                      /*
 +                       * frame was destined for the previous interface
 +                       * so invoke RX handlers for it
 +                       */
 +
 +                      skb_new = skb_copy(skb, GFP_ATOMIC);
 +                      if (!skb_new) {
 +                              if (net_ratelimit())
 +                                      printk(KERN_DEBUG "%s: failed to copy "
 +                                             "multicast frame for %s\n",
 +                                             wiphy_name(local->hw.wiphy),
 +                                             prev->name);
 +                              continue;
 +                      }
 +                      ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate);
 +                      prev = sdata;
                }
 -              ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate);
 -              prev = sdata;
        }
        if (prev)
                ieee80211_invoke_rx_handlers(prev, &rx, skb, rate);
diff --combined net/packet/af_packet.c
index a97acfe7e770ec5588d11eb04bb3c181f7237fdd,f126d18dbdc481598fcd4de58c74fd434b0a18f9..53633c5fdb1d612070911a484904906c280a2abf
@@@ -1021,8 -1021,20 +1021,20 @@@ static int tpacket_snd(struct packet_so
  
                status = TP_STATUS_SEND_REQUEST;
                err = dev_queue_xmit(skb);
-               if (unlikely(err > 0 && (err = net_xmit_errno(err)) != 0))
-                       goto out_xmit;
+               if (unlikely(err > 0)) {
+                       err = net_xmit_errno(err);
+                       if (err && __packet_get_status(po, ph) ==
+                                  TP_STATUS_AVAILABLE) {
+                               /* skb was destructed already */
+                               skb = NULL;
+                               goto out_status;
+                       }
+                       /*
+                        * skb was dropped but not destructed yet;
+                        * let's treat it like congestion or err < 0
+                        */
+                       err = 0;
+               }
                packet_increment_head(&po->tx_ring);
                len_sum += tp_len;
        } while (likely((ph != NULL) ||
        err = len_sum;
        goto out_put;
  
- out_xmit:
-       skb->destructor = sock_wfree;
-       atomic_dec(&po->tx_ring.pending);
  out_status:
        __packet_set_status(po, ph, status);
        kfree_skb(skb);
@@@ -2448,7 -2457,7 +2457,7 @@@ static const struct file_operations pac
  
  #endif
  
 -static int packet_net_init(struct net *net)
 +static int __net_init packet_net_init(struct net *net)
  {
        rwlock_init(&net->packet.sklist_lock);
        INIT_HLIST_HEAD(&net->packet.sklist);
        return 0;
  }
  
 -static void packet_net_exit(struct net *net)
 +static void __net_exit packet_net_exit(struct net *net)
  {
        proc_net_remove(net, "packet");
  }
diff --combined net/wireless/core.c
index 0a545bb6ed0537e893a9c0ac1ace32fb99f475dd,92b81244248840fa9ff4437dddf02cbd4beda711..20db90246de5a04889cce289d13edd0f4f5bae5c
@@@ -402,7 -402,6 +402,7 @@@ struct wiphy *wiphy_new(const struct cf
        rdev->wiphy.retry_long = 4;
        rdev->wiphy.frag_threshold = (u32) -1;
        rdev->wiphy.rts_threshold = (u32) -1;
 +      rdev->wiphy.coverage_class = 0;
  
        return &rdev->wiphy;
  }
@@@ -746,9 -745,9 +746,9 @@@ static int cfg80211_netdev_notifier_cal
                        mutex_unlock(&rdev->devlist_mtx);
                        dev_put(dev);
                }
- #ifdef CONFIG_CFG80211_WEXT
                cfg80211_lock_rdev(rdev);
                mutex_lock(&rdev->devlist_mtx);
+ #ifdef CONFIG_CFG80211_WEXT
                wdev_lock(wdev);
                switch (wdev->iftype) {
                case NL80211_IFTYPE_ADHOC:
                        break;
                }
                wdev_unlock(wdev);
+ #endif
                rdev->opencount++;
                mutex_unlock(&rdev->devlist_mtx);
                cfg80211_unlock_rdev(rdev);
- #endif
                break;
        case NETDEV_UNREGISTER:
                /*
diff --combined net/wireless/sme.c
index 2ce5e1609a3dfcec3bcf1aba228b3ee155730197,dc0fc4989d54b1f92738ead9f911f309db863372..745c37e7992e1e410972dcfff89b332fdf619f30
@@@ -454,7 -454,6 +454,7 @@@ void __cfg80211_connect_result(struct n
         * - and country_ie[1] which is the IE length
         */
        regulatory_hint_11d(wdev->wiphy,
 +                          bss->channel->band,
                            country_ie + 2,
                            country_ie[1]);
  }
@@@ -656,6 -655,7 +656,7 @@@ void __cfg80211_disconnected(struct net
        memset(&wrqu, 0, sizeof(wrqu));
        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
        wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+       wdev->wext.connect.ssid_len = 0;
  #endif
  }