diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 207 |
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 | ||
2423 | static 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 | |||
2434 | static const struct ieee80211_iface_limit iwlagn_2sta_limits[] = { | ||
2435 | { | ||
2436 | .max = 2, | ||
2437 | .types = BIT(NL80211_IFTYPE_STATION), | ||
2438 | }, | ||
2439 | }; | ||
2440 | |||
2441 | static 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 | |||
2453 | static 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 | |||
2464 | static const struct ieee80211_iface_combination | ||
2465 | iwlagn_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 | |||
2479 | static const struct ieee80211_iface_combination | ||
2480 | iwlagn_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 | |||
2912 | out: | 2993 | out: |
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: |