Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f9b6777 authored by Arik Nemtsov's avatar Arik Nemtsov Committed by Luciano Coelho
Browse files

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: default avatarArik Nemtsov <arik@wizery.com>
Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
parent 7c482c10
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -109,3 +109,34 @@ out:
	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 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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 */
+1 −0
Original line number Diff line number Diff line
@@ -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:
+8 −0
Original line number Diff line number Diff line
@@ -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
Loading