diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 546 |
1 files changed, 420 insertions, 126 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 3ced9ea9c5fe..ad0e67f5c0d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -87,6 +87,9 @@ MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); | |||
87 | MODULE_LICENSE("GPL"); | 87 | MODULE_LICENSE("GPL"); |
88 | MODULE_ALIAS("iwl4965"); | 88 | MODULE_ALIAS("iwl4965"); |
89 | 89 | ||
90 | static int iwlagn_ant_coupling; | ||
91 | static bool iwlagn_bt_ch_announce = 1; | ||
92 | |||
90 | /** | 93 | /** |
91 | * iwl_commit_rxon - commit staging_rxon to hardware | 94 | * iwl_commit_rxon - commit staging_rxon to hardware |
92 | * | 95 | * |
@@ -95,21 +98,22 @@ MODULE_ALIAS("iwl4965"); | |||
95 | * function correctly transitions out of the RXON_ASSOC_MSK state if | 98 | * function correctly transitions out of the RXON_ASSOC_MSK state if |
96 | * a HW tune is required based on the RXON structure changes. | 99 | * a HW tune is required based on the RXON structure changes. |
97 | */ | 100 | */ |
98 | int iwl_commit_rxon(struct iwl_priv *priv) | 101 | int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) |
99 | { | 102 | { |
100 | /* cast away the const for active_rxon in this function */ | 103 | /* cast away the const for active_rxon in this function */ |
101 | struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon; | 104 | struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active; |
102 | int ret; | 105 | int ret; |
103 | bool new_assoc = | 106 | bool new_assoc = |
104 | !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK); | 107 | !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); |
108 | bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK); | ||
105 | 109 | ||
106 | if (!iwl_is_alive(priv)) | 110 | if (!iwl_is_alive(priv)) |
107 | return -EBUSY; | 111 | return -EBUSY; |
108 | 112 | ||
109 | /* always get timestamp with Rx frame */ | 113 | /* always get timestamp with Rx frame */ |
110 | priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK; | 114 | ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; |
111 | 115 | ||
112 | ret = iwl_check_rxon_cmd(priv); | 116 | ret = iwl_check_rxon_cmd(priv, ctx); |
113 | if (ret) { | 117 | if (ret) { |
114 | IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); | 118 | IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); |
115 | return -EINVAL; | 119 | return -EINVAL; |
@@ -120,7 +124,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
120 | * abort any previous channel switch if still in process | 124 | * abort any previous channel switch if still in process |
121 | */ | 125 | */ |
122 | if (priv->switch_rxon.switch_in_progress && | 126 | if (priv->switch_rxon.switch_in_progress && |
123 | (priv->switch_rxon.channel != priv->staging_rxon.channel)) { | 127 | (priv->switch_rxon.channel != ctx->staging.channel)) { |
124 | IWL_DEBUG_11H(priv, "abort channel switch on %d\n", | 128 | IWL_DEBUG_11H(priv, "abort channel switch on %d\n", |
125 | le16_to_cpu(priv->switch_rxon.channel)); | 129 | le16_to_cpu(priv->switch_rxon.channel)); |
126 | iwl_chswitch_done(priv, false); | 130 | iwl_chswitch_done(priv, false); |
@@ -129,15 +133,15 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
129 | /* If we don't need to send a full RXON, we can use | 133 | /* If we don't need to send a full RXON, we can use |
130 | * iwl_rxon_assoc_cmd which is used to reconfigure filter | 134 | * iwl_rxon_assoc_cmd which is used to reconfigure filter |
131 | * and other flags for the current radio configuration. */ | 135 | * and other flags for the current radio configuration. */ |
132 | if (!iwl_full_rxon_required(priv)) { | 136 | if (!iwl_full_rxon_required(priv, ctx)) { |
133 | ret = iwl_send_rxon_assoc(priv); | 137 | ret = iwl_send_rxon_assoc(priv, ctx); |
134 | if (ret) { | 138 | if (ret) { |
135 | IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret); | 139 | IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret); |
136 | return ret; | 140 | return ret; |
137 | } | 141 | } |
138 | 142 | ||
139 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); | 143 | memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); |
140 | iwl_print_rx_config_cmd(priv); | 144 | iwl_print_rx_config_cmd(priv, ctx); |
141 | return 0; | 145 | return 0; |
142 | } | 146 | } |
143 | 147 | ||
@@ -145,13 +149,13 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
145 | * an RXON_ASSOC and the new config wants the associated mask enabled, | 149 | * an RXON_ASSOC and the new config wants the associated mask enabled, |
146 | * we must clear the associated from the active configuration | 150 | * we must clear the associated from the active configuration |
147 | * before we apply the new config */ | 151 | * before we apply the new config */ |
148 | if (iwl_is_associated(priv) && new_assoc) { | 152 | if (iwl_is_associated_ctx(ctx) && new_assoc) { |
149 | IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); | 153 | IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); |
150 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 154 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
151 | 155 | ||
152 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON, | 156 | ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, |
153 | sizeof(struct iwl_rxon_cmd), | 157 | sizeof(struct iwl_rxon_cmd), |
154 | &priv->active_rxon); | 158 | active_rxon); |
155 | 159 | ||
156 | /* If the mask clearing failed then we set | 160 | /* If the mask clearing failed then we set |
157 | * active_rxon back to what it was previously */ | 161 | * active_rxon back to what it was previously */ |
@@ -160,9 +164,9 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
160 | IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); | 164 | IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); |
161 | return ret; | 165 | return ret; |
162 | } | 166 | } |
163 | iwl_clear_ucode_stations(priv); | 167 | iwl_clear_ucode_stations(priv, ctx); |
164 | iwl_restore_stations(priv); | 168 | iwl_restore_stations(priv, ctx); |
165 | ret = iwl_restore_default_wep_keys(priv); | 169 | ret = iwl_restore_default_wep_keys(priv, ctx); |
166 | if (ret) { | 170 | if (ret) { |
167 | IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); | 171 | IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); |
168 | return ret; | 172 | return ret; |
@@ -174,27 +178,46 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
174 | "* channel = %d\n" | 178 | "* channel = %d\n" |
175 | "* bssid = %pM\n", | 179 | "* bssid = %pM\n", |
176 | (new_assoc ? "" : "out"), | 180 | (new_assoc ? "" : "out"), |
177 | le16_to_cpu(priv->staging_rxon.channel), | 181 | le16_to_cpu(ctx->staging.channel), |
178 | priv->staging_rxon.bssid_addr); | 182 | ctx->staging.bssid_addr); |
183 | |||
184 | iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto); | ||
185 | |||
186 | if (!old_assoc) { | ||
187 | /* | ||
188 | * First of all, before setting associated, we need to | ||
189 | * send RXON timing so the device knows about the DTIM | ||
190 | * period and other timing values | ||
191 | */ | ||
192 | ret = iwl_send_rxon_timing(priv, ctx); | ||
193 | if (ret) { | ||
194 | IWL_ERR(priv, "Error setting RXON timing!\n"); | ||
195 | return ret; | ||
196 | } | ||
197 | } | ||
179 | 198 | ||
180 | iwl_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto); | 199 | if (priv->cfg->ops->hcmd->set_pan_params) { |
200 | ret = priv->cfg->ops->hcmd->set_pan_params(priv); | ||
201 | if (ret) | ||
202 | return ret; | ||
203 | } | ||
181 | 204 | ||
182 | /* Apply the new configuration | 205 | /* Apply the new configuration |
183 | * RXON unassoc clears the station table in uCode so restoration of | 206 | * RXON unassoc clears the station table in uCode so restoration of |
184 | * stations is needed after it (the RXON command) completes | 207 | * stations is needed after it (the RXON command) completes |
185 | */ | 208 | */ |
186 | if (!new_assoc) { | 209 | if (!new_assoc) { |
187 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON, | 210 | ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, |
188 | sizeof(struct iwl_rxon_cmd), &priv->staging_rxon); | 211 | sizeof(struct iwl_rxon_cmd), &ctx->staging); |
189 | if (ret) { | 212 | if (ret) { |
190 | IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); | 213 | IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); |
191 | return ret; | 214 | return ret; |
192 | } | 215 | } |
193 | IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); | 216 | IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); |
194 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); | 217 | memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); |
195 | iwl_clear_ucode_stations(priv); | 218 | iwl_clear_ucode_stations(priv, ctx); |
196 | iwl_restore_stations(priv); | 219 | iwl_restore_stations(priv, ctx); |
197 | ret = iwl_restore_default_wep_keys(priv); | 220 | ret = iwl_restore_default_wep_keys(priv, ctx); |
198 | if (ret) { | 221 | if (ret) { |
199 | IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); | 222 | IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); |
200 | return ret; | 223 | return ret; |
@@ -206,15 +229,15 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
206 | /* Apply the new configuration | 229 | /* Apply the new configuration |
207 | * RXON assoc doesn't clear the station table in uCode, | 230 | * RXON assoc doesn't clear the station table in uCode, |
208 | */ | 231 | */ |
209 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON, | 232 | ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, |
210 | sizeof(struct iwl_rxon_cmd), &priv->staging_rxon); | 233 | sizeof(struct iwl_rxon_cmd), &ctx->staging); |
211 | if (ret) { | 234 | if (ret) { |
212 | IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); | 235 | IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); |
213 | return ret; | 236 | return ret; |
214 | } | 237 | } |
215 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); | 238 | memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); |
216 | } | 239 | } |
217 | iwl_print_rx_config_cmd(priv); | 240 | iwl_print_rx_config_cmd(priv, ctx); |
218 | 241 | ||
219 | iwl_init_sensitivity(priv); | 242 | iwl_init_sensitivity(priv); |
220 | 243 | ||
@@ -231,10 +254,14 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
231 | 254 | ||
232 | void iwl_update_chain_flags(struct iwl_priv *priv) | 255 | void iwl_update_chain_flags(struct iwl_priv *priv) |
233 | { | 256 | { |
257 | struct iwl_rxon_context *ctx; | ||
234 | 258 | ||
235 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 259 | if (priv->cfg->ops->hcmd->set_rxon_chain) { |
236 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 260 | for_each_context(priv, ctx) { |
237 | iwlcore_commit_rxon(priv); | 261 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); |
262 | iwlcore_commit_rxon(priv, ctx); | ||
263 | } | ||
264 | } | ||
238 | } | 265 | } |
239 | 266 | ||
240 | static void iwl_clear_free_frames(struct iwl_priv *priv) | 267 | static void iwl_clear_free_frames(struct iwl_priv *priv) |
@@ -338,6 +365,13 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, | |||
338 | * beacon contents. | 365 | * beacon contents. |
339 | */ | 366 | */ |
340 | 367 | ||
368 | lockdep_assert_held(&priv->mutex); | ||
369 | |||
370 | if (!priv->beacon_ctx) { | ||
371 | IWL_ERR(priv, "trying to build beacon w/o beacon context!\n"); | ||
372 | return -EINVAL; | ||
373 | } | ||
374 | |||
341 | /* Initialize memory */ | 375 | /* Initialize memory */ |
342 | tx_beacon_cmd = &frame->u.beacon; | 376 | tx_beacon_cmd = &frame->u.beacon; |
343 | memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); | 377 | memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); |
@@ -350,7 +384,7 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, | |||
350 | 384 | ||
351 | /* Set up TX command fields */ | 385 | /* Set up TX command fields */ |
352 | tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); | 386 | tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); |
353 | tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; | 387 | tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id; |
354 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | 388 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; |
355 | tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK | | 389 | tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK | |
356 | TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK; | 390 | TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK; |
@@ -360,7 +394,7 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, | |||
360 | frame_size); | 394 | frame_size); |
361 | 395 | ||
362 | /* Set up packet rate and flags */ | 396 | /* Set up packet rate and flags */ |
363 | rate = iwl_rate_get_lowest_plcp(priv); | 397 | rate = iwl_rate_get_lowest_plcp(priv, priv->beacon_ctx); |
364 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 398 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
365 | priv->hw_params.valid_tx_ant); | 399 | priv->hw_params.valid_tx_ant); |
366 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | 400 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); |
@@ -593,23 +627,84 @@ static void iwl_bg_beacon_update(struct work_struct *work) | |||
593 | container_of(work, struct iwl_priv, beacon_update); | 627 | container_of(work, struct iwl_priv, beacon_update); |
594 | struct sk_buff *beacon; | 628 | struct sk_buff *beacon; |
595 | 629 | ||
596 | /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ | 630 | mutex_lock(&priv->mutex); |
597 | beacon = ieee80211_beacon_get(priv->hw, priv->vif); | 631 | if (!priv->beacon_ctx) { |
632 | IWL_ERR(priv, "updating beacon w/o beacon context!\n"); | ||
633 | goto out; | ||
634 | } | ||
635 | |||
636 | if (priv->beacon_ctx->vif->type != NL80211_IFTYPE_AP) { | ||
637 | /* | ||
638 | * The ucode will send beacon notifications even in | ||
639 | * IBSS mode, but we don't want to process them. But | ||
640 | * we need to defer the type check to here due to | ||
641 | * requiring locking around the beacon_ctx access. | ||
642 | */ | ||
643 | goto out; | ||
644 | } | ||
598 | 645 | ||
646 | /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ | ||
647 | beacon = ieee80211_beacon_get(priv->hw, priv->beacon_ctx->vif); | ||
599 | if (!beacon) { | 648 | if (!beacon) { |
600 | IWL_ERR(priv, "update beacon failed\n"); | 649 | IWL_ERR(priv, "update beacon failed\n"); |
601 | return; | 650 | goto out; |
602 | } | 651 | } |
603 | 652 | ||
604 | mutex_lock(&priv->mutex); | ||
605 | /* new beacon skb is allocated every time; dispose previous.*/ | 653 | /* new beacon skb is allocated every time; dispose previous.*/ |
606 | if (priv->ibss_beacon) | 654 | if (priv->ibss_beacon) |
607 | dev_kfree_skb(priv->ibss_beacon); | 655 | dev_kfree_skb(priv->ibss_beacon); |
608 | 656 | ||
609 | priv->ibss_beacon = beacon; | 657 | priv->ibss_beacon = beacon; |
610 | mutex_unlock(&priv->mutex); | ||
611 | 658 | ||
612 | iwl_send_beacon_cmd(priv); | 659 | iwl_send_beacon_cmd(priv); |
660 | out: | ||
661 | mutex_unlock(&priv->mutex); | ||
662 | } | ||
663 | |||
664 | static void iwl_bg_bt_runtime_config(struct work_struct *work) | ||
665 | { | ||
666 | struct iwl_priv *priv = | ||
667 | container_of(work, struct iwl_priv, bt_runtime_config); | ||
668 | |||
669 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
670 | return; | ||
671 | |||
672 | /* dont send host command if rf-kill is on */ | ||
673 | if (!iwl_is_ready_rf(priv)) | ||
674 | return; | ||
675 | priv->cfg->ops->hcmd->send_bt_config(priv); | ||
676 | } | ||
677 | |||
678 | static void iwl_bg_bt_full_concurrency(struct work_struct *work) | ||
679 | { | ||
680 | struct iwl_priv *priv = | ||
681 | container_of(work, struct iwl_priv, bt_full_concurrency); | ||
682 | struct iwl_rxon_context *ctx; | ||
683 | |||
684 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
685 | return; | ||
686 | |||
687 | /* dont send host command if rf-kill is on */ | ||
688 | if (!iwl_is_ready_rf(priv)) | ||
689 | return; | ||
690 | |||
691 | IWL_DEBUG_INFO(priv, "BT coex in %s mode\n", | ||
692 | priv->bt_full_concurrent ? | ||
693 | "full concurrency" : "3-wire"); | ||
694 | |||
695 | /* | ||
696 | * LQ & RXON updated cmds must be sent before BT Config cmd | ||
697 | * to avoid 3-wire collisions | ||
698 | */ | ||
699 | mutex_lock(&priv->mutex); | ||
700 | for_each_context(priv, ctx) { | ||
701 | if (priv->cfg->ops->hcmd->set_rxon_chain) | ||
702 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); | ||
703 | iwlcore_commit_rxon(priv, ctx); | ||
704 | } | ||
705 | mutex_unlock(&priv->mutex); | ||
706 | |||
707 | priv->cfg->ops->hcmd->send_bt_config(priv); | ||
613 | } | 708 | } |
614 | 709 | ||
615 | /** | 710 | /** |
@@ -781,8 +876,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, | |||
781 | 876 | ||
782 | priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); | 877 | priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); |
783 | 878 | ||
784 | if ((priv->iw_mode == NL80211_IFTYPE_AP) && | 879 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) |
785 | (!test_bit(STATUS_EXIT_PENDING, &priv->status))) | ||
786 | queue_work(priv->workqueue, &priv->beacon_update); | 880 | queue_work(priv->workqueue, &priv->beacon_update); |
787 | } | 881 | } |
788 | 882 | ||
@@ -1653,6 +1747,7 @@ static void iwl_nic_start(struct iwl_priv *priv) | |||
1653 | struct iwlagn_ucode_capabilities { | 1747 | struct iwlagn_ucode_capabilities { |
1654 | u32 max_probe_length; | 1748 | u32 max_probe_length; |
1655 | u32 standard_phy_calibration_size; | 1749 | u32 standard_phy_calibration_size; |
1750 | bool pan; | ||
1656 | }; | 1751 | }; |
1657 | 1752 | ||
1658 | static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); | 1753 | static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); |
@@ -1890,6 +1985,11 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, | |||
1890 | capa->max_probe_length = | 1985 | capa->max_probe_length = |
1891 | le32_to_cpup((__le32 *)tlv_data); | 1986 | le32_to_cpup((__le32 *)tlv_data); |
1892 | break; | 1987 | break; |
1988 | case IWL_UCODE_TLV_PAN: | ||
1989 | if (tlv_len) | ||
1990 | goto invalid_tlv_len; | ||
1991 | capa->pan = true; | ||
1992 | break; | ||
1893 | case IWL_UCODE_TLV_INIT_EVTLOG_PTR: | 1993 | case IWL_UCODE_TLV_INIT_EVTLOG_PTR: |
1894 | if (tlv_len != sizeof(u32)) | 1994 | if (tlv_len != sizeof(u32)) |
1895 | goto invalid_tlv_len; | 1995 | goto invalid_tlv_len; |
@@ -2165,6 +2265,12 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
2165 | priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size; | 2265 | priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size; |
2166 | priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; | 2266 | priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; |
2167 | 2267 | ||
2268 | if (ucode_capa.pan) { | ||
2269 | priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN); | ||
2270 | priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; | ||
2271 | } else | ||
2272 | priv->sta_key_max_num = STA_KEY_MAX_NUM; | ||
2273 | |||
2168 | /* Copy images into buffers for card's bus-master reads ... */ | 2274 | /* Copy images into buffers for card's bus-master reads ... */ |
2169 | 2275 | ||
2170 | /* Runtime instructions (first block of data in file) */ | 2276 | /* Runtime instructions (first block of data in file) */ |
@@ -2563,6 +2669,9 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
2563 | return pos; | 2669 | return pos; |
2564 | } | 2670 | } |
2565 | 2671 | ||
2672 | /* enable/disable bt channel announcement */ | ||
2673 | priv->bt_ch_announce = iwlagn_bt_ch_announce; | ||
2674 | |||
2566 | #ifdef CONFIG_IWLWIFI_DEBUG | 2675 | #ifdef CONFIG_IWLWIFI_DEBUG |
2567 | if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log) | 2676 | if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log) |
2568 | size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) | 2677 | size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) |
@@ -2663,6 +2772,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) | |||
2663 | static void iwl_alive_start(struct iwl_priv *priv) | 2772 | static void iwl_alive_start(struct iwl_priv *priv) |
2664 | { | 2773 | { |
2665 | int ret = 0; | 2774 | int ret = 0; |
2775 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
2666 | 2776 | ||
2667 | IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); | 2777 | IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); |
2668 | 2778 | ||
@@ -2711,27 +2821,31 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2711 | if (priv->cfg->ops->hcmd->set_tx_ant) | 2821 | if (priv->cfg->ops->hcmd->set_tx_ant) |
2712 | priv->cfg->ops->hcmd->set_tx_ant(priv, priv->cfg->valid_tx_ant); | 2822 | priv->cfg->ops->hcmd->set_tx_ant(priv, priv->cfg->valid_tx_ant); |
2713 | 2823 | ||
2714 | if (iwl_is_associated(priv)) { | 2824 | if (iwl_is_associated_ctx(ctx)) { |
2715 | struct iwl_rxon_cmd *active_rxon = | 2825 | struct iwl_rxon_cmd *active_rxon = |
2716 | (struct iwl_rxon_cmd *)&priv->active_rxon; | 2826 | (struct iwl_rxon_cmd *)&ctx->active; |
2717 | /* apply any changes in staging */ | 2827 | /* apply any changes in staging */ |
2718 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 2828 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; |
2719 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2829 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2720 | } else { | 2830 | } else { |
2831 | struct iwl_rxon_context *tmp; | ||
2721 | /* Initialize our rx_config data */ | 2832 | /* Initialize our rx_config data */ |
2722 | iwl_connection_init_rx_config(priv, NULL); | 2833 | for_each_context(priv, tmp) |
2834 | iwl_connection_init_rx_config(priv, tmp); | ||
2723 | 2835 | ||
2724 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 2836 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2725 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 2837 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); |
2726 | } | 2838 | } |
2727 | 2839 | ||
2728 | /* Configure Bluetooth device coexistence support */ | 2840 | if (!priv->cfg->advanced_bt_coexist) { |
2729 | priv->cfg->ops->hcmd->send_bt_config(priv); | 2841 | /* Configure Bluetooth device coexistence support */ |
2842 | priv->cfg->ops->hcmd->send_bt_config(priv); | ||
2843 | } | ||
2730 | 2844 | ||
2731 | iwl_reset_run_time_calib(priv); | 2845 | iwl_reset_run_time_calib(priv); |
2732 | 2846 | ||
2733 | /* Configure the adapter for unassociated operation */ | 2847 | /* Configure the adapter for unassociated operation */ |
2734 | iwlcore_commit_rxon(priv); | 2848 | iwlcore_commit_rxon(priv, ctx); |
2735 | 2849 | ||
2736 | /* At this point, the NIC is initialized and operational */ | 2850 | /* At this point, the NIC is initialized and operational */ |
2737 | iwl_rf_kill_ct_config(priv); | 2851 | iwl_rf_kill_ct_config(priv); |
@@ -2764,10 +2878,22 @@ static void __iwl_down(struct iwl_priv *priv) | |||
2764 | if (!exit_pending) | 2878 | if (!exit_pending) |
2765 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 2879 | set_bit(STATUS_EXIT_PENDING, &priv->status); |
2766 | 2880 | ||
2767 | iwl_clear_ucode_stations(priv); | 2881 | /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set |
2768 | iwl_dealloc_bcast_station(priv); | 2882 | * to prevent rearm timer */ |
2883 | if (priv->cfg->ops->lib->recover_from_tx_stall) | ||
2884 | del_timer_sync(&priv->monitor_recover); | ||
2885 | |||
2886 | iwl_clear_ucode_stations(priv, NULL); | ||
2887 | iwl_dealloc_bcast_stations(priv); | ||
2769 | iwl_clear_driver_stations(priv); | 2888 | iwl_clear_driver_stations(priv); |
2770 | 2889 | ||
2890 | /* reset BT coex data */ | ||
2891 | priv->bt_status = 0; | ||
2892 | priv->bt_traffic_load = priv->cfg->bt_init_traffic_load; | ||
2893 | priv->bt_sco_active = false; | ||
2894 | priv->bt_full_concurrent = false; | ||
2895 | priv->bt_ci_compliance = 0; | ||
2896 | |||
2771 | /* Unblock any waiting calls */ | 2897 | /* Unblock any waiting calls */ |
2772 | wake_up_interruptible_all(&priv->wait_command_queue); | 2898 | wake_up_interruptible_all(&priv->wait_command_queue); |
2773 | 2899 | ||
@@ -2900,6 +3026,7 @@ static int iwl_prepare_card_hw(struct iwl_priv *priv) | |||
2900 | 3026 | ||
2901 | static int __iwl_up(struct iwl_priv *priv) | 3027 | static int __iwl_up(struct iwl_priv *priv) |
2902 | { | 3028 | { |
3029 | struct iwl_rxon_context *ctx; | ||
2903 | int i; | 3030 | int i; |
2904 | int ret; | 3031 | int ret; |
2905 | 3032 | ||
@@ -2913,9 +3040,13 @@ static int __iwl_up(struct iwl_priv *priv) | |||
2913 | return -EIO; | 3040 | return -EIO; |
2914 | } | 3041 | } |
2915 | 3042 | ||
2916 | ret = iwl_alloc_bcast_station(priv, true); | 3043 | for_each_context(priv, ctx) { |
2917 | if (ret) | 3044 | ret = iwl_alloc_bcast_station(priv, ctx, true); |
2918 | return ret; | 3045 | if (ret) { |
3046 | iwl_dealloc_bcast_stations(priv); | ||
3047 | return ret; | ||
3048 | } | ||
3049 | } | ||
2919 | 3050 | ||
2920 | iwl_prepare_card_hw(priv); | 3051 | iwl_prepare_card_hw(priv); |
2921 | 3052 | ||
@@ -2940,6 +3071,12 @@ static int __iwl_up(struct iwl_priv *priv) | |||
2940 | 3071 | ||
2941 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); | 3072 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); |
2942 | 3073 | ||
3074 | /* must be initialised before iwl_hw_nic_init */ | ||
3075 | if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) | ||
3076 | priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; | ||
3077 | else | ||
3078 | priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; | ||
3079 | |||
2943 | ret = iwlagn_hw_nic_init(priv); | 3080 | ret = iwlagn_hw_nic_init(priv); |
2944 | if (ret) { | 3081 | if (ret) { |
2945 | IWL_ERR(priv, "Unable to init nic\n"); | 3082 | IWL_ERR(priv, "Unable to init nic\n"); |
@@ -3070,11 +3207,42 @@ static void iwl_bg_restart(struct work_struct *data) | |||
3070 | return; | 3207 | return; |
3071 | 3208 | ||
3072 | if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { | 3209 | if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { |
3210 | struct iwl_rxon_context *ctx; | ||
3211 | bool bt_sco, bt_full_concurrent; | ||
3212 | u8 bt_ci_compliance; | ||
3213 | u8 bt_load; | ||
3214 | u8 bt_status; | ||
3215 | |||
3073 | mutex_lock(&priv->mutex); | 3216 | mutex_lock(&priv->mutex); |
3074 | priv->vif = NULL; | 3217 | for_each_context(priv, ctx) |
3218 | ctx->vif = NULL; | ||
3075 | priv->is_open = 0; | 3219 | priv->is_open = 0; |
3220 | |||
3221 | /* | ||
3222 | * __iwl_down() will clear the BT status variables, | ||
3223 | * which is correct, but when we restart we really | ||
3224 | * want to keep them so restore them afterwards. | ||
3225 | * | ||
3226 | * The restart process will later pick them up and | ||
3227 | * re-configure the hw when we reconfigure the BT | ||
3228 | * command. | ||
3229 | */ | ||
3230 | bt_sco = priv->bt_sco_active; | ||
3231 | bt_full_concurrent = priv->bt_full_concurrent; | ||
3232 | bt_ci_compliance = priv->bt_ci_compliance; | ||
3233 | bt_load = priv->bt_traffic_load; | ||
3234 | bt_status = priv->bt_status; | ||
3235 | |||
3236 | __iwl_down(priv); | ||
3237 | |||
3238 | priv->bt_sco_active = bt_sco; | ||
3239 | priv->bt_full_concurrent = bt_full_concurrent; | ||
3240 | priv->bt_ci_compliance = bt_ci_compliance; | ||
3241 | priv->bt_traffic_load = bt_load; | ||
3242 | priv->bt_status = bt_status; | ||
3243 | |||
3076 | mutex_unlock(&priv->mutex); | 3244 | mutex_unlock(&priv->mutex); |
3077 | iwl_down(priv); | 3245 | iwl_cancel_deferred_work(priv); |
3078 | ieee80211_restart_hw(priv->hw); | 3246 | ieee80211_restart_hw(priv->hw); |
3079 | } else { | 3247 | } else { |
3080 | iwl_down(priv); | 3248 | iwl_down(priv); |
@@ -3105,12 +3273,15 @@ static void iwl_bg_rx_replenish(struct work_struct *data) | |||
3105 | 3273 | ||
3106 | void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) | 3274 | void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) |
3107 | { | 3275 | { |
3276 | struct iwl_rxon_context *ctx; | ||
3108 | struct ieee80211_conf *conf = NULL; | 3277 | struct ieee80211_conf *conf = NULL; |
3109 | int ret = 0; | 3278 | int ret = 0; |
3110 | 3279 | ||
3111 | if (!vif || !priv->is_open) | 3280 | if (!vif || !priv->is_open) |
3112 | return; | 3281 | return; |
3113 | 3282 | ||
3283 | ctx = iwl_rxon_ctx_from_vif(vif); | ||
3284 | |||
3114 | if (vif->type == NL80211_IFTYPE_AP) { | 3285 | if (vif->type == NL80211_IFTYPE_AP) { |
3115 | IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); | 3286 | IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); |
3116 | return; | 3287 | return; |
@@ -3123,42 +3294,42 @@ void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3123 | 3294 | ||
3124 | conf = ieee80211_get_hw_conf(priv->hw); | 3295 | conf = ieee80211_get_hw_conf(priv->hw); |
3125 | 3296 | ||
3126 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 3297 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
3127 | iwlcore_commit_rxon(priv); | 3298 | iwlcore_commit_rxon(priv, ctx); |
3128 | 3299 | ||
3129 | ret = iwl_send_rxon_timing(priv, vif); | 3300 | ret = iwl_send_rxon_timing(priv, ctx); |
3130 | if (ret) | 3301 | if (ret) |
3131 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " | 3302 | IWL_WARN(priv, "RXON timing - " |
3132 | "Attempting to continue.\n"); | 3303 | "Attempting to continue.\n"); |
3133 | 3304 | ||
3134 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 3305 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; |
3135 | 3306 | ||
3136 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | 3307 | iwl_set_rxon_ht(priv, &priv->current_ht_config); |
3137 | 3308 | ||
3138 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 3309 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
3139 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 3310 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); |
3140 | 3311 | ||
3141 | priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid); | 3312 | ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); |
3142 | 3313 | ||
3143 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", | 3314 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", |
3144 | vif->bss_conf.aid, vif->bss_conf.beacon_int); | 3315 | vif->bss_conf.aid, vif->bss_conf.beacon_int); |
3145 | 3316 | ||
3146 | if (vif->bss_conf.use_short_preamble) | 3317 | if (vif->bss_conf.use_short_preamble) |
3147 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 3318 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
3148 | else | 3319 | else |
3149 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3320 | ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
3150 | 3321 | ||
3151 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 3322 | if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { |
3152 | if (vif->bss_conf.use_short_slot) | 3323 | if (vif->bss_conf.use_short_slot) |
3153 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 3324 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; |
3154 | else | 3325 | else |
3155 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 3326 | ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
3156 | } | 3327 | } |
3157 | 3328 | ||
3158 | iwlcore_commit_rxon(priv); | 3329 | iwlcore_commit_rxon(priv, ctx); |
3159 | 3330 | ||
3160 | IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", | 3331 | IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", |
3161 | vif->bss_conf.aid, priv->active_rxon.bssid_addr); | 3332 | vif->bss_conf.aid, ctx->active.bssid_addr); |
3162 | 3333 | ||
3163 | switch (vif->type) { | 3334 | switch (vif->type) { |
3164 | case NL80211_IFTYPE_STATION: | 3335 | case NL80211_IFTYPE_STATION: |
@@ -3201,11 +3372,14 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, | |||
3201 | { | 3372 | { |
3202 | int ret; | 3373 | int ret; |
3203 | struct ieee80211_hw *hw = priv->hw; | 3374 | struct ieee80211_hw *hw = priv->hw; |
3375 | struct iwl_rxon_context *ctx; | ||
3376 | |||
3204 | hw->rate_control_algorithm = "iwl-agn-rs"; | 3377 | hw->rate_control_algorithm = "iwl-agn-rs"; |
3205 | 3378 | ||
3206 | /* Tell mac80211 our characteristics */ | 3379 | /* Tell mac80211 our characteristics */ |
3207 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | 3380 | hw->flags = IEEE80211_HW_SIGNAL_DBM | |
3208 | IEEE80211_HW_AMPDU_AGGREGATION | | 3381 | IEEE80211_HW_AMPDU_AGGREGATION | |
3382 | IEEE80211_HW_NEED_DTIM_PERIOD | | ||
3209 | IEEE80211_HW_SPECTRUM_MGMT; | 3383 | IEEE80211_HW_SPECTRUM_MGMT; |
3210 | 3384 | ||
3211 | if (!priv->cfg->broken_powersave) | 3385 | if (!priv->cfg->broken_powersave) |
@@ -3219,9 +3393,10 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, | |||
3219 | hw->sta_data_size = sizeof(struct iwl_station_priv); | 3393 | hw->sta_data_size = sizeof(struct iwl_station_priv); |
3220 | hw->vif_data_size = sizeof(struct iwl_vif_priv); | 3394 | hw->vif_data_size = sizeof(struct iwl_vif_priv); |
3221 | 3395 | ||
3222 | hw->wiphy->interface_modes = | 3396 | for_each_context(priv, ctx) { |
3223 | BIT(NL80211_IFTYPE_STATION) | | 3397 | hw->wiphy->interface_modes |= ctx->interface_modes; |
3224 | BIT(NL80211_IFTYPE_ADHOC); | 3398 | hw->wiphy->interface_modes |= ctx->exclusive_interface_modes; |
3399 | } | ||
3225 | 3400 | ||
3226 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | | 3401 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | |
3227 | WIPHY_FLAG_DISABLE_BEACON_HINTS; | 3402 | WIPHY_FLAG_DISABLE_BEACON_HINTS; |
@@ -3349,22 +3524,25 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
3349 | 3524 | ||
3350 | void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | 3525 | void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) |
3351 | { | 3526 | { |
3527 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | ||
3352 | int ret = 0; | 3528 | int ret = 0; |
3353 | 3529 | ||
3530 | lockdep_assert_held(&priv->mutex); | ||
3531 | |||
3354 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 3532 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
3355 | return; | 3533 | return; |
3356 | 3534 | ||
3357 | /* The following should be done only at AP bring up */ | 3535 | /* The following should be done only at AP bring up */ |
3358 | if (!iwl_is_associated(priv)) { | 3536 | if (!iwl_is_associated_ctx(ctx)) { |
3359 | 3537 | ||
3360 | /* RXON - unassoc (to set timing command) */ | 3538 | /* RXON - unassoc (to set timing command) */ |
3361 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 3539 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
3362 | iwlcore_commit_rxon(priv); | 3540 | iwlcore_commit_rxon(priv, ctx); |
3363 | 3541 | ||
3364 | /* RXON Timing */ | 3542 | /* RXON Timing */ |
3365 | ret = iwl_send_rxon_timing(priv, vif); | 3543 | ret = iwl_send_rxon_timing(priv, ctx); |
3366 | if (ret) | 3544 | if (ret) |
3367 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " | 3545 | IWL_WARN(priv, "RXON timing failed - " |
3368 | "Attempting to continue.\n"); | 3546 | "Attempting to continue.\n"); |
3369 | 3547 | ||
3370 | /* AP has all antennas */ | 3548 | /* AP has all antennas */ |
@@ -3372,28 +3550,30 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3372 | priv->hw_params.valid_rx_ant; | 3550 | priv->hw_params.valid_rx_ant; |
3373 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | 3551 | iwl_set_rxon_ht(priv, &priv->current_ht_config); |
3374 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 3552 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
3375 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 3553 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); |
3376 | 3554 | ||
3377 | priv->staging_rxon.assoc_id = 0; | 3555 | ctx->staging.assoc_id = 0; |
3378 | 3556 | ||
3379 | if (vif->bss_conf.use_short_preamble) | 3557 | if (vif->bss_conf.use_short_preamble) |
3380 | priv->staging_rxon.flags |= | 3558 | ctx->staging.flags |= |
3381 | RXON_FLG_SHORT_PREAMBLE_MSK; | 3559 | RXON_FLG_SHORT_PREAMBLE_MSK; |
3382 | else | 3560 | else |
3383 | priv->staging_rxon.flags &= | 3561 | ctx->staging.flags &= |
3384 | ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3562 | ~RXON_FLG_SHORT_PREAMBLE_MSK; |
3385 | 3563 | ||
3386 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 3564 | if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { |
3387 | if (vif->bss_conf.use_short_slot) | 3565 | if (vif->bss_conf.use_short_slot) |
3388 | priv->staging_rxon.flags |= | 3566 | ctx->staging.flags |= |
3389 | RXON_FLG_SHORT_SLOT_MSK; | 3567 | RXON_FLG_SHORT_SLOT_MSK; |
3390 | else | 3568 | else |
3391 | priv->staging_rxon.flags &= | 3569 | ctx->staging.flags &= |
3392 | ~RXON_FLG_SHORT_SLOT_MSK; | 3570 | ~RXON_FLG_SHORT_SLOT_MSK; |
3393 | } | 3571 | } |
3572 | /* need to send beacon cmd before committing assoc RXON! */ | ||
3573 | iwl_send_beacon_cmd(priv); | ||
3394 | /* restore RXON assoc */ | 3574 | /* restore RXON assoc */ |
3395 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 3575 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; |
3396 | iwlcore_commit_rxon(priv); | 3576 | iwlcore_commit_rxon(priv, ctx); |
3397 | } | 3577 | } |
3398 | iwl_send_beacon_cmd(priv); | 3578 | iwl_send_beacon_cmd(priv); |
3399 | 3579 | ||
@@ -3410,9 +3590,11 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, | |||
3410 | { | 3590 | { |
3411 | 3591 | ||
3412 | struct iwl_priv *priv = hw->priv; | 3592 | struct iwl_priv *priv = hw->priv; |
3593 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
3594 | |||
3413 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 3595 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
3414 | 3596 | ||
3415 | iwl_update_tkip_key(priv, keyconf, sta, | 3597 | iwl_update_tkip_key(priv, vif_priv->ctx, keyconf, sta, |
3416 | iv32, phase1key); | 3598 | iv32, phase1key); |
3417 | 3599 | ||
3418 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 3600 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
@@ -3424,6 +3606,8 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3424 | struct ieee80211_key_conf *key) | 3606 | struct ieee80211_key_conf *key) |
3425 | { | 3607 | { |
3426 | struct iwl_priv *priv = hw->priv; | 3608 | struct iwl_priv *priv = hw->priv; |
3609 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
3610 | struct iwl_rxon_context *ctx = vif_priv->ctx; | ||
3427 | int ret; | 3611 | int ret; |
3428 | u8 sta_id; | 3612 | u8 sta_id; |
3429 | bool is_default_wep_key = false; | 3613 | bool is_default_wep_key = false; |
@@ -3435,7 +3619,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3435 | return -EOPNOTSUPP; | 3619 | return -EOPNOTSUPP; |
3436 | } | 3620 | } |
3437 | 3621 | ||
3438 | sta_id = iwl_sta_id_or_broadcast(priv, sta); | 3622 | sta_id = iwl_sta_id_or_broadcast(priv, vif_priv->ctx, sta); |
3439 | if (sta_id == IWL_INVALID_STATION) | 3623 | if (sta_id == IWL_INVALID_STATION) |
3440 | return -EINVAL; | 3624 | return -EINVAL; |
3441 | 3625 | ||
@@ -3452,7 +3636,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3452 | key->cipher == WLAN_CIPHER_SUITE_WEP104) && | 3636 | key->cipher == WLAN_CIPHER_SUITE_WEP104) && |
3453 | !sta) { | 3637 | !sta) { |
3454 | if (cmd == SET_KEY) | 3638 | if (cmd == SET_KEY) |
3455 | is_default_wep_key = !priv->key_mapping_key; | 3639 | is_default_wep_key = !ctx->key_mapping_keys; |
3456 | else | 3640 | else |
3457 | is_default_wep_key = | 3641 | is_default_wep_key = |
3458 | (key->hw_key_idx == HW_KEY_DEFAULT); | 3642 | (key->hw_key_idx == HW_KEY_DEFAULT); |
@@ -3461,17 +3645,18 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3461 | switch (cmd) { | 3645 | switch (cmd) { |
3462 | case SET_KEY: | 3646 | case SET_KEY: |
3463 | if (is_default_wep_key) | 3647 | if (is_default_wep_key) |
3464 | ret = iwl_set_default_wep_key(priv, key); | 3648 | ret = iwl_set_default_wep_key(priv, vif_priv->ctx, key); |
3465 | else | 3649 | else |
3466 | ret = iwl_set_dynamic_key(priv, key, sta_id); | 3650 | ret = iwl_set_dynamic_key(priv, vif_priv->ctx, |
3651 | key, sta_id); | ||
3467 | 3652 | ||
3468 | IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n"); | 3653 | IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n"); |
3469 | break; | 3654 | break; |
3470 | case DISABLE_KEY: | 3655 | case DISABLE_KEY: |
3471 | if (is_default_wep_key) | 3656 | if (is_default_wep_key) |
3472 | ret = iwl_remove_default_wep_key(priv, key); | 3657 | ret = iwl_remove_default_wep_key(priv, ctx, key); |
3473 | else | 3658 | else |
3474 | ret = iwl_remove_dynamic_key(priv, key, sta_id); | 3659 | ret = iwl_remove_dynamic_key(priv, ctx, key, sta_id); |
3475 | 3660 | ||
3476 | IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n"); | 3661 | IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n"); |
3477 | break; | 3662 | break; |
@@ -3540,8 +3725,8 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
3540 | 3725 | ||
3541 | sta_priv->lq_sta.lq.general_params.flags &= | 3726 | sta_priv->lq_sta.lq.general_params.flags &= |
3542 | ~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; | 3727 | ~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; |
3543 | iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq, | 3728 | iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif), |
3544 | CMD_ASYNC, false); | 3729 | &sta_priv->lq_sta.lq, CMD_ASYNC, false); |
3545 | } | 3730 | } |
3546 | break; | 3731 | break; |
3547 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 3732 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
@@ -3556,8 +3741,8 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
3556 | 3741 | ||
3557 | sta_priv->lq_sta.lq.general_params.flags |= | 3742 | sta_priv->lq_sta.lq.general_params.flags |= |
3558 | LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; | 3743 | LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; |
3559 | iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq, | 3744 | iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif), |
3560 | CMD_ASYNC, false); | 3745 | &sta_priv->lq_sta.lq, CMD_ASYNC, false); |
3561 | } | 3746 | } |
3562 | ret = 0; | 3747 | ret = 0; |
3563 | break; | 3748 | break; |
@@ -3603,6 +3788,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | |||
3603 | { | 3788 | { |
3604 | struct iwl_priv *priv = hw->priv; | 3789 | struct iwl_priv *priv = hw->priv; |
3605 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | 3790 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; |
3791 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
3606 | bool is_ap = vif->type == NL80211_IFTYPE_STATION; | 3792 | bool is_ap = vif->type == NL80211_IFTYPE_STATION; |
3607 | int ret; | 3793 | int ret; |
3608 | u8 sta_id; | 3794 | u8 sta_id; |
@@ -3618,8 +3804,8 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | |||
3618 | if (vif->type == NL80211_IFTYPE_AP) | 3804 | if (vif->type == NL80211_IFTYPE_AP) |
3619 | sta_priv->client = true; | 3805 | sta_priv->client = true; |
3620 | 3806 | ||
3621 | ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap, | 3807 | ret = iwl_add_station_common(priv, vif_priv->ctx, sta->addr, |
3622 | &sta_id); | 3808 | is_ap, sta, &sta_id); |
3623 | if (ret) { | 3809 | if (ret) { |
3624 | IWL_ERR(priv, "Unable to add station %pM (%d)\n", | 3810 | IWL_ERR(priv, "Unable to add station %pM (%d)\n", |
3625 | sta->addr, ret); | 3811 | sta->addr, ret); |
@@ -3647,6 +3833,15 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, | |||
3647 | struct ieee80211_conf *conf = &hw->conf; | 3833 | struct ieee80211_conf *conf = &hw->conf; |
3648 | struct ieee80211_channel *channel = ch_switch->channel; | 3834 | struct ieee80211_channel *channel = ch_switch->channel; |
3649 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | 3835 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
3836 | /* | ||
3837 | * MULTI-FIXME | ||
3838 | * When we add support for multiple interfaces, we need to | ||
3839 | * revisit this. The channel switch command in the device | ||
3840 | * only affects the BSS context, but what does that really | ||
3841 | * mean? And what if we get a CSA on the second interface? | ||
3842 | * This needs a lot of work. | ||
3843 | */ | ||
3844 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
3650 | u16 ch; | 3845 | u16 ch; |
3651 | unsigned long flags = 0; | 3846 | unsigned long flags = 0; |
3652 | 3847 | ||
@@ -3659,7 +3854,7 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, | |||
3659 | test_bit(STATUS_SCANNING, &priv->status)) | 3854 | test_bit(STATUS_SCANNING, &priv->status)) |
3660 | goto out_exit; | 3855 | goto out_exit; |
3661 | 3856 | ||
3662 | if (!iwl_is_associated(priv)) | 3857 | if (!iwl_is_associated_ctx(ctx)) |
3663 | goto out_exit; | 3858 | goto out_exit; |
3664 | 3859 | ||
3665 | /* channel switch in progress */ | 3860 | /* channel switch in progress */ |
@@ -3670,7 +3865,7 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, | |||
3670 | if (priv->cfg->ops->lib->set_channel_switch) { | 3865 | if (priv->cfg->ops->lib->set_channel_switch) { |
3671 | 3866 | ||
3672 | ch = channel->hw_value; | 3867 | ch = channel->hw_value; |
3673 | if (le16_to_cpu(priv->active_rxon.channel) != ch) { | 3868 | if (le16_to_cpu(ctx->active.channel) != ch) { |
3674 | ch_info = iwl_get_channel_info(priv, | 3869 | ch_info = iwl_get_channel_info(priv, |
3675 | channel->band, | 3870 | channel->band, |
3676 | ch); | 3871 | ch); |
@@ -3683,31 +3878,31 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, | |||
3683 | priv->current_ht_config.smps = conf->smps_mode; | 3878 | priv->current_ht_config.smps = conf->smps_mode; |
3684 | 3879 | ||
3685 | /* Configure HT40 channels */ | 3880 | /* Configure HT40 channels */ |
3686 | ht_conf->is_ht = conf_is_ht(conf); | 3881 | ctx->ht.enabled = conf_is_ht(conf); |
3687 | if (ht_conf->is_ht) { | 3882 | if (ctx->ht.enabled) { |
3688 | if (conf_is_ht40_minus(conf)) { | 3883 | if (conf_is_ht40_minus(conf)) { |
3689 | ht_conf->extension_chan_offset = | 3884 | ctx->ht.extension_chan_offset = |
3690 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; | 3885 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; |
3691 | ht_conf->is_40mhz = true; | 3886 | ctx->ht.is_40mhz = true; |
3692 | } else if (conf_is_ht40_plus(conf)) { | 3887 | } else if (conf_is_ht40_plus(conf)) { |
3693 | ht_conf->extension_chan_offset = | 3888 | ctx->ht.extension_chan_offset = |
3694 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | 3889 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; |
3695 | ht_conf->is_40mhz = true; | 3890 | ctx->ht.is_40mhz = true; |
3696 | } else { | 3891 | } else { |
3697 | ht_conf->extension_chan_offset = | 3892 | ctx->ht.extension_chan_offset = |
3698 | IEEE80211_HT_PARAM_CHA_SEC_NONE; | 3893 | IEEE80211_HT_PARAM_CHA_SEC_NONE; |
3699 | ht_conf->is_40mhz = false; | 3894 | ctx->ht.is_40mhz = false; |
3700 | } | 3895 | } |
3701 | } else | 3896 | } else |
3702 | ht_conf->is_40mhz = false; | 3897 | ctx->ht.is_40mhz = false; |
3703 | 3898 | ||
3704 | if (le16_to_cpu(priv->staging_rxon.channel) != ch) | 3899 | if ((le16_to_cpu(ctx->staging.channel) != ch)) |
3705 | priv->staging_rxon.flags = 0; | 3900 | ctx->staging.flags = 0; |
3706 | 3901 | ||
3707 | iwl_set_rxon_channel(priv, channel); | 3902 | iwl_set_rxon_channel(priv, channel, ctx); |
3708 | iwl_set_rxon_ht(priv, ht_conf); | 3903 | iwl_set_rxon_ht(priv, ht_conf); |
3709 | iwl_set_flags_for_band(priv, channel->band, | 3904 | iwl_set_flags_for_band(priv, ctx, channel->band, |
3710 | priv->vif); | 3905 | ctx->vif); |
3711 | spin_unlock_irqrestore(&priv->lock, flags); | 3906 | spin_unlock_irqrestore(&priv->lock, flags); |
3712 | 3907 | ||
3713 | iwl_set_rate(priv); | 3908 | iwl_set_rate(priv); |
@@ -3724,7 +3919,7 @@ out: | |||
3724 | mutex_unlock(&priv->mutex); | 3919 | mutex_unlock(&priv->mutex); |
3725 | out_exit: | 3920 | out_exit: |
3726 | if (!priv->switch_rxon.switch_in_progress) | 3921 | if (!priv->switch_rxon.switch_in_progress) |
3727 | ieee80211_chswitch_done(priv->vif, false); | 3922 | ieee80211_chswitch_done(ctx->vif, false); |
3728 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 3923 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
3729 | } | 3924 | } |
3730 | 3925 | ||
@@ -3735,6 +3930,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, | |||
3735 | { | 3930 | { |
3736 | struct iwl_priv *priv = hw->priv; | 3931 | struct iwl_priv *priv = hw->priv; |
3737 | __le32 filter_or = 0, filter_nand = 0; | 3932 | __le32 filter_or = 0, filter_nand = 0; |
3933 | struct iwl_rxon_context *ctx; | ||
3738 | 3934 | ||
3739 | #define CHK(test, flag) do { \ | 3935 | #define CHK(test, flag) do { \ |
3740 | if (*total_flags & (test)) \ | 3936 | if (*total_flags & (test)) \ |
@@ -3754,10 +3950,11 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, | |||
3754 | 3950 | ||
3755 | mutex_lock(&priv->mutex); | 3951 | mutex_lock(&priv->mutex); |
3756 | 3952 | ||
3757 | priv->staging_rxon.filter_flags &= ~filter_nand; | 3953 | for_each_context(priv, ctx) { |
3758 | priv->staging_rxon.filter_flags |= filter_or; | 3954 | ctx->staging.filter_flags &= ~filter_nand; |
3759 | 3955 | ctx->staging.filter_flags |= filter_or; | |
3760 | iwlcore_commit_rxon(priv); | 3956 | iwlcore_commit_rxon(priv, ctx); |
3957 | } | ||
3761 | 3958 | ||
3762 | mutex_unlock(&priv->mutex); | 3959 | mutex_unlock(&priv->mutex); |
3763 | 3960 | ||
@@ -3826,6 +4023,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
3826 | INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); | 4023 | INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); |
3827 | INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); | 4024 | INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); |
3828 | INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush); | 4025 | INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush); |
4026 | INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency); | ||
4027 | INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config); | ||
3829 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); | 4028 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); |
3830 | INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); | 4029 | INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); |
3831 | 4030 | ||
@@ -3868,10 +4067,10 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) | |||
3868 | cancel_delayed_work(&priv->alive_start); | 4067 | cancel_delayed_work(&priv->alive_start); |
3869 | cancel_work_sync(&priv->run_time_calib_work); | 4068 | cancel_work_sync(&priv->run_time_calib_work); |
3870 | cancel_work_sync(&priv->beacon_update); | 4069 | cancel_work_sync(&priv->beacon_update); |
4070 | cancel_work_sync(&priv->bt_full_concurrency); | ||
4071 | cancel_work_sync(&priv->bt_runtime_config); | ||
3871 | del_timer_sync(&priv->statistics_periodic); | 4072 | del_timer_sync(&priv->statistics_periodic); |
3872 | del_timer_sync(&priv->ucode_trace); | 4073 | del_timer_sync(&priv->ucode_trace); |
3873 | if (priv->cfg->ops->lib->recover_from_tx_stall) | ||
3874 | del_timer_sync(&priv->monitor_recover); | ||
3875 | } | 4074 | } |
3876 | 4075 | ||
3877 | static void iwl_init_hw_rates(struct iwl_priv *priv, | 4076 | static void iwl_init_hw_rates(struct iwl_priv *priv, |
@@ -3926,10 +4125,22 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3926 | 4125 | ||
3927 | /* Choose which receivers/antennas to use */ | 4126 | /* Choose which receivers/antennas to use */ |
3928 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 4127 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
3929 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 4128 | priv->cfg->ops->hcmd->set_rxon_chain(priv, |
4129 | &priv->contexts[IWL_RXON_CTX_BSS]); | ||
3930 | 4130 | ||
3931 | iwl_init_scan_params(priv); | 4131 | iwl_init_scan_params(priv); |
3932 | 4132 | ||
4133 | /* init bt coex */ | ||
4134 | if (priv->cfg->advanced_bt_coexist) { | ||
4135 | priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT; | ||
4136 | priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT; | ||
4137 | priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK; | ||
4138 | priv->bt_on_thresh = BT_ON_THRESHOLD_DEF; | ||
4139 | priv->bt_duration = BT_DURATION_LIMIT_DEF; | ||
4140 | priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF; | ||
4141 | priv->dynamic_agg_thresh = BT_AGG_THRESHOLD_DEF; | ||
4142 | } | ||
4143 | |||
3933 | /* Set the tx_power_user_lmt to the lowest power level | 4144 | /* Set the tx_power_user_lmt to the lowest power level |
3934 | * this value will get overwritten by channel max power avg | 4145 | * this value will get overwritten by channel max power avg |
3935 | * from eeprom */ | 4146 | * from eeprom */ |
@@ -4013,9 +4224,31 @@ static int iwl_set_hw_params(struct iwl_priv *priv) | |||
4013 | return priv->cfg->ops->lib->set_hw_params(priv); | 4224 | return priv->cfg->ops->lib->set_hw_params(priv); |
4014 | } | 4225 | } |
4015 | 4226 | ||
4227 | static const u8 iwlagn_bss_ac_to_fifo[] = { | ||
4228 | IWL_TX_FIFO_VO, | ||
4229 | IWL_TX_FIFO_VI, | ||
4230 | IWL_TX_FIFO_BE, | ||
4231 | IWL_TX_FIFO_BK, | ||
4232 | }; | ||
4233 | |||
4234 | static const u8 iwlagn_bss_ac_to_queue[] = { | ||
4235 | 0, 1, 2, 3, | ||
4236 | }; | ||
4237 | |||
4238 | static const u8 iwlagn_pan_ac_to_fifo[] = { | ||
4239 | IWL_TX_FIFO_VO_IPAN, | ||
4240 | IWL_TX_FIFO_VI_IPAN, | ||
4241 | IWL_TX_FIFO_BE_IPAN, | ||
4242 | IWL_TX_FIFO_BK_IPAN, | ||
4243 | }; | ||
4244 | |||
4245 | static const u8 iwlagn_pan_ac_to_queue[] = { | ||
4246 | 7, 6, 5, 4, | ||
4247 | }; | ||
4248 | |||
4016 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 4249 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
4017 | { | 4250 | { |
4018 | int err = 0; | 4251 | int err = 0, i; |
4019 | struct iwl_priv *priv; | 4252 | struct iwl_priv *priv; |
4020 | struct ieee80211_hw *hw; | 4253 | struct ieee80211_hw *hw; |
4021 | struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); | 4254 | struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); |
@@ -4043,6 +4276,51 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
4043 | priv = hw->priv; | 4276 | priv = hw->priv; |
4044 | /* At this point both hw and priv are allocated. */ | 4277 | /* At this point both hw and priv are allocated. */ |
4045 | 4278 | ||
4279 | /* | ||
4280 | * The default context is always valid, | ||
4281 | * more may be discovered when firmware | ||
4282 | * is loaded. | ||
4283 | */ | ||
4284 | priv->valid_contexts = BIT(IWL_RXON_CTX_BSS); | ||
4285 | |||
4286 | for (i = 0; i < NUM_IWL_RXON_CTX; i++) | ||
4287 | priv->contexts[i].ctxid = i; | ||
4288 | |||
4289 | priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON; | ||
4290 | priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING; | ||
4291 | priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC; | ||
4292 | priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; | ||
4293 | priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; | ||
4294 | priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; | ||
4295 | priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo = iwlagn_bss_ac_to_fifo; | ||
4296 | priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwlagn_bss_ac_to_queue; | ||
4297 | priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes = | ||
4298 | BIT(NL80211_IFTYPE_ADHOC); | ||
4299 | priv->contexts[IWL_RXON_CTX_BSS].interface_modes = | ||
4300 | BIT(NL80211_IFTYPE_STATION); | ||
4301 | priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS; | ||
4302 | priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS; | ||
4303 | priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS; | ||
4304 | |||
4305 | priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON; | ||
4306 | priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = REPLY_WIPAN_RXON_TIMING; | ||
4307 | priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd = REPLY_WIPAN_RXON_ASSOC; | ||
4308 | priv->contexts[IWL_RXON_CTX_PAN].qos_cmd = REPLY_WIPAN_QOS_PARAM; | ||
4309 | priv->contexts[IWL_RXON_CTX_PAN].ap_sta_id = IWL_AP_ID_PAN; | ||
4310 | priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY; | ||
4311 | priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID; | ||
4312 | priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION; | ||
4313 | priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo = iwlagn_pan_ac_to_fifo; | ||
4314 | priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue = iwlagn_pan_ac_to_queue; | ||
4315 | priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE; | ||
4316 | priv->contexts[IWL_RXON_CTX_PAN].interface_modes = | ||
4317 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); | ||
4318 | priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP; | ||
4319 | priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA; | ||
4320 | priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P; | ||
4321 | |||
4322 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | ||
4323 | |||
4046 | SET_IEEE80211_DEV(hw, &pdev->dev); | 4324 | SET_IEEE80211_DEV(hw, &pdev->dev); |
4047 | 4325 | ||
4048 | IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); | 4326 | IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); |
@@ -4050,6 +4328,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
4050 | priv->pci_dev = pdev; | 4328 | priv->pci_dev = pdev; |
4051 | priv->inta_mask = CSR_INI_SET_MASK; | 4329 | priv->inta_mask = CSR_INI_SET_MASK; |
4052 | 4330 | ||
4331 | /* is antenna coupling more than 35dB ? */ | ||
4332 | priv->bt_ant_couple_ok = | ||
4333 | (iwlagn_ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD) ? | ||
4334 | true : false; | ||
4335 | |||
4336 | /* enable/disable bt channel announcement */ | ||
4337 | priv->bt_ch_announce = iwlagn_bt_ch_announce; | ||
4338 | |||
4053 | if (iwl_alloc_traffic_mem(priv)) | 4339 | if (iwl_alloc_traffic_mem(priv)) |
4054 | IWL_ERR(priv, "Not enough memory to generate traffic log\n"); | 4340 | IWL_ERR(priv, "Not enough memory to generate traffic log\n"); |
4055 | 4341 | ||
@@ -4583,3 +4869,11 @@ module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int, | |||
4583 | S_IRUGO); | 4869 | S_IRUGO); |
4584 | MODULE_PARM_DESC(ucode_alternative, | 4870 | MODULE_PARM_DESC(ucode_alternative, |
4585 | "specify ucode alternative to use from ucode file"); | 4871 | "specify ucode alternative to use from ucode file"); |
4872 | |||
4873 | module_param_named(antenna_coupling, iwlagn_ant_coupling, int, S_IRUGO); | ||
4874 | MODULE_PARM_DESC(antenna_coupling, | ||
4875 | "specify antenna coupling in dB (defualt: 0 dB)"); | ||
4876 | |||
4877 | module_param_named(bt_ch_announce, iwlagn_bt_ch_announce, bool, S_IRUGO); | ||
4878 | MODULE_PARM_DESC(bt_ch_announce, | ||
4879 | "Enable BT channel announcement mode (default: enable)"); | ||