Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Vasanthakumar Thiagarajan and committed by
Kalle Valo
df90b369 bed56e31

+116 -21
+56 -21
drivers/net/wireless/ath/ath6kl/cfg80211.c
··· 2424 2424 } 2425 2425 #endif 2426 2426 2427 - static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev, 2428 - struct ieee80211_channel *chan, 2429 - enum nl80211_channel_type channel_type) 2427 + static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band, 2428 + bool ht_enable) 2430 2429 { 2431 - struct ath6kl_vif *vif; 2430 + struct ath6kl_htcap *htcap = &vif->htcap; 2432 2431 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; 2432 + if (htcap->ht_enable == ht_enable) 2433 + return 0; 2441 2434 2442 - vif = netdev_priv(dev); 2435 + if (ht_enable) { 2436 + /* Set default ht capabilities */ 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)); 2443 2443 2444 - if (!ath6kl_cfg80211_ready(vif)) 2445 - return -EIO; 2446 - 2447 - ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n", 2448 - __func__, chan->center_freq, chan->hw_value); 2449 - vif->next_chan = chan->center_freq; 2450 - 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 2448 static bool ath6kl_is_p2p_ie(const u8 *pos) ··· 2515 2521 info->assocresp_ies_len); 2516 2522 if (res) 2517 2523 return res; 2524 + 2525 + return 0; 2526 + } 2527 + 2528 + static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev, 2529 + struct ieee80211_channel *chan, 2530 + enum nl80211_channel_type channel_type) 2531 + { 2532 + struct ath6kl_vif *vif; 2533 + 2534 + /* 2535 + * 'dev' could be NULL if a channel change is required for the hardware 2536 + * device itself, instead of a particular VIF. 2537 + * 2538 + * FIXME: To be handled properly when monitor mode is supported. 2539 + */ 2540 + if (!dev) 2541 + return -EBUSY; 2542 + 2543 + vif = netdev_priv(dev); 2544 + 2545 + if (!ath6kl_cfg80211_ready(vif)) 2546 + return -EIO; 2547 + 2548 + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n", 2549 + __func__, chan->center_freq, chan->hw_value); 2550 + vif->next_chan = chan->center_freq; 2551 + vif->next_ch_type = channel_type; 2552 + vif->next_ch_band = chan->band; 2518 2553 2519 2554 return 0; 2520 2555 } ··· 2696 2673 return res; 2697 2674 } 2698 2675 2676 + if (ath6kl_set_htcap(vif, vif->next_ch_band, 2677 + vif->next_ch_type != NL80211_CHAN_NO_HT)) 2678 + return -EIO; 2679 + 2699 2680 res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p); 2700 2681 if (res < 0) 2701 2682 return res; ··· 2733 2706 2734 2707 ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx); 2735 2708 clear_bit(CONNECTED, &vif->flags); 2709 + 2710 + /* Restore ht setting in firmware */ 2711 + if (ath6kl_set_htcap(vif, IEEE80211_BAND_2GHZ, true)) 2712 + return -EIO; 2713 + 2714 + if (ath6kl_set_htcap(vif, IEEE80211_BAND_5GHZ, true)) 2715 + return -EIO; 2736 2716 2737 2717 return 0; 2738 2718 } ··· 3286 3252 vif->next_mode = nw_type; 3287 3253 vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; 3288 3254 vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; 3255 + vif->htcap.ht_enable = true; 3289 3256 3290 3257 memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); 3291 3258 if (fw_vif_idx != 0)
+1
drivers/net/wireless/ath/ath6kl/common.h
··· 78 78 79 79 struct htc_endpoint_credit_dist; 80 80 struct ath6kl; 81 + struct ath6kl_htcap; 81 82 enum htc_credit_dist_reason; 82 83 struct ath6kl_htc_credit_info; 83 84
+9
drivers/net/wireless/ath/ath6kl/core.h
··· 474 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 484 * Driver's maximum limit, note that some firmwares support only one vif 479 485 * and the runtime (current) limit must be checked from ar->vif_max. ··· 528 522 struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; 529 523 struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1]; 530 524 struct aggr_info *aggr_cntxt; 525 + struct ath6kl_htcap htcap; 531 526 532 527 struct timer_list disconnect_timer; 533 528 struct timer_list sched_scan_timer; ··· 541 534 u32 send_action_id; 542 535 bool probe_req_report; 543 536 u16 next_chan; 537 + enum nl80211_channel_type next_ch_type; 538 + enum ieee80211_band next_ch_band; 544 539 u16 assoc_bss_beacon_int; 545 540 u16 listen_intvl_t; 546 541 u16 bmiss_time_t;
+37
drivers/net/wireless/ath/ath6kl/wmi.c
··· 2882 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 2922 int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len) 2886 2923 { 2887 2924 struct sk_buff *skb;
+13
drivers/net/wireless/ath/ath6kl/wmi.h
··· 1271 1271 u8 mcast_mac[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE]; 1272 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 1284 /* Command Replies */ 1275 1285 1276 1286 /* WMI_GET_CHANNEL_LIST_CMDID reply */ ··· 2483 2473 int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, u8 if_idx, enum wmi_txop_cfg cfg); 2484 2474 int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx, 2485 2475 u8 keep_alive_intvl); 2476 + int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx, 2477 + enum ieee80211_band band, 2478 + struct ath6kl_htcap *htcap); 2486 2479 int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len); 2487 2480 2488 2481 s32 ath6kl_wmi_get_rate(s8 rate_index);