linux-next: manual merge of the net-next tree with the origin tree
From: Mark Brown
Date: Mon Aug 17 2026 - 10:48:12 EST
Hi all,
Today's linux-next merge of the net-next tree got a conflict in:
drivers/net/wireless/mediatek/mt76/mt7921/regd.c
between commit:
d6e7d57ed967d ("wifi: mt76: mt7921: refactor regd update to fix recursive mutex deadlock")
from the origin tree and commits:
1f83a8378eb26 ("wifi: mt76: mt7921: refactor regd update to fix recursive mutex deadlock")
9b80bd9cab40c ("wifi: mt76: mt7921: add regulatory wiphy self manager support")
from the net-next tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --combined drivers/net/wireless/mediatek/mt76/mt7921/regd.c
index 4722007abafd5,4a8ea4624fee5..0000000000000
--- a/drivers/net/wireless/mediatek/mt76/mt7921/regd.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/regd.c
@@@ -10,6 -10,15 +10,15 @@@ static bool mt7921_disable_clc
module_param_named(disable_clc, mt7921_disable_clc, bool, 0644);
MODULE_PARM_DESC(disable_clc, "disable CLC support");
+ static struct ieee80211_regdomain mt7921_regd_ww = {
+ .n_reg_rules = 1,
+ .alpha2 = "00",
+ .reg_rules = {
+ /* IEEE 802.11b/g, channels 1..11 */
+ REG_RULE(2412 - 10, 2462 + 10, 40, 6, 20, 0),
+ }
+ };
+
bool mt7921_regd_clc_supported(struct mt792x_dev *dev)
{
if (mt7921_disable_clc ||
@@@ -33,6 -42,9 +42,9 @@@ mt7921_regd_channel_update(struct wiph
np = mt76_find_power_limits_node(mdev);
sband = wiphy->bands[NL80211_BAND_5GHZ];
+ if (!sband)
+ return;
+
band_np = np ? of_get_child_by_name(np, "txpower-5g") : NULL;
for (i = 0; i < sband->n_channels; i++) {
ch = &sband->channels[i];
@@@ -71,14 -83,15 +83,16 @@@
}
}
+/* Internal version that assumes mutex is already held by caller */
int __mt7921_mcu_regd_update(struct mt792x_dev *dev, u8 *alpha2,
enum environment_cap country_ie_env)
{
struct mt76_dev *mdev = &dev->mt76;
struct ieee80211_hw *hw = mdev->hw;
struct wiphy *wiphy = hw->wiphy;
- int ret = 0;
+ int ret;
+
+ lockdep_assert_held(&dev->mt76.mutex);
if (!dev->regd_change)
return 0;
@@@ -101,7 -114,7 +115,7 @@@
int mt7921_mcu_regd_update(struct mt792x_dev *dev, u8 *alpha2,
enum environment_cap country_ie_env)
{
- int ret = 0;
+ int ret;
dev->regd_in_progress = true;
@@@ -150,10 -163,176 +164,176 @@@ void mt7921_regd_notifier(struct wiphy
if (pm->suspended)
return;
+ if (MT7921_REGD_SUPPORTED(&dev->phy)) {
+ mt7921_regd_update(&dev->phy, req->alpha2);
+
+ return;
+ }
+
mt7921_mcu_regd_update(dev, req->alpha2,
req->country_ie_env);
}
+ static struct sk_buff *
+ mt7921_regd_query_regdb(struct mt792x_phy *phy, char *alpha2)
+ {
+ struct wiphy *wiphy = phy->mt76->hw->wiphy;
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct mt792x_dev *dev = mt792x_hw_dev(hw);
+ struct mt7921_clc *clc = phy->clc[MT792x_CLC_REGD];
+ struct mt7921_regd_query_req *req;
+ struct mt7921_regd_cc *regd_cc;
+ struct sk_buff *ret_skb = NULL;
+ u8 *pos, *last_pos;
+ int ret = 0;
+
+ if (!clc)
+ return NULL;
+
+ pos = clc->data;
+ last_pos = pos + le32_to_cpu(clc->len) - sizeof(struct mt7921_clc);
+ while (pos < last_pos) {
+ u32 req_len = 0;
+ u32 rules_len = 0;
+ u32 sign_len = 4;
+ u32 n_reg_rules;
+
+ if (pos + sizeof(*regd_cc) > last_pos)
+ break;
+
+ regd_cc = (struct mt7921_regd_cc *)pos;
+ n_reg_rules = le32_to_cpu(regd_cc->n_reg_rules);
+ if (n_reg_rules > NL80211_MAX_SUPP_REG_RULES)
+ break;
+
+ rules_len = sizeof(struct mt7921_regd_rule_header) +
+ sizeof(struct mt7921_regd_rule) * n_reg_rules;
+
+ if (pos + sizeof(*regd_cc) + rules_len + sign_len > last_pos)
+ break;
+
+ pos += sizeof(*regd_cc) + rules_len + sign_len;
+ if (memcmp(regd_cc->alpha2, alpha2, 2))
+ continue;
+
+ req_len = sizeof(*req) + rules_len + sign_len;
+ req = kzalloc(req_len, GFP_KERNEL);
+
+ if (!req)
+ return NULL;
+
+ req->ver = regd_cc->ver;
+ req->sign_type = regd_cc->sign_type;
+ req->size = cpu_to_le32(rules_len + sign_len);
+ req->n_reg_rules = regd_cc->n_reg_rules;
+
+ memcpy(req->alpha2, regd_cc->alpha2, 2);
+ memcpy(req->data, regd_cc->data, rules_len + sign_len);
+
+ ret = mt76_mcu_send_and_get_msg(&dev->mt76,
+ MCU_CE_CMD(SET_REGD_CH),
+ req, req_len, true, &ret_skb);
+
+ kfree(req);
+
+ return ret < 0 ? NULL : ret_skb;
+ }
+
+ return NULL;
+ }
+
+ int mt7921_regd_update(struct mt792x_phy *phy, char *alpha2)
+ {
+ struct wiphy *wiphy = phy->mt76->hw->wiphy;
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct mt792x_dev *dev = mt792x_hw_dev(hw);
+ struct mt7921_regd_rule *mt7921_rule;
+ struct mt76_dev *mdev = &dev->mt76;
+ struct ieee80211_regdomain *regd;
+ struct ieee80211_reg_rule *rule;
+ struct mt7921_regd_rule_ev *ev;
+ int i, num_of_rules = 0;
+ struct sk_buff *skb;
+ int ret = 0;
+
+ if (dev->hw_full_reset)
+ return 0;
+
+ if (!MT7921_REGD_SUPPORTED(phy))
+ return -EOPNOTSUPP;
+
+ mt792x_mutex_acquire(dev);
+ skb = mt7921_regd_query_regdb(phy, alpha2);
+ mt792x_mutex_release(dev);
+
+ if (!skb) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (skb->len < sizeof(*ev) + 4) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ev = (struct mt7921_regd_rule_ev *)(skb->data + 4);
+ num_of_rules = le32_to_cpu(ev->n_reg_rules);
+
+ if (!num_of_rules ||
+ WARN_ON_ONCE(num_of_rules > NL80211_MAX_SUPP_REG_RULES)) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (skb->len < struct_size(ev, reg_rule, num_of_rules) + 4) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ regd = kzalloc(struct_size(regd, reg_rules, num_of_rules), GFP_KERNEL);
+ if (!regd) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ for (i = 0; i < num_of_rules; i++) {
+ mt7921_rule = &ev->reg_rule[i];
+ rule = ®d->reg_rules[i];
+
+ rule->freq_range.start_freq_khz =
+ MHZ_TO_KHZ(le32_to_cpu(mt7921_rule->start_freq));
+ rule->freq_range.end_freq_khz =
+ MHZ_TO_KHZ(le32_to_cpu(mt7921_rule->end_freq));
+ rule->freq_range.max_bandwidth_khz =
+ MHZ_TO_KHZ(le32_to_cpu(mt7921_rule->max_bw));
+ /* not used by fw */
+ rule->power_rule.max_antenna_gain = DBI_TO_MBI(6);
+ rule->power_rule.max_eirp = DBM_TO_MBM(22);
+ rule->flags = le32_to_cpu(mt7921_rule->flags);
+ }
+
+ regd->n_reg_rules = num_of_rules;
+ regd->dfs_region = ev->dfs_region;
+
+ memcpy(regd->alpha2, alpha2, 2);
+ memcpy(mdev->alpha2, alpha2, 2);
+
+ dev->regd_change = true;
+ mt7921_mcu_regd_update(dev, alpha2, ENVIRON_ANY);
+
+ ret = regulatory_set_wiphy_regd(wiphy, regd);
+
+ kfree(regd);
+ err:
+ dev_kfree_skb(skb);
+
+ if (ret < 0)
+ return regulatory_set_wiphy_regd(wiphy, &mt7921_regd_ww);
+
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(mt7921_regd_update);
+
static bool
mt7921_regd_is_valid_alpha2(const char *alpha2)
{
@@@ -191,7 -370,9 +371,9 @@@ int mt7921_regd_change(struct mt792x_ph
if (!memcmp(alpha2, mdev->alpha2, 2))
return 0;
- if (phy->chip_cap & MT792x_CHIP_CAP_11D_EN)
+ if (MT7921_REGD_SUPPORTED(phy))
+ return mt7921_regd_update(phy, alpha2);
+ else if (phy->chip_cap & MT792x_CHIP_CAP_11D_EN)
return regulatory_hint(wiphy, alpha2);
else
return mt7921_mcu_set_clc(dev, alpha2, ENVIRON_INDOOR);
@@@ -204,7 -385,11 +386,11 @@@ int mt7921_regd_init(struct mt792x_phy
struct mt792x_dev *dev = mt792x_hw_dev(hw);
struct mt76_dev *mdev = &dev->mt76;
- if (phy->chip_cap & MT792x_CHIP_CAP_11D_EN)
+ if (MT7921_REGD_SUPPORTED(phy)) {
+ wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED |
+ REGULATORY_DISABLE_BEACON_HINTS;
+ return mt7921_regd_update(phy, "00");
+ } else if (phy->chip_cap & MT792x_CHIP_CAP_11D_EN)
wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE |
REGULATORY_DISABLE_BEACON_HINTS;
else