Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
John W. Linville [Tue, 7 Jun 2011 18:07:11 +0000 (14:07 -0400)]
33 files changed:
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath5k/reset.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/eeprom_9287.c
drivers/net/wireless/iwlegacy/iwl-4965.c
drivers/net/wireless/iwlwifi/iwl-2000.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-agn.h
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-rx.c
drivers/net/wireless/libertas/cmd.c
drivers/net/wireless/libertas/if_sdio.c
drivers/net/wireless/rt2x00/rt2x00config.c
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/wl12xx/conf.h
drivers/net/wireless/wl12xx/main.c
drivers/net/wireless/wl12xx/scan.c
drivers/net/wireless/wl12xx/scan.h
drivers/net/wireless/zd1211rw/zd_usb.c
drivers/ssb/driver_pcicore.c
include/linux/ieee80211.h
net/bluetooth/l2cap_core.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/key.c
net/mac80211/tx.c
net/wireless/scan.c

index 2204762..b6c5d37 100644 (file)
@@ -72,6 +72,11 @@ static int modparam_all_channels;
 module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO);
 MODULE_PARM_DESC(all_channels, "Expose all channels the device can use.");
 
+static int modparam_fastchanswitch;
+module_param_named(fastchanswitch, modparam_fastchanswitch, bool, S_IRUGO);
+MODULE_PARM_DESC(fastchanswitch, "Enable fast channel switching for AR2413/AR5413 radios.");
+
+
 /* Module info */
 MODULE_AUTHOR("Jiri Slaby");
 MODULE_AUTHOR("Nick Kossifidis");
@@ -2686,6 +2691,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
        struct ath5k_hw *ah = sc->ah;
        struct ath_common *common = ath5k_hw_common(ah);
        int ret, ani_mode;
+       bool fast;
 
        ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
 
@@ -2705,7 +2711,10 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
        ath5k_drain_tx_buffs(sc);
        if (chan)
                sc->curchan = chan;
-       ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL,
+
+       fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0;
+
+       ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, fast,
                                                                skip_pcu);
        if (ret) {
                ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
index 3510de2..126a4ea 100644 (file)
@@ -1124,8 +1124,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
                        /* Non fatal, can happen eg.
                         * on mode change */
                        ret = 0;
-               } else
+               } else {
+                       ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
+                               "fast chan change successful\n");
                        return 0;
+               }
        }
 
        /*
index 0ca7635..ff8150e 100644 (file)
@@ -4645,10 +4645,16 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
        case 1:
                break;
        case 2:
-               scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+               if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+               else
+                       scaledPower = 0;
                break;
        case 3:
-               scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+               if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+               else
+                       scaledPower = 0;
                break;
        }
 
index 7856f0d..343fc9f 100644 (file)
@@ -524,10 +524,16 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
        case 1:
                break;
        case 2:
-               scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+               if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+               else
+                       scaledPower = 0;
                break;
        case 3:
-               scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+               if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+               else
+                       scaledPower = 0;
                break;
        }
        scaledPower = max((u16)0, scaledPower);
index 79e7ce6..3a022bc 100644 (file)
@@ -1235,7 +1235,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c
 
                memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
                iwl_legacy_print_rx_config_cmd(priv, ctx);
-               return 0;
+               goto set_tx_power;
        }
 
        /* If we are currently associated and the new config requires
@@ -1315,6 +1315,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c
 
        iwl4965_init_sensitivity(priv);
 
+set_tx_power:
        /* If we issue a new RXON command which required a tune then we must
         * send a new TXPOWER command or we won't be able to Tx any frames */
        ret = iwl_legacy_set_tx_power(priv, priv->tx_power_next, true);
@@ -1541,7 +1542,7 @@ static void iwl4965_temperature_calib(struct iwl_priv *priv)
        s32 temp;
 
        temp = iwl4965_hw_get_temperature(priv);
-       if (temp < 0)
+       if (IWL_TX_POWER_TEMPERATURE_OUT_OF_RANGE(temp))
                return;
 
        if (priv->temperature != temp) {
index a37c41b..5484ab7 100644 (file)
@@ -177,79 +177,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
        return 0;
 }
 
-static int iwl2030_hw_channel_switch(struct iwl_priv *priv,
-                                    struct ieee80211_channel_switch *ch_switch)
-{
-       /*
-        * MULTI-FIXME
-        * See iwl_mac_channel_switch.
-        */
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       struct iwl6000_channel_switch_cmd cmd;
-       const struct iwl_channel_info *ch_info;
-       u32 switch_time_in_usec, ucode_switch_time;
-       u16 ch;
-       u32 tsf_low;
-       u8 switch_count;
-       u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
-       struct ieee80211_vif *vif = ctx->vif;
-       struct iwl_host_cmd hcmd = {
-               .id = REPLY_CHANNEL_SWITCH,
-               .len = { sizeof(cmd), },
-               .flags = CMD_SYNC,
-               .data = { &cmd, },
-       };
-
-       cmd.band = priv->band == IEEE80211_BAND_2GHZ;
-       ch = ch_switch->channel->hw_value;
-       IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
-               ctx->active.channel, ch);
-       cmd.channel = cpu_to_le16(ch);
-       cmd.rxon_flags = ctx->staging.flags;
-       cmd.rxon_filter_flags = ctx->staging.filter_flags;
-       switch_count = ch_switch->count;
-       tsf_low = ch_switch->timestamp & 0x0ffffffff;
-       /*
-        * calculate the ucode channel switch time
-        * adding TSF as one of the factor for when to switch
-        */
-       if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
-               if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
-                   beacon_interval)) {
-                       switch_count -= (priv->ucode_beacon_time -
-                               tsf_low) / beacon_interval;
-               } else
-                       switch_count = 0;
-       }
-       if (switch_count <= 1)
-               cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
-       else {
-               switch_time_in_usec =
-                       vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
-               ucode_switch_time = iwl_usecs_to_beacons(priv,
-                                               switch_time_in_usec,
-                                               beacon_interval);
-               cmd.switch_time = iwl_add_beacon_time(priv,
-                                               priv->ucode_beacon_time,
-                                               ucode_switch_time,
-                                               beacon_interval);
-       }
-       IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
-                     cmd.switch_time);
-       ch_info = iwl_get_channel_info(priv, priv->band, ch);
-       if (ch_info)
-               cmd.expect_beacon = is_channel_radar(ch_info);
-       else {
-               IWL_ERR(priv, "invalid channel switch from %u to %u\n",
-                       ctx->active.channel, ch);
-               return -EFAULT;
-       }
-       priv->switch_rxon.channel = cmd.channel;
-       priv->switch_rxon.switch_in_progress = true;
-
-       return iwl_send_cmd_sync(priv, &hcmd);
-}
-
 static struct iwl_lib_ops iwl2000_lib = {
        .set_hw_params = iwl2000_hw_set_hw_params,
        .rx_handler_setup = iwlagn_rx_handler_setup,
@@ -257,7 +184,6 @@ static struct iwl_lib_ops iwl2000_lib = {
        .cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
        .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
        .update_chain_flags = iwl_update_chain_flags,
-       .set_channel_switch = iwl2030_hw_channel_switch,
        .apm_ops = {
                .init = iwl_apm_init,
                .config = iwl2000_nic_config,
index a8dbbd0..4353a65 100644 (file)
@@ -331,8 +331,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
                        ctx->active.channel, ch);
                return -EFAULT;
        }
-       priv->switch_rxon.channel = cmd.channel;
-       priv->switch_rxon.switch_in_progress = true;
 
        return iwl_send_cmd_sync(priv, &hcmd);
 }
@@ -423,7 +421,6 @@ static struct iwl_base_params iwl5000_base_params = {
 };
 static struct iwl_ht_params iwl5000_ht_params = {
        .ht_greenfield_support = true,
-       .use_rts_for_aggregation = true, /* use rts/cts protection */
 };
 
 #define IWL_DEVICE_5000                                                \
index eabf3b8..6e5ce44 100644 (file)
@@ -270,8 +270,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
                        ctx->active.channel, ch);
                return -EFAULT;
        }
-       priv->switch_rxon.channel = cmd.channel;
-       priv->switch_rxon.switch_in_progress = true;
 
        return iwl_send_cmd_sync(priv, &hcmd);
 }
@@ -601,19 +599,27 @@ struct iwl_cfg iwl6050_2abg_cfg = {
        IWL_DEVICE_6050,
 };
 
+#define IWL_DEVICE_6150                                                \
+       .fw_name_pre = IWL6050_FW_PRE,                          \
+       .ucode_api_max = IWL6050_UCODE_API_MAX,                 \
+       .ucode_api_min = IWL6050_UCODE_API_MIN,                 \
+       .ops = &iwl6150_ops,                                    \
+       .eeprom_ver = EEPROM_6150_EEPROM_VERSION,               \
+       .eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION,       \
+       .base_params = &iwl6050_base_params,                    \
+       .need_dc_calib = true,                                  \
+       .led_mode = IWL_LED_BLINK,                              \
+       .internal_wimax_coex = true
+
 struct iwl_cfg iwl6150_bgn_cfg = {
        .name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN",
-       .fw_name_pre = IWL6050_FW_PRE,
-       .ucode_api_max = IWL6050_UCODE_API_MAX,
-       .ucode_api_min = IWL6050_UCODE_API_MIN,
-       .eeprom_ver = EEPROM_6150_EEPROM_VERSION,
-       .eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION,
-       .ops = &iwl6150_ops,
-       .base_params = &iwl6050_base_params,
+       IWL_DEVICE_6150,
        .ht_params = &iwl6000_ht_params,
-       .need_dc_calib = true,
-       .led_mode = IWL_LED_RF_STATE,
-       .internal_wimax_coex = true,
+};
+
+struct iwl_cfg iwl6150_bg_cfg = {
+       .name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BG",
+       IWL_DEVICE_6150,
 };
 
 struct iwl_cfg iwl6000_3agn_cfg = {
index 87fd05a..23eee0c 100644 (file)
@@ -163,17 +163,9 @@ static void iwlagn_tx_cmd_protection(struct iwl_priv *priv,
                                     __le16 fc, __le32 *tx_flags)
 {
        if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS ||
-           info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+           info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT ||
+           info->flags & IEEE80211_TX_CTL_AMPDU)
                *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
-               return;
-       }
-
-       if (priv->cfg->ht_params &&
-           priv->cfg->ht_params->use_rts_for_aggregation &&
-           info->flags & IEEE80211_TX_CTL_AMPDU) {
-               *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
-               return;
-       }
 }
 
 /* Calc max signal level (dBm) among 3 possible receivers */
index 18e6900..c8f6da8 100644 (file)
@@ -359,6 +359,14 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
                        return 0;
        }
 
+       /*
+        * force CTS-to-self frames protection if RTS-CTS is not preferred
+        * one aggregation protection method
+        */
+       if (!(priv->cfg->ht_params &&
+             priv->cfg->ht_params->use_rts_for_aggregation))
+               ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
+
        if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
            !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK))
                ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
@@ -376,10 +384,10 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
         * receive commit_rxon request
         * abort any previous channel switch if still in process
         */
-       if (priv->switch_rxon.switch_in_progress &&
-           (priv->switch_rxon.channel != ctx->staging.channel)) {
+       if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) &&
+           (priv->switch_channel != ctx->staging.channel)) {
                IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
-                     le16_to_cpu(priv->switch_rxon.channel));
+                             le16_to_cpu(priv->switch_channel));
                iwl_chswitch_done(priv, false);
        }
 
index 96c7288..0b2d2cd 100644 (file)
@@ -2926,16 +2926,13 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
                goto out;
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
-           test_bit(STATUS_SCANNING, &priv->status))
+           test_bit(STATUS_SCANNING, &priv->status) ||
+           test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
                goto out;
 
        if (!iwl_is_associated_ctx(ctx))
                goto out;
 
-       /* channel switch in progress */
-       if (priv->switch_rxon.switch_in_progress == true)
-               goto out;
-
        if (priv->cfg->ops->lib->set_channel_switch) {
 
                ch = channel->hw_value;
@@ -2984,15 +2981,19 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
                         * at this point, staging_rxon has the
                         * configuration for channel switch
                         */
+                       set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+                       priv->switch_channel = cpu_to_le16(ch);
                        if (priv->cfg->ops->lib->set_channel_switch(priv,
-                                                                   ch_switch))
-                               priv->switch_rxon.switch_in_progress = false;
+                                                                   ch_switch)) {
+                               clear_bit(STATUS_CHANNEL_SWITCH_PENDING,
+                                         &priv->status);
+                               priv->switch_channel = 0;
+                               ieee80211_chswitch_done(ctx->vif, false);
+                       }
                }
        }
 out:
        mutex_unlock(&priv->mutex);
-       if (!priv->switch_rxon.switch_in_progress)
-               ieee80211_chswitch_done(ctx->vif, false);
        IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
@@ -3914,11 +3915,11 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
 
 /* 6150 WiFi/WiMax Series */
        {IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0885, 0x1306, iwl6150_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0885, 0x1307, iwl6150_bg_cfg)},
        {IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0885, 0x1326, iwl6150_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0885, 0x1327, iwl6150_bg_cfg)},
        {IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0886, 0x1316, iwl6150_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0886, 0x1317, iwl6150_bg_cfg)},
 
 /* 1000 Series WiFi */
        {IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)},
index 2495fe7..d171684 100644 (file)
@@ -89,6 +89,7 @@ extern struct iwl_cfg iwl6000_3agn_cfg;
 extern struct iwl_cfg iwl6050_2agn_cfg;
 extern struct iwl_cfg iwl6050_2abg_cfg;
 extern struct iwl_cfg iwl6150_bgn_cfg;
+extern struct iwl_cfg iwl6150_bg_cfg;
 extern struct iwl_cfg iwl1000_bgn_cfg;
 extern struct iwl_cfg iwl1000_bg_cfg;
 extern struct iwl_cfg iwl100_bgn_cfg;
index de18916..5416b12 100644 (file)
@@ -843,12 +843,8 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
-       if (priv->switch_rxon.switch_in_progress) {
+       if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
                ieee80211_chswitch_done(ctx->vif, is_success);
-               mutex_lock(&priv->mutex);
-               priv->switch_rxon.switch_in_progress = false;
-               mutex_unlock(&priv->mutex);
-       }
 }
 
 #ifdef CONFIG_IWLWIFI_DEBUG
index b38477c..05ea88a 100644 (file)
@@ -558,6 +558,7 @@ void iwlcore_free_geos(struct iwl_priv *priv);
 #define STATUS_POWER_PMI       16
 #define STATUS_FW_ERROR                17
 #define STATUS_DEVICE_ENABLED  18
+#define STATUS_CHANNEL_SWITCH_PENDING 19
 
 
 static inline int iwl_is_ready(struct iwl_priv *priv)
index 22a6e3e..c8de236 100644 (file)
@@ -982,17 +982,6 @@ struct traffic_stats {
 };
 
 /*
- * iwl_switch_rxon: "channel switch" structure
- *
- * @ switch_in_progress: channel switch in progress
- * @ channel: new channel
- */
-struct iwl_switch_rxon {
-       bool switch_in_progress;
-       __le16 channel;
-};
-
-/*
  * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds
  * to perform continuous uCode event logging operation if enabled
  */
@@ -1287,7 +1276,7 @@ struct iwl_priv {
 
        struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX];
 
-       struct iwl_switch_rxon switch_rxon;
+       __le16 switch_channel;
 
        struct {
                u32 error_event_table;
index 0053e9e..b774517 100644 (file)
@@ -250,19 +250,19 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
        struct iwl_rxon_cmd *rxon = (void *)&ctx->active;
 
-       if (priv->switch_rxon.switch_in_progress) {
-               if (!le32_to_cpu(csa->status) &&
-                   (csa->channel == priv->switch_rxon.channel)) {
-                       rxon->channel = csa->channel;
-                       ctx->staging.channel = csa->channel;
-                       IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
-                             le16_to_cpu(csa->channel));
-                       iwl_chswitch_done(priv, true);
-               } else {
-                       IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
+       if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+               return;
+
+       if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) {
+               rxon->channel = csa->channel;
+               ctx->staging.channel = csa->channel;
+               IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
                              le16_to_cpu(csa->channel));
-                       iwl_chswitch_done(priv, false);
-               }
+               iwl_chswitch_done(priv, true);
+       } else {
+               IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
+                       le16_to_cpu(csa->channel));
+               iwl_chswitch_done(priv, false);
        }
 }
 
index 84566db..71c8f3f 100644 (file)
@@ -994,6 +994,8 @@ static void lbs_submit_command(struct lbs_private *priv,
        cmd = cmdnode->cmdbuf;
 
        spin_lock_irqsave(&priv->driver_lock, flags);
+       priv->seqnum++;
+       cmd->seqnum = cpu_to_le16(priv->seqnum);
        priv->cur_cmd = cmdnode;
        spin_unlock_irqrestore(&priv->driver_lock, flags);
 
@@ -1621,11 +1623,9 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
        /* Copy the incoming command to the buffer */
        memcpy(cmdnode->cmdbuf, in_cmd, in_cmd_size);
 
-       /* Set sequence number, clean result, move to buffer */
-       priv->seqnum++;
+       /* Set command, clean result, move to buffer */
        cmdnode->cmdbuf->command = cpu_to_le16(command);
        cmdnode->cmdbuf->size    = cpu_to_le16(in_cmd_size);
-       cmdnode->cmdbuf->seqnum  = cpu_to_le16(priv->seqnum);
        cmdnode->cmdbuf->result  = 0;
 
        lbs_deb_host("PREP_CMD: command 0x%04x\n", command);
index a7b5cb0..224e985 100644 (file)
@@ -907,7 +907,7 @@ static void if_sdio_interrupt(struct sdio_func *func)
        card = sdio_get_drvdata(func);
 
        cause = sdio_readb(card->func, IF_SDIO_H_INT_STATUS, &ret);
-       if (ret)
+       if (ret || !cause)
                goto out;
 
        lbs_deb_sdio("interrupt: 0x%X\n", (unsigned)cause);
@@ -1008,10 +1008,6 @@ static int if_sdio_probe(struct sdio_func *func,
        if (ret)
                goto release;
 
-       ret = sdio_claim_irq(func, if_sdio_interrupt);
-       if (ret)
-               goto disable;
-
        /* For 1-bit transfers to the 8686 model, we need to enable the
         * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
         * bit to allow access to non-vendor registers. */
@@ -1083,6 +1079,21 @@ static int if_sdio_probe(struct sdio_func *func,
                card->rx_unit = 0;
 
        /*
+        * Set up the interrupt handler late.
+        *
+        * If we set it up earlier, the (buggy) hardware generates a spurious
+        * interrupt, even before the interrupt has been enabled, with
+        * CCCR_INTx = 0.
+        *
+        * We register the interrupt handler late so that we can handle any
+        * spurious interrupts, and also to avoid generation of that known
+        * spurious interrupt in the first place.
+        */
+       ret = sdio_claim_irq(func, if_sdio_interrupt);
+       if (ret)
+               goto disable;
+
+       /*
         * Enable interrupts now that everything is set up
         */
        sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret);
index 555180d..b704e5b 100644 (file)
@@ -250,7 +250,8 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
        if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL)
                rt2x00link_reset_tuner(rt2x00dev, false);
 
-       if (test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) &&
+       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
+           test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) &&
            (ieee80211_flags & IEEE80211_CONF_CHANGE_PS) &&
            (conf->flags & IEEE80211_CONF_PS)) {
                beacon_diff = (long)jiffies - (long)rt2x00dev->last_beacon;
index c018d67..939821b 100644 (file)
@@ -146,6 +146,9 @@ static void rt2x00lib_autowakeup(struct work_struct *work)
        struct rt2x00_dev *rt2x00dev =
            container_of(work, struct rt2x00_dev, autowakeup_work.work);
 
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               return;
+
        if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
                ERROR(rt2x00dev, "Device failed to wakeup.\n");
        clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
@@ -1160,6 +1163,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
         * Stop all work.
         */
        cancel_work_sync(&rt2x00dev->intf_work);
+       cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
        if (rt2x00_is_usb(rt2x00dev)) {
                del_timer_sync(&rt2x00dev->txstatus_timer);
                cancel_work_sync(&rt2x00dev->rxdone_work);
index 1ab6c86..c83fefb 100644 (file)
@@ -1157,6 +1157,9 @@ struct conf_sched_scan_settings {
        /* time to wait on the channel for passive scans (in TUs) */
        u32 dwell_time_passive;
 
+       /* time to wait on the channel for DFS scans (in TUs) */
+       u32 dwell_time_dfs;
+
        /* number of probe requests to send on each channel in active scans */
        u8 num_probe_reqs;
 
index bc00e52..e6497dc 100644 (file)
@@ -311,6 +311,7 @@ static struct conf_drv_settings default_conf = {
                .min_dwell_time_active = 8,
                .max_dwell_time_active = 30,
                .dwell_time_passive    = 100,
+               .dwell_time_dfs        = 150,
                .num_probe_reqs        = 2,
                .rssi_threshold        = -90,
                .snr_threshold         = 0,
index f37e5a3..56f76ab 100644 (file)
@@ -331,16 +331,22 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
        struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
        int i, j;
        u32 flags;
+       bool force_passive = !req->n_ssids;
 
        for (i = 0, j = start;
             i < req->n_channels && j < MAX_CHANNELS_ALL_BANDS;
             i++) {
                flags = req->channels[i]->flags;
 
-               if (!(flags & IEEE80211_CHAN_DISABLED) &&
-                   ((flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive) &&
-                   ((flags & IEEE80211_CHAN_RADAR) == radar) &&
-                   (req->channels[i]->band == band)) {
+               if (force_passive)
+                       flags |= IEEE80211_CHAN_PASSIVE_SCAN;
+
+               if ((req->channels[i]->band == band) &&
+                   !(flags & IEEE80211_CHAN_DISABLED) &&
+                   (!!(flags & IEEE80211_CHAN_RADAR) == radar) &&
+                   /* if radar is set, we ignore the passive flag */
+                   (radar ||
+                    !!(flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive)) {
                        wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ",
                                     req->channels[i]->band,
                                     req->channels[i]->center_freq);
@@ -350,7 +356,12 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
                        wl1271_debug(DEBUG_SCAN, "max_power %d",
                                     req->channels[i]->max_power);
 
-                       if (flags & IEEE80211_CHAN_PASSIVE_SCAN) {
+                       if (flags & IEEE80211_CHAN_RADAR) {
+                               channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS;
+                               channels[j].passive_duration =
+                                       cpu_to_le16(c->dwell_time_dfs);
+                       }
+                       else if (flags & IEEE80211_CHAN_PASSIVE_SCAN) {
                                channels[j].passive_duration =
                                        cpu_to_le16(c->dwell_time_passive);
                        } else {
@@ -359,7 +370,7 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
                                channels[j].max_duration =
                                        cpu_to_le16(c->max_dwell_time_active);
                        }
-                       channels[j].tx_power_att = req->channels[j]->max_power;
+                       channels[j].tx_power_att = req->channels[i]->max_power;
                        channels[j].channel = req->channels[i]->hw_value;
 
                        j++;
@@ -386,7 +397,11 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,
                wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
                                                    IEEE80211_BAND_2GHZ,
                                                    false, false, idx);
-       idx += cfg->active[0];
+       /*
+        * 5GHz channels always start at position 14, not immediately
+        * after the last 2.4GHz channel
+        */
+       idx = 14;
 
        cfg->passive[1] =
                wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
@@ -394,22 +409,23 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,
                                                    false, true, idx);
        idx += cfg->passive[1];
 
-       cfg->active[1] =
+       cfg->dfs =
                wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
                                                    IEEE80211_BAND_5GHZ,
-                                                   false, false, 14);
-       idx += cfg->active[1];
+                                                   true, true, idx);
+       idx += cfg->dfs;
 
-       cfg->dfs =
+       cfg->active[1] =
                wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
                                                    IEEE80211_BAND_5GHZ,
-                                                   true, false, idx);
-       idx += cfg->dfs;
+                                                   false, false, idx);
+       idx += cfg->active[1];
 
        wl1271_debug(DEBUG_SCAN, "    2.4GHz: active %d passive %d",
                     cfg->active[0], cfg->passive[0]);
        wl1271_debug(DEBUG_SCAN, "    5GHz: active %d passive %d",
                     cfg->active[1], cfg->passive[1]);
+       wl1271_debug(DEBUG_SCAN, "    DFS: %d", cfg->dfs);
 
        return idx;
 }
@@ -421,6 +437,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
        struct wl1271_cmd_sched_scan_config *cfg = NULL;
        struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
        int i, total_channels, ret;
+       bool force_passive = !req->n_ssids;
 
        wl1271_debug(DEBUG_CMD, "cmd sched_scan scan config");
 
@@ -444,7 +461,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
        for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++)
                cfg->intervals[i] = cpu_to_le32(req->interval);
 
-       if (req->ssids[0].ssid_len && req->ssids[0].ssid) {
+       if (!force_passive && req->ssids[0].ssid_len && req->ssids[0].ssid) {
                cfg->filter_type = SCAN_SSID_FILTER_SPECIFIC;
                cfg->ssid_len = req->ssids[0].ssid_len;
                memcpy(cfg->ssid, req->ssids[0].ssid,
@@ -461,7 +478,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
                goto out;
        }
 
-       if (cfg->active[0]) {
+       if (!force_passive && cfg->active[0]) {
                ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid,
                                                 req->ssids[0].ssid_len,
                                                 ies->ie[IEEE80211_BAND_2GHZ],
@@ -473,7 +490,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
                }
        }
 
-       if (cfg->active[1]) {
+       if (!force_passive && cfg->active[1]) {
                ret = wl1271_cmd_build_probe_req(wl,  req->ssids[0].ssid,
                                                 req->ssids[0].ssid_len,
                                                 ies->ie[IEEE80211_BAND_5GHZ],
index c833195..a0b6c5d 100644 (file)
@@ -137,6 +137,9 @@ enum {
        SCAN_BSS_TYPE_ANY,
 };
 
+#define SCAN_CHANNEL_FLAGS_DFS         BIT(0)
+#define SCAN_CHANNEL_FLAGS_DFS_ENABLED BIT(1)
+
 struct conn_scan_ch_params {
        __le16 min_duration;
        __le16 max_duration;
index 0e81994..631194d 100644 (file)
@@ -1533,6 +1533,31 @@ static void __exit usb_exit(void)
 module_init(usb_init);
 module_exit(usb_exit);
 
+static int zd_ep_regs_out_msg(struct usb_device *udev, void *data, int len,
+                             int *actual_length, int timeout)
+{
+       /* In USB 2.0 mode EP_REGS_OUT endpoint is interrupt type. However in
+        * USB 1.1 mode endpoint is bulk. Select correct type URB by endpoint
+        * descriptor.
+        */
+       struct usb_host_endpoint *ep;
+       unsigned int pipe;
+
+       pipe = usb_sndintpipe(udev, EP_REGS_OUT);
+       ep = usb_pipe_endpoint(udev, pipe);
+       if (!ep)
+               return -EINVAL;
+
+       if (usb_endpoint_xfer_int(&ep->desc)) {
+               return usb_interrupt_msg(udev, pipe, data, len,
+                                        actual_length, timeout);
+       } else {
+               pipe = usb_sndbulkpipe(udev, EP_REGS_OUT);
+               return usb_bulk_msg(udev, pipe, data, len, actual_length,
+                                   timeout);
+       }
+}
+
 static int usb_int_regs_length(unsigned int count)
 {
        return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data);
@@ -1648,15 +1673,14 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
 
        udev = zd_usb_to_usbdev(usb);
        prepare_read_regs_int(usb);
-       r = usb_interrupt_msg(udev, usb_sndintpipe(udev, EP_REGS_OUT),
-                             req, req_len, &actual_req_len, 50 /* ms */);
+       r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);
        if (r) {
                dev_dbg_f(zd_usb_dev(usb),
-                       "error in usb_interrupt_msg(). Error number %d\n", r);
+                       "error in zd_ep_regs_out_msg(). Error number %d\n", r);
                goto error;
        }
        if (req_len != actual_req_len) {
-               dev_dbg_f(zd_usb_dev(usb), "error in usb_interrupt_msg()\n"
+               dev_dbg_f(zd_usb_dev(usb), "error in zd_ep_regs_out_msg()\n"
                        " req_len %d != actual_req_len %d\n",
                        req_len, actual_req_len);
                r = -EIO;
@@ -1818,9 +1842,17 @@ int zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
                rw->value = cpu_to_le16(ioreqs[i].value);
        }
 
-       usb_fill_int_urb(urb, udev, usb_sndintpipe(udev, EP_REGS_OUT),
-                        req, req_len, iowrite16v_urb_complete, usb,
-                        ep->desc.bInterval);
+       /* In USB 2.0 mode endpoint is interrupt type. However in USB 1.1 mode
+        * endpoint is bulk. Select correct type URB by endpoint descriptor.
+        */
+       if (usb_endpoint_xfer_int(&ep->desc))
+               usb_fill_int_urb(urb, udev, usb_sndintpipe(udev, EP_REGS_OUT),
+                                req, req_len, iowrite16v_urb_complete, usb,
+                                ep->desc.bInterval);
+       else
+               usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_REGS_OUT),
+                                 req, req_len, iowrite16v_urb_complete, usb);
+
        urb->transfer_flags |= URB_FREE_BUFFER;
 
        /* Submit previous URB */
@@ -1924,15 +1956,14 @@ int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits)
        }
 
        udev = zd_usb_to_usbdev(usb);
-       r = usb_interrupt_msg(udev, usb_sndintpipe(udev, EP_REGS_OUT),
-                             req, req_len, &actual_req_len, 50 /* ms */);
+       r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);
        if (r) {
                dev_dbg_f(zd_usb_dev(usb),
-                       "error in usb_interrupt_msg(). Error number %d\n", r);
+                       "error in zd_ep_regs_out_msg(). Error number %d\n", r);
                goto out;
        }
        if (req_len != actual_req_len) {
-               dev_dbg_f(zd_usb_dev(usb), "error in usb_interrupt_msg()"
+               dev_dbg_f(zd_usb_dev(usb), "error in zd_ep_regs_out_msg()"
                        " req_len %d != actual_req_len %d\n",
                        req_len, actual_req_len);
                r = -EIO;
index 82feb34..2a20dab 100644 (file)
@@ -539,10 +539,12 @@ void ssb_pcicore_init(struct ssb_pcicore *pc)
        if (!pc->hostmode)
                ssb_pcicore_init_clientmode(pc);
 
-       /* Additional always once-executed workarounds */
-       ssb_pcicore_serdes_workaround(pc);
-       /* TODO: ASPM */
-       /* TODO: Clock Request Update */
+       /* Additional PCIe always once-executed workarounds */
+       if (dev->id.coreid == SSB_DEV_PCIE) {
+               ssb_pcicore_serdes_workaround(pc);
+               /* TODO: ASPM */
+               /* TODO: Clock Request Update */
+       }
 }
 
 static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address)
index b2eee58..bf56b6f 100644 (file)
@@ -1003,8 +1003,12 @@ struct ieee80211_ht_info {
 #define WLAN_CAPABILITY_ESS            (1<<0)
 #define WLAN_CAPABILITY_IBSS           (1<<1)
 
-/* A mesh STA sets the ESS and IBSS capability bits to zero */
-#define WLAN_CAPABILITY_IS_MBSS(cap)   \
+/*
+ * A mesh STA sets the ESS and IBSS capability bits to zero.
+ * however, this holds true for p2p probe responses (in the p2p_find
+ * phase) as well.
+ */
+#define WLAN_CAPABILITY_IS_STA_BSS(cap)        \
        (!((cap) & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)))
 
 #define WLAN_CAPABILITY_CF_POLLABLE    (1<<2)
index a86f9ba..e64a1c2 100644 (file)
@@ -906,7 +906,7 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr
                if (c->psm == psm) {
                        /* Exact match. */
                        if (!bacmp(&bt_sk(sk)->src, src)) {
-                               read_unlock_bh(&chan_list_lock);
+                               read_unlock(&chan_list_lock);
                                return c;
                        }
 
index 2025af5..090b0ec 100644 (file)
@@ -775,9 +775,6 @@ struct ieee80211_local {
 
        int tx_headroom; /* required headroom for hardware/radiotap */
 
-       /* count for keys needing tailroom space allocation */
-       int crypto_tx_tailroom_needed_cnt;
-
        /* Tasklet and skb queue to process calls from IRQ mode. All frames
         * added to skb_queue will be processed, but frames in
         * skb_queue_unreliable may be dropped if the total length of these
index 49d4f86..dee30ae 100644 (file)
@@ -1145,6 +1145,10 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
                                + IEEE80211_ENCRYPT_HEADROOM;
        ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM;
 
+       ret = dev_alloc_name(ndev, ndev->name);
+       if (ret < 0)
+               goto fail;
+
        ieee80211_assign_perm_addr(local, ndev, type);
        memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN);
        SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
index 31afd71..f825e2f 100644 (file)
@@ -101,11 +101,6 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
 
        if (!ret) {
                key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
-
-               if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
-                     (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
-                       key->local->crypto_tx_tailroom_needed_cnt--;
-
                return 0;
        }
 
@@ -161,10 +156,6 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
                          key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
 
        key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
-
-       if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
-             (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
-               key->local->crypto_tx_tailroom_needed_cnt++;
 }
 
 void ieee80211_key_removed(struct ieee80211_key_conf *key_conf)
@@ -403,10 +394,8 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)
                ieee80211_aes_key_free(key->u.ccmp.tfm);
        if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)
                ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
-       if (key->local) {
+       if (key->local)
                ieee80211_debugfs_key_remove(key);
-               key->local->crypto_tx_tailroom_needed_cnt--;
-       }
 
        kfree(key);
 }
@@ -468,8 +457,6 @@ int ieee80211_key_link(struct ieee80211_key *key,
 
        ieee80211_debugfs_key_add(key);
 
-       key->local->crypto_tx_tailroom_needed_cnt++;
-
        ret = ieee80211_key_enable_hw_accel(key);
 
        mutex_unlock(&sdata->local->key_mtx);
@@ -511,12 +498,8 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
 
        mutex_lock(&sdata->local->key_mtx);
 
-       sdata->local->crypto_tx_tailroom_needed_cnt = 0;
-
-       list_for_each_entry(key, &sdata->key_list, list) {
-               sdata->local->crypto_tx_tailroom_needed_cnt++;
+       list_for_each_entry(key, &sdata->key_list, list)
                ieee80211_key_enable_hw_accel(key);
-       }
 
        mutex_unlock(&sdata->local->key_mtx);
 }
index 64e0f75..3104c84 100644 (file)
@@ -1480,7 +1480,12 @@ static int ieee80211_skb_resize(struct ieee80211_local *local,
 {
        int tail_need = 0;
 
-       if (may_encrypt && local->crypto_tx_tailroom_needed_cnt) {
+       /*
+        * This could be optimised, devices that do full hardware
+        * crypto (including TKIP MMIC) need no tailroom... But we
+        * have no drivers for such devices currently.
+        */
+       if (may_encrypt) {
                tail_need = IEEE80211_ENCRYPT_TAILROOM;
                tail_need -= skb_tailroom(skb);
                tail_need = max_t(int, tail_need, 0);
index 73a441d..7a6c676 100644 (file)
@@ -267,13 +267,35 @@ static bool is_bss(struct cfg80211_bss *a,
        return memcmp(ssidie + 2, ssid, ssid_len) == 0;
 }
 
+static bool is_mesh_bss(struct cfg80211_bss *a)
+{
+       const u8 *ie;
+
+       if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability))
+               return false;
+
+       ie = cfg80211_find_ie(WLAN_EID_MESH_ID,
+                             a->information_elements,
+                             a->len_information_elements);
+       if (!ie)
+               return false;
+
+       ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
+                             a->information_elements,
+                             a->len_information_elements);
+       if (!ie)
+               return false;
+
+       return true;
+}
+
 static bool is_mesh(struct cfg80211_bss *a,
                    const u8 *meshid, size_t meshidlen,
                    const u8 *meshcfg)
 {
        const u8 *ie;
 
-       if (!WLAN_CAPABILITY_IS_MBSS(a->capability))
+       if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability))
                return false;
 
        ie = cfg80211_find_ie(WLAN_EID_MESH_ID,
@@ -311,7 +333,7 @@ static int cmp_bss(struct cfg80211_bss *a,
        if (a->channel != b->channel)
                return b->channel->center_freq - a->channel->center_freq;
 
-       if (WLAN_CAPABILITY_IS_MBSS(a->capability | b->capability)) {
+       if (is_mesh_bss(a) && is_mesh_bss(b)) {
                r = cmp_ies(WLAN_EID_MESH_ID,
                            a->information_elements,
                            a->len_information_elements,
@@ -457,7 +479,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
                    struct cfg80211_internal_bss *res)
 {
        struct cfg80211_internal_bss *found = NULL;
-       const u8 *meshid, *meshcfg;
 
        /*
         * The reference to "res" is donated to this function.
@@ -470,22 +491,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
 
        res->ts = jiffies;
 
-       if (WLAN_CAPABILITY_IS_MBSS(res->pub.capability)) {
-               /* must be mesh, verify */
-               meshid = cfg80211_find_ie(WLAN_EID_MESH_ID,
-                                         res->pub.information_elements,
-                                         res->pub.len_information_elements);
-               meshcfg = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
-                                          res->pub.information_elements,
-                                          res->pub.len_information_elements);
-               if (!meshid || !meshcfg ||
-                   meshcfg[1] != sizeof(struct ieee80211_meshconf_ie)) {
-                       /* bogus mesh */
-                       kref_put(&res->ref, bss_release);
-                       return NULL;
-               }
-       }
-
        spin_lock_bh(&dev->bss_lock);
 
        found = rb_find_bss(dev, res);