]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: mac80211: Convert color collision detection to wiphy work
authorRemi Pommarel <repk@triplefau.lt>
Tue, 24 Sep 2024 19:28:05 +0000 (21:28 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 8 Oct 2024 19:24:19 +0000 (21:24 +0200)
Call to ieee80211_color_collision_detection_work() needs wiphy lock to
be held (see lockdep assert in cfg80211_bss_color_notify()). Not locking
wiphy causes the following lockdep error:

  WARNING: CPU: 2 PID: 42 at net/wireless/nl80211.c:19505 cfg80211_bss_color_notify+0x1a4/0x25c
  Modules linked in:
  CPU: 2 PID: 42 Comm: kworker/u8:3 Tainted: G        W          6.4.0-02327-g36c6cb260481 #1048
  Hardware name:
  Workqueue: phy1 ieee80211_color_collision_detection_work
  pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
  pc : cfg80211_bss_color_notify+0x1a4/0x25c
  lr : cfg80211_bss_color_notify+0x1a0/0x25c
  sp : ffff000002947d00
  x29: ffff000002947d00 x28: ffff800008e1a000 x27: ffff000002bd4705
  x26: ffff00000d034000 x25: ffff80000903cf40 x24: 0000000000000000
  x23: ffff00000cb70720 x22: 0000000000800000 x21: ffff800008dfb008
  x20: 000000000000008d x19: ffff00000d035fa8 x18: 0000000000000010
  x17: 0000000000000001 x16: 000003564b1ce96a x15: 000d69696d057970
  x14: 000000000000003b x13: 0000000000000001 x12: 0000000000040000
  x11: 0000000000000001 x10: ffff80000978f9c0 x9 : ffff0000028d3174
  x8 : ffff800008e30000 x7 : 0000000000000000 x6 : 0000000000000028
  x5 : 000000000002f498 x4 : ffff00000d034a80 x3 : 0000000000800000
  x2 : ffff800016143000 x1 : 0000000000000000 x0 : 0000000000000000
  Call trace:
   cfg80211_bss_color_notify+0x1a4/0x25c
   ieee80211_color_collision_detection_work+0x20/0x118
   process_one_work+0x294/0x554
   worker_thread+0x70/0x440
   kthread+0xf4/0xf8
   ret_from_fork+0x10/0x20
  irq event stamp: 77372
  hardirqs last  enabled at (77371): [<ffff800008a346fc>] _raw_spin_unlock_irq+0x2c/0x4c
  hardirqs last disabled at (77372): [<ffff800008a28754>] el1_dbg+0x20/0x48
  softirqs last  enabled at (77350): [<ffff8000089e120c>] batadv_send_outstanding_bcast_packet+0xb8/0x120
  softirqs last disabled at (77348): [<ffff8000089e11d4>] batadv_send_outstanding_bcast_packet+0x80/0x120

The wiphy lock cannot be taken directly from color collision detection
delayed work (ieee80211_color_collision_detection_work()) because this
work is cancel_delayed_work_sync() under this wiphy lock causing a
potential deadlock( see [0] for details).

To fix that ieee80211_color_collision_detection_work() could be
converted to a wiphy work and cancel_delayed_work_sync() can be simply
replaced by wiphy_delayed_work_cancel() serving the same purpose under
wiphy lock.

This could potentially fix [1].

[0]: https://lore.kernel.org/linux-wireless/D4A40Q44OAY2.W3SIF6UEPBUN@freebox.fr/
[1]: https://lore.kernel.org/lkml/000000000000612f290618eee3e5@google.com/

Reported-by: Nicolas Escande <nescande@freebox.fr>
Signed-off-by: Remi Pommarel <repk@triplefau.lt>
Link: https://patch.msgid.link/20240924192805.13859-3-repk@triplefau.lt
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/cfg.c
net/mac80211/ieee80211_i.h
net/mac80211/link.c

index 7cefe763b772004aa60f900269d2122ec28be387..13294cc20a9ba17f59438f5ec6e538a12ab6e2ae 100644 (file)
@@ -4831,12 +4831,12 @@ void ieee80211_color_change_finalize_work(struct wiphy *wiphy,
        ieee80211_color_change_finalize(link);
 }
 
-void ieee80211_color_collision_detection_work(struct work_struct *work)
+void ieee80211_color_collision_detection_work(struct wiphy *wiphy,
+                                             struct wiphy_work *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);
+               container_of(work, struct ieee80211_link_data,
+                            color_collision_detect_work.work);
        struct ieee80211_sub_if_data *sdata = link->sdata;
 
        cfg80211_obss_color_collision_notify(sdata->dev, link->color_bitmap,
@@ -4889,7 +4889,8 @@ ieee80211_obss_color_collision_notify(struct ieee80211_vif *vif,
                return;
        }
 
-       if (delayed_work_pending(&link->color_collision_detect_work)) {
+       if (wiphy_delayed_work_pending(sdata->local->hw.wiphy,
+                                      &link->color_collision_detect_work)) {
                rcu_read_unlock();
                return;
        }
@@ -4898,9 +4899,9 @@ ieee80211_obss_color_collision_notify(struct ieee80211_vif *vif,
        /* 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));
+       wiphy_delayed_work_queue(sdata->local->hw.wiphy,
+                                &link->color_collision_detect_work,
+                                msecs_to_jiffies(500));
 
        rcu_read_unlock();
 }
index 4f0390918b60027bc7eb7c7b30e840a983f91a76..04fec7e516cf896aafc3c3b95fb72ac71a3f1c93 100644 (file)
@@ -1053,7 +1053,7 @@ struct ieee80211_link_data {
        } csa;
 
        struct wiphy_work color_change_finalize_work;
-       struct delayed_work color_collision_detect_work;
+       struct wiphy_delayed_work color_collision_detect_work;
        u64 color_bitmap;
 
        /* context reservation -- protected with wiphy mutex */
@@ -2005,7 +2005,8 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
 /* color change handling */
 void ieee80211_color_change_finalize_work(struct wiphy *wiphy,
                                          struct wiphy_work *work);
-void ieee80211_color_collision_detection_work(struct work_struct *work);
+void ieee80211_color_collision_detection_work(struct wiphy *wiphy,
+                                             struct wiphy_work *work);
 
 /* interface handling */
 #define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
index 0bbac64d5fa0132b748f775256d9c93b55ecc07d..46092fbcde90ebaef21d3086cb60698c0ef28a8f 100644 (file)
@@ -41,8 +41,8 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
                        ieee80211_csa_finalize_work);
        wiphy_work_init(&link->color_change_finalize_work,
                        ieee80211_color_change_finalize_work);
-       INIT_DELAYED_WORK(&link->color_collision_detect_work,
-                         ieee80211_color_collision_detection_work);
+       wiphy_delayed_work_init(&link->color_collision_detect_work,
+                               ieee80211_color_collision_detection_work);
        INIT_LIST_HEAD(&link->assigned_chanctx_list);
        INIT_LIST_HEAD(&link->reserved_chanctx_list);
        wiphy_delayed_work_init(&link->dfs_cac_timer_work,
@@ -72,7 +72,8 @@ 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);
+       wiphy_delayed_work_cancel(link->sdata->local->hw.wiphy,
+                                 &link->color_collision_detect_work);
        wiphy_work_cancel(link->sdata->local->hw.wiphy,
                          &link->color_change_finalize_work);
        wiphy_work_cancel(link->sdata->local->hw.wiphy,