developer | a143290 | 2023-04-01 04:45:58 +0800 | [diff] [blame] | 1 | From: Johannes Berg <johannes.berg@intel.com> |
| 2 | Date: Mon, 13 Mar 2023 11:53:51 +0100 |
| 3 | Subject: [PATCH] wifi: mac80211: add flush_sta method |
| 4 | |
| 5 | Some drivers like iwlwifi might have per-STA queues, so we |
| 6 | may want to flush/drop just those queues rather than all |
| 7 | when removing a station. Add a separate method for that. |
| 8 | |
| 9 | Signed-off-by: Johannes Berg <johannes.berg@intel.com> |
| 10 | Reviewed-by: Greenman, Gregory <gregory.greenman@intel.com> |
| 11 | --- |
| 12 | |
| 13 | --- a/include/net/mac80211.h |
| 14 | +++ b/include/net/mac80211.h |
| 15 | @@ -3688,6 +3688,10 @@ struct ieee80211_prep_tx_info { |
| 16 | * Note that vif can be NULL. |
| 17 | * The callback can sleep. |
| 18 | * |
| 19 | + * @flush_sta: Flush or drop all pending frames from the hardware queue(s) for |
| 20 | + * the given station, as it's about to be removed. |
| 21 | + * The callback can sleep. |
| 22 | + * |
| 23 | * @channel_switch: Drivers that need (or want) to offload the channel |
| 24 | * switch operation for CSAs received from the AP may implement this |
| 25 | * callback. They must then call ieee80211_chswitch_done() to indicate |
| 26 | @@ -4116,6 +4120,8 @@ struct ieee80211_ops { |
| 27 | #endif |
| 28 | void (*flush)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
| 29 | u32 queues, bool drop); |
| 30 | + void (*flush_sta)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
| 31 | + struct ieee80211_sta *sta); |
| 32 | void (*channel_switch)(struct ieee80211_hw *hw, |
| 33 | struct ieee80211_vif *vif, |
| 34 | struct ieee80211_channel_switch *ch_switch); |
| 35 | --- a/net/mac80211/driver-ops.h |
| 36 | +++ b/net/mac80211/driver-ops.h |
| 37 | @@ -639,6 +639,21 @@ static inline void drv_flush(struct ieee |
| 38 | trace_drv_return_void(local); |
| 39 | } |
| 40 | |
| 41 | +static inline void drv_flush_sta(struct ieee80211_local *local, |
| 42 | + struct ieee80211_sub_if_data *sdata, |
| 43 | + struct sta_info *sta) |
| 44 | +{ |
| 45 | + might_sleep(); |
| 46 | + |
| 47 | + if (sdata && !check_sdata_in_driver(sdata)) |
| 48 | + return; |
| 49 | + |
| 50 | + trace_drv_flush_sta(local, sdata, &sta->sta); |
| 51 | + if (local->ops->flush_sta) |
| 52 | + local->ops->flush_sta(&local->hw, &sdata->vif, &sta->sta); |
| 53 | + trace_drv_return_void(local); |
| 54 | +} |
| 55 | + |
| 56 | static inline void drv_channel_switch(struct ieee80211_local *local, |
| 57 | struct ieee80211_sub_if_data *sdata, |
| 58 | struct ieee80211_channel_switch *ch_switch) |
| 59 | --- a/net/mac80211/sta_info.c |
| 60 | +++ b/net/mac80211/sta_info.c |
| 61 | @@ -1075,8 +1075,12 @@ static void __sta_info_destroy_part2(str |
| 62 | * frames sitting on hardware queues might be sent out without |
| 63 | * any encryption at all. |
| 64 | */ |
| 65 | - if (local->ops->set_key) |
| 66 | - ieee80211_flush_queues(local, sta->sdata, false); |
| 67 | + if (local->ops->set_key) { |
| 68 | + if (local->ops->flush_sta) |
| 69 | + drv_flush_sta(local, sta->sdata, sta); |
| 70 | + else |
| 71 | + ieee80211_flush_queues(local, sta->sdata, false); |
| 72 | + } |
| 73 | |
| 74 | /* now keys can no longer be reached */ |
| 75 | ieee80211_free_sta_keys(local, sta); |
| 76 | --- a/net/mac80211/trace.h |
| 77 | +++ b/net/mac80211/trace.h |
| 78 | @@ -1140,6 +1140,13 @@ TRACE_EVENT(drv_flush, |
| 79 | ) |
| 80 | ); |
| 81 | |
| 82 | +DEFINE_EVENT(sta_event, drv_flush_sta, |
| 83 | + TP_PROTO(struct ieee80211_local *local, |
| 84 | + struct ieee80211_sub_if_data *sdata, |
| 85 | + struct ieee80211_sta *sta), |
| 86 | + TP_ARGS(local, sdata, sta) |
| 87 | +); |
| 88 | + |
| 89 | TRACE_EVENT(drv_channel_switch, |
| 90 | TP_PROTO(struct ieee80211_local *local, |
| 91 | struct ieee80211_sub_if_data *sdata, |