diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-core.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 747 |
1 files changed, 465 insertions, 282 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 3d9443b9bec1..87a2e40972ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -64,7 +64,8 @@ MODULE_LICENSE("GPL"); | |||
64 | * | 64 | * |
65 | * default: bt_coex_active = true (BT_COEX_ENABLE) | 65 | * default: bt_coex_active = true (BT_COEX_ENABLE) |
66 | */ | 66 | */ |
67 | static bool bt_coex_active = true; | 67 | bool bt_coex_active = true; |
68 | EXPORT_SYMBOL_GPL(bt_coex_active); | ||
68 | module_param(bt_coex_active, bool, S_IRUGO); | 69 | module_param(bt_coex_active, bool, S_IRUGO); |
69 | MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist"); | 70 | MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist"); |
70 | 71 | ||
@@ -146,6 +147,10 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) | |||
146 | int i; | 147 | int i; |
147 | u8 ind = ant; | 148 | u8 ind = ant; |
148 | 149 | ||
150 | if (priv->band == IEEE80211_BAND_2GHZ && | ||
151 | priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) | ||
152 | return 0; | ||
153 | |||
149 | for (i = 0; i < RATE_ANT_NUM - 1; i++) { | 154 | for (i = 0; i < RATE_ANT_NUM - 1; i++) { |
150 | ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0; | 155 | ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0; |
151 | if (valid & BIT(ind)) | 156 | if (valid & BIT(ind)) |
@@ -186,27 +191,27 @@ EXPORT_SYMBOL(iwl_alloc_all); | |||
186 | /* | 191 | /* |
187 | * QoS support | 192 | * QoS support |
188 | */ | 193 | */ |
189 | static void iwl_update_qos(struct iwl_priv *priv) | 194 | static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx) |
190 | { | 195 | { |
191 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 196 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
192 | return; | 197 | return; |
193 | 198 | ||
194 | priv->qos_data.def_qos_parm.qos_flags = 0; | 199 | ctx->qos_data.def_qos_parm.qos_flags = 0; |
195 | 200 | ||
196 | if (priv->qos_data.qos_active) | 201 | if (ctx->qos_data.qos_active) |
197 | priv->qos_data.def_qos_parm.qos_flags |= | 202 | ctx->qos_data.def_qos_parm.qos_flags |= |
198 | QOS_PARAM_FLG_UPDATE_EDCA_MSK; | 203 | QOS_PARAM_FLG_UPDATE_EDCA_MSK; |
199 | 204 | ||
200 | if (priv->current_ht_config.is_ht) | 205 | if (ctx->ht.enabled) |
201 | priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; | 206 | ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; |
202 | 207 | ||
203 | IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", | 208 | IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", |
204 | priv->qos_data.qos_active, | 209 | ctx->qos_data.qos_active, |
205 | priv->qos_data.def_qos_parm.qos_flags); | 210 | ctx->qos_data.def_qos_parm.qos_flags); |
206 | 211 | ||
207 | iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM, | 212 | iwl_send_cmd_pdu_async(priv, ctx->qos_cmd, |
208 | sizeof(struct iwl_qosparam_cmd), | 213 | sizeof(struct iwl_qosparam_cmd), |
209 | &priv->qos_data.def_qos_parm, NULL); | 214 | &ctx->qos_data.def_qos_parm, NULL); |
210 | } | 215 | } |
211 | 216 | ||
212 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ | 217 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ |
@@ -436,15 +441,15 @@ static bool is_single_rx_stream(struct iwl_priv *priv) | |||
436 | priv->current_ht_config.single_chain_sufficient; | 441 | priv->current_ht_config.single_chain_sufficient; |
437 | } | 442 | } |
438 | 443 | ||
439 | static u8 iwl_is_channel_extension(struct iwl_priv *priv, | 444 | static bool iwl_is_channel_extension(struct iwl_priv *priv, |
440 | enum ieee80211_band band, | 445 | enum ieee80211_band band, |
441 | u16 channel, u8 extension_chan_offset) | 446 | u16 channel, u8 extension_chan_offset) |
442 | { | 447 | { |
443 | const struct iwl_channel_info *ch_info; | 448 | const struct iwl_channel_info *ch_info; |
444 | 449 | ||
445 | ch_info = iwl_get_channel_info(priv, band, channel); | 450 | ch_info = iwl_get_channel_info(priv, band, channel); |
446 | if (!is_channel_valid(ch_info)) | 451 | if (!is_channel_valid(ch_info)) |
447 | return 0; | 452 | return false; |
448 | 453 | ||
449 | if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) | 454 | if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) |
450 | return !(ch_info->ht40_extension_channel & | 455 | return !(ch_info->ht40_extension_channel & |
@@ -453,31 +458,31 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv, | |||
453 | return !(ch_info->ht40_extension_channel & | 458 | return !(ch_info->ht40_extension_channel & |
454 | IEEE80211_CHAN_NO_HT40MINUS); | 459 | IEEE80211_CHAN_NO_HT40MINUS); |
455 | 460 | ||
456 | return 0; | 461 | return false; |
457 | } | 462 | } |
458 | 463 | ||
459 | u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | 464 | bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, |
460 | struct ieee80211_sta_ht_cap *sta_ht_inf) | 465 | struct iwl_rxon_context *ctx, |
466 | struct ieee80211_sta_ht_cap *ht_cap) | ||
461 | { | 467 | { |
462 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | 468 | if (!ctx->ht.enabled || !ctx->ht.is_40mhz) |
463 | 469 | return false; | |
464 | if (!ht_conf->is_ht || !ht_conf->is_40mhz) | ||
465 | return 0; | ||
466 | 470 | ||
467 | /* We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 471 | /* |
472 | * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40 | ||
468 | * the bit will not set if it is pure 40MHz case | 473 | * the bit will not set if it is pure 40MHz case |
469 | */ | 474 | */ |
470 | if (sta_ht_inf) { | 475 | if (ht_cap && !ht_cap->ht_supported) |
471 | if (!sta_ht_inf->ht_supported) | 476 | return false; |
472 | return 0; | 477 | |
473 | } | ||
474 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 478 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
475 | if (priv->disable_ht40) | 479 | if (priv->disable_ht40) |
476 | return 0; | 480 | return false; |
477 | #endif | 481 | #endif |
482 | |||
478 | return iwl_is_channel_extension(priv, priv->band, | 483 | return iwl_is_channel_extension(priv, priv->band, |
479 | le16_to_cpu(priv->staging_rxon.channel), | 484 | le16_to_cpu(ctx->staging.channel), |
480 | ht_conf->extension_chan_offset); | 485 | ctx->ht.extension_chan_offset); |
481 | } | 486 | } |
482 | EXPORT_SYMBOL(iwl_is_ht40_tx_allowed); | 487 | EXPORT_SYMBOL(iwl_is_ht40_tx_allowed); |
483 | 488 | ||
@@ -495,55 +500,64 @@ static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) | |||
495 | return new_val; | 500 | return new_val; |
496 | } | 501 | } |
497 | 502 | ||
498 | int iwl_send_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) | 503 | int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) |
499 | { | 504 | { |
500 | u64 tsf; | 505 | u64 tsf; |
501 | s32 interval_tm, rem; | 506 | s32 interval_tm, rem; |
502 | struct ieee80211_conf *conf = NULL; | 507 | struct ieee80211_conf *conf = NULL; |
503 | u16 beacon_int; | 508 | u16 beacon_int; |
509 | struct ieee80211_vif *vif = ctx->vif; | ||
504 | 510 | ||
505 | conf = ieee80211_get_hw_conf(priv->hw); | 511 | conf = ieee80211_get_hw_conf(priv->hw); |
506 | 512 | ||
507 | lockdep_assert_held(&priv->mutex); | 513 | lockdep_assert_held(&priv->mutex); |
508 | 514 | ||
509 | memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); | 515 | memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd)); |
510 | 516 | ||
511 | priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp); | 517 | ctx->timing.timestamp = cpu_to_le64(priv->timestamp); |
512 | priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval); | 518 | ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval); |
513 | 519 | ||
514 | beacon_int = vif->bss_conf.beacon_int; | 520 | beacon_int = vif ? vif->bss_conf.beacon_int : 0; |
515 | 521 | ||
516 | if (vif->type == NL80211_IFTYPE_ADHOC) { | 522 | /* |
517 | /* TODO: we need to get atim_window from upper stack | 523 | * TODO: For IBSS we need to get atim_window from mac80211, |
518 | * for now we set to 0 */ | 524 | * for now just always use 0 |
519 | priv->rxon_timing.atim_window = 0; | 525 | */ |
520 | } else { | 526 | ctx->timing.atim_window = 0; |
521 | priv->rxon_timing.atim_window = 0; | ||
522 | } | ||
523 | 527 | ||
524 | beacon_int = iwl_adjust_beacon_interval(beacon_int, | 528 | if (ctx->ctxid == IWL_RXON_CTX_PAN && |
529 | (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION)) { | ||
530 | ctx->timing.beacon_interval = | ||
531 | priv->contexts[IWL_RXON_CTX_BSS].timing.beacon_interval; | ||
532 | beacon_int = le16_to_cpu(ctx->timing.beacon_interval); | ||
533 | } else { | ||
534 | beacon_int = iwl_adjust_beacon_interval(beacon_int, | ||
525 | priv->hw_params.max_beacon_itrvl * TIME_UNIT); | 535 | priv->hw_params.max_beacon_itrvl * TIME_UNIT); |
526 | priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int); | 536 | ctx->timing.beacon_interval = cpu_to_le16(beacon_int); |
537 | } | ||
527 | 538 | ||
528 | tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */ | 539 | tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */ |
529 | interval_tm = beacon_int * TIME_UNIT; | 540 | interval_tm = beacon_int * TIME_UNIT; |
530 | rem = do_div(tsf, interval_tm); | 541 | rem = do_div(tsf, interval_tm); |
531 | priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem); | 542 | ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem); |
543 | |||
544 | ctx->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ?: 1) : 1; | ||
532 | 545 | ||
533 | IWL_DEBUG_ASSOC(priv, | 546 | IWL_DEBUG_ASSOC(priv, |
534 | "beacon interval %d beacon timer %d beacon tim %d\n", | 547 | "beacon interval %d beacon timer %d beacon tim %d\n", |
535 | le16_to_cpu(priv->rxon_timing.beacon_interval), | 548 | le16_to_cpu(ctx->timing.beacon_interval), |
536 | le32_to_cpu(priv->rxon_timing.beacon_init_val), | 549 | le32_to_cpu(ctx->timing.beacon_init_val), |
537 | le16_to_cpu(priv->rxon_timing.atim_window)); | 550 | le16_to_cpu(ctx->timing.atim_window)); |
538 | 551 | ||
539 | return iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | 552 | return iwl_send_cmd_pdu(priv, ctx->rxon_timing_cmd, |
540 | sizeof(priv->rxon_timing), &priv->rxon_timing); | 553 | sizeof(ctx->timing), &ctx->timing); |
541 | } | 554 | } |
542 | EXPORT_SYMBOL(iwl_send_rxon_timing); | 555 | EXPORT_SYMBOL(iwl_send_rxon_timing); |
543 | 556 | ||
544 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) | 557 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, |
558 | int hw_decrypt) | ||
545 | { | 559 | { |
546 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; | 560 | struct iwl_rxon_cmd *rxon = &ctx->staging; |
547 | 561 | ||
548 | if (hw_decrypt) | 562 | if (hw_decrypt) |
549 | rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; | 563 | rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; |
@@ -560,11 +574,11 @@ EXPORT_SYMBOL(iwl_set_rxon_hwcrypto); | |||
560 | * be #ifdef'd out once the driver is stable and folks aren't actively | 574 | * be #ifdef'd out once the driver is stable and folks aren't actively |
561 | * making changes | 575 | * making changes |
562 | */ | 576 | */ |
563 | int iwl_check_rxon_cmd(struct iwl_priv *priv) | 577 | int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx) |
564 | { | 578 | { |
565 | int error = 0; | 579 | int error = 0; |
566 | int counter = 1; | 580 | int counter = 1; |
567 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; | 581 | struct iwl_rxon_cmd *rxon = &ctx->staging; |
568 | 582 | ||
569 | if (rxon->flags & RXON_FLG_BAND_24G_MSK) { | 583 | if (rxon->flags & RXON_FLG_BAND_24G_MSK) { |
570 | error |= le32_to_cpu(rxon->flags & | 584 | error |= le32_to_cpu(rxon->flags & |
@@ -636,66 +650,83 @@ EXPORT_SYMBOL(iwl_check_rxon_cmd); | |||
636 | * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that | 650 | * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that |
637 | * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. | 651 | * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. |
638 | */ | 652 | */ |
639 | int iwl_full_rxon_required(struct iwl_priv *priv) | 653 | int iwl_full_rxon_required(struct iwl_priv *priv, |
654 | struct iwl_rxon_context *ctx) | ||
640 | { | 655 | { |
656 | const struct iwl_rxon_cmd *staging = &ctx->staging; | ||
657 | const struct iwl_rxon_cmd *active = &ctx->active; | ||
658 | |||
659 | #define CHK(cond) \ | ||
660 | if ((cond)) { \ | ||
661 | IWL_DEBUG_INFO(priv, "need full RXON - " #cond "\n"); \ | ||
662 | return 1; \ | ||
663 | } | ||
664 | |||
665 | #define CHK_NEQ(c1, c2) \ | ||
666 | if ((c1) != (c2)) { \ | ||
667 | IWL_DEBUG_INFO(priv, "need full RXON - " \ | ||
668 | #c1 " != " #c2 " - %d != %d\n", \ | ||
669 | (c1), (c2)); \ | ||
670 | return 1; \ | ||
671 | } | ||
641 | 672 | ||
642 | /* These items are only settable from the full RXON command */ | 673 | /* These items are only settable from the full RXON command */ |
643 | if (!(iwl_is_associated(priv)) || | 674 | CHK(!iwl_is_associated_ctx(ctx)); |
644 | compare_ether_addr(priv->staging_rxon.bssid_addr, | 675 | CHK(compare_ether_addr(staging->bssid_addr, active->bssid_addr)); |
645 | priv->active_rxon.bssid_addr) || | 676 | CHK(compare_ether_addr(staging->node_addr, active->node_addr)); |
646 | compare_ether_addr(priv->staging_rxon.node_addr, | 677 | CHK(compare_ether_addr(staging->wlap_bssid_addr, |
647 | priv->active_rxon.node_addr) || | 678 | active->wlap_bssid_addr)); |
648 | compare_ether_addr(priv->staging_rxon.wlap_bssid_addr, | 679 | CHK_NEQ(staging->dev_type, active->dev_type); |
649 | priv->active_rxon.wlap_bssid_addr) || | 680 | CHK_NEQ(staging->channel, active->channel); |
650 | (priv->staging_rxon.dev_type != priv->active_rxon.dev_type) || | 681 | CHK_NEQ(staging->air_propagation, active->air_propagation); |
651 | (priv->staging_rxon.channel != priv->active_rxon.channel) || | 682 | CHK_NEQ(staging->ofdm_ht_single_stream_basic_rates, |
652 | (priv->staging_rxon.air_propagation != | 683 | active->ofdm_ht_single_stream_basic_rates); |
653 | priv->active_rxon.air_propagation) || | 684 | CHK_NEQ(staging->ofdm_ht_dual_stream_basic_rates, |
654 | (priv->staging_rxon.ofdm_ht_single_stream_basic_rates != | 685 | active->ofdm_ht_dual_stream_basic_rates); |
655 | priv->active_rxon.ofdm_ht_single_stream_basic_rates) || | 686 | CHK_NEQ(staging->ofdm_ht_triple_stream_basic_rates, |
656 | (priv->staging_rxon.ofdm_ht_dual_stream_basic_rates != | 687 | active->ofdm_ht_triple_stream_basic_rates); |
657 | priv->active_rxon.ofdm_ht_dual_stream_basic_rates) || | 688 | CHK_NEQ(staging->assoc_id, active->assoc_id); |
658 | (priv->staging_rxon.ofdm_ht_triple_stream_basic_rates != | ||
659 | priv->active_rxon.ofdm_ht_triple_stream_basic_rates) || | ||
660 | (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id)) | ||
661 | return 1; | ||
662 | 689 | ||
663 | /* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can | 690 | /* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can |
664 | * be updated with the RXON_ASSOC command -- however only some | 691 | * be updated with the RXON_ASSOC command -- however only some |
665 | * flag transitions are allowed using RXON_ASSOC */ | 692 | * flag transitions are allowed using RXON_ASSOC */ |
666 | 693 | ||
667 | /* Check if we are not switching bands */ | 694 | /* Check if we are not switching bands */ |
668 | if ((priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) != | 695 | CHK_NEQ(staging->flags & RXON_FLG_BAND_24G_MSK, |
669 | (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)) | 696 | active->flags & RXON_FLG_BAND_24G_MSK); |
670 | return 1; | ||
671 | 697 | ||
672 | /* Check if we are switching association toggle */ | 698 | /* Check if we are switching association toggle */ |
673 | if ((priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) != | 699 | CHK_NEQ(staging->filter_flags & RXON_FILTER_ASSOC_MSK, |
674 | (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) | 700 | active->filter_flags & RXON_FILTER_ASSOC_MSK); |
675 | return 1; | 701 | |
702 | #undef CHK | ||
703 | #undef CHK_NEQ | ||
676 | 704 | ||
677 | return 0; | 705 | return 0; |
678 | } | 706 | } |
679 | EXPORT_SYMBOL(iwl_full_rxon_required); | 707 | EXPORT_SYMBOL(iwl_full_rxon_required); |
680 | 708 | ||
681 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv) | 709 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv, |
710 | struct iwl_rxon_context *ctx) | ||
682 | { | 711 | { |
683 | /* | 712 | /* |
684 | * Assign the lowest rate -- should really get this from | 713 | * Assign the lowest rate -- should really get this from |
685 | * the beacon skb from mac80211. | 714 | * the beacon skb from mac80211. |
686 | */ | 715 | */ |
687 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) | 716 | if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) |
688 | return IWL_RATE_1M_PLCP; | 717 | return IWL_RATE_1M_PLCP; |
689 | else | 718 | else |
690 | return IWL_RATE_6M_PLCP; | 719 | return IWL_RATE_6M_PLCP; |
691 | } | 720 | } |
692 | EXPORT_SYMBOL(iwl_rate_get_lowest_plcp); | 721 | EXPORT_SYMBOL(iwl_rate_get_lowest_plcp); |
693 | 722 | ||
694 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) | 723 | static void _iwl_set_rxon_ht(struct iwl_priv *priv, |
724 | struct iwl_ht_config *ht_conf, | ||
725 | struct iwl_rxon_context *ctx) | ||
695 | { | 726 | { |
696 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; | 727 | struct iwl_rxon_cmd *rxon = &ctx->staging; |
697 | 728 | ||
698 | if (!ht_conf->is_ht) { | 729 | if (!ctx->ht.enabled) { |
699 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | | 730 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | |
700 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | | 731 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | |
701 | RXON_FLG_HT40_PROT_MSK | | 732 | RXON_FLG_HT40_PROT_MSK | |
@@ -703,22 +734,22 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) | |||
703 | return; | 734 | return; |
704 | } | 735 | } |
705 | 736 | ||
706 | /* FIXME: if the definition of ht_protection changed, the "translation" | 737 | /* FIXME: if the definition of ht.protection changed, the "translation" |
707 | * will be needed for rxon->flags | 738 | * will be needed for rxon->flags |
708 | */ | 739 | */ |
709 | rxon->flags |= cpu_to_le32(ht_conf->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS); | 740 | rxon->flags |= cpu_to_le32(ctx->ht.protection << RXON_FLG_HT_OPERATING_MODE_POS); |
710 | 741 | ||
711 | /* Set up channel bandwidth: | 742 | /* Set up channel bandwidth: |
712 | * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */ | 743 | * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */ |
713 | /* clear the HT channel mode before set the mode */ | 744 | /* clear the HT channel mode before set the mode */ |
714 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | | 745 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | |
715 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); | 746 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); |
716 | if (iwl_is_ht40_tx_allowed(priv, NULL)) { | 747 | if (iwl_is_ht40_tx_allowed(priv, ctx, NULL)) { |
717 | /* pure ht40 */ | 748 | /* pure ht40 */ |
718 | if (ht_conf->ht_protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { | 749 | if (ctx->ht.protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { |
719 | rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40; | 750 | rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40; |
720 | /* Note: control channel is opposite of extension channel */ | 751 | /* Note: control channel is opposite of extension channel */ |
721 | switch (ht_conf->extension_chan_offset) { | 752 | switch (ctx->ht.extension_chan_offset) { |
722 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 753 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
723 | rxon->flags &= ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; | 754 | rxon->flags &= ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; |
724 | break; | 755 | break; |
@@ -728,7 +759,7 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) | |||
728 | } | 759 | } |
729 | } else { | 760 | } else { |
730 | /* Note: control channel is opposite of extension channel */ | 761 | /* Note: control channel is opposite of extension channel */ |
731 | switch (ht_conf->extension_chan_offset) { | 762 | switch (ctx->ht.extension_chan_offset) { |
732 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 763 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
733 | rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); | 764 | rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); |
734 | rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED; | 765 | rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED; |
@@ -749,12 +780,20 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) | |||
749 | } | 780 | } |
750 | 781 | ||
751 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 782 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
752 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 783 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); |
753 | 784 | ||
754 | IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X " | 785 | IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X " |
755 | "extension channel offset 0x%x\n", | 786 | "extension channel offset 0x%x\n", |
756 | le32_to_cpu(rxon->flags), ht_conf->ht_protection, | 787 | le32_to_cpu(rxon->flags), ctx->ht.protection, |
757 | ht_conf->extension_chan_offset); | 788 | ctx->ht.extension_chan_offset); |
789 | } | ||
790 | |||
791 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) | ||
792 | { | ||
793 | struct iwl_rxon_context *ctx; | ||
794 | |||
795 | for_each_context(priv, ctx) | ||
796 | _iwl_set_rxon_ht(priv, ht_conf, ctx); | ||
758 | } | 797 | } |
759 | EXPORT_SYMBOL(iwl_set_rxon_ht); | 798 | EXPORT_SYMBOL(iwl_set_rxon_ht); |
760 | 799 | ||
@@ -775,6 +814,14 @@ EXPORT_SYMBOL(iwl_set_rxon_ht); | |||
775 | */ | 814 | */ |
776 | static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) | 815 | static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) |
777 | { | 816 | { |
817 | if (priv->cfg->advanced_bt_coexist && (priv->bt_full_concurrent || | ||
818 | priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { | ||
819 | /* | ||
820 | * only use chain 'A' in bt high traffic load or | ||
821 | * full concurrency mode | ||
822 | */ | ||
823 | return IWL_NUM_RX_CHAINS_SINGLE; | ||
824 | } | ||
778 | /* # of Rx chains to use when expecting MIMO. */ | 825 | /* # of Rx chains to use when expecting MIMO. */ |
779 | if (is_single_rx_stream(priv)) | 826 | if (is_single_rx_stream(priv)) |
780 | return IWL_NUM_RX_CHAINS_SINGLE; | 827 | return IWL_NUM_RX_CHAINS_SINGLE; |
@@ -819,7 +866,7 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap) | |||
819 | * Selects how many and which Rx receivers/antennas/chains to use. | 866 | * Selects how many and which Rx receivers/antennas/chains to use. |
820 | * This should not be used for scan command ... it puts data in wrong place. | 867 | * This should not be used for scan command ... it puts data in wrong place. |
821 | */ | 868 | */ |
822 | void iwl_set_rxon_chain(struct iwl_priv *priv) | 869 | void iwl_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) |
823 | { | 870 | { |
824 | bool is_single = is_single_rx_stream(priv); | 871 | bool is_single = is_single_rx_stream(priv); |
825 | bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); | 872 | bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); |
@@ -831,11 +878,20 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) | |||
831 | * Before first association, we assume all antennas are connected. | 878 | * Before first association, we assume all antennas are connected. |
832 | * Just after first association, iwl_chain_noise_calibration() | 879 | * Just after first association, iwl_chain_noise_calibration() |
833 | * checks which antennas actually *are* connected. */ | 880 | * checks which antennas actually *are* connected. */ |
834 | if (priv->chain_noise_data.active_chains) | 881 | if (priv->chain_noise_data.active_chains) |
835 | active_chains = priv->chain_noise_data.active_chains; | 882 | active_chains = priv->chain_noise_data.active_chains; |
836 | else | 883 | else |
837 | active_chains = priv->hw_params.valid_rx_ant; | 884 | active_chains = priv->hw_params.valid_rx_ant; |
838 | 885 | ||
886 | if (priv->cfg->advanced_bt_coexist && (priv->bt_full_concurrent || | ||
887 | priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { | ||
888 | /* | ||
889 | * only use chain 'A' in bt high traffic load or | ||
890 | * full concurrency mode | ||
891 | */ | ||
892 | active_chains = first_antenna(active_chains); | ||
893 | } | ||
894 | |||
839 | rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS; | 895 | rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS; |
840 | 896 | ||
841 | /* How many receivers should we use? */ | 897 | /* How many receivers should we use? */ |
@@ -856,15 +912,15 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) | |||
856 | rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS; | 912 | rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS; |
857 | rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; | 913 | rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; |
858 | 914 | ||
859 | priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain); | 915 | ctx->staging.rx_chain = cpu_to_le16(rx_chain); |
860 | 916 | ||
861 | if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam) | 917 | if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam) |
862 | priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; | 918 | ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; |
863 | else | 919 | else |
864 | priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; | 920 | ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; |
865 | 921 | ||
866 | IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n", | 922 | IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n", |
867 | priv->staging_rxon.rx_chain, | 923 | ctx->staging.rx_chain, |
868 | active_rx_cnt, idle_rx_cnt); | 924 | active_rx_cnt, idle_rx_cnt); |
869 | 925 | ||
870 | WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 || | 926 | WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 || |
@@ -872,39 +928,41 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) | |||
872 | } | 928 | } |
873 | EXPORT_SYMBOL(iwl_set_rxon_chain); | 929 | EXPORT_SYMBOL(iwl_set_rxon_chain); |
874 | 930 | ||
875 | /* Return valid channel */ | 931 | /* Return valid, unused, channel for a passive scan to reset the RF */ |
876 | u8 iwl_get_single_channel_number(struct iwl_priv *priv, | 932 | u8 iwl_get_single_channel_number(struct iwl_priv *priv, |
877 | enum ieee80211_band band) | 933 | enum ieee80211_band band) |
878 | { | 934 | { |
879 | const struct iwl_channel_info *ch_info; | 935 | const struct iwl_channel_info *ch_info; |
880 | int i; | 936 | int i; |
881 | u8 channel = 0; | 937 | u8 channel = 0; |
938 | u8 min, max; | ||
939 | struct iwl_rxon_context *ctx; | ||
882 | 940 | ||
883 | /* only scan single channel, good enough to reset the RF */ | ||
884 | /* pick the first valid not in-use channel */ | ||
885 | if (band == IEEE80211_BAND_5GHZ) { | 941 | if (band == IEEE80211_BAND_5GHZ) { |
886 | for (i = 14; i < priv->channel_count; i++) { | 942 | min = 14; |
887 | if (priv->channel_info[i].channel != | 943 | max = priv->channel_count; |
888 | le16_to_cpu(priv->staging_rxon.channel)) { | ||
889 | channel = priv->channel_info[i].channel; | ||
890 | ch_info = iwl_get_channel_info(priv, | ||
891 | band, channel); | ||
892 | if (is_channel_valid(ch_info)) | ||
893 | break; | ||
894 | } | ||
895 | } | ||
896 | } else { | 944 | } else { |
897 | for (i = 0; i < 14; i++) { | 945 | min = 0; |
898 | if (priv->channel_info[i].channel != | 946 | max = 14; |
899 | le16_to_cpu(priv->staging_rxon.channel)) { | 947 | } |
900 | channel = | 948 | |
901 | priv->channel_info[i].channel; | 949 | for (i = min; i < max; i++) { |
902 | ch_info = iwl_get_channel_info(priv, | 950 | bool busy = false; |
903 | band, channel); | 951 | |
904 | if (is_channel_valid(ch_info)) | 952 | for_each_context(priv, ctx) { |
905 | break; | 953 | busy = priv->channel_info[i].channel == |
906 | } | 954 | le16_to_cpu(ctx->staging.channel); |
955 | if (busy) | ||
956 | break; | ||
907 | } | 957 | } |
958 | |||
959 | if (busy) | ||
960 | continue; | ||
961 | |||
962 | channel = priv->channel_info[i].channel; | ||
963 | ch_info = iwl_get_channel_info(priv, band, channel); | ||
964 | if (is_channel_valid(ch_info)) | ||
965 | break; | ||
908 | } | 966 | } |
909 | 967 | ||
910 | return channel; | 968 | return channel; |
@@ -915,25 +973,24 @@ EXPORT_SYMBOL(iwl_get_single_channel_number); | |||
915 | * iwl_set_rxon_channel - Set the band and channel values in staging RXON | 973 | * iwl_set_rxon_channel - Set the band and channel values in staging RXON |
916 | * @ch: requested channel as a pointer to struct ieee80211_channel | 974 | * @ch: requested channel as a pointer to struct ieee80211_channel |
917 | 975 | ||
918 | * In addition to setting the staging RXON, priv->band is also set. | ||
919 | * | ||
920 | * NOTE: Does not commit to the hardware; it sets appropriate bit fields | 976 | * NOTE: Does not commit to the hardware; it sets appropriate bit fields |
921 | * in the staging RXON flag structure based on the ch->band | 977 | * in the staging RXON flag structure based on the ch->band |
922 | */ | 978 | */ |
923 | int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) | 979 | int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch, |
980 | struct iwl_rxon_context *ctx) | ||
924 | { | 981 | { |
925 | enum ieee80211_band band = ch->band; | 982 | enum ieee80211_band band = ch->band; |
926 | u16 channel = ch->hw_value; | 983 | u16 channel = ch->hw_value; |
927 | 984 | ||
928 | if ((le16_to_cpu(priv->staging_rxon.channel) == channel) && | 985 | if ((le16_to_cpu(ctx->staging.channel) == channel) && |
929 | (priv->band == band)) | 986 | (priv->band == band)) |
930 | return 0; | 987 | return 0; |
931 | 988 | ||
932 | priv->staging_rxon.channel = cpu_to_le16(channel); | 989 | ctx->staging.channel = cpu_to_le16(channel); |
933 | if (band == IEEE80211_BAND_5GHZ) | 990 | if (band == IEEE80211_BAND_5GHZ) |
934 | priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK; | 991 | ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK; |
935 | else | 992 | else |
936 | priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; | 993 | ctx->staging.flags |= RXON_FLG_BAND_24G_MSK; |
937 | 994 | ||
938 | priv->band = band; | 995 | priv->band = band; |
939 | 996 | ||
@@ -944,24 +1001,25 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) | |||
944 | EXPORT_SYMBOL(iwl_set_rxon_channel); | 1001 | EXPORT_SYMBOL(iwl_set_rxon_channel); |
945 | 1002 | ||
946 | void iwl_set_flags_for_band(struct iwl_priv *priv, | 1003 | void iwl_set_flags_for_band(struct iwl_priv *priv, |
1004 | struct iwl_rxon_context *ctx, | ||
947 | enum ieee80211_band band, | 1005 | enum ieee80211_band band, |
948 | struct ieee80211_vif *vif) | 1006 | struct ieee80211_vif *vif) |
949 | { | 1007 | { |
950 | if (band == IEEE80211_BAND_5GHZ) { | 1008 | if (band == IEEE80211_BAND_5GHZ) { |
951 | priv->staging_rxon.flags &= | 1009 | ctx->staging.flags &= |
952 | ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | 1010 | ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK |
953 | | RXON_FLG_CCK_MSK); | 1011 | | RXON_FLG_CCK_MSK); |
954 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 1012 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; |
955 | } else { | 1013 | } else { |
956 | /* Copied from iwl_post_associate() */ | 1014 | /* Copied from iwl_post_associate() */ |
957 | if (vif && vif->bss_conf.use_short_slot) | 1015 | if (vif && vif->bss_conf.use_short_slot) |
958 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 1016 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; |
959 | else | 1017 | else |
960 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 1018 | ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
961 | 1019 | ||
962 | priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; | 1020 | ctx->staging.flags |= RXON_FLG_BAND_24G_MSK; |
963 | priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK; | 1021 | ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK; |
964 | priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK; | 1022 | ctx->staging.flags &= ~RXON_FLG_CCK_MSK; |
965 | } | 1023 | } |
966 | } | 1024 | } |
967 | EXPORT_SYMBOL(iwl_set_flags_for_band); | 1025 | EXPORT_SYMBOL(iwl_set_flags_for_band); |
@@ -970,35 +1028,34 @@ EXPORT_SYMBOL(iwl_set_flags_for_band); | |||
970 | * initialize rxon structure with default values from eeprom | 1028 | * initialize rxon structure with default values from eeprom |
971 | */ | 1029 | */ |
972 | void iwl_connection_init_rx_config(struct iwl_priv *priv, | 1030 | void iwl_connection_init_rx_config(struct iwl_priv *priv, |
973 | struct ieee80211_vif *vif) | 1031 | struct iwl_rxon_context *ctx) |
974 | { | 1032 | { |
975 | const struct iwl_channel_info *ch_info; | 1033 | const struct iwl_channel_info *ch_info; |
976 | enum nl80211_iftype type = NL80211_IFTYPE_STATION; | ||
977 | 1034 | ||
978 | if (vif) | 1035 | memset(&ctx->staging, 0, sizeof(ctx->staging)); |
979 | type = vif->type; | ||
980 | 1036 | ||
981 | memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon)); | 1037 | if (!ctx->vif) { |
982 | 1038 | ctx->staging.dev_type = ctx->unused_devtype; | |
983 | switch (type) { | 1039 | } else switch (ctx->vif->type) { |
984 | case NL80211_IFTYPE_AP: | 1040 | case NL80211_IFTYPE_AP: |
985 | priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP; | 1041 | ctx->staging.dev_type = ctx->ap_devtype; |
986 | break; | 1042 | break; |
987 | 1043 | ||
988 | case NL80211_IFTYPE_STATION: | 1044 | case NL80211_IFTYPE_STATION: |
989 | priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS; | 1045 | ctx->staging.dev_type = ctx->station_devtype; |
990 | priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; | 1046 | ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; |
991 | break; | 1047 | break; |
992 | 1048 | ||
993 | case NL80211_IFTYPE_ADHOC: | 1049 | case NL80211_IFTYPE_ADHOC: |
994 | priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS; | 1050 | ctx->staging.dev_type = ctx->ibss_devtype; |
995 | priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK; | 1051 | ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; |
996 | priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK | | 1052 | ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK | |
997 | RXON_FILTER_ACCEPT_GRP_MSK; | 1053 | RXON_FILTER_ACCEPT_GRP_MSK; |
998 | break; | 1054 | break; |
999 | 1055 | ||
1000 | default: | 1056 | default: |
1001 | IWL_ERR(priv, "Unsupported interface type %d\n", type); | 1057 | IWL_ERR(priv, "Unsupported interface type %d\n", |
1058 | ctx->vif->type); | ||
1002 | break; | 1059 | break; |
1003 | } | 1060 | } |
1004 | 1061 | ||
@@ -1006,37 +1063,36 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, | |||
1006 | /* TODO: Figure out when short_preamble would be set and cache from | 1063 | /* TODO: Figure out when short_preamble would be set and cache from |
1007 | * that */ | 1064 | * that */ |
1008 | if (!hw_to_local(priv->hw)->short_preamble) | 1065 | if (!hw_to_local(priv->hw)->short_preamble) |
1009 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 1066 | ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
1010 | else | 1067 | else |
1011 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 1068 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
1012 | #endif | 1069 | #endif |
1013 | 1070 | ||
1014 | ch_info = iwl_get_channel_info(priv, priv->band, | 1071 | ch_info = iwl_get_channel_info(priv, priv->band, |
1015 | le16_to_cpu(priv->active_rxon.channel)); | 1072 | le16_to_cpu(ctx->active.channel)); |
1016 | 1073 | ||
1017 | if (!ch_info) | 1074 | if (!ch_info) |
1018 | ch_info = &priv->channel_info[0]; | 1075 | ch_info = &priv->channel_info[0]; |
1019 | 1076 | ||
1020 | priv->staging_rxon.channel = cpu_to_le16(ch_info->channel); | 1077 | ctx->staging.channel = cpu_to_le16(ch_info->channel); |
1021 | priv->band = ch_info->band; | 1078 | priv->band = ch_info->band; |
1022 | 1079 | ||
1023 | iwl_set_flags_for_band(priv, priv->band, vif); | 1080 | iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif); |
1024 | 1081 | ||
1025 | priv->staging_rxon.ofdm_basic_rates = | 1082 | ctx->staging.ofdm_basic_rates = |
1026 | (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | 1083 | (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; |
1027 | priv->staging_rxon.cck_basic_rates = | 1084 | ctx->staging.cck_basic_rates = |
1028 | (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; | 1085 | (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; |
1029 | 1086 | ||
1030 | /* clear both MIX and PURE40 mode flag */ | 1087 | /* clear both MIX and PURE40 mode flag */ |
1031 | priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | | 1088 | ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | |
1032 | RXON_FLG_CHANNEL_MODE_PURE_40); | 1089 | RXON_FLG_CHANNEL_MODE_PURE_40); |
1090 | if (ctx->vif) | ||
1091 | memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN); | ||
1033 | 1092 | ||
1034 | if (vif) | 1093 | ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff; |
1035 | memcpy(priv->staging_rxon.node_addr, vif->addr, ETH_ALEN); | 1094 | ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff; |
1036 | 1095 | ctx->staging.ofdm_ht_triple_stream_basic_rates = 0xff; | |
1037 | priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff; | ||
1038 | priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff; | ||
1039 | priv->staging_rxon.ofdm_ht_triple_stream_basic_rates = 0xff; | ||
1040 | } | 1096 | } |
1041 | EXPORT_SYMBOL(iwl_connection_init_rx_config); | 1097 | EXPORT_SYMBOL(iwl_connection_init_rx_config); |
1042 | 1098 | ||
@@ -1044,6 +1100,7 @@ void iwl_set_rate(struct iwl_priv *priv) | |||
1044 | { | 1100 | { |
1045 | const struct ieee80211_supported_band *hw = NULL; | 1101 | const struct ieee80211_supported_band *hw = NULL; |
1046 | struct ieee80211_rate *rate; | 1102 | struct ieee80211_rate *rate; |
1103 | struct iwl_rxon_context *ctx; | ||
1047 | int i; | 1104 | int i; |
1048 | 1105 | ||
1049 | hw = iwl_get_hw_mode(priv, priv->band); | 1106 | hw = iwl_get_hw_mode(priv, priv->band); |
@@ -1062,21 +1119,29 @@ void iwl_set_rate(struct iwl_priv *priv) | |||
1062 | 1119 | ||
1063 | IWL_DEBUG_RATE(priv, "Set active_rate = %0x\n", priv->active_rate); | 1120 | IWL_DEBUG_RATE(priv, "Set active_rate = %0x\n", priv->active_rate); |
1064 | 1121 | ||
1065 | priv->staging_rxon.cck_basic_rates = | 1122 | for_each_context(priv, ctx) { |
1066 | (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; | 1123 | ctx->staging.cck_basic_rates = |
1124 | (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; | ||
1067 | 1125 | ||
1068 | priv->staging_rxon.ofdm_basic_rates = | 1126 | ctx->staging.ofdm_basic_rates = |
1069 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | 1127 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; |
1128 | } | ||
1070 | } | 1129 | } |
1071 | EXPORT_SYMBOL(iwl_set_rate); | 1130 | EXPORT_SYMBOL(iwl_set_rate); |
1072 | 1131 | ||
1073 | void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) | 1132 | void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) |
1074 | { | 1133 | { |
1134 | /* | ||
1135 | * MULTI-FIXME | ||
1136 | * See iwl_mac_channel_switch. | ||
1137 | */ | ||
1138 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
1139 | |||
1075 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 1140 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
1076 | return; | 1141 | return; |
1077 | 1142 | ||
1078 | if (priv->switch_rxon.switch_in_progress) { | 1143 | if (priv->switch_rxon.switch_in_progress) { |
1079 | ieee80211_chswitch_done(priv->vif, is_success); | 1144 | ieee80211_chswitch_done(ctx->vif, is_success); |
1080 | mutex_lock(&priv->mutex); | 1145 | mutex_lock(&priv->mutex); |
1081 | priv->switch_rxon.switch_in_progress = false; | 1146 | priv->switch_rxon.switch_in_progress = false; |
1082 | mutex_unlock(&priv->mutex); | 1147 | mutex_unlock(&priv->mutex); |
@@ -1087,14 +1152,19 @@ EXPORT_SYMBOL(iwl_chswitch_done); | |||
1087 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | 1152 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) |
1088 | { | 1153 | { |
1089 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 1154 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
1090 | struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon; | ||
1091 | struct iwl_csa_notification *csa = &(pkt->u.csa_notif); | 1155 | struct iwl_csa_notification *csa = &(pkt->u.csa_notif); |
1156 | /* | ||
1157 | * MULTI-FIXME | ||
1158 | * See iwl_mac_channel_switch. | ||
1159 | */ | ||
1160 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
1161 | struct iwl_rxon_cmd *rxon = (void *)&ctx->active; | ||
1092 | 1162 | ||
1093 | if (priv->switch_rxon.switch_in_progress) { | 1163 | if (priv->switch_rxon.switch_in_progress) { |
1094 | if (!le32_to_cpu(csa->status) && | 1164 | if (!le32_to_cpu(csa->status) && |
1095 | (csa->channel == priv->switch_rxon.channel)) { | 1165 | (csa->channel == priv->switch_rxon.channel)) { |
1096 | rxon->channel = csa->channel; | 1166 | rxon->channel = csa->channel; |
1097 | priv->staging_rxon.channel = csa->channel; | 1167 | ctx->staging.channel = csa->channel; |
1098 | IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", | 1168 | IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", |
1099 | le16_to_cpu(csa->channel)); | 1169 | le16_to_cpu(csa->channel)); |
1100 | iwl_chswitch_done(priv, true); | 1170 | iwl_chswitch_done(priv, true); |
@@ -1108,9 +1178,10 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1108 | EXPORT_SYMBOL(iwl_rx_csa); | 1178 | EXPORT_SYMBOL(iwl_rx_csa); |
1109 | 1179 | ||
1110 | #ifdef CONFIG_IWLWIFI_DEBUG | 1180 | #ifdef CONFIG_IWLWIFI_DEBUG |
1111 | void iwl_print_rx_config_cmd(struct iwl_priv *priv) | 1181 | void iwl_print_rx_config_cmd(struct iwl_priv *priv, |
1182 | struct iwl_rxon_context *ctx) | ||
1112 | { | 1183 | { |
1113 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; | 1184 | struct iwl_rxon_cmd *rxon = &ctx->staging; |
1114 | 1185 | ||
1115 | IWL_DEBUG_RADIO(priv, "RX CONFIG:\n"); | 1186 | IWL_DEBUG_RADIO(priv, "RX CONFIG:\n"); |
1116 | iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); | 1187 | iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); |
@@ -1150,7 +1221,8 @@ void iwl_irq_handle_error(struct iwl_priv *priv) | |||
1150 | priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false); | 1221 | priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false); |
1151 | #ifdef CONFIG_IWLWIFI_DEBUG | 1222 | #ifdef CONFIG_IWLWIFI_DEBUG |
1152 | if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) | 1223 | if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) |
1153 | iwl_print_rx_config_cmd(priv); | 1224 | iwl_print_rx_config_cmd(priv, |
1225 | &priv->contexts[IWL_RXON_CTX_BSS]); | ||
1154 | #endif | 1226 | #endif |
1155 | 1227 | ||
1156 | wake_up_interruptible(&priv->wait_command_queue); | 1228 | wake_up_interruptible(&priv->wait_command_queue); |
@@ -1518,6 +1590,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1518 | const struct ieee80211_tx_queue_params *params) | 1590 | const struct ieee80211_tx_queue_params *params) |
1519 | { | 1591 | { |
1520 | struct iwl_priv *priv = hw->priv; | 1592 | struct iwl_priv *priv = hw->priv; |
1593 | struct iwl_rxon_context *ctx; | ||
1521 | unsigned long flags; | 1594 | unsigned long flags; |
1522 | int q; | 1595 | int q; |
1523 | 1596 | ||
@@ -1537,13 +1610,21 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1537 | 1610 | ||
1538 | spin_lock_irqsave(&priv->lock, flags); | 1611 | spin_lock_irqsave(&priv->lock, flags); |
1539 | 1612 | ||
1540 | priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min); | 1613 | /* |
1541 | priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max); | 1614 | * MULTI-FIXME |
1542 | priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs; | 1615 | * This may need to be done per interface in nl80211/cfg80211/mac80211. |
1543 | priv->qos_data.def_qos_parm.ac[q].edca_txop = | 1616 | */ |
1544 | cpu_to_le16((params->txop * 32)); | 1617 | for_each_context(priv, ctx) { |
1618 | ctx->qos_data.def_qos_parm.ac[q].cw_min = | ||
1619 | cpu_to_le16(params->cw_min); | ||
1620 | ctx->qos_data.def_qos_parm.ac[q].cw_max = | ||
1621 | cpu_to_le16(params->cw_max); | ||
1622 | ctx->qos_data.def_qos_parm.ac[q].aifsn = params->aifs; | ||
1623 | ctx->qos_data.def_qos_parm.ac[q].edca_txop = | ||
1624 | cpu_to_le16((params->txop * 32)); | ||
1545 | 1625 | ||
1546 | priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; | 1626 | ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0; |
1627 | } | ||
1547 | 1628 | ||
1548 | spin_unlock_irqrestore(&priv->lock, flags); | 1629 | spin_unlock_irqrestore(&priv->lock, flags); |
1549 | 1630 | ||
@@ -1566,15 +1647,16 @@ static void iwl_ht_conf(struct iwl_priv *priv, | |||
1566 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | 1647 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
1567 | struct ieee80211_sta *sta; | 1648 | struct ieee80211_sta *sta; |
1568 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 1649 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
1650 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | ||
1569 | 1651 | ||
1570 | IWL_DEBUG_MAC80211(priv, "enter:\n"); | 1652 | IWL_DEBUG_MAC80211(priv, "enter:\n"); |
1571 | 1653 | ||
1572 | if (!ht_conf->is_ht) | 1654 | if (!ctx->ht.enabled) |
1573 | return; | 1655 | return; |
1574 | 1656 | ||
1575 | ht_conf->ht_protection = | 1657 | ctx->ht.protection = |
1576 | bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; | 1658 | bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; |
1577 | ht_conf->non_GF_STA_present = | 1659 | ctx->ht.non_gf_sta_present = |
1578 | !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | 1660 | !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); |
1579 | 1661 | ||
1580 | ht_conf->single_chain_sufficient = false; | 1662 | ht_conf->single_chain_sufficient = false; |
@@ -1618,18 +1700,20 @@ static void iwl_ht_conf(struct iwl_priv *priv, | |||
1618 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 1700 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
1619 | } | 1701 | } |
1620 | 1702 | ||
1621 | static inline void iwl_set_no_assoc(struct iwl_priv *priv) | 1703 | static inline void iwl_set_no_assoc(struct iwl_priv *priv, |
1704 | struct ieee80211_vif *vif) | ||
1622 | { | 1705 | { |
1706 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | ||
1707 | |||
1623 | iwl_led_disassociate(priv); | 1708 | iwl_led_disassociate(priv); |
1624 | /* | 1709 | /* |
1625 | * inform the ucode that there is no longer an | 1710 | * inform the ucode that there is no longer an |
1626 | * association and that no more packets should be | 1711 | * association and that no more packets should be |
1627 | * sent | 1712 | * sent |
1628 | */ | 1713 | */ |
1629 | priv->staging_rxon.filter_flags &= | 1714 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
1630 | ~RXON_FILTER_ASSOC_MSK; | 1715 | ctx->staging.assoc_id = 0; |
1631 | priv->staging_rxon.assoc_id = 0; | 1716 | iwlcore_commit_rxon(priv, ctx); |
1632 | iwlcore_commit_rxon(priv); | ||
1633 | } | 1717 | } |
1634 | 1718 | ||
1635 | static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | 1719 | static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) |
@@ -1640,6 +1724,14 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1640 | 1724 | ||
1641 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 1725 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
1642 | 1726 | ||
1727 | lockdep_assert_held(&priv->mutex); | ||
1728 | |||
1729 | if (!priv->beacon_ctx) { | ||
1730 | IWL_ERR(priv, "update beacon but no beacon context!\n"); | ||
1731 | dev_kfree_skb(skb); | ||
1732 | return -EINVAL; | ||
1733 | } | ||
1734 | |||
1643 | if (!iwl_is_ready_rf(priv)) { | 1735 | if (!iwl_is_ready_rf(priv)) { |
1644 | IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); | 1736 | IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); |
1645 | return -EIO; | 1737 | return -EIO; |
@@ -1658,7 +1750,7 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1658 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 1750 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
1659 | spin_unlock_irqrestore(&priv->lock, flags); | 1751 | spin_unlock_irqrestore(&priv->lock, flags); |
1660 | 1752 | ||
1661 | priv->cfg->ops->lib->post_associate(priv, priv->vif); | 1753 | priv->cfg->ops->lib->post_associate(priv, priv->beacon_ctx->vif); |
1662 | 1754 | ||
1663 | return 0; | 1755 | return 0; |
1664 | } | 1756 | } |
@@ -1669,6 +1761,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
1669 | u32 changes) | 1761 | u32 changes) |
1670 | { | 1762 | { |
1671 | struct iwl_priv *priv = hw->priv; | 1763 | struct iwl_priv *priv = hw->priv; |
1764 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | ||
1672 | int ret; | 1765 | int ret; |
1673 | 1766 | ||
1674 | IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); | 1767 | IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); |
@@ -1682,11 +1775,23 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
1682 | unsigned long flags; | 1775 | unsigned long flags; |
1683 | 1776 | ||
1684 | spin_lock_irqsave(&priv->lock, flags); | 1777 | spin_lock_irqsave(&priv->lock, flags); |
1685 | priv->qos_data.qos_active = bss_conf->qos; | 1778 | ctx->qos_data.qos_active = bss_conf->qos; |
1686 | iwl_update_qos(priv); | 1779 | iwl_update_qos(priv, ctx); |
1687 | spin_unlock_irqrestore(&priv->lock, flags); | 1780 | spin_unlock_irqrestore(&priv->lock, flags); |
1688 | } | 1781 | } |
1689 | 1782 | ||
1783 | if (changes & BSS_CHANGED_BEACON_ENABLED) { | ||
1784 | /* | ||
1785 | * the add_interface code must make sure we only ever | ||
1786 | * have a single interface that could be beaconing at | ||
1787 | * any time. | ||
1788 | */ | ||
1789 | if (vif->bss_conf.enable_beacon) | ||
1790 | priv->beacon_ctx = ctx; | ||
1791 | else | ||
1792 | priv->beacon_ctx = NULL; | ||
1793 | } | ||
1794 | |||
1690 | if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) { | 1795 | if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) { |
1691 | dev_kfree_skb(priv->ibss_beacon); | 1796 | dev_kfree_skb(priv->ibss_beacon); |
1692 | priv->ibss_beacon = ieee80211_beacon_get(hw, vif); | 1797 | priv->ibss_beacon = ieee80211_beacon_get(hw, vif); |
@@ -1713,13 +1818,13 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
1713 | 1818 | ||
1714 | /* mac80211 only sets assoc when in STATION mode */ | 1819 | /* mac80211 only sets assoc when in STATION mode */ |
1715 | if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) { | 1820 | if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) { |
1716 | memcpy(priv->staging_rxon.bssid_addr, | 1821 | memcpy(ctx->staging.bssid_addr, |
1717 | bss_conf->bssid, ETH_ALEN); | 1822 | bss_conf->bssid, ETH_ALEN); |
1718 | 1823 | ||
1719 | /* currently needed in a few places */ | 1824 | /* currently needed in a few places */ |
1720 | memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); | 1825 | memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); |
1721 | } else { | 1826 | } else { |
1722 | priv->staging_rxon.filter_flags &= | 1827 | ctx->staging.filter_flags &= |
1723 | ~RXON_FILTER_ASSOC_MSK; | 1828 | ~RXON_FILTER_ASSOC_MSK; |
1724 | } | 1829 | } |
1725 | 1830 | ||
@@ -1742,21 +1847,21 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
1742 | IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", | 1847 | IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", |
1743 | bss_conf->use_short_preamble); | 1848 | bss_conf->use_short_preamble); |
1744 | if (bss_conf->use_short_preamble) | 1849 | if (bss_conf->use_short_preamble) |
1745 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 1850 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
1746 | else | 1851 | else |
1747 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 1852 | ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
1748 | } | 1853 | } |
1749 | 1854 | ||
1750 | if (changes & BSS_CHANGED_ERP_CTS_PROT) { | 1855 | if (changes & BSS_CHANGED_ERP_CTS_PROT) { |
1751 | IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot); | 1856 | IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot); |
1752 | if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) | 1857 | if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) |
1753 | priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; | 1858 | ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; |
1754 | else | 1859 | else |
1755 | priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; | 1860 | ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; |
1756 | if (bss_conf->use_cts_prot) | 1861 | if (bss_conf->use_cts_prot) |
1757 | priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN; | 1862 | ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; |
1758 | else | 1863 | else |
1759 | priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; | 1864 | ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN; |
1760 | } | 1865 | } |
1761 | 1866 | ||
1762 | if (changes & BSS_CHANGED_BASIC_RATES) { | 1867 | if (changes & BSS_CHANGED_BASIC_RATES) { |
@@ -1766,12 +1871,12 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
1766 | * like this here: | 1871 | * like this here: |
1767 | * | 1872 | * |
1768 | if (A-band) | 1873 | if (A-band) |
1769 | priv->staging_rxon.ofdm_basic_rates = | 1874 | ctx->staging.ofdm_basic_rates = |
1770 | bss_conf->basic_rates; | 1875 | bss_conf->basic_rates; |
1771 | else | 1876 | else |
1772 | priv->staging_rxon.ofdm_basic_rates = | 1877 | ctx->staging.ofdm_basic_rates = |
1773 | bss_conf->basic_rates >> 4; | 1878 | bss_conf->basic_rates >> 4; |
1774 | priv->staging_rxon.cck_basic_rates = | 1879 | ctx->staging.cck_basic_rates = |
1775 | bss_conf->basic_rates & 0xF; | 1880 | bss_conf->basic_rates & 0xF; |
1776 | */ | 1881 | */ |
1777 | } | 1882 | } |
@@ -1780,7 +1885,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
1780 | iwl_ht_conf(priv, vif); | 1885 | iwl_ht_conf(priv, vif); |
1781 | 1886 | ||
1782 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 1887 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
1783 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 1888 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); |
1784 | } | 1889 | } |
1785 | 1890 | ||
1786 | if (changes & BSS_CHANGED_ASSOC) { | 1891 | if (changes & BSS_CHANGED_ASSOC) { |
@@ -1793,29 +1898,29 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
1793 | if (!iwl_is_rfkill(priv)) | 1898 | if (!iwl_is_rfkill(priv)) |
1794 | priv->cfg->ops->lib->post_associate(priv, vif); | 1899 | priv->cfg->ops->lib->post_associate(priv, vif); |
1795 | } else | 1900 | } else |
1796 | iwl_set_no_assoc(priv); | 1901 | iwl_set_no_assoc(priv, vif); |
1797 | } | 1902 | } |
1798 | 1903 | ||
1799 | if (changes && iwl_is_associated(priv) && bss_conf->aid) { | 1904 | if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) { |
1800 | IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n", | 1905 | IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n", |
1801 | changes); | 1906 | changes); |
1802 | ret = iwl_send_rxon_assoc(priv); | 1907 | ret = iwl_send_rxon_assoc(priv, ctx); |
1803 | if (!ret) { | 1908 | if (!ret) { |
1804 | /* Sync active_rxon with latest change. */ | 1909 | /* Sync active_rxon with latest change. */ |
1805 | memcpy((void *)&priv->active_rxon, | 1910 | memcpy((void *)&ctx->active, |
1806 | &priv->staging_rxon, | 1911 | &ctx->staging, |
1807 | sizeof(struct iwl_rxon_cmd)); | 1912 | sizeof(struct iwl_rxon_cmd)); |
1808 | } | 1913 | } |
1809 | } | 1914 | } |
1810 | 1915 | ||
1811 | if (changes & BSS_CHANGED_BEACON_ENABLED) { | 1916 | if (changes & BSS_CHANGED_BEACON_ENABLED) { |
1812 | if (vif->bss_conf.enable_beacon) { | 1917 | if (vif->bss_conf.enable_beacon) { |
1813 | memcpy(priv->staging_rxon.bssid_addr, | 1918 | memcpy(ctx->staging.bssid_addr, |
1814 | bss_conf->bssid, ETH_ALEN); | 1919 | bss_conf->bssid, ETH_ALEN); |
1815 | memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); | 1920 | memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); |
1816 | iwlcore_config_ap(priv, vif); | 1921 | iwlcore_config_ap(priv, vif); |
1817 | } else | 1922 | } else |
1818 | iwl_set_no_assoc(priv); | 1923 | iwl_set_no_assoc(priv, vif); |
1819 | } | 1924 | } |
1820 | 1925 | ||
1821 | if (changes & BSS_CHANGED_IBSS) { | 1926 | if (changes & BSS_CHANGED_IBSS) { |
@@ -1827,6 +1932,12 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
1827 | bss_conf->bssid); | 1932 | bss_conf->bssid); |
1828 | } | 1933 | } |
1829 | 1934 | ||
1935 | if (changes & BSS_CHANGED_IDLE && | ||
1936 | priv->cfg->ops->hcmd->set_pan_params) { | ||
1937 | if (priv->cfg->ops->hcmd->set_pan_params(priv)) | ||
1938 | IWL_ERR(priv, "failed to update PAN params\n"); | ||
1939 | } | ||
1940 | |||
1830 | mutex_unlock(&priv->mutex); | 1941 | mutex_unlock(&priv->mutex); |
1831 | 1942 | ||
1832 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 1943 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
@@ -1835,17 +1946,21 @@ EXPORT_SYMBOL(iwl_bss_info_changed); | |||
1835 | 1946 | ||
1836 | static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) | 1947 | static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) |
1837 | { | 1948 | { |
1838 | iwl_connection_init_rx_config(priv, vif); | 1949 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); |
1950 | |||
1951 | iwl_connection_init_rx_config(priv, ctx); | ||
1839 | 1952 | ||
1840 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 1953 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
1841 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 1954 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); |
1842 | 1955 | ||
1843 | return iwlcore_commit_rxon(priv); | 1956 | return iwlcore_commit_rxon(priv, ctx); |
1844 | } | 1957 | } |
1845 | 1958 | ||
1846 | int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | 1959 | int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
1847 | { | 1960 | { |
1848 | struct iwl_priv *priv = hw->priv; | 1961 | struct iwl_priv *priv = hw->priv; |
1962 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
1963 | struct iwl_rxon_context *tmp, *ctx = NULL; | ||
1849 | int err = 0; | 1964 | int err = 0; |
1850 | 1965 | ||
1851 | IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", | 1966 | IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", |
@@ -1858,23 +1973,60 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
1858 | goto out; | 1973 | goto out; |
1859 | } | 1974 | } |
1860 | 1975 | ||
1861 | if (priv->vif) { | 1976 | for_each_context(priv, tmp) { |
1862 | IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); | 1977 | u32 possible_modes = |
1978 | tmp->interface_modes | tmp->exclusive_interface_modes; | ||
1979 | |||
1980 | if (tmp->vif) { | ||
1981 | /* check if this busy context is exclusive */ | ||
1982 | if (tmp->exclusive_interface_modes & | ||
1983 | BIT(tmp->vif->type)) { | ||
1984 | err = -EINVAL; | ||
1985 | goto out; | ||
1986 | } | ||
1987 | continue; | ||
1988 | } | ||
1989 | |||
1990 | if (!(possible_modes & BIT(vif->type))) | ||
1991 | continue; | ||
1992 | |||
1993 | /* have maybe usable context w/o interface */ | ||
1994 | ctx = tmp; | ||
1995 | break; | ||
1996 | } | ||
1997 | |||
1998 | if (!ctx) { | ||
1863 | err = -EOPNOTSUPP; | 1999 | err = -EOPNOTSUPP; |
1864 | goto out; | 2000 | goto out; |
1865 | } | 2001 | } |
1866 | 2002 | ||
1867 | priv->vif = vif; | 2003 | vif_priv->ctx = ctx; |
2004 | ctx->vif = vif; | ||
2005 | /* | ||
2006 | * This variable will be correct only when there's just | ||
2007 | * a single context, but all code using it is for hardware | ||
2008 | * that supports only one context. | ||
2009 | */ | ||
1868 | priv->iw_mode = vif->type; | 2010 | priv->iw_mode = vif->type; |
1869 | 2011 | ||
1870 | err = iwl_set_mode(priv, vif); | 2012 | err = iwl_set_mode(priv, vif); |
1871 | if (err) | 2013 | if (err) |
1872 | goto out_err; | 2014 | goto out_err; |
1873 | 2015 | ||
2016 | if (priv->cfg->advanced_bt_coexist && | ||
2017 | vif->type == NL80211_IFTYPE_ADHOC) { | ||
2018 | /* | ||
2019 | * pretend to have high BT traffic as long as we | ||
2020 | * are operating in IBSS mode, as this will cause | ||
2021 | * the rate scaling etc. to behave as intended. | ||
2022 | */ | ||
2023 | priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH; | ||
2024 | } | ||
2025 | |||
1874 | goto out; | 2026 | goto out; |
1875 | 2027 | ||
1876 | out_err: | 2028 | out_err: |
1877 | priv->vif = NULL; | 2029 | ctx->vif = NULL; |
1878 | priv->iw_mode = NL80211_IFTYPE_STATION; | 2030 | priv->iw_mode = NL80211_IFTYPE_STATION; |
1879 | out: | 2031 | out: |
1880 | mutex_unlock(&priv->mutex); | 2032 | mutex_unlock(&priv->mutex); |
@@ -1888,26 +2040,36 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
1888 | struct ieee80211_vif *vif) | 2040 | struct ieee80211_vif *vif) |
1889 | { | 2041 | { |
1890 | struct iwl_priv *priv = hw->priv; | 2042 | struct iwl_priv *priv = hw->priv; |
2043 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | ||
1891 | bool scan_completed = false; | 2044 | bool scan_completed = false; |
1892 | 2045 | ||
1893 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 2046 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
1894 | 2047 | ||
1895 | mutex_lock(&priv->mutex); | 2048 | mutex_lock(&priv->mutex); |
1896 | 2049 | ||
1897 | if (iwl_is_ready_rf(priv)) { | 2050 | WARN_ON(ctx->vif != vif); |
1898 | iwl_scan_cancel_timeout(priv, 100); | 2051 | ctx->vif = NULL; |
1899 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2052 | |
1900 | iwlcore_commit_rxon(priv); | 2053 | iwl_scan_cancel_timeout(priv, 100); |
1901 | } | 2054 | iwl_set_mode(priv, vif); |
1902 | if (priv->vif == vif) { | 2055 | |
1903 | priv->vif = NULL; | 2056 | if (priv->scan_vif == vif) { |
1904 | if (priv->scan_vif == vif) { | 2057 | scan_completed = true; |
1905 | scan_completed = true; | 2058 | priv->scan_vif = NULL; |
1906 | priv->scan_vif = NULL; | 2059 | priv->scan_request = NULL; |
1907 | priv->scan_request = NULL; | ||
1908 | } | ||
1909 | memset(priv->bssid, 0, ETH_ALEN); | ||
1910 | } | 2060 | } |
2061 | |||
2062 | /* | ||
2063 | * When removing the IBSS interface, overwrite the | ||
2064 | * BT traffic load with the stored one from the last | ||
2065 | * notification, if any. If this is a device that | ||
2066 | * doesn't implement this, this has no effect since | ||
2067 | * both values are the same and zero. | ||
2068 | */ | ||
2069 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
2070 | priv->bt_traffic_load = priv->notif_bt_traffic_load; | ||
2071 | |||
2072 | memset(priv->bssid, 0, ETH_ALEN); | ||
1911 | mutex_unlock(&priv->mutex); | 2073 | mutex_unlock(&priv->mutex); |
1912 | 2074 | ||
1913 | if (scan_completed) | 2075 | if (scan_completed) |
@@ -1928,6 +2090,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
1928 | struct ieee80211_conf *conf = &hw->conf; | 2090 | struct ieee80211_conf *conf = &hw->conf; |
1929 | struct ieee80211_channel *channel = conf->channel; | 2091 | struct ieee80211_channel *channel = conf->channel; |
1930 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | 2092 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
2093 | struct iwl_rxon_context *ctx; | ||
1931 | unsigned long flags = 0; | 2094 | unsigned long flags = 0; |
1932 | int ret = 0; | 2095 | int ret = 0; |
1933 | u16 ch; | 2096 | u16 ch; |
@@ -1957,7 +2120,8 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
1957 | * configured. | 2120 | * configured. |
1958 | */ | 2121 | */ |
1959 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 2122 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
1960 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 2123 | for_each_context(priv, ctx) |
2124 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); | ||
1961 | } | 2125 | } |
1962 | 2126 | ||
1963 | /* during scanning mac80211 will delay channel setting until | 2127 | /* during scanning mac80211 will delay channel setting until |
@@ -1977,39 +2141,49 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
1977 | 2141 | ||
1978 | spin_lock_irqsave(&priv->lock, flags); | 2142 | spin_lock_irqsave(&priv->lock, flags); |
1979 | 2143 | ||
1980 | /* Configure HT40 channels */ | 2144 | for_each_context(priv, ctx) { |
1981 | ht_conf->is_ht = conf_is_ht(conf); | 2145 | /* Configure HT40 channels */ |
1982 | if (ht_conf->is_ht) { | 2146 | ctx->ht.enabled = conf_is_ht(conf); |
1983 | if (conf_is_ht40_minus(conf)) { | 2147 | if (ctx->ht.enabled) { |
1984 | ht_conf->extension_chan_offset = | 2148 | if (conf_is_ht40_minus(conf)) { |
1985 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; | 2149 | ctx->ht.extension_chan_offset = |
1986 | ht_conf->is_40mhz = true; | 2150 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; |
1987 | } else if (conf_is_ht40_plus(conf)) { | 2151 | ctx->ht.is_40mhz = true; |
1988 | ht_conf->extension_chan_offset = | 2152 | } else if (conf_is_ht40_plus(conf)) { |
1989 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | 2153 | ctx->ht.extension_chan_offset = |
1990 | ht_conf->is_40mhz = true; | 2154 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; |
1991 | } else { | 2155 | ctx->ht.is_40mhz = true; |
1992 | ht_conf->extension_chan_offset = | 2156 | } else { |
1993 | IEEE80211_HT_PARAM_CHA_SEC_NONE; | 2157 | ctx->ht.extension_chan_offset = |
1994 | ht_conf->is_40mhz = false; | 2158 | IEEE80211_HT_PARAM_CHA_SEC_NONE; |
1995 | } | 2159 | ctx->ht.is_40mhz = false; |
1996 | } else | 2160 | } |
1997 | ht_conf->is_40mhz = false; | 2161 | } else |
1998 | /* Default to no protection. Protection mode will later be set | 2162 | ctx->ht.is_40mhz = false; |
1999 | * from BSS config in iwl_ht_conf */ | ||
2000 | ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; | ||
2001 | 2163 | ||
2002 | if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) | 2164 | /* |
2003 | priv->staging_rxon.flags = 0; | 2165 | * Default to no protection. Protection mode will |
2166 | * later be set from BSS config in iwl_ht_conf | ||
2167 | */ | ||
2168 | ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; | ||
2169 | |||
2170 | /* if we are switching from ht to 2.4 clear flags | ||
2171 | * from any ht related info since 2.4 does not | ||
2172 | * support ht */ | ||
2173 | if ((le16_to_cpu(ctx->staging.channel) != ch)) | ||
2174 | ctx->staging.flags = 0; | ||
2175 | |||
2176 | iwl_set_rxon_channel(priv, channel, ctx); | ||
2177 | iwl_set_rxon_ht(priv, ht_conf); | ||
2004 | 2178 | ||
2005 | iwl_set_rxon_channel(priv, channel); | 2179 | iwl_set_flags_for_band(priv, ctx, channel->band, |
2006 | iwl_set_rxon_ht(priv, ht_conf); | 2180 | ctx->vif); |
2181 | } | ||
2007 | 2182 | ||
2008 | iwl_set_flags_for_band(priv, channel->band, priv->vif); | ||
2009 | spin_unlock_irqrestore(&priv->lock, flags); | 2183 | spin_unlock_irqrestore(&priv->lock, flags); |
2010 | 2184 | ||
2011 | if (priv->cfg->ops->lib->update_bcast_station) | 2185 | if (priv->cfg->ops->lib->update_bcast_stations) |
2012 | ret = priv->cfg->ops->lib->update_bcast_station(priv); | 2186 | ret = priv->cfg->ops->lib->update_bcast_stations(priv); |
2013 | 2187 | ||
2014 | set_ch_out: | 2188 | set_ch_out: |
2015 | /* The list of supported rates and rate mask can be different | 2189 | /* The list of supported rates and rate mask can be different |
@@ -2040,12 +2214,13 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2040 | if (scan_active) | 2214 | if (scan_active) |
2041 | goto out; | 2215 | goto out; |
2042 | 2216 | ||
2043 | if (memcmp(&priv->active_rxon, | 2217 | for_each_context(priv, ctx) { |
2044 | &priv->staging_rxon, sizeof(priv->staging_rxon))) | 2218 | if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging))) |
2045 | iwlcore_commit_rxon(priv); | 2219 | iwlcore_commit_rxon(priv, ctx); |
2046 | else | 2220 | else |
2047 | IWL_DEBUG_INFO(priv, "Not re-sending same RXON configuration.\n"); | 2221 | IWL_DEBUG_INFO(priv, |
2048 | 2222 | "Not re-sending same RXON configuration.\n"); | |
2223 | } | ||
2049 | 2224 | ||
2050 | out: | 2225 | out: |
2051 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2226 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
@@ -2058,6 +2233,8 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | |||
2058 | { | 2233 | { |
2059 | struct iwl_priv *priv = hw->priv; | 2234 | struct iwl_priv *priv = hw->priv; |
2060 | unsigned long flags; | 2235 | unsigned long flags; |
2236 | /* IBSS can only be the IWL_RXON_CTX_BSS context */ | ||
2237 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
2061 | 2238 | ||
2062 | mutex_lock(&priv->mutex); | 2239 | mutex_lock(&priv->mutex); |
2063 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 2240 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
@@ -2088,8 +2265,8 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | |||
2088 | * clear RXON_FILTER_ASSOC_MSK bit | 2265 | * clear RXON_FILTER_ASSOC_MSK bit |
2089 | */ | 2266 | */ |
2090 | iwl_scan_cancel_timeout(priv, 100); | 2267 | iwl_scan_cancel_timeout(priv, 100); |
2091 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2268 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2092 | iwlcore_commit_rxon(priv); | 2269 | iwlcore_commit_rxon(priv, ctx); |
2093 | 2270 | ||
2094 | iwl_set_rate(priv); | 2271 | iwl_set_rate(priv); |
2095 | 2272 | ||
@@ -2498,7 +2675,7 @@ static void iwl_force_rf_reset(struct iwl_priv *priv) | |||
2498 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 2675 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2499 | return; | 2676 | return; |
2500 | 2677 | ||
2501 | if (!iwl_is_associated(priv)) { | 2678 | if (!iwl_is_any_associated(priv)) { |
2502 | IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n"); | 2679 | IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n"); |
2503 | return; | 2680 | return; |
2504 | } | 2681 | } |
@@ -2624,10 +2801,14 @@ static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt) | |||
2624 | "queue %d, not read %d time\n", | 2801 | "queue %d, not read %d time\n", |
2625 | q->id, | 2802 | q->id, |
2626 | q->repeat_same_read_ptr); | 2803 | q->repeat_same_read_ptr); |
2627 | mod_timer(&priv->monitor_recover, jiffies + | 2804 | if (!priv->cfg->advanced_bt_coexist) { |
2628 | msecs_to_jiffies(IWL_ONE_HUNDRED_MSECS)); | 2805 | mod_timer(&priv->monitor_recover, |
2806 | jiffies + msecs_to_jiffies( | ||
2807 | IWL_ONE_HUNDRED_MSECS)); | ||
2808 | return 1; | ||
2809 | } | ||
2629 | } | 2810 | } |
2630 | return 1; | 2811 | return 0; |
2631 | } else { | 2812 | } else { |
2632 | q->last_read_ptr = q->read_ptr; | 2813 | q->last_read_ptr = q->read_ptr; |
2633 | q->repeat_same_read_ptr = 0; | 2814 | q->repeat_same_read_ptr = 0; |
@@ -2645,25 +2826,27 @@ void iwl_bg_monitor_recover(unsigned long data) | |||
2645 | return; | 2826 | return; |
2646 | 2827 | ||
2647 | /* monitor and check for stuck cmd queue */ | 2828 | /* monitor and check for stuck cmd queue */ |
2648 | if (iwl_check_stuck_queue(priv, IWL_CMD_QUEUE_NUM)) | 2829 | if (iwl_check_stuck_queue(priv, priv->cmd_queue)) |
2649 | return; | 2830 | return; |
2650 | 2831 | ||
2651 | /* monitor and check for other stuck queues */ | 2832 | /* monitor and check for other stuck queues */ |
2652 | if (iwl_is_associated(priv)) { | 2833 | if (iwl_is_any_associated(priv)) { |
2653 | for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { | 2834 | for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { |
2654 | /* skip as we already checked the command queue */ | 2835 | /* skip as we already checked the command queue */ |
2655 | if (cnt == IWL_CMD_QUEUE_NUM) | 2836 | if (cnt == priv->cmd_queue) |
2656 | continue; | 2837 | continue; |
2657 | if (iwl_check_stuck_queue(priv, cnt)) | 2838 | if (iwl_check_stuck_queue(priv, cnt)) |
2658 | return; | 2839 | return; |
2659 | } | 2840 | } |
2660 | } | 2841 | } |
2661 | /* | 2842 | if (priv->cfg->monitor_recover_period) { |
2662 | * Reschedule the timer to occur in | 2843 | /* |
2663 | * priv->cfg->monitor_recover_period | 2844 | * Reschedule the timer to occur in |
2664 | */ | 2845 | * priv->cfg->monitor_recover_period |
2665 | mod_timer(&priv->monitor_recover, | 2846 | */ |
2666 | jiffies + msecs_to_jiffies(priv->cfg->monitor_recover_period)); | 2847 | mod_timer(&priv->monitor_recover, jiffies + msecs_to_jiffies( |
2848 | priv->cfg->monitor_recover_period)); | ||
2849 | } | ||
2667 | } | 2850 | } |
2668 | EXPORT_SYMBOL(iwl_bg_monitor_recover); | 2851 | EXPORT_SYMBOL(iwl_bg_monitor_recover); |
2669 | 2852 | ||