aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c207
1 files changed, 144 insertions, 63 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 8e1942ebd9a0..099c2795ec0b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -97,7 +97,7 @@ void iwl_update_chain_flags(struct iwl_priv *priv)
97 for_each_context(priv, ctx) { 97 for_each_context(priv, ctx) {
98 priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); 98 priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
99 if (ctx->active.rx_chain != ctx->staging.rx_chain) 99 if (ctx->active.rx_chain != ctx->staging.rx_chain)
100 iwlcore_commit_rxon(priv, ctx); 100 iwlagn_commit_rxon(priv, ctx);
101 } 101 }
102 } 102 }
103} 103}
@@ -274,7 +274,7 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
274 for_each_context(priv, ctx) { 274 for_each_context(priv, ctx) {
275 if (priv->cfg->ops->hcmd->set_rxon_chain) 275 if (priv->cfg->ops->hcmd->set_rxon_chain)
276 priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); 276 priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
277 iwlcore_commit_rxon(priv, ctx); 277 iwlagn_commit_rxon(priv, ctx);
278 } 278 }
279 279
280 priv->cfg->ops->hcmd->send_bt_config(priv); 280 priv->cfg->ops->hcmd->send_bt_config(priv);
@@ -2056,7 +2056,7 @@ int iwl_alive_start(struct iwl_priv *priv)
2056 set_bit(STATUS_READY, &priv->status); 2056 set_bit(STATUS_READY, &priv->status);
2057 2057
2058 /* Configure the adapter for unassociated operation */ 2058 /* Configure the adapter for unassociated operation */
2059 ret = iwlcore_commit_rxon(priv, ctx); 2059 ret = iwlagn_commit_rxon(priv, ctx);
2060 if (ret) 2060 if (ret)
2061 return ret; 2061 return ret;
2062 2062
@@ -2420,6 +2420,77 @@ unlock:
2420 * 2420 *
2421 *****************************************************************************/ 2421 *****************************************************************************/
2422 2422
2423static const struct ieee80211_iface_limit iwlagn_sta_ap_limits[] = {
2424 {
2425 .max = 1,
2426 .types = BIT(NL80211_IFTYPE_STATION),
2427 },
2428 {
2429 .max = 1,
2430 .types = BIT(NL80211_IFTYPE_AP),
2431 },
2432};
2433
2434static const struct ieee80211_iface_limit iwlagn_2sta_limits[] = {
2435 {
2436 .max = 2,
2437 .types = BIT(NL80211_IFTYPE_STATION),
2438 },
2439};
2440
2441static const struct ieee80211_iface_limit iwlagn_p2p_sta_go_limits[] = {
2442 {
2443 .max = 1,
2444 .types = BIT(NL80211_IFTYPE_STATION),
2445 },
2446 {
2447 .max = 1,
2448 .types = BIT(NL80211_IFTYPE_P2P_GO) |
2449 BIT(NL80211_IFTYPE_AP),
2450 },
2451};
2452
2453static const struct ieee80211_iface_limit iwlagn_p2p_2sta_limits[] = {
2454 {
2455 .max = 2,
2456 .types = BIT(NL80211_IFTYPE_STATION),
2457 },
2458 {
2459 .max = 1,
2460 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
2461 },
2462};
2463
2464static const struct ieee80211_iface_combination
2465iwlagn_iface_combinations_dualmode[] = {
2466 { .num_different_channels = 1,
2467 .max_interfaces = 2,
2468 .beacon_int_infra_match = true,
2469 .limits = iwlagn_sta_ap_limits,
2470 .n_limits = ARRAY_SIZE(iwlagn_sta_ap_limits),
2471 },
2472 { .num_different_channels = 1,
2473 .max_interfaces = 2,
2474 .limits = iwlagn_2sta_limits,
2475 .n_limits = ARRAY_SIZE(iwlagn_2sta_limits),
2476 },
2477};
2478
2479static const struct ieee80211_iface_combination
2480iwlagn_iface_combinations_p2p[] = {
2481 { .num_different_channels = 1,
2482 .max_interfaces = 2,
2483 .beacon_int_infra_match = true,
2484 .limits = iwlagn_p2p_sta_go_limits,
2485 .n_limits = ARRAY_SIZE(iwlagn_p2p_sta_go_limits),
2486 },
2487 { .num_different_channels = 1,
2488 .max_interfaces = 2,
2489 .limits = iwlagn_p2p_2sta_limits,
2490 .n_limits = ARRAY_SIZE(iwlagn_p2p_2sta_limits),
2491 },
2492};
2493
2423/* 2494/*
2424 * Not a mac80211 entry point function, but it fits in with all the 2495 * Not a mac80211 entry point function, but it fits in with all the
2425 * other mac80211 functions grouped here. 2496 * other mac80211 functions grouped here.
@@ -2460,6 +2531,18 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
2460 hw->wiphy->interface_modes |= ctx->exclusive_interface_modes; 2531 hw->wiphy->interface_modes |= ctx->exclusive_interface_modes;
2461 } 2532 }
2462 2533
2534 BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
2535
2536 if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) {
2537 hw->wiphy->iface_combinations = iwlagn_iface_combinations_p2p;
2538 hw->wiphy->n_iface_combinations =
2539 ARRAY_SIZE(iwlagn_iface_combinations_p2p);
2540 } else if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
2541 hw->wiphy->iface_combinations = iwlagn_iface_combinations_dualmode;
2542 hw->wiphy->n_iface_combinations =
2543 ARRAY_SIZE(iwlagn_iface_combinations_dualmode);
2544 }
2545
2463 hw->wiphy->max_remain_on_channel_duration = 1000; 2546 hw->wiphy->max_remain_on_channel_duration = 1000;
2464 2547
2465 hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | 2548 hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
@@ -2711,12 +2794,9 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
2711 ret = 0; 2794 ret = 0;
2712 if (priv->cfg->ht_params && 2795 if (priv->cfg->ht_params &&
2713 priv->cfg->ht_params->use_rts_for_aggregation) { 2796 priv->cfg->ht_params->use_rts_for_aggregation) {
2714 struct iwl_station_priv *sta_priv =
2715 (void *) sta->drv_priv;
2716 /* 2797 /*
2717 * switch off RTS/CTS if it was previously enabled 2798 * switch off RTS/CTS if it was previously enabled
2718 */ 2799 */
2719
2720 sta_priv->lq_sta.lq.general_params.flags &= 2800 sta_priv->lq_sta.lq.general_params.flags &=
2721 ~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; 2801 ~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
2722 iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif), 2802 iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
@@ -2764,6 +2844,9 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
2764 2844
2765 iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif), 2845 iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
2766 &sta_priv->lq_sta.lq, CMD_ASYNC, false); 2846 &sta_priv->lq_sta.lq, CMD_ASYNC, false);
2847
2848 IWL_INFO(priv, "Tx aggregation enabled on ra = %pM tid = %d\n",
2849 sta->addr, tid);
2767 ret = 0; 2850 ret = 0;
2768 break; 2851 break;
2769 } 2852 }
@@ -2833,7 +2916,6 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
2833 */ 2916 */
2834 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; 2917 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
2835 u16 ch; 2918 u16 ch;
2836 unsigned long flags = 0;
2837 2919
2838 IWL_DEBUG_MAC80211(priv, "enter\n"); 2920 IWL_DEBUG_MAC80211(priv, "enter\n");
2839 2921
@@ -2850,65 +2932,64 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
2850 if (!iwl_is_associated_ctx(ctx)) 2932 if (!iwl_is_associated_ctx(ctx))
2851 goto out; 2933 goto out;
2852 2934
2853 if (priv->cfg->ops->lib->set_channel_switch) { 2935 if (!priv->cfg->ops->lib->set_channel_switch)
2936 goto out;
2854 2937
2855 ch = channel->hw_value; 2938 ch = channel->hw_value;
2856 if (le16_to_cpu(ctx->active.channel) != ch) { 2939 if (le16_to_cpu(ctx->active.channel) == ch)
2857 ch_info = iwl_get_channel_info(priv, 2940 goto out;
2858 channel->band,
2859 ch);
2860 if (!is_channel_valid(ch_info)) {
2861 IWL_DEBUG_MAC80211(priv, "invalid channel\n");
2862 goto out;
2863 }
2864 spin_lock_irqsave(&priv->lock, flags);
2865
2866 priv->current_ht_config.smps = conf->smps_mode;
2867
2868 /* Configure HT40 channels */
2869 ctx->ht.enabled = conf_is_ht(conf);
2870 if (ctx->ht.enabled) {
2871 if (conf_is_ht40_minus(conf)) {
2872 ctx->ht.extension_chan_offset =
2873 IEEE80211_HT_PARAM_CHA_SEC_BELOW;
2874 ctx->ht.is_40mhz = true;
2875 } else if (conf_is_ht40_plus(conf)) {
2876 ctx->ht.extension_chan_offset =
2877 IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
2878 ctx->ht.is_40mhz = true;
2879 } else {
2880 ctx->ht.extension_chan_offset =
2881 IEEE80211_HT_PARAM_CHA_SEC_NONE;
2882 ctx->ht.is_40mhz = false;
2883 }
2884 } else
2885 ctx->ht.is_40mhz = false;
2886 2941
2887 if ((le16_to_cpu(ctx->staging.channel) != ch)) 2942 ch_info = iwl_get_channel_info(priv, channel->band, ch);
2888 ctx->staging.flags = 0; 2943 if (!is_channel_valid(ch_info)) {
2944 IWL_DEBUG_MAC80211(priv, "invalid channel\n");
2945 goto out;
2946 }
2889 2947
2890 iwl_set_rxon_channel(priv, channel, ctx); 2948 spin_lock_irq(&priv->lock);
2891 iwl_set_rxon_ht(priv, ht_conf);
2892 iwl_set_flags_for_band(priv, ctx, channel->band,
2893 ctx->vif);
2894 spin_unlock_irqrestore(&priv->lock, flags);
2895 2949
2896 iwl_set_rate(priv); 2950 priv->current_ht_config.smps = conf->smps_mode;
2897 /* 2951
2898 * at this point, staging_rxon has the 2952 /* Configure HT40 channels */
2899 * configuration for channel switch 2953 ctx->ht.enabled = conf_is_ht(conf);
2900 */ 2954 if (ctx->ht.enabled) {
2901 set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); 2955 if (conf_is_ht40_minus(conf)) {
2902 priv->switch_channel = cpu_to_le16(ch); 2956 ctx->ht.extension_chan_offset =
2903 if (priv->cfg->ops->lib->set_channel_switch(priv, 2957 IEEE80211_HT_PARAM_CHA_SEC_BELOW;
2904 ch_switch)) { 2958 ctx->ht.is_40mhz = true;
2905 clear_bit(STATUS_CHANNEL_SWITCH_PENDING, 2959 } else if (conf_is_ht40_plus(conf)) {
2906 &priv->status); 2960 ctx->ht.extension_chan_offset =
2907 priv->switch_channel = 0; 2961 IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
2908 ieee80211_chswitch_done(ctx->vif, false); 2962 ctx->ht.is_40mhz = true;
2909 } 2963 } else {
2964 ctx->ht.extension_chan_offset =
2965 IEEE80211_HT_PARAM_CHA_SEC_NONE;
2966 ctx->ht.is_40mhz = false;
2910 } 2967 }
2968 } else
2969 ctx->ht.is_40mhz = false;
2970
2971 if ((le16_to_cpu(ctx->staging.channel) != ch))
2972 ctx->staging.flags = 0;
2973
2974 iwl_set_rxon_channel(priv, channel, ctx);
2975 iwl_set_rxon_ht(priv, ht_conf);
2976 iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif);
2977
2978 spin_unlock_irq(&priv->lock);
2979
2980 iwl_set_rate(priv);
2981 /*
2982 * at this point, staging_rxon has the
2983 * configuration for channel switch
2984 */
2985 set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
2986 priv->switch_channel = cpu_to_le16(ch);
2987 if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) {
2988 clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
2989 priv->switch_channel = 0;
2990 ieee80211_chswitch_done(ctx->vif, false);
2911 } 2991 }
2992
2912out: 2993out:
2913 mutex_unlock(&priv->mutex); 2994 mutex_unlock(&priv->mutex);
2914 IWL_DEBUG_MAC80211(priv, "leave\n"); 2995 IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -3019,7 +3100,7 @@ static void iwlagn_disable_roc(struct iwl_priv *priv)
3019 3100
3020 priv->_agn.hw_roc_channel = NULL; 3101 priv->_agn.hw_roc_channel = NULL;
3021 3102
3022 iwlcore_commit_rxon(priv, ctx); 3103 iwlagn_commit_rxon(priv, ctx);
3023 3104
3024 ctx->is_active = false; 3105 ctx->is_active = false;
3025} 3106}
@@ -3062,7 +3143,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
3062 priv->_agn.hw_roc_channel = channel; 3143 priv->_agn.hw_roc_channel = channel;
3063 priv->_agn.hw_roc_chantype = channel_type; 3144 priv->_agn.hw_roc_chantype = channel_type;
3064 priv->_agn.hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024); 3145 priv->_agn.hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024);
3065 iwlcore_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]); 3146 iwlagn_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]);
3066 queue_delayed_work(priv->workqueue, &priv->_agn.hw_roc_work, 3147 queue_delayed_work(priv->workqueue, &priv->_agn.hw_roc_work,
3067 msecs_to_jiffies(duration + 20)); 3148 msecs_to_jiffies(duration + 20));
3068 3149
@@ -3619,8 +3700,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
3619 destroy_workqueue(priv->workqueue); 3700 destroy_workqueue(priv->workqueue);
3620 priv->workqueue = NULL; 3701 priv->workqueue = NULL;
3621 free_irq(priv->pci_dev->irq, priv); 3702 free_irq(priv->pci_dev->irq, priv);
3622 iwl_free_isr_ict(priv);
3623 out_disable_msi: 3703 out_disable_msi:
3704 iwl_free_isr_ict(priv);
3624 pci_disable_msi(priv->pci_dev); 3705 pci_disable_msi(priv->pci_dev);
3625 iwl_uninit_drv(priv); 3706 iwl_uninit_drv(priv);
3626 out_free_eeprom: 3707 out_free_eeprom: