aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath6kl
diff options
context:
space:
mode:
authorVasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>2012-04-09 09:33:58 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2012-04-09 11:25:56 -0400
commitdf90b36940019a879d08bc5e8a20daa0c9fe0122 (patch)
tree0be946d8ad4042097b20295cfc806ae6d10a1c5d /drivers/net/wireless/ath/ath6kl
parentbed56e313ada1d25d16e4101677c8f75eda78c60 (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>
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl')
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c77
-rw-r--r--drivers/net/wireless/ath/ath6kl/common.h1
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h9
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c37
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h13
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
2427static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev, 2427static 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
2454static bool ath6kl_is_p2p_ie(const u8 *pos) 2448static 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
2522static 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
2528static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, 2551static 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
79struct htc_endpoint_credit_dist; 79struct htc_endpoint_credit_dist;
80struct ath6kl; 80struct ath6kl;
81struct ath6kl_htcap;
81enum htc_credit_dist_reason; 82enum htc_credit_dist_reason;
82struct ath6kl_htc_credit_info; 83struct 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
477struct 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
2885int 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
2885int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len) 2922int 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
1274struct 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);
2473int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, u8 if_idx, enum wmi_txop_cfg cfg); 2483int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, u8 if_idx, enum wmi_txop_cfg cfg);
2474int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx, 2484int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx,
2475 u8 keep_alive_intvl); 2485 u8 keep_alive_intvl);
2486int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx,
2487 enum ieee80211_band band,
2488 struct ath6kl_htcap *htcap);
2476int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len); 2489int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len);
2477 2490
2478s32 ath6kl_wmi_get_rate(s8 rate_index); 2491s32 ath6kl_wmi_get_rate(s8 rate_index);