mac80211: Fix deadlock when configuring wifi
authorHauke Mehrtens <hauke@hauke-m.de>
Sat, 13 Nov 2021 17:24:52 +0000 (18:24 +0100)
committerHauke Mehrtens <hauke@hauke-m.de>
Sat, 13 Nov 2021 18:09:22 +0000 (19:09 +0100)
The nl80211_set_wiphy() function was changed between kernel 5.11 and
5.12 to take the rdev->wiphy lock which should be freed at the end
again. The 500-mac80211_configure_antenna_gain.patch added some code
which just returned in some cases without unlocking. This resulted in a
deadlock with brcmfmac.
This patch fixes this by also jumping to the out label in case we want
to leave the function.
This fixes a hanging system when brcmfmac is in use. I do not know why
we do not see this with other driver.

The kernel returns very useful debug details when setting these OpenWrt
configuration options:
CONFIG_KERNEL_DETECT_HUNG_TASK=y
CONFIG_KERNEL_PROVE_LOCKING=y

Fixes: FS#4122
Fixes: b96c2569ac76 ("mac80211: Update to version 5.12.19-1")
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch

index 3f2cc182530adfaf9dc81ecd29d2b1762cce1fc2..821032fa893679495ce3ea9c7e3ead935874442c 100644 (file)
  };
  
  /* policy for the key attributes */
-@@ -3325,6 +3326,20 @@ static int nl80211_set_wiphy(struct sk_b
+@@ -3324,6 +3325,22 @@ static int nl80211_set_wiphy(struct sk_b
+               if (result)
                        goto out;
        }
++
 +      if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) {
 +              int idx, dbi = 0;
 +
-+              if (!rdev->ops->set_antenna_gain)
-+                      return -EOPNOTSUPP;
++              if (!rdev->ops->set_antenna_gain) {
++                      result = -EOPNOTSUPP;
++                      goto out;
++              }
 +
 +              idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN;
 +              dbi = nla_get_u32(info->attrs[idx]);
 +
 +              result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi);
 +              if (result)
-+                      return result;
++                      goto out;
 +      }
-+
        if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
                struct wireless_dev *txp_wdev = wdev;
-               enum nl80211_tx_power_setting type;