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

Commit 09f2645a authored by Weilun Du's avatar Weilun Du Committed by Alistair Delva
Browse files

BACKPORT: mac80211_hwsim: add concurrent channels scanning support over virtio



This fixed the crash when setting channels to 2 or more when
communicating over virtio.
Bug: 182576217

Signed-off-by: default avatarWeilun Du <wdu@google.com>
Link: https://lore.kernel.org/r/20210506180530.3418576-1-wdu@google.com


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>

Change-Id: Id319bd63b757237fa8601b823001024bf067c36c
Signed-off-by: default avatarWeilun Du <wdu@google.com>
Bug: 265875490
(cherry picked from commit 2ed290642538fc7394c3c835b1fdc2870e38da26)
parent d2c7910f
Loading
Loading
Loading
Loading
+41 −12
Original line number Diff line number Diff line
@@ -521,6 +521,7 @@ struct mac80211_hwsim_data {
	struct ieee80211_iface_combination if_combination;

	struct mac_address addresses[2];
	struct ieee80211_chanctx_conf *chanctx;
	int channels, idx;
	bool use_chanctx;
	bool destroy_on_close;
@@ -1111,7 +1112,8 @@ static inline u16 trans_tx_rate_flags_ieee2hwsim(struct ieee80211_tx_rate *rate)

static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
				       struct sk_buff *my_skb,
				       int dst_portid)
				       int dst_portid,
				       struct ieee80211_channel *channel)
{
	struct sk_buff *skb;
	struct mac80211_hwsim_data *data = hw->priv;
@@ -1505,7 +1507,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
	_portid = READ_ONCE(data->wmediumd);

	if (_portid || hwsim_virtio_enabled)
		return mac80211_hwsim_tx_frame_nl(hw, skb, _portid);
		return mac80211_hwsim_tx_frame_nl(hw, skb, _portid, channel);

	/* NO wmediumd detected, perfect medium simulation */
	data->tx_pkts++;
@@ -1611,7 +1613,7 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
	mac80211_hwsim_monitor_rx(hw, skb, chan);

	if (_pid || hwsim_virtio_enabled)
		return mac80211_hwsim_tx_frame_nl(hw, skb, _pid);
		return mac80211_hwsim_tx_frame_nl(hw, skb, _pid, chan);

	mac80211_hwsim_tx_frame_no_nl(hw, skb, chan);
	dev_kfree_skb(skb);
@@ -2332,6 +2334,11 @@ static int mac80211_hwsim_croc(struct ieee80211_hw *hw)
static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw,
				      struct ieee80211_chanctx_conf *ctx)
{
	struct mac80211_hwsim_data *hwsim = hw->priv;

	mutex_lock(&hwsim->mutex);
	hwsim->chanctx = ctx;
	mutex_unlock(&hwsim->mutex);
	hwsim_set_chanctx_magic(ctx);
	wiphy_dbg(hw->wiphy,
		  "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
@@ -2343,7 +2350,12 @@ static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw,
static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw,
					  struct ieee80211_chanctx_conf *ctx)
{
	wiphy_dbg(hw->wiphy,
	struct mac80211_hwsim_data *hwsim = hw->priv;

	mutex_lock(&hwsim->mutex);
	hwsim->chanctx = NULL;
	mutex_unlock(&hwsim->mutex);
	wiphy_debug(hw->wiphy,
		    "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
		    ctx->def.chan->center_freq, ctx->def.width,
		    ctx->def.center_freq1, ctx->def.center_freq2);
@@ -2355,6 +2367,11 @@ static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw,
					  struct ieee80211_chanctx_conf *ctx,
					  u32 changed)
{
	struct mac80211_hwsim_data *hwsim = hw->priv;

	mutex_lock(&hwsim->mutex);
	hwsim->chanctx = ctx;
	mutex_unlock(&hwsim->mutex);
	hwsim_check_chanctx_magic(ctx);
	wiphy_dbg(hw->wiphy,
		  "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
@@ -2806,6 +2823,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
		/* For channels > 1 DFS is not allowed */
		data->if_combination.radar_detect_widths = 0;
		data->if_combination.num_different_channels = data->channels;
		data->chanctx = NULL;
	} else if (param->p2p_device) {
		hw->wiphy->iface_combinations = hwsim_if_comb_p2p_dev;
		hw->wiphy->n_iface_combinations =
@@ -3274,6 +3292,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
	int frame_data_len;
	void *frame_data;
	struct sk_buff *skb = NULL;
	struct ieee80211_channel *channel = NULL;

	if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] ||
	    !info->attrs[HWSIM_ATTR_FRAME] ||
@@ -3299,6 +3318,16 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
	data2 = get_hwsim_data_ref_from_addr(dst);
	if (!data2)
		goto out;
	if (data2->use_chanctx) {
		if (data2->tmp_chan)
			channel = data2->tmp_chan;
		else if (data2->chanctx)
			channel = data2->chanctx->def.chan;
	} else {
		channel = data2->channel;
	}
	if (!channel)
		goto out;

	if (!hwsim_virtio_enabled) {
		if (hwsim_net_get_netgroup(genl_info_net(info)) !=
@@ -3311,7 +3340,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,

	/* check if radio is configured properly */

	if (data2->idle || !data2->started)
	if ((data2->idle && !data2->tmp_chan) || !data2->started)
		goto out;

	/* A frame is received from user space */
@@ -3324,17 +3353,17 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
		mutex_lock(&data2->mutex);
		rx_status.freq = nla_get_u32(info->attrs[HWSIM_ATTR_FREQ]);

		if (rx_status.freq != data2->channel->center_freq &&
		    (!data2->tmp_chan ||
		     rx_status.freq != data2->tmp_chan->center_freq)) {
		if (rx_status.freq != channel->center_freq) {
			mutex_unlock(&data2->mutex);
			goto out;
		}
		mutex_unlock(&data2->mutex);
	} else {
		rx_status.freq = data2->channel->center_freq;
		rx_status.freq = channel->center_freq;
	}

	rx_status.band = channel->band;
	rx_status.freq = data2->channel->center_freq;
	rx_status.band = data2->channel->band;
	rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]);
	if (rx_status.rate_idx >= data2->hw->wiphy->bands[rx_status.band]->n_bitrates)