wifi: mac80211: add flush_sta method
authorJohannes Berg <johannes.berg@intel.com>
Fri, 31 Mar 2023 14:59:17 +0000 (16:59 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 13 Apr 2023 14:32:31 +0000 (16:32 +0200)
Some drivers like iwlwifi might have per-STA queues, so we
may want to flush/drop just those queues rather than all
when removing a station. Add a separate method for that.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/mac80211.h
net/mac80211/driver-ops.h
net/mac80211/sta_info.c
net/mac80211/trace.h

index 679421d37a423283dbc294acdc16b0686c01d5f7..a8dadbd83d95b91a5173c9dc5ad270648a5c5ca9 100644 (file)
@@ -3950,6 +3950,10 @@ struct ieee80211_prep_tx_info {
  *     Note that vif can be NULL.
  *     The callback can sleep.
  *
+ * @flush_sta: Flush or drop all pending frames from the hardware queue(s) for
+ *     the given station, as it's about to be removed.
+ *     The callback can sleep.
+ *
  * @channel_switch: Drivers that need (or want) to offload the channel
  *     switch operation for CSAs received from the AP may implement this
  *     callback. They must then call ieee80211_chswitch_done() to indicate
@@ -4415,6 +4419,8 @@ struct ieee80211_ops {
 #endif
        void (*flush)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                      u32 queues, bool drop);
+       void (*flush_sta)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                         struct ieee80211_sta *sta);
        void (*channel_switch)(struct ieee80211_hw *hw,
                               struct ieee80211_vif *vif,
                               struct ieee80211_channel_switch *ch_switch);
index 0bf208f5bbc5dec278392e8373f9f69043b318aa..45d3e53c7383291465efdf2d3014343ec7a5aa11 100644 (file)
@@ -649,6 +649,21 @@ static inline void drv_flush(struct ieee80211_local *local,
        trace_drv_return_void(local);
 }
 
+static inline void drv_flush_sta(struct ieee80211_local *local,
+                                struct ieee80211_sub_if_data *sdata,
+                                struct sta_info *sta)
+{
+       might_sleep();
+
+       if (sdata && !check_sdata_in_driver(sdata))
+               return;
+
+       trace_drv_flush_sta(local, sdata, &sta->sta);
+       if (local->ops->flush_sta)
+               local->ops->flush_sta(&local->hw, &sdata->vif, &sta->sta);
+       trace_drv_return_void(local);
+}
+
 static inline void drv_channel_switch(struct ieee80211_local *local,
                                      struct ieee80211_sub_if_data *sdata,
                                      struct ieee80211_channel_switch *ch_switch)
index ce7c3b997269bd21f982fdda6b3a24e3bb1815b1..1400512e0dde5df8ebd3b5a06d93c31b5704d7f6 100644 (file)
@@ -1299,8 +1299,12 @@ static void __sta_info_destroy_part2(struct sta_info *sta)
         * frames sitting on hardware queues might be sent out without
         * any encryption at all.
         */
-       if (local->ops->set_key)
-               ieee80211_flush_queues(local, sta->sdata, false);
+       if (local->ops->set_key) {
+               if (local->ops->flush_sta)
+                       drv_flush_sta(local, sta->sdata, sta);
+               else
+                       ieee80211_flush_queues(local, sta->sdata, false);
+       }
 
        /* now keys can no longer be reached */
        ieee80211_free_sta_keys(local, sta);
index e0ccf5fe708ad28592b4ab829b12b54a3e9674e9..de5d69f21306f5edcff12553e0f6ac83edcecb8c 100644 (file)
@@ -1177,6 +1177,13 @@ TRACE_EVENT(drv_flush,
        )
 );
 
+DEFINE_EVENT(sta_event, drv_flush_sta,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_sub_if_data *sdata,
+                struct ieee80211_sta *sta),
+       TP_ARGS(local, sdata, sta)
+);
+
 TRACE_EVENT(drv_channel_switch,
        TP_PROTO(struct ieee80211_local *local,
                 struct ieee80211_sub_if_data *sdata,