diff options
author | Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com> | 2012-04-09 09:33:58 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2012-04-09 11:25:56 -0400 |
commit | df90b36940019a879d08bc5e8a20daa0c9fe0122 (patch) | |
tree | 0be946d8ad4042097b20295cfc806ae6d10a1c5d | |
parent | bed56e313ada1d25d16e4101677c8f75eda78c60 (diff) |
ath6kl: Configure htcap in fw based on the channel type in AP mode
This patch disables HT in start_ap if the type of the channel on
which the AP mode is going to be operating is non-HT. HT is enabled
with default ht cap setting if the operating channel is going to be
11n.
Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/cfg80211.c | 77 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/common.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/core.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/wmi.c | 37 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/wmi.h | 13 |
5 files changed, 116 insertions, 21 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 1229ce96ba90..900993017d09 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -2424,31 +2424,25 @@ void ath6kl_check_wow_status(struct ath6kl *ar) | |||
2424 | } | 2424 | } |
2425 | #endif | 2425 | #endif |
2426 | 2426 | ||
2427 | static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev, | 2427 | static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band, |
2428 | struct ieee80211_channel *chan, | 2428 | bool ht_enable) |
2429 | enum nl80211_channel_type channel_type) | ||
2430 | { | 2429 | { |
2431 | struct ath6kl_vif *vif; | 2430 | struct ath6kl_htcap *htcap = &vif->htcap; |
2432 | |||
2433 | /* | ||
2434 | * 'dev' could be NULL if a channel change is required for the hardware | ||
2435 | * device itself, instead of a particular VIF. | ||
2436 | * | ||
2437 | * FIXME: To be handled properly when monitor mode is supported. | ||
2438 | */ | ||
2439 | if (!dev) | ||
2440 | return -EBUSY; | ||
2441 | |||
2442 | vif = netdev_priv(dev); | ||
2443 | 2431 | ||
2444 | if (!ath6kl_cfg80211_ready(vif)) | 2432 | if (htcap->ht_enable == ht_enable) |
2445 | return -EIO; | 2433 | return 0; |
2446 | 2434 | ||
2447 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n", | 2435 | if (ht_enable) { |
2448 | __func__, chan->center_freq, chan->hw_value); | 2436 | /* Set default ht capabilities */ |
2449 | vif->next_chan = chan->center_freq; | 2437 | htcap->ht_enable = true; |
2438 | htcap->cap_info = (band == IEEE80211_BAND_2GHZ) ? | ||
2439 | ath6kl_g_htcap : ath6kl_a_htcap; | ||
2440 | htcap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K; | ||
2441 | } else /* Disable ht */ | ||
2442 | memset(htcap, 0, sizeof(*htcap)); | ||
2450 | 2443 | ||
2451 | return 0; | 2444 | return ath6kl_wmi_set_htcap_cmd(vif->ar->wmi, vif->fw_vif_idx, |
2445 | band, htcap); | ||
2452 | } | 2446 | } |
2453 | 2447 | ||
2454 | static bool ath6kl_is_p2p_ie(const u8 *pos) | 2448 | static bool ath6kl_is_p2p_ie(const u8 *pos) |
@@ -2525,6 +2519,35 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif, | |||
2525 | return 0; | 2519 | return 0; |
2526 | } | 2520 | } |
2527 | 2521 | ||
2522 | static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev, | ||
2523 | struct ieee80211_channel *chan, | ||
2524 | enum nl80211_channel_type channel_type) | ||
2525 | { | ||
2526 | struct ath6kl_vif *vif; | ||
2527 | |||
2528 | /* | ||
2529 | * 'dev' could be NULL if a channel change is required for the hardware | ||
2530 | * device itself, instead of a particular VIF. | ||
2531 | * | ||
2532 | * FIXME: To be handled properly when monitor mode is supported. | ||
2533 | */ | ||
2534 | if (!dev) | ||
2535 | return -EBUSY; | ||
2536 | |||
2537 | vif = netdev_priv(dev); | ||
2538 | |||
2539 | if (!ath6kl_cfg80211_ready(vif)) | ||
2540 | return -EIO; | ||
2541 | |||
2542 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n", | ||
2543 | __func__, chan->center_freq, chan->hw_value); | ||
2544 | vif->next_chan = chan->center_freq; | ||
2545 | vif->next_ch_type = channel_type; | ||
2546 | vif->next_ch_band = chan->band; | ||
2547 | |||
2548 | return 0; | ||
2549 | } | ||
2550 | |||
2528 | static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, | 2551 | static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, |
2529 | struct cfg80211_ap_settings *info) | 2552 | struct cfg80211_ap_settings *info) |
2530 | { | 2553 | { |
@@ -2673,6 +2696,10 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
2673 | return res; | 2696 | return res; |
2674 | } | 2697 | } |
2675 | 2698 | ||
2699 | if (ath6kl_set_htcap(vif, vif->next_ch_band, | ||
2700 | vif->next_ch_type != NL80211_CHAN_NO_HT)) | ||
2701 | return -EIO; | ||
2702 | |||
2676 | res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p); | 2703 | res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p); |
2677 | if (res < 0) | 2704 | if (res < 0) |
2678 | return res; | 2705 | return res; |
@@ -2707,6 +2734,13 @@ static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
2707 | ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx); | 2734 | ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx); |
2708 | clear_bit(CONNECTED, &vif->flags); | 2735 | clear_bit(CONNECTED, &vif->flags); |
2709 | 2736 | ||
2737 | /* Restore ht setting in firmware */ | ||
2738 | if (ath6kl_set_htcap(vif, IEEE80211_BAND_2GHZ, true)) | ||
2739 | return -EIO; | ||
2740 | |||
2741 | if (ath6kl_set_htcap(vif, IEEE80211_BAND_5GHZ, true)) | ||
2742 | return -EIO; | ||
2743 | |||
2710 | return 0; | 2744 | return 0; |
2711 | } | 2745 | } |
2712 | 2746 | ||
@@ -3252,6 +3286,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, | |||
3252 | vif->next_mode = nw_type; | 3286 | vif->next_mode = nw_type; |
3253 | vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; | 3287 | vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; |
3254 | vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; | 3288 | vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; |
3289 | vif->htcap.ht_enable = true; | ||
3255 | 3290 | ||
3256 | memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); | 3291 | memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); |
3257 | if (fw_vif_idx != 0) | 3292 | if (fw_vif_idx != 0) |
diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h index 71f54501464a..98a886154d9c 100644 --- a/drivers/net/wireless/ath/ath6kl/common.h +++ b/drivers/net/wireless/ath/ath6kl/common.h | |||
@@ -78,6 +78,7 @@ enum crypto_type { | |||
78 | 78 | ||
79 | struct htc_endpoint_credit_dist; | 79 | struct htc_endpoint_credit_dist; |
80 | struct ath6kl; | 80 | struct ath6kl; |
81 | struct ath6kl_htcap; | ||
81 | enum htc_credit_dist_reason; | 82 | enum htc_credit_dist_reason; |
82 | struct ath6kl_htc_credit_info; | 83 | struct ath6kl_htc_credit_info; |
83 | 84 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 75b1d864090a..8e7e9480a786 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -474,6 +474,12 @@ struct ath6kl_mc_filter { | |||
474 | char hw_addr[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE]; | 474 | char hw_addr[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE]; |
475 | }; | 475 | }; |
476 | 476 | ||
477 | struct ath6kl_htcap { | ||
478 | bool ht_enable; | ||
479 | u8 ampdu_factor; | ||
480 | unsigned short cap_info; | ||
481 | }; | ||
482 | |||
477 | /* | 483 | /* |
478 | * Driver's maximum limit, note that some firmwares support only one vif | 484 | * Driver's maximum limit, note that some firmwares support only one vif |
479 | * and the runtime (current) limit must be checked from ar->vif_max. | 485 | * and the runtime (current) limit must be checked from ar->vif_max. |
@@ -522,6 +528,7 @@ struct ath6kl_vif { | |||
522 | struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; | 528 | struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; |
523 | struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1]; | 529 | struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1]; |
524 | struct aggr_info *aggr_cntxt; | 530 | struct aggr_info *aggr_cntxt; |
531 | struct ath6kl_htcap htcap; | ||
525 | 532 | ||
526 | struct timer_list disconnect_timer; | 533 | struct timer_list disconnect_timer; |
527 | struct timer_list sched_scan_timer; | 534 | struct timer_list sched_scan_timer; |
@@ -534,6 +541,8 @@ struct ath6kl_vif { | |||
534 | u32 send_action_id; | 541 | u32 send_action_id; |
535 | bool probe_req_report; | 542 | bool probe_req_report; |
536 | u16 next_chan; | 543 | u16 next_chan; |
544 | enum nl80211_channel_type next_ch_type; | ||
545 | enum ieee80211_band next_ch_band; | ||
537 | u16 assoc_bss_beacon_int; | 546 | u16 assoc_bss_beacon_int; |
538 | u16 listen_intvl_t; | 547 | u16 listen_intvl_t; |
539 | u16 bmiss_time_t; | 548 | u16 bmiss_time_t; |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index b1b1f347a118..efd707e69255 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
@@ -2882,6 +2882,43 @@ int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx, | |||
2882 | return ret; | 2882 | return ret; |
2883 | } | 2883 | } |
2884 | 2884 | ||
2885 | int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx, | ||
2886 | enum ieee80211_band band, | ||
2887 | struct ath6kl_htcap *htcap) | ||
2888 | { | ||
2889 | struct sk_buff *skb; | ||
2890 | struct wmi_set_htcap_cmd *cmd; | ||
2891 | |||
2892 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); | ||
2893 | if (!skb) | ||
2894 | return -ENOMEM; | ||
2895 | |||
2896 | cmd = (struct wmi_set_htcap_cmd *) skb->data; | ||
2897 | |||
2898 | /* | ||
2899 | * NOTE: Band in firmware matches enum ieee80211_band, it is unlikely | ||
2900 | * this will be changed in firmware. If at all there is any change in | ||
2901 | * band value, the host needs to be fixed. | ||
2902 | */ | ||
2903 | cmd->band = band; | ||
2904 | cmd->ht_enable = !!htcap->ht_enable; | ||
2905 | cmd->ht20_sgi = !!(htcap->cap_info & IEEE80211_HT_CAP_SGI_20); | ||
2906 | cmd->ht40_supported = | ||
2907 | !!(htcap->cap_info & IEEE80211_HT_CAP_SUP_WIDTH_20_40); | ||
2908 | cmd->ht40_sgi = !!(htcap->cap_info & IEEE80211_HT_CAP_SGI_40); | ||
2909 | cmd->intolerant_40mhz = | ||
2910 | !!(htcap->cap_info & IEEE80211_HT_CAP_40MHZ_INTOLERANT); | ||
2911 | cmd->max_ampdu_len_exp = htcap->ampdu_factor; | ||
2912 | |||
2913 | ath6kl_dbg(ATH6KL_DBG_WMI, | ||
2914 | "Set htcap: band:%d ht_enable:%d 40mhz:%d sgi_20mhz:%d sgi_40mhz:%d 40mhz_intolerant:%d ampdu_len_exp:%d\n", | ||
2915 | cmd->band, cmd->ht_enable, cmd->ht40_supported, | ||
2916 | cmd->ht20_sgi, cmd->ht40_sgi, cmd->intolerant_40mhz, | ||
2917 | cmd->max_ampdu_len_exp); | ||
2918 | return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_HT_CAP_CMDID, | ||
2919 | NO_SYNC_WMIFLAG); | ||
2920 | } | ||
2921 | |||
2885 | int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len) | 2922 | int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len) |
2886 | { | 2923 | { |
2887 | struct sk_buff *skb; | 2924 | struct sk_buff *skb; |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index b99e9bdca7c6..ee45d1022532 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h | |||
@@ -1271,6 +1271,16 @@ struct wmi_mcast_filter_add_del_cmd { | |||
1271 | u8 mcast_mac[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE]; | 1271 | u8 mcast_mac[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE]; |
1272 | } __packed; | 1272 | } __packed; |
1273 | 1273 | ||
1274 | struct wmi_set_htcap_cmd { | ||
1275 | u8 band; | ||
1276 | u8 ht_enable; | ||
1277 | u8 ht40_supported; | ||
1278 | u8 ht20_sgi; | ||
1279 | u8 ht40_sgi; | ||
1280 | u8 intolerant_40mhz; | ||
1281 | u8 max_ampdu_len_exp; | ||
1282 | } __packed; | ||
1283 | |||
1274 | /* Command Replies */ | 1284 | /* Command Replies */ |
1275 | 1285 | ||
1276 | /* WMI_GET_CHANNEL_LIST_CMDID reply */ | 1286 | /* WMI_GET_CHANNEL_LIST_CMDID reply */ |
@@ -2473,6 +2483,9 @@ int ath6kl_wmi_get_roam_tbl_cmd(struct wmi *wmi); | |||
2473 | int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, u8 if_idx, enum wmi_txop_cfg cfg); | 2483 | int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, u8 if_idx, enum wmi_txop_cfg cfg); |
2474 | int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx, | 2484 | int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx, |
2475 | u8 keep_alive_intvl); | 2485 | u8 keep_alive_intvl); |
2486 | int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx, | ||
2487 | enum ieee80211_band band, | ||
2488 | struct ath6kl_htcap *htcap); | ||
2476 | int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len); | 2489 | int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len); |
2477 | 2490 | ||
2478 | s32 ath6kl_wmi_get_rate(s8 rate_index); | 2491 | s32 ath6kl_wmi_get_rate(s8 rate_index); |