forked from Minki/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>
This commit is contained in:
parent
bed56e313a
commit
df90b36940
@ -2424,31 +2424,25 @@ void ath6kl_check_wow_status(struct ath6kl *ar)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev,
|
static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band,
|
||||||
struct ieee80211_channel *chan,
|
bool ht_enable)
|
||||||
enum nl80211_channel_type channel_type)
|
|
||||||
{
|
{
|
||||||
struct ath6kl_vif *vif;
|
struct ath6kl_htcap *htcap = &vif->htcap;
|
||||||
|
|
||||||
/*
|
if (htcap->ht_enable == ht_enable)
|
||||||
* 'dev' could be NULL if a channel change is required for the hardware
|
return 0;
|
||||||
* device itself, instead of a particular VIF.
|
|
||||||
*
|
|
||||||
* FIXME: To be handled properly when monitor mode is supported.
|
|
||||||
*/
|
|
||||||
if (!dev)
|
|
||||||
return -EBUSY;
|
|
||||||
|
|
||||||
vif = netdev_priv(dev);
|
if (ht_enable) {
|
||||||
|
/* Set default ht capabilities */
|
||||||
|
htcap->ht_enable = true;
|
||||||
|
htcap->cap_info = (band == IEEE80211_BAND_2GHZ) ?
|
||||||
|
ath6kl_g_htcap : ath6kl_a_htcap;
|
||||||
|
htcap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K;
|
||||||
|
} else /* Disable ht */
|
||||||
|
memset(htcap, 0, sizeof(*htcap));
|
||||||
|
|
||||||
if (!ath6kl_cfg80211_ready(vif))
|
return ath6kl_wmi_set_htcap_cmd(vif->ar->wmi, vif->fw_vif_idx,
|
||||||
return -EIO;
|
band, htcap);
|
||||||
|
|
||||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n",
|
|
||||||
__func__, chan->center_freq, chan->hw_value);
|
|
||||||
vif->next_chan = chan->center_freq;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ath6kl_is_p2p_ie(const u8 *pos)
|
static bool ath6kl_is_p2p_ie(const u8 *pos)
|
||||||
@ -2525,6 +2519,35 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev,
|
||||||
|
struct ieee80211_channel *chan,
|
||||||
|
enum nl80211_channel_type channel_type)
|
||||||
|
{
|
||||||
|
struct ath6kl_vif *vif;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 'dev' could be NULL if a channel change is required for the hardware
|
||||||
|
* device itself, instead of a particular VIF.
|
||||||
|
*
|
||||||
|
* FIXME: To be handled properly when monitor mode is supported.
|
||||||
|
*/
|
||||||
|
if (!dev)
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
vif = netdev_priv(dev);
|
||||||
|
|
||||||
|
if (!ath6kl_cfg80211_ready(vif))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n",
|
||||||
|
__func__, chan->center_freq, chan->hw_value);
|
||||||
|
vif->next_chan = chan->center_freq;
|
||||||
|
vif->next_ch_type = channel_type;
|
||||||
|
vif->next_ch_band = chan->band;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||||
struct cfg80211_ap_settings *info)
|
struct cfg80211_ap_settings *info)
|
||||||
{
|
{
|
||||||
@ -2673,6 +2696,10 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ath6kl_set_htcap(vif, vif->next_ch_band,
|
||||||
|
vif->next_ch_type != NL80211_CHAN_NO_HT))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p);
|
res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return res;
|
return res;
|
||||||
@ -2707,6 +2734,13 @@ static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
|||||||
ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
|
ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
|
||||||
clear_bit(CONNECTED, &vif->flags);
|
clear_bit(CONNECTED, &vif->flags);
|
||||||
|
|
||||||
|
/* Restore ht setting in firmware */
|
||||||
|
if (ath6kl_set_htcap(vif, IEEE80211_BAND_2GHZ, true))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
if (ath6kl_set_htcap(vif, IEEE80211_BAND_5GHZ, true))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3252,6 +3286,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
|
|||||||
vif->next_mode = nw_type;
|
vif->next_mode = nw_type;
|
||||||
vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
|
vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
|
||||||
vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;
|
vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;
|
||||||
|
vif->htcap.ht_enable = true;
|
||||||
|
|
||||||
memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
|
memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
|
||||||
if (fw_vif_idx != 0)
|
if (fw_vif_idx != 0)
|
||||||
|
@ -78,6 +78,7 @@ enum crypto_type {
|
|||||||
|
|
||||||
struct htc_endpoint_credit_dist;
|
struct htc_endpoint_credit_dist;
|
||||||
struct ath6kl;
|
struct ath6kl;
|
||||||
|
struct ath6kl_htcap;
|
||||||
enum htc_credit_dist_reason;
|
enum htc_credit_dist_reason;
|
||||||
struct ath6kl_htc_credit_info;
|
struct ath6kl_htc_credit_info;
|
||||||
|
|
||||||
|
@ -474,6 +474,12 @@ struct ath6kl_mc_filter {
|
|||||||
char hw_addr[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE];
|
char hw_addr[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ath6kl_htcap {
|
||||||
|
bool ht_enable;
|
||||||
|
u8 ampdu_factor;
|
||||||
|
unsigned short cap_info;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Driver's maximum limit, note that some firmwares support only one vif
|
* Driver's maximum limit, note that some firmwares support only one vif
|
||||||
* and the runtime (current) limit must be checked from ar->vif_max.
|
* and the runtime (current) limit must be checked from ar->vif_max.
|
||||||
@ -522,6 +528,7 @@ struct ath6kl_vif {
|
|||||||
struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1];
|
struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1];
|
||||||
struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1];
|
struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1];
|
||||||
struct aggr_info *aggr_cntxt;
|
struct aggr_info *aggr_cntxt;
|
||||||
|
struct ath6kl_htcap htcap;
|
||||||
|
|
||||||
struct timer_list disconnect_timer;
|
struct timer_list disconnect_timer;
|
||||||
struct timer_list sched_scan_timer;
|
struct timer_list sched_scan_timer;
|
||||||
@ -534,6 +541,8 @@ struct ath6kl_vif {
|
|||||||
u32 send_action_id;
|
u32 send_action_id;
|
||||||
bool probe_req_report;
|
bool probe_req_report;
|
||||||
u16 next_chan;
|
u16 next_chan;
|
||||||
|
enum nl80211_channel_type next_ch_type;
|
||||||
|
enum ieee80211_band next_ch_band;
|
||||||
u16 assoc_bss_beacon_int;
|
u16 assoc_bss_beacon_int;
|
||||||
u16 listen_intvl_t;
|
u16 listen_intvl_t;
|
||||||
u16 bmiss_time_t;
|
u16 bmiss_time_t;
|
||||||
|
@ -2882,6 +2882,43 @@ int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx,
|
||||||
|
enum ieee80211_band band,
|
||||||
|
struct ath6kl_htcap *htcap)
|
||||||
|
{
|
||||||
|
struct sk_buff *skb;
|
||||||
|
struct wmi_set_htcap_cmd *cmd;
|
||||||
|
|
||||||
|
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
|
||||||
|
if (!skb)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
cmd = (struct wmi_set_htcap_cmd *) skb->data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: Band in firmware matches enum ieee80211_band, it is unlikely
|
||||||
|
* this will be changed in firmware. If at all there is any change in
|
||||||
|
* band value, the host needs to be fixed.
|
||||||
|
*/
|
||||||
|
cmd->band = band;
|
||||||
|
cmd->ht_enable = !!htcap->ht_enable;
|
||||||
|
cmd->ht20_sgi = !!(htcap->cap_info & IEEE80211_HT_CAP_SGI_20);
|
||||||
|
cmd->ht40_supported =
|
||||||
|
!!(htcap->cap_info & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
|
||||||
|
cmd->ht40_sgi = !!(htcap->cap_info & IEEE80211_HT_CAP_SGI_40);
|
||||||
|
cmd->intolerant_40mhz =
|
||||||
|
!!(htcap->cap_info & IEEE80211_HT_CAP_40MHZ_INTOLERANT);
|
||||||
|
cmd->max_ampdu_len_exp = htcap->ampdu_factor;
|
||||||
|
|
||||||
|
ath6kl_dbg(ATH6KL_DBG_WMI,
|
||||||
|
"Set htcap: band:%d ht_enable:%d 40mhz:%d sgi_20mhz:%d sgi_40mhz:%d 40mhz_intolerant:%d ampdu_len_exp:%d\n",
|
||||||
|
cmd->band, cmd->ht_enable, cmd->ht40_supported,
|
||||||
|
cmd->ht20_sgi, cmd->ht40_sgi, cmd->intolerant_40mhz,
|
||||||
|
cmd->max_ampdu_len_exp);
|
||||||
|
return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_HT_CAP_CMDID,
|
||||||
|
NO_SYNC_WMIFLAG);
|
||||||
|
}
|
||||||
|
|
||||||
int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len)
|
int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
@ -1271,6 +1271,16 @@ struct wmi_mcast_filter_add_del_cmd {
|
|||||||
u8 mcast_mac[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE];
|
u8 mcast_mac[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
struct wmi_set_htcap_cmd {
|
||||||
|
u8 band;
|
||||||
|
u8 ht_enable;
|
||||||
|
u8 ht40_supported;
|
||||||
|
u8 ht20_sgi;
|
||||||
|
u8 ht40_sgi;
|
||||||
|
u8 intolerant_40mhz;
|
||||||
|
u8 max_ampdu_len_exp;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
/* Command Replies */
|
/* Command Replies */
|
||||||
|
|
||||||
/* WMI_GET_CHANNEL_LIST_CMDID reply */
|
/* WMI_GET_CHANNEL_LIST_CMDID reply */
|
||||||
@ -2473,6 +2483,9 @@ int ath6kl_wmi_get_roam_tbl_cmd(struct wmi *wmi);
|
|||||||
int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, u8 if_idx, enum wmi_txop_cfg cfg);
|
int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, u8 if_idx, enum wmi_txop_cfg cfg);
|
||||||
int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx,
|
int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx,
|
||||||
u8 keep_alive_intvl);
|
u8 keep_alive_intvl);
|
||||||
|
int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx,
|
||||||
|
enum ieee80211_band band,
|
||||||
|
struct ath6kl_htcap *htcap);
|
||||||
int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len);
|
int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len);
|
||||||
|
|
||||||
s32 ath6kl_wmi_get_rate(s8 rate_index);
|
s32 ath6kl_wmi_get_rate(s8 rate_index);
|
||||||
|
Loading…
Reference in New Issue
Block a user