Skip to content

Commit e0b3591

Browse files
committed
wifi: mac80211: fix a queue stall in certain cases of CSA
JIRA: https://issues.redhat.com/browse/RHEL-73817 commit 11ac0d7 Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Date: Tue Nov 19 17:35:40 2024 +0200 wifi: mac80211: fix a queue stall in certain cases of CSA If we got an unprotected action frame with CSA and then we heard the beacon with the CSA IE, we'll block the queues with the CSA reason twice. Since this reason is refcounted, we won't wake up the queues since we wake them up only once and the ref count will never reach 0. This led to blocked queues that prevented any activity (even disconnection wouldn't reset the queue state and the only way to recover would be to reload the kernel module. Fix this by not refcounting the CSA reason. It becomes now pointless to maintain the csa_blocked_queues state. Remove it. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Fixes: 414e090 ("wifi: mac80211: restrict public action ECSA frame handling") Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219447 Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Link: https://patch.msgid.link/20241119173108.5ea90828c2cc.I4f89e58572fb71ae48e47a81e74595cac410fbac@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
1 parent 10c810c commit e0b3591

File tree

7 files changed

+50
-45
lines changed

7 files changed

+50
-45
lines changed

drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1967,7 +1967,7 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
19671967
if (csa_err_mask & (CS_ERR_COUNT_ERROR |
19681968
CS_ERR_LONG_DELAY_AFTER_CS |
19691969
CS_ERR_TX_BLOCK_TIMER_EXPIRED))
1970-
ieee80211_channel_switch_disconnect(vif, true);
1970+
ieee80211_channel_switch_disconnect(vif);
19711971
rcu_read_unlock();
19721972
}
19731973

include/net/mac80211.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6770,14 +6770,12 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success,
67706770
/**
67716771
* ieee80211_channel_switch_disconnect - disconnect due to channel switch error
67726772
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
6773-
* @block_tx: if %true, do not send deauth frame.
67746773
*
67756774
* Instruct mac80211 to disconnect due to a channel switch error. The channel
67766775
* switch can request to block the tx and so, we need to make sure we do not send
67776776
* a deauth frame in this case.
67786777
*/
6779-
void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif,
6780-
bool block_tx);
6778+
void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif);
67816779

67826780
/**
67836781
* ieee80211_request_smps - request SM PS transition

net/mac80211/cfg.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3674,13 +3674,12 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif, unsigned int link_id)
36743674
}
36753675
EXPORT_SYMBOL(ieee80211_csa_finish);
36763676

3677-
void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif, bool block_tx)
3677+
void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif)
36783678
{
36793679
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
36803680
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
36813681
struct ieee80211_local *local = sdata->local;
36823682

3683-
sdata->csa_blocked_queues = block_tx;
36843683
sdata_info(sdata, "channel switch failed, disconnecting\n");
36853684
wiphy_work_queue(local->hw.wiphy, &ifmgd->csa_connection_drop_work);
36863685
}

net/mac80211/ieee80211_i.h

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,8 +1106,6 @@ struct ieee80211_sub_if_data {
11061106

11071107
unsigned long state;
11081108

1109-
bool csa_blocked_queues;
1110-
11111109
char name[IFNAMSIZ];
11121110

11131111
struct ieee80211_fragment_cache frags;
@@ -2411,17 +2409,13 @@ void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
24112409
struct ieee80211_sub_if_data *sdata);
24122410
void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
24132411
struct ieee80211_hdr *hdr, bool ack, u16 tx_time);
2414-
2412+
unsigned int
2413+
ieee80211_get_vif_queues(struct ieee80211_local *local,
2414+
struct ieee80211_sub_if_data *sdata);
24152415
void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
24162416
unsigned long queues,
24172417
enum queue_stop_reason reason,
24182418
bool refcounted);
2419-
void ieee80211_stop_vif_queues(struct ieee80211_local *local,
2420-
struct ieee80211_sub_if_data *sdata,
2421-
enum queue_stop_reason reason);
2422-
void ieee80211_wake_vif_queues(struct ieee80211_local *local,
2423-
struct ieee80211_sub_if_data *sdata,
2424-
enum queue_stop_reason reason);
24252419
void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
24262420
unsigned long queues,
24272421
enum queue_stop_reason reason,
@@ -2432,6 +2426,43 @@ void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
24322426
void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
24332427
enum queue_stop_reason reason,
24342428
bool refcounted);
2429+
static inline void
2430+
ieee80211_stop_vif_queues(struct ieee80211_local *local,
2431+
struct ieee80211_sub_if_data *sdata,
2432+
enum queue_stop_reason reason)
2433+
{
2434+
ieee80211_stop_queues_by_reason(&local->hw,
2435+
ieee80211_get_vif_queues(local, sdata),
2436+
reason, true);
2437+
}
2438+
2439+
static inline void
2440+
ieee80211_wake_vif_queues(struct ieee80211_local *local,
2441+
struct ieee80211_sub_if_data *sdata,
2442+
enum queue_stop_reason reason)
2443+
{
2444+
ieee80211_wake_queues_by_reason(&local->hw,
2445+
ieee80211_get_vif_queues(local, sdata),
2446+
reason, true);
2447+
}
2448+
static inline void
2449+
ieee80211_stop_vif_queues_norefcount(struct ieee80211_local *local,
2450+
struct ieee80211_sub_if_data *sdata,
2451+
enum queue_stop_reason reason)
2452+
{
2453+
ieee80211_stop_queues_by_reason(&local->hw,
2454+
ieee80211_get_vif_queues(local, sdata),
2455+
reason, false);
2456+
}
2457+
static inline void
2458+
ieee80211_wake_vif_queues_norefcount(struct ieee80211_local *local,
2459+
struct ieee80211_sub_if_data *sdata,
2460+
enum queue_stop_reason reason)
2461+
{
2462+
ieee80211_wake_queues_by_reason(&local->hw,
2463+
ieee80211_get_vif_queues(local, sdata),
2464+
reason, false);
2465+
}
24352466
void ieee80211_add_pending_skb(struct ieee80211_local *local,
24362467
struct sk_buff *skb);
24372468
void ieee80211_add_pending_skbs(struct ieee80211_local *local,

net/mac80211/iface.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2364,18 +2364,14 @@ void ieee80211_vif_block_queues_csa(struct ieee80211_sub_if_data *sdata)
23642364
if (ieee80211_hw_check(&local->hw, HANDLES_QUIET_CSA))
23652365
return;
23662366

2367-
ieee80211_stop_vif_queues(local, sdata,
2368-
IEEE80211_QUEUE_STOP_REASON_CSA);
2369-
sdata->csa_blocked_queues = true;
2367+
ieee80211_stop_vif_queues_norefcount(local, sdata,
2368+
IEEE80211_QUEUE_STOP_REASON_CSA);
23702369
}
23712370

23722371
void ieee80211_vif_unblock_queues_csa(struct ieee80211_sub_if_data *sdata)
23732372
{
23742373
struct ieee80211_local *local = sdata->local;
23752374

2376-
if (sdata->csa_blocked_queues) {
2377-
ieee80211_wake_vif_queues(local, sdata,
2378-
IEEE80211_QUEUE_STOP_REASON_CSA);
2379-
sdata->csa_blocked_queues = false;
2380-
}
2375+
ieee80211_wake_vif_queues_norefcount(local, sdata,
2376+
IEEE80211_QUEUE_STOP_REASON_CSA);
23812377
}

net/mac80211/mlme.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2636,8 +2636,6 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
26362636
*/
26372637
link->conf->csa_active = true;
26382638
link->u.mgd.csa.blocked_tx = csa_ie.mode;
2639-
sdata->csa_blocked_queues =
2640-
csa_ie.mode && !ieee80211_hw_check(&local->hw, HANDLES_QUIET_CSA);
26412639

26422640
wiphy_work_queue(sdata->local->hw.wiphy,
26432641
&ifmgd->csa_connection_drop_work);

net/mac80211/util.c

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw)
657657
}
658658
EXPORT_SYMBOL(ieee80211_wake_queues);
659659

660-
static unsigned int
660+
unsigned int
661661
ieee80211_get_vif_queues(struct ieee80211_local *local,
662662
struct ieee80211_sub_if_data *sdata)
663663
{
@@ -669,7 +669,8 @@ ieee80211_get_vif_queues(struct ieee80211_local *local,
669669
queues = 0;
670670

671671
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
672-
queues |= BIT(sdata->vif.hw_queue[ac]);
672+
if (sdata->vif.hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
673+
queues |= BIT(sdata->vif.hw_queue[ac]);
673674
if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE)
674675
queues |= BIT(sdata->vif.cab_queue);
675676
} else {
@@ -724,24 +725,6 @@ void ieee80211_flush_queues(struct ieee80211_local *local,
724725
__ieee80211_flush_queues(local, sdata, 0, drop);
725726
}
726727

727-
void ieee80211_stop_vif_queues(struct ieee80211_local *local,
728-
struct ieee80211_sub_if_data *sdata,
729-
enum queue_stop_reason reason)
730-
{
731-
ieee80211_stop_queues_by_reason(&local->hw,
732-
ieee80211_get_vif_queues(local, sdata),
733-
reason, true);
734-
}
735-
736-
void ieee80211_wake_vif_queues(struct ieee80211_local *local,
737-
struct ieee80211_sub_if_data *sdata,
738-
enum queue_stop_reason reason)
739-
{
740-
ieee80211_wake_queues_by_reason(&local->hw,
741-
ieee80211_get_vif_queues(local, sdata),
742-
reason, true);
743-
}
744-
745728
static void __iterate_interfaces(struct ieee80211_local *local,
746729
u32 iter_flags,
747730
void (*iterator)(void *data, u8 *mac,

0 commit comments

Comments
 (0)