diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-sta.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-sta.c | 183 |
1 files changed, 112 insertions, 71 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index d5e8db37b86e..ccd09027c7cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -172,12 +172,14 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
172 | EXPORT_SYMBOL(iwl_send_add_sta); | 172 | EXPORT_SYMBOL(iwl_send_add_sta); |
173 | 173 | ||
174 | static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, | 174 | static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, |
175 | struct ieee80211_sta_ht_cap *sta_ht_inf) | 175 | struct ieee80211_sta *sta, |
176 | struct iwl_rxon_context *ctx) | ||
176 | { | 177 | { |
178 | struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap; | ||
177 | __le32 sta_flags; | 179 | __le32 sta_flags; |
178 | u8 mimo_ps_mode; | 180 | u8 mimo_ps_mode; |
179 | 181 | ||
180 | if (!sta_ht_inf || !sta_ht_inf->ht_supported) | 182 | if (!sta || !sta_ht_inf->ht_supported) |
181 | goto done; | 183 | goto done; |
182 | 184 | ||
183 | mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; | 185 | mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; |
@@ -211,7 +213,7 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, | |||
211 | sta_flags |= cpu_to_le32( | 213 | sta_flags |= cpu_to_le32( |
212 | (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS); | 214 | (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS); |
213 | 215 | ||
214 | if (iwl_is_ht40_tx_allowed(priv, sta_ht_inf)) | 216 | if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap)) |
215 | sta_flags |= STA_FLG_HT40_EN_MSK; | 217 | sta_flags |= STA_FLG_HT40_EN_MSK; |
216 | else | 218 | else |
217 | sta_flags &= ~STA_FLG_HT40_EN_MSK; | 219 | sta_flags &= ~STA_FLG_HT40_EN_MSK; |
@@ -226,9 +228,9 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, | |||
226 | * | 228 | * |
227 | * should be called with sta_lock held | 229 | * should be called with sta_lock held |
228 | */ | 230 | */ |
229 | static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr, | 231 | static u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, |
230 | bool is_ap, | 232 | const u8 *addr, bool is_ap, |
231 | struct ieee80211_sta_ht_cap *ht_info) | 233 | struct ieee80211_sta *sta) |
232 | { | 234 | { |
233 | struct iwl_station_entry *station; | 235 | struct iwl_station_entry *station; |
234 | int i; | 236 | int i; |
@@ -236,9 +238,9 @@ static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr, | |||
236 | u16 rate; | 238 | u16 rate; |
237 | 239 | ||
238 | if (is_ap) | 240 | if (is_ap) |
239 | sta_id = IWL_AP_ID; | 241 | sta_id = ctx->ap_sta_id; |
240 | else if (is_broadcast_ether_addr(addr)) | 242 | else if (is_broadcast_ether_addr(addr)) |
241 | sta_id = priv->hw_params.bcast_sta_id; | 243 | sta_id = ctx->bcast_sta_id; |
242 | else | 244 | else |
243 | for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) { | 245 | for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) { |
244 | if (!compare_ether_addr(priv->stations[i].sta.sta.addr, | 246 | if (!compare_ether_addr(priv->stations[i].sta.sta.addr, |
@@ -289,14 +291,22 @@ static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr, | |||
289 | memcpy(station->sta.sta.addr, addr, ETH_ALEN); | 291 | memcpy(station->sta.sta.addr, addr, ETH_ALEN); |
290 | station->sta.mode = 0; | 292 | station->sta.mode = 0; |
291 | station->sta.sta.sta_id = sta_id; | 293 | station->sta.sta.sta_id = sta_id; |
292 | station->sta.station_flags = 0; | 294 | station->sta.station_flags = ctx->station_flags; |
295 | station->ctxid = ctx->ctxid; | ||
296 | |||
297 | if (sta) { | ||
298 | struct iwl_station_priv_common *sta_priv; | ||
299 | |||
300 | sta_priv = (void *)sta->drv_priv; | ||
301 | sta_priv->ctx = ctx; | ||
302 | } | ||
293 | 303 | ||
294 | /* | 304 | /* |
295 | * OK to call unconditionally, since local stations (IBSS BSSID | 305 | * OK to call unconditionally, since local stations (IBSS BSSID |
296 | * STA and broadcast STA) pass in a NULL ht_info, and mac80211 | 306 | * STA and broadcast STA) pass in a NULL sta, and mac80211 |
297 | * doesn't allow HT IBSS. | 307 | * doesn't allow HT IBSS. |
298 | */ | 308 | */ |
299 | iwl_set_ht_add_station(priv, sta_id, ht_info); | 309 | iwl_set_ht_add_station(priv, sta_id, sta, ctx); |
300 | 310 | ||
301 | /* 3945 only */ | 311 | /* 3945 only */ |
302 | rate = (priv->band == IEEE80211_BAND_5GHZ) ? | 312 | rate = (priv->band == IEEE80211_BAND_5GHZ) ? |
@@ -313,10 +323,9 @@ static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr, | |||
313 | /** | 323 | /** |
314 | * iwl_add_station_common - | 324 | * iwl_add_station_common - |
315 | */ | 325 | */ |
316 | int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, | 326 | int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, |
317 | bool is_ap, | 327 | const u8 *addr, bool is_ap, |
318 | struct ieee80211_sta_ht_cap *ht_info, | 328 | struct ieee80211_sta *sta, u8 *sta_id_r) |
319 | u8 *sta_id_r) | ||
320 | { | 329 | { |
321 | unsigned long flags_spin; | 330 | unsigned long flags_spin; |
322 | int ret = 0; | 331 | int ret = 0; |
@@ -325,7 +334,7 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, | |||
325 | 334 | ||
326 | *sta_id_r = 0; | 335 | *sta_id_r = 0; |
327 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 336 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
328 | sta_id = iwl_prep_station(priv, addr, is_ap, ht_info); | 337 | sta_id = iwl_prep_station(priv, ctx, addr, is_ap, sta); |
329 | if (sta_id == IWL_INVALID_STATION) { | 338 | if (sta_id == IWL_INVALID_STATION) { |
330 | IWL_ERR(priv, "Unable to prepare station %pM for addition\n", | 339 | IWL_ERR(priv, "Unable to prepare station %pM for addition\n", |
331 | addr); | 340 | addr); |
@@ -431,8 +440,8 @@ static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv, | |||
431 | * | 440 | * |
432 | * Function sleeps. | 441 | * Function sleeps. |
433 | */ | 442 | */ |
434 | int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, | 443 | int iwl_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, |
435 | u8 *sta_id_r) | 444 | const u8 *addr, bool init_rs, u8 *sta_id_r) |
436 | { | 445 | { |
437 | int ret; | 446 | int ret; |
438 | u8 sta_id; | 447 | u8 sta_id; |
@@ -442,7 +451,7 @@ int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, | |||
442 | if (sta_id_r) | 451 | if (sta_id_r) |
443 | *sta_id_r = IWL_INVALID_STATION; | 452 | *sta_id_r = IWL_INVALID_STATION; |
444 | 453 | ||
445 | ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id); | 454 | ret = iwl_add_station_common(priv, ctx, addr, 0, NULL, &sta_id); |
446 | if (ret) { | 455 | if (ret) { |
447 | IWL_ERR(priv, "Unable to add station %pM\n", addr); | 456 | IWL_ERR(priv, "Unable to add station %pM\n", addr); |
448 | return ret; | 457 | return ret; |
@@ -464,7 +473,7 @@ int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, | |||
464 | return -ENOMEM; | 473 | return -ENOMEM; |
465 | } | 474 | } |
466 | 475 | ||
467 | ret = iwl_send_lq_cmd(priv, link_cmd, CMD_SYNC, true); | 476 | ret = iwl_send_lq_cmd(priv, ctx, link_cmd, CMD_SYNC, true); |
468 | if (ret) | 477 | if (ret) |
469 | IWL_ERR(priv, "Link quality command failed (%d)\n", ret); | 478 | IWL_ERR(priv, "Link quality command failed (%d)\n", ret); |
470 | 479 | ||
@@ -616,7 +625,8 @@ EXPORT_SYMBOL_GPL(iwl_remove_station); | |||
616 | * other than explicit station management would cause this in | 625 | * other than explicit station management would cause this in |
617 | * the ucode, e.g. unassociated RXON. | 626 | * the ucode, e.g. unassociated RXON. |
618 | */ | 627 | */ |
619 | void iwl_clear_ucode_stations(struct iwl_priv *priv) | 628 | void iwl_clear_ucode_stations(struct iwl_priv *priv, |
629 | struct iwl_rxon_context *ctx) | ||
620 | { | 630 | { |
621 | int i; | 631 | int i; |
622 | unsigned long flags_spin; | 632 | unsigned long flags_spin; |
@@ -626,6 +636,9 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv) | |||
626 | 636 | ||
627 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 637 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
628 | for (i = 0; i < priv->hw_params.max_stations; i++) { | 638 | for (i = 0; i < priv->hw_params.max_stations; i++) { |
639 | if (ctx && ctx->ctxid != priv->stations[i].ctxid) | ||
640 | continue; | ||
641 | |||
629 | if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) { | 642 | if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) { |
630 | IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i); | 643 | IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i); |
631 | priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; | 644 | priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; |
@@ -647,7 +660,7 @@ EXPORT_SYMBOL(iwl_clear_ucode_stations); | |||
647 | * | 660 | * |
648 | * Function sleeps. | 661 | * Function sleeps. |
649 | */ | 662 | */ |
650 | void iwl_restore_stations(struct iwl_priv *priv) | 663 | void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) |
651 | { | 664 | { |
652 | struct iwl_addsta_cmd sta_cmd; | 665 | struct iwl_addsta_cmd sta_cmd; |
653 | struct iwl_link_quality_cmd lq; | 666 | struct iwl_link_quality_cmd lq; |
@@ -665,6 +678,8 @@ void iwl_restore_stations(struct iwl_priv *priv) | |||
665 | IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n"); | 678 | IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n"); |
666 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 679 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
667 | for (i = 0; i < priv->hw_params.max_stations; i++) { | 680 | for (i = 0; i < priv->hw_params.max_stations; i++) { |
681 | if (ctx->ctxid != priv->stations[i].ctxid) | ||
682 | continue; | ||
668 | if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) && | 683 | if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) && |
669 | !(priv->stations[i].used & IWL_STA_UCODE_ACTIVE)) { | 684 | !(priv->stations[i].used & IWL_STA_UCODE_ACTIVE)) { |
670 | IWL_DEBUG_ASSOC(priv, "Restoring sta %pM\n", | 685 | IWL_DEBUG_ASSOC(priv, "Restoring sta %pM\n", |
@@ -700,7 +715,7 @@ void iwl_restore_stations(struct iwl_priv *priv) | |||
700 | * current LQ command | 715 | * current LQ command |
701 | */ | 716 | */ |
702 | if (send_lq) | 717 | if (send_lq) |
703 | iwl_send_lq_cmd(priv, &lq, CMD_SYNC, true); | 718 | iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true); |
704 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 719 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
705 | priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; | 720 | priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; |
706 | } | 721 | } |
@@ -718,7 +733,7 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv) | |||
718 | { | 733 | { |
719 | int i; | 734 | int i; |
720 | 735 | ||
721 | for (i = 0; i < STA_KEY_MAX_NUM; i++) | 736 | for (i = 0; i < priv->sta_key_max_num; i++) |
722 | if (!test_and_set_bit(i, &priv->ucode_key_table)) | 737 | if (!test_and_set_bit(i, &priv->ucode_key_table)) |
723 | return i; | 738 | return i; |
724 | 739 | ||
@@ -726,7 +741,9 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv) | |||
726 | } | 741 | } |
727 | EXPORT_SYMBOL(iwl_get_free_ucode_key_index); | 742 | EXPORT_SYMBOL(iwl_get_free_ucode_key_index); |
728 | 743 | ||
729 | static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) | 744 | static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, |
745 | struct iwl_rxon_context *ctx, | ||
746 | bool send_if_empty) | ||
730 | { | 747 | { |
731 | int i, not_empty = 0; | 748 | int i, not_empty = 0; |
732 | u8 buff[sizeof(struct iwl_wep_cmd) + | 749 | u8 buff[sizeof(struct iwl_wep_cmd) + |
@@ -734,7 +751,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) | |||
734 | struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff; | 751 | struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff; |
735 | size_t cmd_size = sizeof(struct iwl_wep_cmd); | 752 | size_t cmd_size = sizeof(struct iwl_wep_cmd); |
736 | struct iwl_host_cmd cmd = { | 753 | struct iwl_host_cmd cmd = { |
737 | .id = REPLY_WEPKEY, | 754 | .id = ctx->wep_key_cmd, |
738 | .data = wep_cmd, | 755 | .data = wep_cmd, |
739 | .flags = CMD_SYNC, | 756 | .flags = CMD_SYNC, |
740 | }; | 757 | }; |
@@ -746,16 +763,16 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) | |||
746 | 763 | ||
747 | for (i = 0; i < WEP_KEYS_MAX ; i++) { | 764 | for (i = 0; i < WEP_KEYS_MAX ; i++) { |
748 | wep_cmd->key[i].key_index = i; | 765 | wep_cmd->key[i].key_index = i; |
749 | if (priv->wep_keys[i].key_size) { | 766 | if (ctx->wep_keys[i].key_size) { |
750 | wep_cmd->key[i].key_offset = i; | 767 | wep_cmd->key[i].key_offset = i; |
751 | not_empty = 1; | 768 | not_empty = 1; |
752 | } else { | 769 | } else { |
753 | wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET; | 770 | wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET; |
754 | } | 771 | } |
755 | 772 | ||
756 | wep_cmd->key[i].key_size = priv->wep_keys[i].key_size; | 773 | wep_cmd->key[i].key_size = ctx->wep_keys[i].key_size; |
757 | memcpy(&wep_cmd->key[i].key[3], priv->wep_keys[i].key, | 774 | memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key, |
758 | priv->wep_keys[i].key_size); | 775 | ctx->wep_keys[i].key_size); |
759 | } | 776 | } |
760 | 777 | ||
761 | wep_cmd->global_key_type = WEP_KEY_WEP_TYPE; | 778 | wep_cmd->global_key_type = WEP_KEY_WEP_TYPE; |
@@ -771,15 +788,17 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) | |||
771 | return 0; | 788 | return 0; |
772 | } | 789 | } |
773 | 790 | ||
774 | int iwl_restore_default_wep_keys(struct iwl_priv *priv) | 791 | int iwl_restore_default_wep_keys(struct iwl_priv *priv, |
792 | struct iwl_rxon_context *ctx) | ||
775 | { | 793 | { |
776 | lockdep_assert_held(&priv->mutex); | 794 | lockdep_assert_held(&priv->mutex); |
777 | 795 | ||
778 | return iwl_send_static_wepkey_cmd(priv, 0); | 796 | return iwl_send_static_wepkey_cmd(priv, ctx, false); |
779 | } | 797 | } |
780 | EXPORT_SYMBOL(iwl_restore_default_wep_keys); | 798 | EXPORT_SYMBOL(iwl_restore_default_wep_keys); |
781 | 799 | ||
782 | int iwl_remove_default_wep_key(struct iwl_priv *priv, | 800 | int iwl_remove_default_wep_key(struct iwl_priv *priv, |
801 | struct iwl_rxon_context *ctx, | ||
783 | struct ieee80211_key_conf *keyconf) | 802 | struct ieee80211_key_conf *keyconf) |
784 | { | 803 | { |
785 | int ret; | 804 | int ret; |
@@ -789,13 +808,13 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, | |||
789 | IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", | 808 | IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", |
790 | keyconf->keyidx); | 809 | keyconf->keyidx); |
791 | 810 | ||
792 | memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); | 811 | memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0])); |
793 | if (iwl_is_rfkill(priv)) { | 812 | if (iwl_is_rfkill(priv)) { |
794 | IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); | 813 | IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); |
795 | /* but keys in device are clear anyway so return success */ | 814 | /* but keys in device are clear anyway so return success */ |
796 | return 0; | 815 | return 0; |
797 | } | 816 | } |
798 | ret = iwl_send_static_wepkey_cmd(priv, 1); | 817 | ret = iwl_send_static_wepkey_cmd(priv, ctx, 1); |
799 | IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n", | 818 | IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n", |
800 | keyconf->keyidx, ret); | 819 | keyconf->keyidx, ret); |
801 | 820 | ||
@@ -804,6 +823,7 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, | |||
804 | EXPORT_SYMBOL(iwl_remove_default_wep_key); | 823 | EXPORT_SYMBOL(iwl_remove_default_wep_key); |
805 | 824 | ||
806 | int iwl_set_default_wep_key(struct iwl_priv *priv, | 825 | int iwl_set_default_wep_key(struct iwl_priv *priv, |
826 | struct iwl_rxon_context *ctx, | ||
807 | struct ieee80211_key_conf *keyconf) | 827 | struct ieee80211_key_conf *keyconf) |
808 | { | 828 | { |
809 | int ret; | 829 | int ret; |
@@ -818,13 +838,13 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, | |||
818 | 838 | ||
819 | keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; | 839 | keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; |
820 | keyconf->hw_key_idx = HW_KEY_DEFAULT; | 840 | keyconf->hw_key_idx = HW_KEY_DEFAULT; |
821 | priv->stations[IWL_AP_ID].keyinfo.cipher = keyconf->cipher; | 841 | priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher; |
822 | 842 | ||
823 | priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; | 843 | ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; |
824 | memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, | 844 | memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key, |
825 | keyconf->keylen); | 845 | keyconf->keylen); |
826 | 846 | ||
827 | ret = iwl_send_static_wepkey_cmd(priv, 0); | 847 | ret = iwl_send_static_wepkey_cmd(priv, ctx, false); |
828 | IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n", | 848 | IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n", |
829 | keyconf->keylen, keyconf->keyidx, ret); | 849 | keyconf->keylen, keyconf->keyidx, ret); |
830 | 850 | ||
@@ -833,8 +853,9 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, | |||
833 | EXPORT_SYMBOL(iwl_set_default_wep_key); | 853 | EXPORT_SYMBOL(iwl_set_default_wep_key); |
834 | 854 | ||
835 | static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, | 855 | static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, |
836 | struct ieee80211_key_conf *keyconf, | 856 | struct iwl_rxon_context *ctx, |
837 | u8 sta_id) | 857 | struct ieee80211_key_conf *keyconf, |
858 | u8 sta_id) | ||
838 | { | 859 | { |
839 | unsigned long flags; | 860 | unsigned long flags; |
840 | __le16 key_flags = 0; | 861 | __le16 key_flags = 0; |
@@ -851,7 +872,7 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, | |||
851 | if (keyconf->keylen == WEP_KEY_LEN_128) | 872 | if (keyconf->keylen == WEP_KEY_LEN_128) |
852 | key_flags |= STA_KEY_FLG_KEY_SIZE_MSK; | 873 | key_flags |= STA_KEY_FLG_KEY_SIZE_MSK; |
853 | 874 | ||
854 | if (sta_id == priv->hw_params.bcast_sta_id) | 875 | if (sta_id == ctx->bcast_sta_id) |
855 | key_flags |= STA_KEY_MULTICAST_MSK; | 876 | key_flags |= STA_KEY_MULTICAST_MSK; |
856 | 877 | ||
857 | spin_lock_irqsave(&priv->sta_lock, flags); | 878 | spin_lock_irqsave(&priv->sta_lock, flags); |
@@ -887,8 +908,9 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, | |||
887 | } | 908 | } |
888 | 909 | ||
889 | static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, | 910 | static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, |
890 | struct ieee80211_key_conf *keyconf, | 911 | struct iwl_rxon_context *ctx, |
891 | u8 sta_id) | 912 | struct ieee80211_key_conf *keyconf, |
913 | u8 sta_id) | ||
892 | { | 914 | { |
893 | unsigned long flags; | 915 | unsigned long flags; |
894 | __le16 key_flags = 0; | 916 | __le16 key_flags = 0; |
@@ -900,7 +922,7 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, | |||
900 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); | 922 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); |
901 | key_flags &= ~STA_KEY_FLG_INVALID; | 923 | key_flags &= ~STA_KEY_FLG_INVALID; |
902 | 924 | ||
903 | if (sta_id == priv->hw_params.bcast_sta_id) | 925 | if (sta_id == ctx->bcast_sta_id) |
904 | key_flags |= STA_KEY_MULTICAST_MSK; | 926 | key_flags |= STA_KEY_MULTICAST_MSK; |
905 | 927 | ||
906 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 928 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
@@ -936,8 +958,9 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, | |||
936 | } | 958 | } |
937 | 959 | ||
938 | static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, | 960 | static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, |
939 | struct ieee80211_key_conf *keyconf, | 961 | struct iwl_rxon_context *ctx, |
940 | u8 sta_id) | 962 | struct ieee80211_key_conf *keyconf, |
963 | u8 sta_id) | ||
941 | { | 964 | { |
942 | unsigned long flags; | 965 | unsigned long flags; |
943 | int ret = 0; | 966 | int ret = 0; |
@@ -947,7 +970,7 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, | |||
947 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); | 970 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); |
948 | key_flags &= ~STA_KEY_FLG_INVALID; | 971 | key_flags &= ~STA_KEY_FLG_INVALID; |
949 | 972 | ||
950 | if (sta_id == priv->hw_params.bcast_sta_id) | 973 | if (sta_id == ctx->bcast_sta_id) |
951 | key_flags |= STA_KEY_MULTICAST_MSK; | 974 | key_flags |= STA_KEY_MULTICAST_MSK; |
952 | 975 | ||
953 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 976 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
@@ -982,8 +1005,9 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, | |||
982 | } | 1005 | } |
983 | 1006 | ||
984 | void iwl_update_tkip_key(struct iwl_priv *priv, | 1007 | void iwl_update_tkip_key(struct iwl_priv *priv, |
985 | struct ieee80211_key_conf *keyconf, | 1008 | struct iwl_rxon_context *ctx, |
986 | struct ieee80211_sta *sta, u32 iv32, u16 *phase1key) | 1009 | struct ieee80211_key_conf *keyconf, |
1010 | struct ieee80211_sta *sta, u32 iv32, u16 *phase1key) | ||
987 | { | 1011 | { |
988 | u8 sta_id; | 1012 | u8 sta_id; |
989 | unsigned long flags; | 1013 | unsigned long flags; |
@@ -995,7 +1019,7 @@ void iwl_update_tkip_key(struct iwl_priv *priv, | |||
995 | return; | 1019 | return; |
996 | } | 1020 | } |
997 | 1021 | ||
998 | sta_id = iwl_sta_id_or_broadcast(priv, sta); | 1022 | sta_id = iwl_sta_id_or_broadcast(priv, ctx, sta); |
999 | if (sta_id == IWL_INVALID_STATION) | 1023 | if (sta_id == IWL_INVALID_STATION) |
1000 | return; | 1024 | return; |
1001 | 1025 | ||
@@ -1018,8 +1042,9 @@ void iwl_update_tkip_key(struct iwl_priv *priv, | |||
1018 | EXPORT_SYMBOL(iwl_update_tkip_key); | 1042 | EXPORT_SYMBOL(iwl_update_tkip_key); |
1019 | 1043 | ||
1020 | int iwl_remove_dynamic_key(struct iwl_priv *priv, | 1044 | int iwl_remove_dynamic_key(struct iwl_priv *priv, |
1021 | struct ieee80211_key_conf *keyconf, | 1045 | struct iwl_rxon_context *ctx, |
1022 | u8 sta_id) | 1046 | struct ieee80211_key_conf *keyconf, |
1047 | u8 sta_id) | ||
1023 | { | 1048 | { |
1024 | unsigned long flags; | 1049 | unsigned long flags; |
1025 | u16 key_flags; | 1050 | u16 key_flags; |
@@ -1028,7 +1053,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, | |||
1028 | 1053 | ||
1029 | lockdep_assert_held(&priv->mutex); | 1054 | lockdep_assert_held(&priv->mutex); |
1030 | 1055 | ||
1031 | priv->key_mapping_key--; | 1056 | ctx->key_mapping_keys--; |
1032 | 1057 | ||
1033 | spin_lock_irqsave(&priv->sta_lock, flags); | 1058 | spin_lock_irqsave(&priv->sta_lock, flags); |
1034 | key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags); | 1059 | key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags); |
@@ -1080,26 +1105,26 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, | |||
1080 | } | 1105 | } |
1081 | EXPORT_SYMBOL(iwl_remove_dynamic_key); | 1106 | EXPORT_SYMBOL(iwl_remove_dynamic_key); |
1082 | 1107 | ||
1083 | int iwl_set_dynamic_key(struct iwl_priv *priv, | 1108 | int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, |
1084 | struct ieee80211_key_conf *keyconf, u8 sta_id) | 1109 | struct ieee80211_key_conf *keyconf, u8 sta_id) |
1085 | { | 1110 | { |
1086 | int ret; | 1111 | int ret; |
1087 | 1112 | ||
1088 | lockdep_assert_held(&priv->mutex); | 1113 | lockdep_assert_held(&priv->mutex); |
1089 | 1114 | ||
1090 | priv->key_mapping_key++; | 1115 | ctx->key_mapping_keys++; |
1091 | keyconf->hw_key_idx = HW_KEY_DYNAMIC; | 1116 | keyconf->hw_key_idx = HW_KEY_DYNAMIC; |
1092 | 1117 | ||
1093 | switch (keyconf->cipher) { | 1118 | switch (keyconf->cipher) { |
1094 | case WLAN_CIPHER_SUITE_CCMP: | 1119 | case WLAN_CIPHER_SUITE_CCMP: |
1095 | ret = iwl_set_ccmp_dynamic_key_info(priv, keyconf, sta_id); | 1120 | ret = iwl_set_ccmp_dynamic_key_info(priv, ctx, keyconf, sta_id); |
1096 | break; | 1121 | break; |
1097 | case WLAN_CIPHER_SUITE_TKIP: | 1122 | case WLAN_CIPHER_SUITE_TKIP: |
1098 | ret = iwl_set_tkip_dynamic_key_info(priv, keyconf, sta_id); | 1123 | ret = iwl_set_tkip_dynamic_key_info(priv, ctx, keyconf, sta_id); |
1099 | break; | 1124 | break; |
1100 | case WLAN_CIPHER_SUITE_WEP40: | 1125 | case WLAN_CIPHER_SUITE_WEP40: |
1101 | case WLAN_CIPHER_SUITE_WEP104: | 1126 | case WLAN_CIPHER_SUITE_WEP104: |
1102 | ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id); | 1127 | ret = iwl_set_wep_dynamic_key_info(priv, ctx, keyconf, sta_id); |
1103 | break; | 1128 | break; |
1104 | default: | 1129 | default: |
1105 | IWL_ERR(priv, | 1130 | IWL_ERR(priv, |
@@ -1149,16 +1174,16 @@ static inline void iwl_dump_lq_cmd(struct iwl_priv *priv, | |||
1149 | * RXON flags are updated and when LQ command is updated. | 1174 | * RXON flags are updated and when LQ command is updated. |
1150 | */ | 1175 | */ |
1151 | static bool is_lq_table_valid(struct iwl_priv *priv, | 1176 | static bool is_lq_table_valid(struct iwl_priv *priv, |
1177 | struct iwl_rxon_context *ctx, | ||
1152 | struct iwl_link_quality_cmd *lq) | 1178 | struct iwl_link_quality_cmd *lq) |
1153 | { | 1179 | { |
1154 | int i; | 1180 | int i; |
1155 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | ||
1156 | 1181 | ||
1157 | if (ht_conf->is_ht) | 1182 | if (ctx->ht.enabled) |
1158 | return true; | 1183 | return true; |
1159 | 1184 | ||
1160 | IWL_DEBUG_INFO(priv, "Channel %u is not an HT channel\n", | 1185 | IWL_DEBUG_INFO(priv, "Channel %u is not an HT channel\n", |
1161 | priv->active_rxon.channel); | 1186 | ctx->active.channel); |
1162 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { | 1187 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { |
1163 | if (le32_to_cpu(lq->rs_table[i].rate_n_flags) & RATE_MCS_HT_MSK) { | 1188 | if (le32_to_cpu(lq->rs_table[i].rate_n_flags) & RATE_MCS_HT_MSK) { |
1164 | IWL_DEBUG_INFO(priv, | 1189 | IWL_DEBUG_INFO(priv, |
@@ -1180,7 +1205,7 @@ static bool is_lq_table_valid(struct iwl_priv *priv, | |||
1180 | * this case to clear the state indicating that station creation is in | 1205 | * this case to clear the state indicating that station creation is in |
1181 | * progress. | 1206 | * progress. |
1182 | */ | 1207 | */ |
1183 | int iwl_send_lq_cmd(struct iwl_priv *priv, | 1208 | int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, |
1184 | struct iwl_link_quality_cmd *lq, u8 flags, bool init) | 1209 | struct iwl_link_quality_cmd *lq, u8 flags, bool init) |
1185 | { | 1210 | { |
1186 | int ret = 0; | 1211 | int ret = 0; |
@@ -1199,7 +1224,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, | |||
1199 | iwl_dump_lq_cmd(priv, lq); | 1224 | iwl_dump_lq_cmd(priv, lq); |
1200 | BUG_ON(init && (cmd.flags & CMD_ASYNC)); | 1225 | BUG_ON(init && (cmd.flags & CMD_ASYNC)); |
1201 | 1226 | ||
1202 | if (is_lq_table_valid(priv, lq)) | 1227 | if (is_lq_table_valid(priv, ctx, lq)) |
1203 | ret = iwl_send_cmd(priv, &cmd); | 1228 | ret = iwl_send_cmd(priv, &cmd); |
1204 | else | 1229 | else |
1205 | ret = -EINVAL; | 1230 | ret = -EINVAL; |
@@ -1225,14 +1250,15 @@ EXPORT_SYMBOL(iwl_send_lq_cmd); | |||
1225 | * and marks it driver active, so that it will be restored to the | 1250 | * and marks it driver active, so that it will be restored to the |
1226 | * device at the next best time. | 1251 | * device at the next best time. |
1227 | */ | 1252 | */ |
1228 | int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq) | 1253 | int iwl_alloc_bcast_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, |
1254 | bool init_lq) | ||
1229 | { | 1255 | { |
1230 | struct iwl_link_quality_cmd *link_cmd; | 1256 | struct iwl_link_quality_cmd *link_cmd; |
1231 | unsigned long flags; | 1257 | unsigned long flags; |
1232 | u8 sta_id; | 1258 | u8 sta_id; |
1233 | 1259 | ||
1234 | spin_lock_irqsave(&priv->sta_lock, flags); | 1260 | spin_lock_irqsave(&priv->sta_lock, flags); |
1235 | sta_id = iwl_prep_station(priv, iwl_bcast_addr, false, NULL); | 1261 | sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL); |
1236 | if (sta_id == IWL_INVALID_STATION) { | 1262 | if (sta_id == IWL_INVALID_STATION) { |
1237 | IWL_ERR(priv, "Unable to prepare broadcast station\n"); | 1263 | IWL_ERR(priv, "Unable to prepare broadcast station\n"); |
1238 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1264 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
@@ -1267,11 +1293,12 @@ EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station); | |||
1267 | * Only used by iwlagn. Placed here to have all bcast station management | 1293 | * Only used by iwlagn. Placed here to have all bcast station management |
1268 | * code together. | 1294 | * code together. |
1269 | */ | 1295 | */ |
1270 | int iwl_update_bcast_station(struct iwl_priv *priv) | 1296 | static int iwl_update_bcast_station(struct iwl_priv *priv, |
1297 | struct iwl_rxon_context *ctx) | ||
1271 | { | 1298 | { |
1272 | unsigned long flags; | 1299 | unsigned long flags; |
1273 | struct iwl_link_quality_cmd *link_cmd; | 1300 | struct iwl_link_quality_cmd *link_cmd; |
1274 | u8 sta_id = priv->hw_params.bcast_sta_id; | 1301 | u8 sta_id = ctx->bcast_sta_id; |
1275 | 1302 | ||
1276 | link_cmd = iwl_sta_alloc_lq(priv, sta_id); | 1303 | link_cmd = iwl_sta_alloc_lq(priv, sta_id); |
1277 | if (!link_cmd) { | 1304 | if (!link_cmd) { |
@@ -1289,9 +1316,23 @@ int iwl_update_bcast_station(struct iwl_priv *priv) | |||
1289 | 1316 | ||
1290 | return 0; | 1317 | return 0; |
1291 | } | 1318 | } |
1292 | EXPORT_SYMBOL_GPL(iwl_update_bcast_station); | ||
1293 | 1319 | ||
1294 | void iwl_dealloc_bcast_station(struct iwl_priv *priv) | 1320 | int iwl_update_bcast_stations(struct iwl_priv *priv) |
1321 | { | ||
1322 | struct iwl_rxon_context *ctx; | ||
1323 | int ret = 0; | ||
1324 | |||
1325 | for_each_context(priv, ctx) { | ||
1326 | ret = iwl_update_bcast_station(priv, ctx); | ||
1327 | if (ret) | ||
1328 | break; | ||
1329 | } | ||
1330 | |||
1331 | return ret; | ||
1332 | } | ||
1333 | EXPORT_SYMBOL_GPL(iwl_update_bcast_stations); | ||
1334 | |||
1335 | void iwl_dealloc_bcast_stations(struct iwl_priv *priv) | ||
1295 | { | 1336 | { |
1296 | unsigned long flags; | 1337 | unsigned long flags; |
1297 | int i; | 1338 | int i; |
@@ -1309,7 +1350,7 @@ void iwl_dealloc_bcast_station(struct iwl_priv *priv) | |||
1309 | } | 1350 | } |
1310 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1351 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1311 | } | 1352 | } |
1312 | EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station); | 1353 | EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_stations); |
1313 | 1354 | ||
1314 | /** | 1355 | /** |
1315 | * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table | 1356 | * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table |