]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorDavid S. Miller <davem@davemloft.net>
Tue, 24 Nov 2009 23:01:29 +0000 (15:01 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 24 Nov 2009 23:01:29 +0000 (15:01 -0800)
1  2 
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/iwlwifi/iwl-4965.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-tx.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
net/wireless/core.c

index 9fe0e8078a8820538c7e4e51a4f9da9435816c2c,5b01b5b2e15958da24f59d63e4af51576c155f76..c28984ae46ff4bd2b726ad38589c1b911e71abc3
@@@ -30,7 -30,6 +30,7 @@@
  
  ******************************************************************************/
  
 +#include <linux/sched.h>
  #include "ipw2200.h"
  
  
@@@ -109,6 -108,25 +109,25 @@@ static int antenna = CFG_SYS_ANTENNA_BO
  static int rtap_iface = 0;     /* def: 0 -- do not create rtap interface */
  #endif
  
+ static struct ieee80211_rate ipw2200_rates[] = {
+       { .bitrate = 10 },
+       { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+       { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+       { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+       { .bitrate = 60 },
+       { .bitrate = 90 },
+       { .bitrate = 120 },
+       { .bitrate = 180 },
+       { .bitrate = 240 },
+       { .bitrate = 360 },
+       { .bitrate = 480 },
+       { .bitrate = 540 }
+ };
+ #define ipw2200_a_rates               (ipw2200_rates + 4)
+ #define ipw2200_num_a_rates   8
+ #define ipw2200_bg_rates      (ipw2200_rates + 0)
+ #define ipw2200_num_bg_rates  12
  
  #ifdef CONFIG_IPW2200_QOS
  static int qos_enable = 0;
@@@ -1739,10 -1757,13 +1758,13 @@@ static DEVICE_ATTR(direct_dword, S_IWUS
  
  static int rf_kill_active(struct ipw_priv *priv)
  {
-       if (0 == (ipw_read32(priv, 0x30) & 0x10000))
+       if (0 == (ipw_read32(priv, 0x30) & 0x10000)) {
                priv->status |= STATUS_RF_KILL_HW;
-       else
+               wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true);
+       } else {
                priv->status &= ~STATUS_RF_KILL_HW;
+               wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, false);
+       }
  
        return (priv->status & STATUS_RF_KILL_HW) ? 1 : 0;
  }
@@@ -2025,6 -2046,7 +2047,7 @@@ static void ipw_irq_tasklet(struct ipw_
        if (inta & IPW_INTA_BIT_RF_KILL_DONE) {
                IPW_DEBUG_RF_KILL("RF_KILL_DONE\n");
                priv->status |= STATUS_RF_KILL_HW;
+               wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true);
                wake_up_interruptible(&priv->wait_command_queue);
                priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
                cancel_delayed_work(&priv->request_scan);
@@@ -8660,24 -8682,6 +8683,6 @@@ static int ipw_sw_reset(struct ipw_pri
   *
   */
  
- static int ipw_wx_get_name(struct net_device *dev,
-                          struct iw_request_info *info,
-                          union iwreq_data *wrqu, char *extra)
- {
-       struct ipw_priv *priv = libipw_priv(dev);
-       mutex_lock(&priv->mutex);
-       if (priv->status & STATUS_RF_KILL_MASK)
-               strcpy(wrqu->name, "radio off");
-       else if (!(priv->status & STATUS_ASSOCIATED))
-               strcpy(wrqu->name, "unassociated");
-       else
-               snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c",
-                        ipw_modes[priv->assoc_request.ieee_mode]);
-       IPW_DEBUG_WX("Name: %s\n", wrqu->name);
-       mutex_unlock(&priv->mutex);
-       return 0;
- }
  static int ipw_set_channel(struct ipw_priv *priv, u8 channel)
  {
        if (channel == 0) {
@@@ -9977,7 -9981,7 +9982,7 @@@ static int ipw_wx_sw_reset(struct net_d
  /* Rebase the WE IOCTLs to zero for the handler array */
  #define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT]
  static iw_handler ipw_wx_handlers[] = {
-       IW_IOCTL(SIOCGIWNAME) = ipw_wx_get_name,
+       IW_IOCTL(SIOCGIWNAME) = (iw_handler) cfg80211_wext_giwname,
        IW_IOCTL(SIOCSIWFREQ) = ipw_wx_set_freq,
        IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq,
        IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode,
@@@ -11422,16 -11426,100 +11427,100 @@@ static void ipw_bg_down(struct work_str
  /* Called by register_netdev() */
  static int ipw_net_init(struct net_device *dev)
  {
+       int i, rc = 0;
        struct ipw_priv *priv = libipw_priv(dev);
+       const struct libipw_geo *geo = libipw_get_geo(priv->ieee);
+       struct wireless_dev *wdev = &priv->ieee->wdev;
        mutex_lock(&priv->mutex);
  
        if (ipw_up(priv)) {
-               mutex_unlock(&priv->mutex);
-               return -EIO;
+               rc = -EIO;
+               goto out;
+       }
+       memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN);
+       /* fill-out priv->ieee->bg_band */
+       if (geo->bg_channels) {
+               struct ieee80211_supported_band *bg_band = &priv->ieee->bg_band;
+               bg_band->band = IEEE80211_BAND_2GHZ;
+               bg_band->n_channels = geo->bg_channels;
+               bg_band->channels =
+                       kzalloc(geo->bg_channels *
+                               sizeof(struct ieee80211_channel), GFP_KERNEL);
+               /* translate geo->bg to bg_band.channels */
+               for (i = 0; i < geo->bg_channels; i++) {
+                       bg_band->channels[i].band = IEEE80211_BAND_2GHZ;
+                       bg_band->channels[i].center_freq = geo->bg[i].freq;
+                       bg_band->channels[i].hw_value = geo->bg[i].channel;
+                       bg_band->channels[i].max_power = geo->bg[i].max_power;
+                       if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY)
+                               bg_band->channels[i].flags |=
+                                       IEEE80211_CHAN_PASSIVE_SCAN;
+                       if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS)
+                               bg_band->channels[i].flags |=
+                                       IEEE80211_CHAN_NO_IBSS;
+                       if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT)
+                               bg_band->channels[i].flags |=
+                                       IEEE80211_CHAN_RADAR;
+                       /* No equivalent for LIBIPW_CH_80211H_RULES,
+                          LIBIPW_CH_UNIFORM_SPREADING, or
+                          LIBIPW_CH_B_ONLY... */
+               }
+               /* point at bitrate info */
+               bg_band->bitrates = ipw2200_bg_rates;
+               bg_band->n_bitrates = ipw2200_num_bg_rates;
+               wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band;
        }
  
+       /* fill-out priv->ieee->a_band */
+       if (geo->a_channels) {
+               struct ieee80211_supported_band *a_band = &priv->ieee->a_band;
+               a_band->band = IEEE80211_BAND_5GHZ;
+               a_band->n_channels = geo->a_channels;
+               a_band->channels =
+                       kzalloc(geo->a_channels *
+                               sizeof(struct ieee80211_channel), GFP_KERNEL);
+               /* translate geo->bg to a_band.channels */
+               for (i = 0; i < geo->a_channels; i++) {
+                       a_band->channels[i].band = IEEE80211_BAND_2GHZ;
+                       a_band->channels[i].center_freq = geo->a[i].freq;
+                       a_band->channels[i].hw_value = geo->a[i].channel;
+                       a_band->channels[i].max_power = geo->a[i].max_power;
+                       if (geo->a[i].flags & LIBIPW_CH_PASSIVE_ONLY)
+                               a_band->channels[i].flags |=
+                                       IEEE80211_CHAN_PASSIVE_SCAN;
+                       if (geo->a[i].flags & LIBIPW_CH_NO_IBSS)
+                               a_band->channels[i].flags |=
+                                       IEEE80211_CHAN_NO_IBSS;
+                       if (geo->a[i].flags & LIBIPW_CH_RADAR_DETECT)
+                               a_band->channels[i].flags |=
+                                       IEEE80211_CHAN_RADAR;
+                       /* No equivalent for LIBIPW_CH_80211H_RULES,
+                          LIBIPW_CH_UNIFORM_SPREADING, or
+                          LIBIPW_CH_B_ONLY... */
+               }
+               /* point at bitrate info */
+               a_band->bitrates = ipw2200_a_rates;
+               a_band->n_bitrates = ipw2200_num_a_rates;
+               wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = a_band;
+       }
+       set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev);
+       /* With that information in place, we can now register the wiphy... */
+       if (wiphy_register(wdev->wiphy)) {
+               rc = -EIO;
+               goto out;
+       }
+ out:
        mutex_unlock(&priv->mutex);
-       return 0;
+       return rc;
  }
  
  /* PCI driver stuff */
@@@ -11562,7 -11650,7 +11651,7 @@@ static int ipw_prom_alloc(struct ipw_pr
        if (priv->prom_net_dev)
                return -EPERM;
  
-       priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv));
+       priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv), 1);
        if (priv->prom_net_dev == NULL)
                return -ENOMEM;
  
  
        rc = register_netdev(priv->prom_net_dev);
        if (rc) {
-               free_ieee80211(priv->prom_net_dev);
+               free_ieee80211(priv->prom_net_dev, 1);
                priv->prom_net_dev = NULL;
                return rc;
        }
@@@ -11595,7 -11683,7 +11684,7 @@@ static void ipw_prom_free(struct ipw_pr
                return;
  
        unregister_netdev(priv->prom_net_dev);
-       free_ieee80211(priv->prom_net_dev);
+       free_ieee80211(priv->prom_net_dev, 1);
  
        priv->prom_net_dev = NULL;
  }
@@@ -11623,7 -11711,7 +11712,7 @@@ static int __devinit ipw_pci_probe(stru
        struct ipw_priv *priv;
        int i;
  
-       net_dev = alloc_ieee80211(sizeof(struct ipw_priv));
+       net_dev = alloc_ieee80211(sizeof(struct ipw_priv), 0);
        if (net_dev == NULL) {
                err = -ENOMEM;
                goto out;
        pci_disable_device(pdev);
        pci_set_drvdata(pdev, NULL);
        out_free_ieee80211:
-       free_ieee80211(priv->net_dev);
+       free_ieee80211(priv->net_dev, 0);
        out:
        return err;
  }
@@@ -11838,7 -11926,11 +11927,11 @@@ static void __devexit ipw_pci_remove(st
        pci_release_regions(pdev);
        pci_disable_device(pdev);
        pci_set_drvdata(pdev, NULL);
-       free_ieee80211(priv->net_dev);
+       /* wiphy_unregister needs to be here, before free_ieee80211 */
+       wiphy_unregister(priv->ieee->wdev.wiphy);
+       kfree(priv->ieee->a_band.channels);
+       kfree(priv->ieee->bg_band.channels);
+       free_ieee80211(priv->net_dev, 0);
        free_firmware();
  }
  
index cc3942448703a4d22b5c25b950cde1ec00c4638a,a8914898133eb535bc0c5ac6f89a6434f8215e63..386513b601f5caff86e22c73d90e106015cdc8be
@@@ -30,7 -30,6 +30,7 @@@
  #include <linux/pci.h>
  #include <linux/dma-mapping.h>
  #include <linux/delay.h>
 +#include <linux/sched.h>
  #include <linux/skbuff.h>
  #include <linux/netdevice.h>
  #include <linux/wireless.h>
@@@ -1818,8 -1817,9 +1818,9 @@@ static u16 iwl4965_build_addsta_hcmd(co
        addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid;
        addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid;
        addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn;
+       addsta->sleep_tx_count = cmd->sleep_tx_count;
        addsta->reserved1 = cpu_to_le16(0);
-       addsta->reserved2 = cpu_to_le32(0);
+       addsta->reserved2 = cpu_to_le16(0);
  
        return (u16)sizeof(struct iwl4965_addsta_cmd);
  }
@@@ -1865,8 -1865,7 +1866,7 @@@ static int iwl4965_tx_status_reply_tx(s
                info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]);
                info->status.rates[0].count = tx_resp->failure_frame + 1;
                info->flags &= ~IEEE80211_TX_CTL_AMPDU;
-               info->flags |= iwl_is_tx_success(status) ?
-                       IEEE80211_TX_STAT_ACK : 0;
+               info->flags |= iwl_tx_status_to_mac80211(status);
                iwl_hwrate_to_tx_control(priv, rate_n_flags, info);
                /* FIXME: code repetition end */
  
@@@ -2021,8 -2020,7 +2021,7 @@@ static void iwl4965_rx_reply_tx(struct 
                }
        } else {
                info->status.rates[0].count = tx_resp->failure_frame + 1;
-               info->flags |= iwl_is_tx_success(status) ?
-                                       IEEE80211_TX_STAT_ACK : 0;
+               info->flags |= iwl_tx_status_to_mac80211(status);
                iwl_hwrate_to_tx_control(priv,
                                        le32_to_cpu(tx_resp->rate_n_flags),
                                        info);
@@@ -2240,6 -2238,7 +2239,7 @@@ 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 e23d301e816fc21fc8e0f36273d9f02a59245e64,9175158f3580a28047c955ac1e87b4adf102cd4b..e2f8615c8c9b77bf81004bc7e415133fc5b2eb74
@@@ -29,7 -29,6 +29,7 @@@
  #include <linux/pci.h>
  #include <linux/dma-mapping.h>
  #include <linux/delay.h>
 +#include <linux/sched.h>
  #include <linux/skbuff.h>
  #include <linux/netdevice.h>
  #include <linux/wireless.h>
@@@ -994,8 -993,7 +994,7 @@@ static int iwl5000_tx_status_reply_tx(s
                info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]);
                info->status.rates[0].count = tx_resp->failure_frame + 1;
                info->flags &= ~IEEE80211_TX_CTL_AMPDU;
-               info->flags |= iwl_is_tx_success(status) ?
-                                       IEEE80211_TX_STAT_ACK : 0;
+               info->flags |= iwl_tx_status_to_mac80211(status);
                iwl_hwrate_to_tx_control(priv, rate_n_flags, info);
  
                /* FIXME: code repetition end */
@@@ -1140,8 -1138,7 +1139,7 @@@ static void iwl5000_rx_reply_tx(struct 
                BUG_ON(txq_id != txq->swq_id);
  
                info->status.rates[0].count = tx_resp->failure_frame + 1;
-               info->flags |= iwl_is_tx_success(status) ?
-                                       IEEE80211_TX_STAT_ACK : 0;
+               info->flags |= iwl_tx_status_to_mac80211(status);
                iwl_hwrate_to_tx_control(priv,
                                        le32_to_cpu(tx_resp->rate_n_flags),
                                        info);
@@@ -1251,6 -1248,22 +1249,22 @@@ int  iwl5000_send_tx_power(struct iwl_p
  
        /* half dBm need to multiply */
        tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt);
+       if (priv->tx_power_lmt_in_half_dbm &&
+           priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) {
+               /*
+                * For the newer devices which using enhanced/extend tx power
+                * table in EEPROM, the format is in half dBm. driver need to
+                * convert to dBm format before report to mac80211.
+                * By doing so, there is a possibility of 1/2 dBm resolution
+                * lost. driver will perform "round-up" operation before
+                * reporting, but it will cause 1/2 dBm tx power over the
+                * regulatory limit. Perform the checking here, if the
+                * "tx_power_user_lmt" is higher than EEPROM value (in
+                * half-dBm format), lower the tx power based on EEPROM
+                */
+               tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm;
+       }
        tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED;
        tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO;
  
@@@ -1584,14 -1597,15 +1598,15 @@@ struct iwl_cfg iwl5300_agn_cfg = 
        .ht_greenfield_support = true,
        .led_compensation = 51,
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
+       .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
  };
  
- struct iwl_cfg iwl5100_bg_cfg = {
-       .name = "5100BG",
+ struct iwl_cfg iwl5100_bgn_cfg = {
+       .name = "5100BGN",
        .fw_name_pre = IWL5000_FW_PRE,
        .ucode_api_max = IWL5000_UCODE_API_MAX,
        .ucode_api_min = IWL5000_UCODE_API_MIN,
-       .sku = IWL_SKU_G,
+       .sku = IWL_SKU_G|IWL_SKU_N,
        .ops = &iwl5000_ops,
        .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
        .eeprom_ver = EEPROM_5000_EEPROM_VERSION,
@@@ -1627,7 -1641,6 +1642,6 @@@ struct iwl_cfg iwl5100_abg_cfg = 
        .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
        .set_l0s = true,
        .use_bsm = false,
-       .ht_greenfield_support = true,
        .led_compensation = 51,
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
  };
@@@ -1653,6 -1666,7 +1667,7 @@@ struct iwl_cfg iwl5100_agn_cfg = 
        .ht_greenfield_support = true,
        .led_compensation = 51,
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
+       .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
  };
  
  struct iwl_cfg iwl5350_agn_cfg = {
        .ht_greenfield_support = true,
        .led_compensation = 51,
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
+       .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
  };
  
  struct iwl_cfg iwl5150_agn_cfg = {
        .ht_greenfield_support = true,
        .led_compensation = 51,
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
+       .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
+ };
+ struct iwl_cfg iwl5150_abg_cfg = {
+       .name = "5150ABG",
+       .fw_name_pre = IWL5150_FW_PRE,
+       .ucode_api_max = IWL5150_UCODE_API_MAX,
+       .ucode_api_min = IWL5150_UCODE_API_MIN,
+       .sku = IWL_SKU_A|IWL_SKU_G,
+       .ops = &iwl5150_ops,
+       .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+       .eeprom_ver = EEPROM_5050_EEPROM_VERSION,
+       .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
+       .num_of_queues = IWL50_NUM_QUEUES,
+       .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
+       .mod_params = &iwl50_mod_params,
+       .valid_tx_ant = ANT_A,
+       .valid_rx_ant = ANT_AB,
+       .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
+       .set_l0s = true,
+       .use_bsm = false,
+       .led_compensation = 51,
+       .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
  };
  
  MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
index 29f7510ecdd7076a063e30819a2a8b2fe9452e20,9b04b25f0e579376d1f344860c6a468e2d402cc3..c96513bddb10b17bc7c81bd8196dd41440ca912c
@@@ -33,7 -33,6 +33,7 @@@
  #include <linux/pci.h>
  #include <linux/dma-mapping.h>
  #include <linux/delay.h>
 +#include <linux/sched.h>
  #include <linux/skbuff.h>
  #include <linux/netdevice.h>
  #include <linux/wireless.h>
@@@ -311,7 -310,7 +311,7 @@@ static void iwl_free_frame(struct iwl_p
        list_add(&frame->list, &priv->free_frames);
  }
  
- static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv,
+ static u32 iwl_fill_beacon_frame(struct iwl_priv *priv,
                                          struct ieee80211_hdr *hdr,
                                          int left)
  {
        return priv->ibss_beacon->len;
  }
  
+ /* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */
+ static void iwl_set_beacon_tim(struct iwl_priv *priv,
+               struct iwl_tx_beacon_cmd *tx_beacon_cmd,
+               u8 *beacon, u32 frame_size)
+ {
+       u16 tim_idx;
+       struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
+       /*
+        * The index is relative to frame start but we start looking at the
+        * variable-length part of the beacon.
+        */
+       tim_idx = mgmt->u.beacon.variable - beacon;
+       /* Parse variable-length elements of beacon to find WLAN_EID_TIM */
+       while ((tim_idx < (frame_size - 2)) &&
+                       (beacon[tim_idx] != WLAN_EID_TIM))
+               tim_idx += beacon[tim_idx+1] + 2;
+       /* If TIM field was found, set variables */
+       if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) {
+               tx_beacon_cmd->tim_idx = cpu_to_le16(tim_idx);
+               tx_beacon_cmd->tim_size = beacon[tim_idx+1];
+       } else
+               IWL_WARN(priv, "Unable to find TIM Element in beacon\n");
+ }
  static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
-                                      struct iwl_frame *frame, u8 rate)
+                                      struct iwl_frame *frame)
  {
        struct iwl_tx_beacon_cmd *tx_beacon_cmd;
-       unsigned int frame_size;
+       u32 frame_size;
+       u32 rate_flags;
+       u32 rate;
+       /*
+        * We have to set up the TX command, the TX Beacon command, and the
+        * beacon contents.
+        */
  
+       /* Initialize memory */
        tx_beacon_cmd = &frame->u.beacon;
        memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
  
-       tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id;
-       tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+       /* Set up TX beacon contents */
        frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame,
                                sizeof(frame->u) - sizeof(*tx_beacon_cmd));
+       if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE))
+               return 0;
  
-       BUG_ON(frame_size > MAX_MPDU_SIZE);
+       /* Set up TX command fields */
        tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
+       tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id;
+       tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+       tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK |
+               TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK;
  
-       if ((rate == IWL_RATE_1M_PLCP) || (rate >= IWL_RATE_2M_PLCP))
-               tx_beacon_cmd->tx.rate_n_flags =
-                       iwl_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK);
-       else
-               tx_beacon_cmd->tx.rate_n_flags =
-                       iwl_hw_set_rate_n_flags(rate, 0);
+       /* Set up TX beacon command fields */
+       iwl_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame,
+                       frame_size);
  
-       tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK |
-                                    TX_CMD_FLG_TSF_MSK |
-                                    TX_CMD_FLG_STA_RATE_MSK;
+       /* Set up packet rate and flags */
+       rate = iwl_rate_get_lowest_plcp(priv);
+       priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant);
+       rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
+       if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE))
+               rate_flags |= RATE_MCS_CCK_MSK;
+       tx_beacon_cmd->tx.rate_n_flags = iwl_hw_set_rate_n_flags(rate,
+                       rate_flags);
  
        return sizeof(*tx_beacon_cmd) + frame_size;
  }
@@@ -364,19 -403,20 +404,20 @@@ static int iwl_send_beacon_cmd(struct i
        struct iwl_frame *frame;
        unsigned int frame_size;
        int rc;
-       u8 rate;
  
        frame = iwl_get_free_frame(priv);
        if (!frame) {
                IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
                          "command.\n");
                return -ENOMEM;
        }
  
-       rate = iwl_rate_get_lowest_plcp(priv);
-       frame_size = iwl_hw_get_beacon_cmd(priv, frame, rate);
+       frame_size = iwl_hw_get_beacon_cmd(priv, frame);
+       if (!frame_size) {
+               IWL_ERR(priv, "Error configuring the beacon command\n");
+               iwl_free_frame(priv, frame);
+               return -EINVAL;
+       }
  
        rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
                              &frame->u.cmd[0]);
@@@ -613,7 -653,7 +654,7 @@@ static void iwl_bg_statistics_periodic(
        if (!iwl_is_ready_rf(priv))
                return;
  
-       iwl_send_statistics_request(priv, CMD_ASYNC);
+       iwl_send_statistics_request(priv, CMD_ASYNC, false);
  }
  
  static void iwl_rx_beacon_notif(struct iwl_priv *priv,
@@@ -730,7 -770,7 +771,7 @@@ static void iwl_setup_rx_handlers(struc
         * statistics request from the host as well as for the periodic
         * statistics notifications (after received beacons) from the uCode.
         */
-       priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_rx_statistics;
+       priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_reply_statistics;
        priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics;
  
        iwl_setup_spectrum_handlers(priv);
@@@ -1038,7 -1078,6 +1079,6 @@@ static void iwl_irq_tasklet_legacy(stru
        if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
                iwl_rx_handle(priv);
                priv->isr_stats.rx++;
-               iwl_leds_background(priv);
                handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
        }
  
@@@ -1226,19 -1265,27 +1266,27 @@@ static void iwl_irq_tasklet(struct iwl_
                 * 3- update RX shared data to indicate last write index.
                 * 4- send interrupt.
                 * This could lead to RX race, driver could receive RX interrupt
-                * but the shared data changes does not reflect this.
-                * this could lead to RX race, RX periodic will solve this race
+                * but the shared data changes does not reflect this;
+                * periodic interrupt will detect any dangling Rx activity.
                 */
-               iwl_write32(priv, CSR_INT_PERIODIC_REG,
+               /* Disable periodic interrupt; we use it as just a one-shot. */
+               iwl_write8(priv, CSR_INT_PERIODIC_REG,
                            CSR_INT_PERIODIC_DIS);
                iwl_rx_handle(priv);
-               /* Only set RX periodic if real RX is received. */
+               /*
+                * Enable periodic interrupt in 8 msec only if we received
+                * real RX interrupt (instead of just periodic int), to catch
+                * any dangling Rx interrupt.  If it was just the periodic
+                * interrupt, there was no dangling Rx activity, and no need
+                * to extend the periodic interrupt; one-shot is enough.
+                */
                if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX))
-                       iwl_write32(priv, CSR_INT_PERIODIC_REG,
+                       iwl_write8(priv, CSR_INT_PERIODIC_REG,
                                    CSR_INT_PERIODIC_ENA);
  
                priv->isr_stats.rx++;
-               iwl_leds_background(priv);
        }
  
        /* This "Tx" DMA channel is used only for loading uCode */
@@@ -1557,7 -1604,6 +1605,6 @@@ static int iwl_read_ucode(struct iwl_pr
        return ret;
  }
  
- #ifdef CONFIG_IWLWIFI_DEBUG
  static const char *desc_lookup_text[] = {
        "OK",
        "FAIL",
@@@ -1710,10 -1756,42 +1757,42 @@@ static void iwl_print_event_log(struct 
        spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
  }
  
+ /**
+  * iwl_print_last_event_logs - Dump the newest # of event log to syslog
+  */
+ static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
+                                     u32 num_wraps, u32 next_entry,
+                                     u32 size, u32 mode)
+ {
+       /*
+        * display the newest DEFAULT_LOG_ENTRIES entries
+        * i.e the entries just before the next ont that uCode would fill.
+        */
+       if (num_wraps) {
+               if (next_entry < size) {
+                       iwl_print_event_log(priv,
+                                       capacity - (size - next_entry),
+                                       size - next_entry, mode);
+                       iwl_print_event_log(priv, 0,
+                                   next_entry, mode);
+               } else
+                       iwl_print_event_log(priv, next_entry - size,
+                                   size, mode);
+       } else {
+               if (next_entry < size)
+                       iwl_print_event_log(priv, 0, next_entry, mode);
+               else
+                       iwl_print_event_log(priv, next_entry - size,
+                                           size, mode);
+       }
+ }
  /* For sanity check only.  Actual size is determined by uCode, typ. 512 */
  #define MAX_EVENT_LOG_SIZE (512)
  
- void iwl_dump_nic_event_log(struct iwl_priv *priv)
+ #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
+ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log)
  {
        u32 base;       /* SRAM byte address of event log header */
        u32 capacity;   /* event log capacity in # entries */
                return;
        }
  
-       IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n",
-                       size, num_wraps);
-       /* if uCode has wrapped back to top of log, start at the oldest entry,
-        * i.e the next one that uCode would fill. */
-       if (num_wraps)
-               iwl_print_event_log(priv, next_entry,
-                                       capacity - next_entry, mode);
-       /* (then/else) start at top of log */
-       iwl_print_event_log(priv, 0, next_entry, mode);
+ #ifdef CONFIG_IWLWIFI_DEBUG
+       if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS))
+               size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
+                       ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
+ #else
+       size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
+               ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
+ #endif
+       IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n",
+               size);
  
- }
+ #ifdef CONFIG_IWLWIFI_DEBUG
+       if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
+               /*
+                * if uCode has wrapped back to top of log,
+                * start at the oldest entry,
+                * i.e the next one that uCode would fill.
+                */
+               if (num_wraps)
+                       iwl_print_event_log(priv, next_entry,
+                                           capacity - next_entry, mode);
+               /* (then/else) start at top of log */
+               iwl_print_event_log(priv, 0, next_entry, mode);
+       } else
+               iwl_print_last_event_logs(priv, capacity, num_wraps,
+                                       next_entry, size, mode);
+ #else
+       iwl_print_last_event_logs(priv, capacity, num_wraps,
+                               next_entry, size, mode);
  #endif
+ }
  
  /**
   * iwl_alive_start - called after REPLY_ALIVE notification received
@@@ -2360,16 -2456,14 +2457,14 @@@ static int iwl_setup_mac(struct iwl_pri
                BIT(NL80211_IFTYPE_STATION) |
                BIT(NL80211_IFTYPE_ADHOC);
  
-       hw->wiphy->custom_regulatory = true;
-       /* Firmware does not support this */
-       hw->wiphy->disable_beacon_hints = true;
+       hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY |
+                           WIPHY_FLAG_DISABLE_BEACON_HINTS;
  
        /*
         * For now, disable PS by default because it affects
         * RX performance significantly.
         */
-       hw->wiphy->ps_default = false;
+       hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
  
        hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
        /* we create the 802.11 header and a zero-length SSID element */
@@@ -2523,6 -2617,10 +2618,10 @@@ void iwl_config_ap(struct iwl_priv *pri
                        IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
                                        "Attempting to continue.\n");
  
+               /* AP has all antennas */
+               priv->chain_noise_data.active_chains =
+                       priv->hw_params.valid_rx_ant;
+               iwl_set_rxon_ht(priv, &priv->current_ht_config);
                if (priv->cfg->ops->hcmd->set_rxon_chain)
                        priv->cfg->ops->hcmd->set_rxon_chain(priv);
  
                /* restore RXON assoc */
                priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
                iwlcore_commit_rxon(priv);
+               iwl_reset_qos(priv);
                spin_lock_irqsave(&priv->lock, flags);
                iwl_activate_qos(priv, 1);
                spin_unlock_irqrestore(&priv->lock, flags);
@@@ -2646,6 -2745,7 +2746,7 @@@ static int iwl_mac_set_key(struct ieee8
  }
  
  static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif,
                             enum ieee80211_ampdu_mlme_action action,
                             struct ieee80211_sta *sta, u16 tid, u16 *ssn)
  {
@@@ -2699,6 -2799,45 +2800,45 @@@ static int iwl_mac_get_stats(struct iee
        return 0;
  }
  
+ static void iwl_mac_sta_notify(struct ieee80211_hw *hw,
+                              struct ieee80211_vif *vif,
+                              enum sta_notify_cmd cmd,
+                              struct ieee80211_sta *sta)
+ {
+       struct iwl_priv *priv = hw->priv;
+       struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+       int sta_id;
+       /*
+        * TODO: We really should use this callback to
+        *       actually maintain the station table in
+        *       the device.
+        */
+       switch (cmd) {
+       case STA_NOTIFY_ADD:
+               atomic_set(&sta_priv->pending_frames, 0);
+               if (vif->type == NL80211_IFTYPE_AP)
+                       sta_priv->client = true;
+               break;
+       case STA_NOTIFY_SLEEP:
+               WARN_ON(!sta_priv->client);
+               sta_priv->asleep = true;
+               if (atomic_read(&sta_priv->pending_frames) > 0)
+                       ieee80211_sta_block_awake(hw, sta, true);
+               break;
+       case STA_NOTIFY_AWAKE:
+               WARN_ON(!sta_priv->client);
+               sta_priv->asleep = false;
+               sta_id = iwl_find_station(priv, sta->addr);
+               if (sta_id != IWL_INVALID_STATION)
+                       iwl_sta_modify_ps_wake(priv, sta_id);
+               break;
+       default:
+               break;
+       }
+ }
  /*****************************************************************************
   *
   * sysfs attributes
@@@ -2893,7 -3032,7 +3033,7 @@@ static ssize_t show_statistics(struct d
                return -EAGAIN;
  
        mutex_lock(&priv->mutex);
-       rc = iwl_send_statistics_request(priv, 0);
+       rc = iwl_send_statistics_request(priv, CMD_SYNC, false);
        mutex_unlock(&priv->mutex);
  
        if (rc) {
@@@ -3045,10 -3184,6 +3185,6 @@@ static int iwl_init_drv(struct iwl_pri
        priv->band = IEEE80211_BAND_2GHZ;
  
        priv->iw_mode = NL80211_IFTYPE_STATION;
-       if (priv->cfg->support_sm_ps)
-               priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DYNAMIC;
-       else
-               priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED;
  
        /* Choose which receivers/antennas to use */
        if (priv->cfg->ops->hcmd->set_rxon_chain)
@@@ -3130,7 -3265,8 +3266,8 @@@ static struct ieee80211_ops iwl_hw_ops 
        .reset_tsf = iwl_mac_reset_tsf,
        .bss_info_changed = iwl_bss_info_changed,
        .ampdu_action = iwl_mac_ampdu_action,
-       .hw_scan = iwl_mac_hw_scan
+       .hw_scan = iwl_mac_hw_scan,
+       .sta_notify = iwl_mac_sta_notify,
  };
  
  static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
@@@ -3454,23 -3590,63 +3591,63 @@@ static struct pci_device_id iwl_hw_card
        {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)},
  #endif /* CONFIG_IWL4965 */
  #ifdef CONFIG_IWL5000
-       {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bg_cfg)},
-       {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bg_cfg)},
-       {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)},
-       {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)},
-       {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)},
-       {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)},
-       {IWL_PCI_DEVICE(0x4232, PCI_ANY_ID, iwl5100_agn_cfg)},
-       {IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)},
-       {IWL_PCI_DEVICE(0x4236, PCI_ANY_ID, iwl5300_agn_cfg)},
-       {IWL_PCI_DEVICE(0x4237, PCI_ANY_ID, iwl5100_agn_cfg)},
- /* 5350 WiFi/WiMax */
-       {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)},
-       {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)},
-       {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)},
- /* 5150 Wifi/WiMax */
-       {IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)},
-       {IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)},
+ /* 5100 Series WiFi */
+       {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */
+ /* 5300 Series WiFi */
+       {IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */
+ /* 5350 Series WiFi/WiMax */
+       {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */
+ /* 5150 Series Wifi/WiMax */
+       {IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */
  
  /* 6x00 Series */
        {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
        {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
  
  /* 6x50 WiFi/WiMax Series */
-       {IWL_PCI_DEVICE(0x0086, 0x1101, iwl6050_3agn_cfg)},
-       {IWL_PCI_DEVICE(0x0086, 0x1121, iwl6050_3agn_cfg)},
        {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
        {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)},
        {IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)},
        {IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x0088, 0x1111, iwl6050_3agn_cfg)},
        {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)},
        {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)},
  
index 6b18aab8fa9ba4a1a7c8804eccc2f06e71ca0796,3629aea250abdb3f0bf1bd3114685e8d4ad40985..574d366587022fdd101f7826221a1d15900d9782
@@@ -29,7 -29,6 +29,7 @@@
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/etherdevice.h>
 +#include <linux/sched.h>
  #include <net/mac80211.h>
  
  #include "iwl-eeprom.h"
@@@ -209,6 -208,7 +209,7 @@@ u8 iwl_toggle_tx_ant(struct iwl_priv *p
        }
        return ant;
  }
+ EXPORT_SYMBOL(iwl_toggle_tx_ant);
  
  const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
  EXPORT_SYMBOL(iwl_bcast_addr);
@@@ -255,7 -255,10 +256,10 @@@ int iwl_hw_nic_init(struct iwl_priv *pr
        /* nic_init */
        spin_lock_irqsave(&priv->lock, flags);
        priv->cfg->ops->lib->apm_ops.init(priv);
-       iwl_write32(priv, CSR_INT_COALESCING, 512 / 32);
+       /* Set interrupt coalescing timer to 512 usecs */
+       iwl_write8(priv, CSR_INT_COALESCING, 512 / 32);
        spin_unlock_irqrestore(&priv->lock, flags);
  
        ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN);
@@@ -446,13 -449,8 +450,8 @@@ 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;
-       if (priv->cfg->support_sm_ps)
-               ht_info->cap |= (IEEE80211_HT_CAP_SM_PS &
-                                    (WLAN_HT_CAP_SM_PS_DYNAMIC << 2));
-       else
-               ht_info->cap |= (IEEE80211_HT_CAP_SM_PS &
-                                    (WLAN_HT_CAP_SM_PS_DISABLED << 2));
+       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;
@@@ -1007,25 -1005,23 +1006,23 @@@ static int iwl_get_idle_rx_chain_count(
        int idle_cnt = active_cnt;
        bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
  
-       if (priv->cfg->support_sm_ps) {
-               /* # Rx chains when idling and maybe trying to save power */
-               switch (priv->current_ht_config.sm_ps) {
-               case WLAN_HT_CAP_SM_PS_STATIC:
-               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:
-                       idle_cnt = (is_cam) ? active_cnt :
-                               IWL_NUM_IDLE_CHAINS_SINGLE;
-                       break;
-               case WLAN_HT_CAP_SM_PS_INVALID:
-               default:
-                       IWL_ERR(priv, "invalid sm_ps mode %d\n",
-                               priv->current_ht_config.sm_ps);
-                       WARN_ON(1);
-                       break;
-               }
+       /* # 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:
+       default:
+               IWL_ERR(priv, "invalid sm_ps mode %u\n",
+                       priv->cfg->sm_ps_mode);
+               WARN_ON(1);
+               break;
        }
        return idle_cnt;
  }
@@@ -1365,12 -1361,11 +1362,11 @@@ void iwl_irq_handle_error(struct iwl_pr
        /* Cancel currently queued command. */
        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);
  #ifdef CONFIG_IWLWIFI_DEBUG
-       if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) {
-               priv->cfg->ops->lib->dump_nic_error_log(priv);
-               priv->cfg->ops->lib->dump_nic_event_log(priv);
+       if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)
                iwl_print_rx_config_cmd(priv);
-       }
  #endif
  
        wake_up_interruptible(&priv->wait_command_queue);
@@@ -1991,16 -1986,21 +1987,21 @@@ int iwl_send_bt_config(struct iwl_priv 
  }
  EXPORT_SYMBOL(iwl_send_bt_config);
  
- int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags)
+ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
  {
-       u32 stat_flags = 0;
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_STATISTICS_CMD,
-               .flags = flags,
-               .len = sizeof(stat_flags),
-               .data = (u8 *) &stat_flags,
+       struct iwl_statistics_cmd statistics_cmd = {
+               .configuration_flags =
+                       clear ? IWL_STATS_CONF_CLEAR_STATS : 0,
        };
-       return iwl_send_cmd(priv, &cmd);
+       if (flags & CMD_ASYNC)
+               return iwl_send_cmd_pdu_async(priv, REPLY_STATISTICS_CMD,
+                                              sizeof(struct iwl_statistics_cmd),
+                                              &statistics_cmd, NULL);
+       else
+               return iwl_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
+                                       sizeof(struct iwl_statistics_cmd),
+                                       &statistics_cmd);
  }
  EXPORT_SYMBOL(iwl_send_statistics_request);
  
@@@ -2477,6 -2477,16 +2478,16 @@@ void iwl_bss_info_changed(struct ieee80
                } 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);
                }
        }
  
                }
        }
  
+       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);
+       }
        mutex_unlock(&priv->mutex);
  
        IWL_DEBUG_MAC80211(priv, "leave\n");
@@@ -3070,15 -3088,11 +3089,11 @@@ const char *get_ctrl_string(int cmd
        }
  }
  
- void iwl_clear_tx_stats(struct iwl_priv *priv)
+ void iwl_clear_traffic_stats(struct iwl_priv *priv)
  {
        memset(&priv->tx_stats, 0, sizeof(struct traffic_stats));
- }
- void iwl_clear_rx_stats(struct iwl_priv *priv)
- {
        memset(&priv->rx_stats, 0, sizeof(struct traffic_stats));
+       priv->led_tpt = 0;
  }
  
  /*
@@@ -3171,6 -3185,7 +3186,7 @@@ void iwl_update_stats(struct iwl_priv *
                stats->data_cnt++;
                stats->data_bytes += len;
        }
+       iwl_leds_background(priv);
  }
  EXPORT_SYMBOL(iwl_update_stats);
  #endif
index 6199bf60d3132e13ba6a9864c1be4ec6a2acce79,2eee950e01957bdaa46f28c9a29af1eef03f6422..888a8e9fe9ef0b2b2896847fd8f661656cc767c8
@@@ -28,7 -28,6 +28,7 @@@
   *****************************************************************************/
  
  #include <linux/etherdevice.h>
 +#include <linux/sched.h>
  #include <net/mac80211.h>
  #include "iwl-eeprom.h"
  #include "iwl-dev.h"
@@@ -710,6 -709,8 +710,8 @@@ int iwl_tx_skb(struct iwl_priv *priv, s
  {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_sta *sta = info->control.sta;
+       struct iwl_station_priv *sta_priv = NULL;
        struct iwl_tx_queue *txq;
        struct iwl_queue *q;
        struct iwl_device_cmd *out_cmd;
  
        IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
  
+       if (sta)
+               sta_priv = (void *)sta->drv_priv;
+       if (sta_priv && sta_id != priv->hw_params.bcast_sta_id &&
+           sta_priv->asleep) {
+               WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE));
+               /*
+                * This sends an asynchronous command to the device,
+                * but we can rely on it being processed before the
+                * next frame is processed -- and the next frame to
+                * this station is the one that will consume this
+                * counter.
+                * For now set the counter to just 1 since we do not
+                * support uAPSD yet.
+                */
+               iwl_sta_modify_sleep_tx_count(priv, sta_id, 1);
+       }
        txq_id = skb_get_queue_mapping(skb);
        if (ieee80211_is_data_qos(fc)) {
                qc = ieee80211_get_qos_ctl(hdr);
        ret = iwl_txq_update_write_ptr(priv, txq);
        spin_unlock_irqrestore(&priv->lock, flags);
  
+       /*
+        * At this point the frame is "transmitted" successfully
+        * and we will get a TX status notification eventually,
+        * regardless of the value of ret. "ret" only indicates
+        * whether or not we should update the write pointer.
+        */
+       /* avoid atomic ops if it isn't an associated client */
+       if (sta_priv && sta_priv->client)
+               atomic_inc(&sta_priv->pending_frames);
        if (ret)
                return ret;
  
@@@ -992,7 -1022,7 +1023,7 @@@ int iwl_enqueue_hcmd(struct iwl_priv *p
        }
  
        if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
-               IWL_ERR(priv, "No space for Tx\n");
+               IWL_ERR(priv, "No space in command queue\n");
                if (iwl_within_ct_kill_margin(priv))
                        iwl_tt_enter_ct_kill(priv);
                else {
        return ret ? ret : idx;
  }
  
+ static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
+ {
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       struct ieee80211_sta *sta;
+       struct iwl_station_priv *sta_priv;
+       sta = ieee80211_find_sta(priv->vif, hdr->addr1);
+       if (sta) {
+               sta_priv = (void *)sta->drv_priv;
+               /* avoid atomic ops if this isn't a client */
+               if (sta_priv->client &&
+                   atomic_dec_return(&sta_priv->pending_frames) == 0)
+                       ieee80211_sta_block_awake(priv->hw, sta, false);
+       }
+       ieee80211_tx_status_irqsafe(priv->hw, skb);
+ }
  int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
  {
        struct iwl_tx_queue *txq = &priv->txq[txq_id];
             q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
  
                tx_info = &txq->txb[txq->q.read_ptr];
-               ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]);
+               iwl_tx_status(priv, tx_info->skb[0]);
                tx_info->skb[0] = NULL;
  
                if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl)
@@@ -1264,7 -1312,7 +1313,7 @@@ int iwl_tx_agg_start(struct iwl_priv *p
        if (tid_data->tfds_in_queue == 0) {
                IWL_DEBUG_HT(priv, "HW queue is empty\n");
                tid_data->agg.state = IWL_AGG_ON;
-               ieee80211_start_tx_ba_cb_irqsafe(priv->hw, ra, tid);
+               ieee80211_start_tx_ba_cb_irqsafe(priv->vif, ra, tid);
        } else {
                IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n",
                             tid_data->tfds_in_queue);
@@@ -1329,7 -1377,7 +1378,7 @@@ int iwl_tx_agg_stop(struct iwl_priv *pr
        if (ret)
                return ret;
  
-       ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, ra, tid);
+       ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid);
  
        return 0;
  }
@@@ -1353,7 -1401,7 +1402,7 @@@ int iwl_txq_check_empty(struct iwl_pri
                        priv->cfg->ops->lib->txq_agg_disable(priv, txq_id,
                                                             ssn, tx_fifo);
                        tid_data->agg.state = IWL_AGG_OFF;
-                       ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, addr, tid);
+                       ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid);
                }
                break;
        case IWL_EMPTYING_HW_QUEUE_ADDBA:
                if (tid_data->tfds_in_queue == 0) {
                        IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n");
                        tid_data->agg.state = IWL_AGG_ON;
-                       ieee80211_start_tx_ba_cb_irqsafe(priv->hw, addr, tid);
+                       ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid);
                }
                break;
        }
index 5d26330b43e8f1208ff83207812ba14dd018ce0b,5e3c35314ffe10004a73f96b6703796305b39c1f..0db9b79a69a6d8bade1db176bc984a17c3e590ea
@@@ -33,7 -33,6 +33,7 @@@
  #include <linux/pci.h>
  #include <linux/dma-mapping.h>
  #include <linux/delay.h>
 +#include <linux/sched.h>
  #include <linux/skbuff.h>
  #include <linux/netdevice.h>
  #include <linux/wireless.h>
@@@ -1483,7 -1482,6 +1483,6 @@@ static inline void iwl_synchronize_irq(
        tasklet_kill(&priv->irq_tasklet);
  }
  
- #ifdef CONFIG_IWLWIFI_DEBUG
  static const char *desc_lookup(int i)
  {
        switch (i) {
@@@ -1614,10 -1612,42 +1613,42 @@@ static void iwl3945_print_event_log(str
        spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
  }
  
+ /**
+  * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog
+  */
+ static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
+                                     u32 num_wraps, u32 next_entry,
+                                     u32 size, u32 mode)
+ {
+       /*
+        * display the newest DEFAULT_LOG_ENTRIES entries
+        * i.e the entries just before the next ont that uCode would fill.
+        */
+       if (num_wraps) {
+               if (next_entry < size) {
+                       iwl3945_print_event_log(priv,
+                                       capacity - (size - next_entry),
+                                       size - next_entry, mode);
+                       iwl3945_print_event_log(priv, 0,
+                                   next_entry, mode);
+               } else
+                       iwl3945_print_event_log(priv, next_entry - size,
+                                   size, mode);
+       } else {
+               if (next_entry < size)
+                       iwl3945_print_event_log(priv, 0, next_entry, mode);
+               else
+                       iwl3945_print_event_log(priv, next_entry - size,
+                                           size, mode);
+       }
+ }
  /* For sanity check only.  Actual size is determined by uCode, typ. 512 */
  #define IWL3945_MAX_EVENT_LOG_SIZE (512)
  
- void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
+ #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20)
+ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log)
  {
        u32 base;       /* SRAM byte address of event log header */
        u32 capacity;   /* event log capacity in # entries */
                return;
        }
  
-       IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n",
-                 size, num_wraps);
+ #ifdef CONFIG_IWLWIFI_DEBUG
+       if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS))
+               size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
+                       ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
+ #else
+       size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
+               ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
+ #endif
+       IWL_ERR(priv, "Start IWL Event Log Dump: display last %d count\n",
+                 size);
  
        /* if uCode has wrapped back to top of log, start at the oldest entry,
         * i.e the next one that uCode would fill. */
        /* (then/else) start at top of log */
        iwl3945_print_event_log(priv, 0, next_entry, mode);
  
- }
+ #ifdef CONFIG_IWLWIFI_DEBUG
+       if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
+               /* if uCode has wrapped back to top of log,
+                * start at the oldest entry,
+                * i.e the next one that uCode would fill.
+                */
+               if (num_wraps)
+                       iwl3945_print_event_log(priv, next_entry,
+                                   capacity - next_entry, mode);
+               /* (then/else) start at top of log */
+               iwl3945_print_event_log(priv, 0, next_entry, mode);
+       } else
+               iwl3945_print_last_event_logs(priv, capacity, num_wraps,
+                                       next_entry, size, mode);
  #else
- void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
- {
- }
+       iwl3945_print_last_event_logs(priv, capacity, num_wraps,
+                               next_entry, size, mode);
+ #endif
  
- void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
- {
  }
  
- #endif
  static void iwl3945_irq_tasklet(struct iwl_priv *priv)
  {
        u32 inta, handled = 0;
@@@ -2494,7 -2543,7 +2544,7 @@@ static void iwl3945_alive_start(struct 
        priv->active_rate = priv->rates_mask;
        priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
  
-       iwl_power_update_mode(priv, false);
+       iwl_power_update_mode(priv, true);
  
        if (iwl_is_associated(priv)) {
                struct iwl3945_rxon_cmd *active_rxon =
@@@ -3650,7 -3699,7 +3700,7 @@@ static ssize_t show_statistics(struct d
                return -EAGAIN;
  
        mutex_lock(&priv->mutex);
-       rc = iwl_send_statistics_request(priv, 0);
+       rc = iwl_send_statistics_request(priv, CMD_SYNC, false);
        mutex_unlock(&priv->mutex);
  
        if (rc) {
@@@ -3905,10 -3954,8 +3955,8 @@@ static int iwl3945_setup_mac(struct iwl
                BIT(NL80211_IFTYPE_STATION) |
                BIT(NL80211_IFTYPE_ADHOC);
  
-       hw->wiphy->custom_regulatory = true;
-       /* Firmware does not support this */
-       hw->wiphy->disable_beacon_hints = true;
+       hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY |
+                           WIPHY_FLAG_DISABLE_BEACON_HINTS;
  
        hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
        /* we create the 802.11 header and a zero-length SSID element */
diff --combined net/wireless/core.c
index 45bd63ad2eb28052ef59c585249a4add53b3bfcb,fc5e9b5086070131f64fb7adf4f1f9a024d55d2c..fe6f402a22af0b404a5b11fbaf689430f4c7753b
@@@ -14,7 -14,6 +14,7 @@@
  #include <linux/device.h>
  #include <linux/etherdevice.h>
  #include <linux/rtnetlink.h>
 +#include <linux/sched.h>
  #include <net/genetlink.h>
  #include <net/cfg80211.h>
  #include "nl80211.h"
@@@ -231,7 -230,7 +231,7 @@@ int cfg80211_switch_netns(struct cfg802
        struct wireless_dev *wdev;
        int err = 0;
  
-       if (!rdev->wiphy.netnsok)
+       if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK))
                return -EOPNOTSUPP;
  
        list_for_each_entry(wdev, &rdev->netdev_list, list) {
@@@ -368,7 -367,9 +368,9 @@@ struct wiphy *wiphy_new(const struct cf
        rdev->wiphy.dev.class = &ieee80211_class;
        rdev->wiphy.dev.platform_data = rdev;
  
-       rdev->wiphy.ps_default = CONFIG_CFG80211_DEFAULT_PS_VALUE;
+ #ifdef CONFIG_CFG80211_DEFAULT_PS
+       rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
+ #endif
  
        wiphy_net_set(&rdev->wiphy, &init_net);
  
@@@ -483,7 -484,7 +485,7 @@@ int wiphy_register(struct wiphy *wiphy
        if (IS_ERR(rdev->wiphy.debugfsdir))
                rdev->wiphy.debugfsdir = NULL;
  
-       if (wiphy->custom_regulatory) {
+       if (wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) {
                struct regulatory_request request;
  
                request.wiphy_idx = get_wiphy_idx(wiphy);
@@@ -681,7 -682,10 +683,10 @@@ static int cfg80211_netdev_notifier_cal
                wdev->wext.default_key = -1;
                wdev->wext.default_mgmt_key = -1;
                wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
-               wdev->wext.ps = wdev->wiphy->ps_default;
+               if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT)
+                       wdev->wext.ps = true;
+               else
+                       wdev->wext.ps = false;
                wdev->wext.ps_timeout = 100;
                if (rdev->ops->set_power_mgmt)
                        if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
  #endif
                if (!dev->ethtool_ops)
                        dev->ethtool_ops = &cfg80211_ethtool_ops;
+               if ((wdev->iftype == NL80211_IFTYPE_STATION ||
+                    wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
+                       dev->priv_flags |= IFF_DONT_BRIDGE;
                break;
        case NETDEV_GOING_DOWN:
                switch (wdev->iftype) {