wifi: mac80211: move color collision detection report in a delayed work
authorLorenzo Bianconi <lorenzo@kernel.org>
Wed, 25 Jan 2023 11:01:02 +0000 (12:01 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 10 Mar 2023 08:33:04 +0000 (09:33 +0100)
[ Upstream commit 9288188438d85e22c23cfd6657ee8a801babc83c ]

Move color collision report in a dedicated delayed work and do not run
it in interrupt context in order to rate-limit the number of events
reported to userspace. Moreover grab wdev mutex in
ieee80211_color_collision_detection_work routine since it is required
by cfg80211_obss_color_collision_notify().

Tested-by: Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Fixes: 5f9404abdf2a ("mac80211: add support for BSS color change")
Link: https://lore.kernel.org/r/3f6cf60c892ad40c1cca4a55d62b1224ef1c6ce9.1674644379.git.lorenzo@kernel.org
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/mac80211/cfg.c
net/mac80211/ieee80211_i.h
net/mac80211/link.c

index 3c66e03..e8beec0 100644 (file)
@@ -4623,6 +4623,20 @@ unlock:
        sdata_unlock(sdata);
 }
 
+void ieee80211_color_collision_detection_work(struct work_struct *work)
+{
+       struct delayed_work *delayed_work = to_delayed_work(work);
+       struct ieee80211_link_data *link =
+               container_of(delayed_work, struct ieee80211_link_data,
+                            color_collision_detect_work);
+       struct ieee80211_sub_if_data *sdata = link->sdata;
+
+       sdata_lock(sdata);
+       cfg80211_obss_color_collision_notify(sdata->dev, link->color_bitmap,
+                                            GFP_KERNEL);
+       sdata_unlock(sdata);
+}
+
 void ieee80211_color_change_finish(struct ieee80211_vif *vif)
 {
        struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
@@ -4637,11 +4651,21 @@ ieeee80211_obss_color_collision_notify(struct ieee80211_vif *vif,
                                       u64 color_bitmap, gfp_t gfp)
 {
        struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+       struct ieee80211_link_data *link = &sdata->deflink;
 
        if (sdata->vif.bss_conf.color_change_active || sdata->vif.bss_conf.csa_active)
                return;
 
-       cfg80211_obss_color_collision_notify(sdata->dev, color_bitmap, gfp);
+       if (delayed_work_pending(&link->color_collision_detect_work))
+               return;
+
+       link->color_bitmap = color_bitmap;
+       /* queue the color collision detection event every 500 ms in order to
+        * avoid sending too much netlink messages to userspace.
+        */
+       ieee80211_queue_delayed_work(&sdata->local->hw,
+                                    &link->color_collision_detect_work,
+                                    msecs_to_jiffies(500));
 }
 EXPORT_SYMBOL_GPL(ieeee80211_obss_color_collision_notify);
 
index a8862f2..e57001e 100644 (file)
@@ -972,6 +972,8 @@ struct ieee80211_link_data {
        struct cfg80211_chan_def csa_chandef;
 
        struct work_struct color_change_finalize_work;
+       struct delayed_work color_collision_detect_work;
+       u64 color_bitmap;
 
        /* context reservation -- protected with chanctx_mtx */
        struct ieee80211_chanctx *reserved_chanctx;
@@ -1916,6 +1918,7 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
 
 /* color change handling */
 void ieee80211_color_change_finalize_work(struct work_struct *work);
+void ieee80211_color_collision_detection_work(struct work_struct *work);
 
 /* interface handling */
 #define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
index e309708..a1b3031 100644 (file)
@@ -39,6 +39,8 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
                  ieee80211_csa_finalize_work);
        INIT_WORK(&link->color_change_finalize_work,
                  ieee80211_color_change_finalize_work);
+       INIT_DELAYED_WORK(&link->color_collision_detect_work,
+                         ieee80211_color_collision_detection_work);
        INIT_LIST_HEAD(&link->assigned_chanctx_list);
        INIT_LIST_HEAD(&link->reserved_chanctx_list);
        INIT_DELAYED_WORK(&link->dfs_cac_timer_work,
@@ -66,6 +68,7 @@ void ieee80211_link_stop(struct ieee80211_link_data *link)
        if (link->sdata->vif.type == NL80211_IFTYPE_STATION)
                ieee80211_mgd_stop_link(link);
 
+       cancel_delayed_work_sync(&link->color_collision_detect_work);
        ieee80211_link_release_channel(link);
 }