mac80211: Fix deadlock when configuring wifi

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: b96c2569ac ("mac80211: Update to version 5.12.19-1")
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
Hauke Mehrtens 2021-11-13 18:24:52 +01:00
parent fa7356dd9d
commit c90e10b62e
1 changed files with 9 additions and 7 deletions

View File

@ -137,24 +137,26 @@
}; };
/* policy for the key attributes */ /* 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; goto out;
} }
+
+ if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) { + if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) {
+ int idx, dbi = 0; + int idx, dbi = 0;
+ +
+ if (!rdev->ops->set_antenna_gain) + if (!rdev->ops->set_antenna_gain) {
+ return -EOPNOTSUPP; + result = -EOPNOTSUPP;
+ goto out;
+ }
+ +
+ idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN; + idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN;
+ dbi = nla_get_u32(info->attrs[idx]); + dbi = nla_get_u32(info->attrs[idx]);
+ +
+ result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi); + result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi);
+ if (result) + if (result)
+ return result; + goto out;
+ } + }
+
if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) { if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
struct wireless_dev *txp_wdev = wdev; struct wireless_dev *txp_wdev = wdev;
enum nl80211_tx_power_setting type;