Skip to content

Commit

Permalink
wlcore: use new set bandwidth command to adjusting channel BW
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Arik Nemtsov authored and Luciano Coelho committed Nov 28, 2012
1 parent 7c482c1 commit 5f9b677
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 0 deletions.
31 changes: 31 additions & 0 deletions drivers/net/wireless/ti/wl18xx/acx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

}
14 changes: 14 additions & 0 deletions drivers/net/wireless/ti/wl18xx/acx.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__ */
38 changes: 38 additions & 0 deletions drivers/net/wireless/ti/wl18xx/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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 */
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/ti/wlcore/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
8 changes: 8 additions & 0 deletions drivers/net/wireless/ti/wlcore/hw_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
12 changes: 12 additions & 0 deletions drivers/net/wireless/ti/wlcore/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
};

Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/ti/wlcore/wlcore.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/ti/wlcore/wlcore_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 5f9b677

Please sign in to comment.