aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-mac80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-mac80211.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-mac80211.c239
1 files changed, 140 insertions, 99 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
index b6805f8e9a01..3ee23134c02b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c
+++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
@@ -44,13 +44,12 @@
#include "iwl-eeprom.h"
#include "iwl-dev.h"
-#include "iwl-core.h"
#include "iwl-io.h"
#include "iwl-agn-calib.h"
#include "iwl-agn.h"
-#include "iwl-shared.h"
#include "iwl-trans.h"
#include "iwl-op-mode.h"
+#include "iwl-modparams.h"
/*****************************************************************************
*
@@ -147,7 +146,14 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
IEEE80211_HW_AMPDU_AGGREGATION |
IEEE80211_HW_NEED_DTIM_PERIOD |
IEEE80211_HW_SPECTRUM_MGMT |
- IEEE80211_HW_REPORTS_TX_ACK_STATUS;
+ IEEE80211_HW_REPORTS_TX_ACK_STATUS |
+ IEEE80211_HW_QUEUE_CONTROL |
+ IEEE80211_HW_SUPPORTS_PS |
+ IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
+ IEEE80211_HW_WANT_MONITOR_VIF |
+ IEEE80211_HW_SCAN_WHILE_IDLE;
+
+ hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE;
/*
* Including the following line will crash some AP's. This
@@ -156,10 +162,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
*/
- hw->flags |= IEEE80211_HW_SUPPORTS_PS |
- IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
-
- if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE)
+ if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE)
hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
IEEE80211_HW_SUPPORTS_STATIC_SMPS;
@@ -196,14 +199,15 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
WIPHY_FLAG_DISABLE_BEACON_HINTS |
WIPHY_FLAG_IBSS_RSN;
+#ifdef CONFIG_PM_SLEEP
if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
- trans(priv)->ops->wowlan_suspend &&
- device_can_wakeup(trans(priv)->dev)) {
+ priv->trans->ops->wowlan_suspend &&
+ device_can_wakeup(priv->trans->dev)) {
hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
WIPHY_WOWLAN_DISCONNECT |
WIPHY_WOWLAN_EAP_IDENTITY_REQ |
WIPHY_WOWLAN_RFKILL_RELEASE;
- if (!iwlagn_mod_params.sw_crypto)
+ if (!iwlwifi_mod_params.sw_crypto)
hw->wiphy->wowlan.flags |=
WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
WIPHY_WOWLAN_GTK_REKEY_FAILURE;
@@ -214,18 +218,22 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
hw->wiphy->wowlan.pattern_max_len =
IWLAGN_WOWLAN_MAX_PATTERN_LEN;
}
+#endif
- if (iwlagn_mod_params.power_save)
+ if (iwlwifi_mod_params.power_save)
hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
else
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 */
- hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 2;
+ /* we create the 802.11 header and a max-length SSID element */
+ hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 34;
- /* Default value; 4 EDCA QOS priorities */
- hw->queues = 4;
+ /*
+ * We don't use all queues: 4 and 9 are unused and any
+ * aggregation queue gets mapped down to the AC queue.
+ */
+ hw->queues = IWLAGN_FIRST_AMPDU_QUEUE;
hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
@@ -236,13 +244,14 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
&priv->bands[IEEE80211_BAND_5GHZ];
- hw->wiphy->hw_version = trans(priv)->hw_id;
+ hw->wiphy->hw_version = priv->trans->hw_id;
iwl_leds_init(priv);
ret = ieee80211_register_hw(priv->hw);
if (ret) {
IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
+ iwl_leds_exit(priv);
return ret;
}
priv->mac80211_registered = 1;
@@ -332,7 +341,7 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw)
return 0;
}
-static void iwlagn_mac_stop(struct ieee80211_hw *hw)
+void iwlagn_mac_stop(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
@@ -355,18 +364,18 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
* even if interface is down, trans->down will leave the RF
* kill interrupt enabled
*/
- iwl_trans_stop_hw(trans(priv));
+ iwl_trans_stop_hw(priv->trans, false);
IWL_DEBUG_MAC80211(priv, "leave\n");
}
-static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct cfg80211_gtk_rekey_data *data)
+void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_gtk_rekey_data *data)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
- if (iwlagn_mod_params.sw_crypto)
+ if (iwlwifi_mod_params.sw_crypto)
return;
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -388,8 +397,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
#ifdef CONFIG_PM_SLEEP
-static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
- struct cfg80211_wowlan *wowlan)
+int iwlagn_mac_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
@@ -412,9 +420,9 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
if (ret)
goto error;
- device_set_wakeup_enable(trans(priv)->dev, true);
+ device_set_wakeup_enable(priv->trans->dev, true);
- iwl_trans_wowlan_suspend(trans(priv));
+ iwl_trans_wowlan_suspend(priv->trans);
goto out;
@@ -437,27 +445,28 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
unsigned long flags;
u32 base, status = 0xffffffff;
int ret = -EIO;
- const struct fw_img *img;
IWL_DEBUG_MAC80211(priv, "enter\n");
mutex_lock(&priv->mutex);
- iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR,
+ iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
- base = priv->shrd->device_pointers.error_event_table;
+ base = priv->device_pointers.error_event_table;
if (iwlagn_hw_valid_rtc_data_addr(base)) {
- spin_lock_irqsave(&trans(priv)->reg_lock, flags);
- ret = iwl_grab_nic_access_silent(trans(priv));
+ spin_lock_irqsave(&priv->trans->reg_lock, flags);
+ ret = iwl_grab_nic_access_silent(priv->trans);
if (likely(ret == 0)) {
- iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, base);
- status = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
- iwl_release_nic_access(trans(priv));
+ iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, base);
+ status = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT);
+ iwl_release_nic_access(priv->trans);
}
- spin_unlock_irqrestore(&trans(priv)->reg_lock, flags);
+ spin_unlock_irqrestore(&priv->trans->reg_lock, flags);
#ifdef CONFIG_IWLWIFI_DEBUGFS
if (ret == 0) {
+ const struct fw_img *img;
+
img = &(priv->fw->img[IWL_UCODE_WOWLAN]);
if (!priv->wowlan_sram) {
priv->wowlan_sram =
@@ -467,7 +476,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
if (priv->wowlan_sram)
_iwl_read_targ_mem_words(
- trans(priv), 0x800000,
+ priv->trans, 0x800000,
priv->wowlan_sram,
img->sec[IWL_UCODE_SECTION_DATA].len / 4);
}
@@ -479,7 +488,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
priv->wowlan = false;
- device_set_wakeup_enable(trans(priv)->dev, false);
+ device_set_wakeup_enable(priv->trans->dev, false);
iwlagn_prepare_restart(priv);
@@ -497,7 +506,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
#endif
-static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
@@ -508,21 +517,21 @@ static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
dev_kfree_skb_any(skb);
}
-static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_key_conf *keyconf,
- struct ieee80211_sta *sta,
- u32 iv32, u16 *phase1key)
+void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_key_conf *keyconf,
+ struct ieee80211_sta *sta,
+ u32 iv32, u16 *phase1key)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
iwl_update_tkip_key(priv, vif, keyconf, sta, iv32, phase1key);
}
-static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key)
+int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
@@ -532,7 +541,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
IWL_DEBUG_MAC80211(priv, "enter\n");
- if (iwlagn_mod_params.sw_crypto) {
+ if (iwlwifi_mod_params.sw_crypto) {
IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n");
return -EOPNOTSUPP;
}
@@ -622,11 +631,11 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return ret;
}
-static int iwlagn_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,
- u8 buf_size)
+int iwlagn_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,
+ u8 buf_size)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
int ret = -EINVAL;
@@ -635,7 +644,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
sta->addr, tid);
- if (!(hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE))
+ if (!(priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE))
return -EACCES;
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -643,7 +652,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
switch (action) {
case IEEE80211_AMPDU_RX_START:
- if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
+ if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
break;
IWL_DEBUG_HT(priv, "start Rx\n");
ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn);
@@ -653,7 +662,9 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
ret = iwl_sta_rx_agg_stop(priv, sta, tid);
break;
case IEEE80211_AMPDU_TX_START:
- if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
+ if (!priv->trans->ops->tx_agg_setup)
+ break;
+ if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
break;
IWL_DEBUG_HT(priv, "start Tx\n");
ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
@@ -667,7 +678,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
priv->agg_tids_count);
}
if (!priv->agg_tids_count &&
- hw_params(priv).use_rts_for_aggregation) {
+ priv->hw_params.use_rts_for_aggregation) {
/*
* switch off RTS/CTS if it was previously enabled
*/
@@ -746,11 +757,11 @@ static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw,
return ret;
}
-static int iwlagn_mac_sta_state(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- enum ieee80211_sta_state old_state,
- enum ieee80211_sta_state new_state)
+int iwlagn_mac_sta_state(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ enum ieee80211_sta_state old_state,
+ enum ieee80211_sta_state new_state)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
@@ -829,8 +840,8 @@ static int iwlagn_mac_sta_state(struct ieee80211_hw *hw,
return ret;
}
-static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_channel_switch *ch_switch)
+void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
+ struct ieee80211_channel_switch *ch_switch)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
const struct iwl_channel_info *ch_info;
@@ -863,7 +874,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
if (!iwl_is_associated_ctx(ctx))
goto out;
- if (!cfg(priv)->lib->set_channel_switch)
+ if (!priv->lib->set_channel_switch)
goto out;
ch = channel->hw_value;
@@ -892,14 +903,13 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
iwl_set_rxon_ht(priv, ht_conf);
iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif);
- iwl_set_rate(priv);
/*
* 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 (cfg(priv)->lib->set_channel_switch(priv, ch_switch)) {
+ if (priv->lib->set_channel_switch(priv, ch_switch)) {
clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
priv->switch_channel = 0;
ieee80211_chswitch_done(ctx->vif, false);
@@ -910,10 +920,25 @@ out:
IWL_DEBUG_MAC80211(priv, "leave\n");
}
-static void iwlagn_configure_filter(struct ieee80211_hw *hw,
- unsigned int changed_flags,
- unsigned int *total_flags,
- u64 multicast)
+void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
+{
+ /*
+ * MULTI-FIXME
+ * See iwlagn_mac_channel_switch.
+ */
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+ ieee80211_chswitch_done(ctx->vif, is_success);
+}
+
+void iwlagn_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *total_flags,
+ u64 multicast)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
__le32 filter_or = 0, filter_nand = 0;
@@ -960,7 +985,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
}
-static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
+void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
@@ -988,7 +1013,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
}
}
IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n");
- iwl_trans_wait_tx_queue_empty(trans(priv));
+ iwl_trans_wait_tx_queue_empty(priv->trans);
done:
mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -1003,7 +1028,7 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
int err = 0;
- if (!(priv->shrd->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
+ if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
return -EOPNOTSUPP;
if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)))
@@ -1087,11 +1112,11 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
return err;
}
-static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
+int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
- if (!(priv->shrd->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
+ if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
return -EOPNOTSUPP;
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -1104,16 +1129,16 @@ static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
return 0;
}
-static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
- enum ieee80211_rssi_event rssi_event)
+void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
+ enum ieee80211_rssi_event rssi_event)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
IWL_DEBUG_MAC80211(priv, "enter\n");
mutex_lock(&priv->mutex);
- if (cfg(priv)->bt_params &&
- cfg(priv)->bt_params->advanced_bt_coexist) {
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist) {
if (rssi_event == RSSI_EVENT_LOW)
priv->bt_enable_pspoll = true;
else if (rssi_event == RSSI_EVENT_HIGH)
@@ -1129,8 +1154,8 @@ static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "leave\n");
}
-static int iwlagn_mac_set_tim(struct ieee80211_hw *hw,
- struct ieee80211_sta *sta, bool set)
+int iwlagn_mac_set_tim(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta, bool set)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
@@ -1139,9 +1164,9 @@ static int iwlagn_mac_set_tim(struct ieee80211_hw *hw,
return 0;
}
-static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, u16 queue,
- const struct ieee80211_tx_queue_params *params)
+int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
+ const struct ieee80211_tx_queue_params *params)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
@@ -1183,7 +1208,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
return 0;
}
-static int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw)
+int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
@@ -1199,11 +1224,10 @@ static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
return iwlagn_commit_rxon(priv, ctx);
}
-static int iwl_setup_interface(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx)
+int iwl_setup_interface(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{
struct ieee80211_vif *vif = ctx->vif;
- int err;
+ int err, ac;
lockdep_assert_held(&priv->mutex);
@@ -1223,7 +1247,7 @@ static int iwl_setup_interface(struct iwl_priv *priv,
return err;
}
- if (cfg(priv)->bt_params && cfg(priv)->bt_params->advanced_bt_coexist &&
+ if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist &&
vif->type == NL80211_IFTYPE_ADHOC) {
/*
* pretend to have high BT traffic as long as we
@@ -1233,17 +1257,27 @@ static int iwl_setup_interface(struct iwl_priv *priv,
priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
}
+ /* set up queue mappings */
+ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+ vif->hw_queue[ac] = ctx->ac_to_queue[ac];
+
+ if (vif->type == NL80211_IFTYPE_AP)
+ vif->cab_queue = ctx->mcast_queue;
+ else
+ vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
+
return 0;
}
static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_vif *vif)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
struct iwl_rxon_context *tmp, *ctx = NULL;
int err;
enum nl80211_iftype viftype = ieee80211_vif_type_p2p(vif);
+ bool reset = false;
IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
viftype, vif->addr);
@@ -1265,6 +1299,13 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
tmp->interface_modes | tmp->exclusive_interface_modes;
if (tmp->vif) {
+ /* On reset we need to add the same interface again */
+ if (tmp->vif == vif) {
+ reset = true;
+ ctx = tmp;
+ break;
+ }
+
/* check if this busy context is exclusive */
if (tmp->exclusive_interface_modes &
BIT(tmp->vif->type)) {
@@ -1291,7 +1332,7 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
ctx->vif = vif;
err = iwl_setup_interface(priv, ctx);
- if (!err)
+ if (!err || reset)
goto out;
ctx->vif = NULL;
@@ -1303,9 +1344,9 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
return err;
}
-static void iwl_teardown_interface(struct iwl_priv *priv,
- struct ieee80211_vif *vif,
- bool mode_change)
+void iwl_teardown_interface(struct iwl_priv *priv,
+ struct ieee80211_vif *vif,
+ bool mode_change)
{
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
@@ -1446,9 +1487,9 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
return err;
}
-static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct cfg80211_scan_request *req)
+int iwlagn_mac_hw_scan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_scan_request *req)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
int ret;
@@ -1503,7 +1544,7 @@ static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
iwl_send_add_sta(priv, &cmd, CMD_ASYNC);
}
-static void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
+void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum sta_notify_cmd cmd,
struct ieee80211_sta *sta)