wlcore: use new set bandwidth command to adjusting channel BW
We support changing the channel BW when we started the STA role on a 40Mhz bandwidth. Otherwise a reconnection is required. Save the started channel width and use it when channel width updates arrive. Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
This commit is contained in:
parent
7c482c1040
commit
5f9b67770b
8 changed files with 108 additions and 0 deletions
|
@ -109,3 +109,34 @@ int wl18xx_acx_clear_statistics(struct wl1271 *wl)
|
|||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl18xx_acx_peer_ht_operation_mode(struct wl1271 *wl, u8 hlid, bool wide)
|
||||
{
|
||||
struct wlcore_peer_ht_operation_mode *acx;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx peer ht operation mode hlid %d bw %d",
|
||||
hlid, wide);
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
acx->hlid = hlid;
|
||||
acx->bandwidth = wide ? WLCORE_BANDWIDTH_40MHZ : WLCORE_BANDWIDTH_20MHZ;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_PEER_HT_OPERATION_MODE_CFG, acx,
|
||||
sizeof(*acx));
|
||||
|
||||
if (ret < 0) {
|
||||
wl1271_warning("acx peer ht operation mode failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
|
|
@ -284,10 +284,24 @@ struct wl18xx_acx_clear_statistics {
|
|||
struct acx_header header;
|
||||
};
|
||||
|
||||
enum wlcore_bandwidth {
|
||||
WLCORE_BANDWIDTH_20MHZ,
|
||||
WLCORE_BANDWIDTH_40MHZ,
|
||||
};
|
||||
|
||||
struct wlcore_peer_ht_operation_mode {
|
||||
struct acx_header header;
|
||||
|
||||
u8 hlid;
|
||||
u8 bandwidth; /* enum wlcore_bandwidth */
|
||||
u8 padding[2];
|
||||
};
|
||||
|
||||
int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap,
|
||||
u32 sdio_blk_size, u32 extra_mem_blks,
|
||||
u32 len_field_size);
|
||||
int wl18xx_acx_set_checksum_state(struct wl1271 *wl);
|
||||
int wl18xx_acx_clear_statistics(struct wl1271 *wl);
|
||||
int wl18xx_acx_peer_ht_operation_mode(struct wl1271 *wl, u8 hlid, bool wide);
|
||||
|
||||
#endif /* __WL18XX_ACX_H__ */
|
||||
|
|
|
@ -1319,6 +1319,43 @@ static u32 wl18xx_pre_pkt_send(struct wl1271 *wl,
|
|||
return buf_offset;
|
||||
}
|
||||
|
||||
static void wl18xx_sta_rc_update(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif,
|
||||
struct ieee80211_sta *sta,
|
||||
u32 changed)
|
||||
{
|
||||
bool wide = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211, "mac80211 sta_rc_update wide %d", wide);
|
||||
|
||||
if (!(changed & IEEE80211_RC_BW_CHANGED))
|
||||
return;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
/* sanity */
|
||||
if (WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS))
|
||||
goto out;
|
||||
|
||||
/* ignore the change before association */
|
||||
if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* If we started out as wide, we can change the operation mode. If we
|
||||
* thought this was a 20mhz AP, we have to reconnect
|
||||
*/
|
||||
if (wlvif->sta.role_chan_type == NL80211_CHAN_HT40MINUS ||
|
||||
wlvif->sta.role_chan_type == NL80211_CHAN_HT40PLUS)
|
||||
wl18xx_acx_peer_ht_operation_mode(wl, wlvif->sta.hlid, wide);
|
||||
else
|
||||
ieee80211_connection_loss(wl12xx_wlvif_to_vif(wlvif));
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
||||
|
||||
static int wl18xx_setup(struct wl1271 *wl);
|
||||
|
||||
static struct wlcore_ops wl18xx_ops = {
|
||||
|
@ -1354,6 +1391,7 @@ static struct wlcore_ops wl18xx_ops = {
|
|||
.set_key = wl18xx_set_key,
|
||||
.channel_switch = wl18xx_cmd_channel_switch,
|
||||
.pre_pkt_send = wl18xx_pre_pkt_send,
|
||||
.sta_rc_update = wl18xx_sta_rc_update,
|
||||
};
|
||||
|
||||
/* HT cap appropriate for wide channels in 2Ghz */
|
||||
|
|
|
@ -480,6 +480,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
|||
goto err_hlid;
|
||||
}
|
||||
|
||||
wlvif->sta.role_chan_type = wlvif->channel_type;
|
||||
goto out_free;
|
||||
|
||||
err_hlid:
|
||||
|
|
|
@ -201,4 +201,12 @@ wlcore_hw_pre_pkt_send(struct wl1271 *wl, u32 buf_offset, u32 last_len)
|
|||
return buf_offset;
|
||||
}
|
||||
|
||||
static inline void
|
||||
wlcore_hw_sta_rc_update(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
struct ieee80211_sta *sta, u32 changed)
|
||||
{
|
||||
if (wl->ops->sta_rc_update)
|
||||
wl->ops->sta_rc_update(wl, wlvif, sta, changed);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4948,6 +4948,17 @@ static int wlcore_op_cancel_remain_on_channel(struct ieee80211_hw *hw)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void wlcore_op_sta_rc_update(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
u32 changed)
|
||||
{
|
||||
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
|
||||
struct wl1271 *wl = hw->priv;
|
||||
|
||||
wlcore_hw_sta_rc_update(wl, wlvif, sta, changed);
|
||||
}
|
||||
|
||||
static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
|
@ -5146,6 +5157,7 @@ static const struct ieee80211_ops wl1271_ops = {
|
|||
.change_chanctx = wlcore_op_change_chanctx,
|
||||
.assign_vif_chanctx = wlcore_op_assign_vif_chanctx,
|
||||
.unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx,
|
||||
.sta_rc_update = wlcore_op_sta_rc_update,
|
||||
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
|
||||
};
|
||||
|
||||
|
|
|
@ -101,6 +101,8 @@ struct wlcore_ops {
|
|||
struct wl12xx_vif *wlvif,
|
||||
struct ieee80211_channel_switch *ch_switch);
|
||||
u32 (*pre_pkt_send)(struct wl1271 *wl, u32 buf_offset, u32 last_len);
|
||||
void (*sta_rc_update)(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
struct ieee80211_sta *sta, u32 changed);
|
||||
};
|
||||
|
||||
enum wlcore_partitions {
|
||||
|
|
|
@ -341,6 +341,8 @@ struct wl12xx_vif {
|
|||
u8 klv_template_id;
|
||||
|
||||
bool qos;
|
||||
/* channel type we started the STA role with */
|
||||
enum nl80211_channel_type role_chan_type;
|
||||
} sta;
|
||||
struct {
|
||||
u8 global_hlid;
|
||||
|
|
Loading…
Add table
Reference in a new issue