Skip to content

Commit 0d9c2be

Browse files
committed
wifi: mac80211: fix monitor channel with chanctx emulation
After the channel context emulation, there were reports that changing the monitor channel no longer works. This is because those drivers don't have WANT_MONITOR_VIF, so the setting the channel always exits out quickly. Fix this by always allocating the virtual monitor sdata, and simply not telling the driver about it unless it wanted to. This way, we have an interface/sdata to bind the chanctx to, and the emulation can work correctly. Cc: stable@vger.kernel.org Fixes: 0a44dfc ("wifi: mac80211: simplify non-chanctx drivers") Reported-and-tested-by: Savyasaachi Vanga <savyasaachiv@gmail.com> Closes: https://lore.kernel.org/r/chwoymvpzwtbmzryrlitpwmta5j6mtndocxsyqvdyikqu63lon@gfds653hkknl Link: https://msgid.link/20240612122351.b12d4a109dde.I1831a44417faaab92bea1071209abbe4efbe3fba@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
1 parent 2663d04 commit 0d9c2be

File tree

3 files changed

+27
-13
lines changed

3 files changed

+27
-13
lines changed

net/mac80211/driver-ops.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,18 @@ int drv_assign_vif_chanctx(struct ieee80211_local *local,
311311
might_sleep();
312312
lockdep_assert_wiphy(local->hw.wiphy);
313313

314+
/*
315+
* We should perhaps push emulate chanctx down and only
316+
* make it call ->config() when the chanctx is actually
317+
* assigned here (and unassigned below), but that's yet
318+
* another change to all drivers to add assign/unassign
319+
* emulation callbacks. Maybe later.
320+
*/
321+
if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
322+
local->emulate_chanctx &&
323+
!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
324+
return 0;
325+
314326
if (!check_sdata_in_driver(sdata))
315327
return -EIO;
316328

@@ -338,6 +350,11 @@ void drv_unassign_vif_chanctx(struct ieee80211_local *local,
338350
might_sleep();
339351
lockdep_assert_wiphy(local->hw.wiphy);
340352

353+
if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
354+
local->emulate_chanctx &&
355+
!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
356+
return;
357+
341358
if (!check_sdata_in_driver(sdata))
342359
return;
343360

net/mac80211/iface.c

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,9 +1122,6 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
11221122
struct ieee80211_sub_if_data *sdata;
11231123
int ret;
11241124

1125-
if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
1126-
return 0;
1127-
11281125
ASSERT_RTNL();
11291126
lockdep_assert_wiphy(local->hw.wiphy);
11301127

@@ -1146,11 +1143,13 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
11461143

11471144
ieee80211_set_default_queues(sdata);
11481145

1149-
ret = drv_add_interface(local, sdata);
1150-
if (WARN_ON(ret)) {
1151-
/* ok .. stupid driver, it asked for this! */
1152-
kfree(sdata);
1153-
return ret;
1146+
if (ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) {
1147+
ret = drv_add_interface(local, sdata);
1148+
if (WARN_ON(ret)) {
1149+
/* ok .. stupid driver, it asked for this! */
1150+
kfree(sdata);
1151+
return ret;
1152+
}
11541153
}
11551154

11561155
set_bit(SDATA_STATE_RUNNING, &sdata->state);
@@ -1188,9 +1187,6 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
11881187
{
11891188
struct ieee80211_sub_if_data *sdata;
11901189

1191-
if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
1192-
return;
1193-
11941190
ASSERT_RTNL();
11951191
lockdep_assert_wiphy(local->hw.wiphy);
11961192

@@ -1210,7 +1206,8 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
12101206

12111207
ieee80211_link_release_channel(&sdata->deflink);
12121208

1213-
drv_remove_interface(local, sdata);
1209+
if (ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
1210+
drv_remove_interface(local, sdata);
12141211

12151212
kfree(sdata);
12161213
}

net/mac80211/util.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1843,7 +1843,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
18431843

18441844
/* add interfaces */
18451845
sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata);
1846-
if (sdata) {
1846+
if (sdata && ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) {
18471847
/* in HW restart it exists already */
18481848
WARN_ON(local->resuming);
18491849
res = drv_add_interface(local, sdata);

0 commit comments

Comments
 (0)