mirror of
https://github.com/torvalds/linux.git
synced 2026-10-24 16:55:02 +02:00
mt76 fixes for 7.3
- mt7925 ACPI SAR fixes - MLO fixes - sta handling fixes - mt7915 napi disable fix -----BEGIN PGP SIGNATURE----- Comment: GPGTools - http://gpgtools.org iF0EABECAB0WIQR10Rp9kadxD0kAQu/XfRQdAqdu9QUCasTFpgAKCRDXfRQdAqdu 9R6sAJ9NkBQV/FFjzYB7/XgwwwNwG+7BKwCgxSMKBJM18DDh9yUTYYp+WDFdbSY= =b8ye -----END PGP SIGNATURE----- Merge tag 'mt76-fixes-2026-10-05' of https://github.com/nbd168/wireless Felix Fietkau says: =================== mt76 fixes for 7.3 - mt7925 ACPI SAR fixes - MLO fixes - sta handling fixes - mt7915 napi disable fix =================== Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
commit
95148fe661
|
|
@ -1426,6 +1426,13 @@ mtxq_to_txq(struct mt76_txq *mtxq)
|
|||
return container_of(ptr, struct ieee80211_txq, drv_priv);
|
||||
}
|
||||
|
||||
/* peer-wide state uses the wcid of the primary link */
|
||||
static inline struct mt76_wcid *
|
||||
mt76_wcid_primary(struct mt76_wcid *wcid)
|
||||
{
|
||||
return wcid->def_wcid ? wcid->def_wcid : wcid;
|
||||
}
|
||||
|
||||
static inline struct ieee80211_sta *
|
||||
wcid_to_sta(struct mt76_wcid *wcid)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -230,6 +230,7 @@ mt7603_mac_init(struct mt7603_dev *dev)
|
|||
|
||||
eth_broadcast_addr(bc_addr);
|
||||
mt7603_wtbl_init(dev, MT7603_WTBL_RESERVED, -1, bc_addr);
|
||||
mt76_wcid_init(&dev->global_sta.wcid, 0);
|
||||
dev->global_sta.wcid.idx = MT7603_WTBL_RESERVED;
|
||||
rcu_assign_pointer(dev->mt76.wcid[MT7603_WTBL_RESERVED],
|
||||
&dev->global_sta.wcid);
|
||||
|
|
|
|||
|
|
@ -1238,6 +1238,12 @@ static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
|
|||
|
||||
static void mt7915_stop_hardware(struct mt7915_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i) {
|
||||
if (!mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
|
||||
napi_disable(&dev->mt76.napi[i]);
|
||||
}
|
||||
mt7915_mcu_exit(dev);
|
||||
mt76_connac2_tx_token_put(&dev->mt76);
|
||||
mt7915_dma_cleanup(dev);
|
||||
|
|
|
|||
|
|
@ -805,6 +805,7 @@ __mt7915_drop_sta(void *ptr, u8 *mac, struct ieee80211_vif *vif)
|
|||
|
||||
msta = (struct mt7915_sta *)sta->drv_priv;
|
||||
mt7915_mcu_add_sta(data->dev, vif, sta, CONN_STATE_DISCONNECT, false);
|
||||
msta->wcid.tx_info &= ~MT_WCID_TX_INFO_SET;
|
||||
msta->wcid.sta_disabled = 1;
|
||||
msta->wcid.sta = 0;
|
||||
}
|
||||
|
|
@ -871,6 +872,7 @@ int mt7915_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
|||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_DISCONNECT, false);
|
||||
msta->wcid.tx_info &= ~MT_WCID_TX_INFO_SET;
|
||||
msta->wcid.sta_disabled = 1;
|
||||
msta->wcid.sta = 0;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -798,7 +798,8 @@ mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
|
|||
val = FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
|
||||
FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
|
||||
|
||||
if (band_idx)
|
||||
/* 0xff means BAND_AUTO to the firmware, and TGID cannot encode it */
|
||||
if (band_idx && band_idx != 0xff)
|
||||
val |= FIELD_PREP(MT_TXD1_TGID, band_idx);
|
||||
|
||||
txwi[1] = cpu_to_le32(val);
|
||||
|
|
|
|||
|
|
@ -2294,6 +2294,18 @@ mt7925_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
|
||||
mvif->valid_links = new_links;
|
||||
|
||||
/* Restore the legacy BSS after disabling MLO */
|
||||
if (old_links && !new_links) {
|
||||
mt792x_mac_link_bss_remove(dev, &mvif->bss_conf,
|
||||
&mvif->sta.deflink);
|
||||
err = mt7925_mac_link_bss_add(dev, &vif->bss_conf,
|
||||
&mvif->sta.deflink);
|
||||
if (err < 0) {
|
||||
mt792x_mutex_release(dev);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
mt792x_mutex_release(dev);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -108,69 +108,99 @@ mt792x_asar_acpi_read_mtcl(struct mt792x_dev *dev, u8 **table, u8 *version)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* A table's layout is decided by the version byte in MTCL, but some firmware
|
||||
* labels a version 2 table as version 1. Accept whichever layout the table
|
||||
* actually has: for every accepted entry count the two do not overlap, since
|
||||
* one is 6 + 5n bytes and the other 7 + 7n.
|
||||
*/
|
||||
static bool
|
||||
mt792x_asar_fits(u8 *table, int len, int prelen, int sarlen, int nr_off,
|
||||
int min, int max)
|
||||
{
|
||||
int tblcnt;
|
||||
|
||||
if (len < prelen || (len - prelen) % sarlen)
|
||||
return false;
|
||||
|
||||
tblcnt = (len - prelen) / sarlen;
|
||||
if (tblcnt < min || tblcnt > max)
|
||||
return false;
|
||||
|
||||
return tblcnt == table[nr_off];
|
||||
}
|
||||
|
||||
/* MTDS : Dynamic SAR Power Table */
|
||||
static int
|
||||
mt792x_asar_acpi_read_mtds(struct mt792x_dev *dev, u8 **table, u8 version)
|
||||
mt792x_asar_acpi_read_mtds(struct mt792x_dev *dev, u8 **table, u8 version,
|
||||
u8 *used)
|
||||
{
|
||||
int len, ret, sarlen, prelen, tblcnt;
|
||||
bool enable;
|
||||
int len, ret;
|
||||
u8 *t;
|
||||
|
||||
ret = mt792x_acpi_read(dev, MT792x_ACPI_MTDS, table, &len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Table content validation */
|
||||
switch (version) {
|
||||
case 1:
|
||||
enable = ((struct mt792x_asar_dyn *)*table)->enable;
|
||||
sarlen = sizeof(struct mt792x_asar_dyn_limit);
|
||||
prelen = sizeof(struct mt792x_asar_dyn);
|
||||
break;
|
||||
case 2:
|
||||
enable = ((struct mt792x_asar_dyn_v2 *)*table)->enable;
|
||||
sarlen = sizeof(struct mt792x_asar_dyn_limit_v2);
|
||||
prelen = sizeof(struct mt792x_asar_dyn_v2);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
t = *table;
|
||||
|
||||
tblcnt = (len - prelen) / sarlen;
|
||||
if (!enable ||
|
||||
tblcnt > MT792x_ASAR_MAX_DYN || tblcnt < MT792x_ASAR_MIN_DYN)
|
||||
/* Table content validation */
|
||||
if (mt792x_asar_fits(t, len, sizeof(struct mt792x_asar_dyn),
|
||||
sizeof(struct mt792x_asar_dyn_limit),
|
||||
offsetof(struct mt792x_asar_dyn, nr_tbl),
|
||||
MT792x_ASAR_MIN_DYN, MT792x_ASAR_MAX_DYN))
|
||||
*used = 1;
|
||||
else if (mt792x_asar_fits(t, len, sizeof(struct mt792x_asar_dyn_v2),
|
||||
sizeof(struct mt792x_asar_dyn_limit_v2),
|
||||
offsetof(struct mt792x_asar_dyn_v2, nr_tbl),
|
||||
MT792x_ASAR_MIN_DYN, MT792x_ASAR_MAX_DYN))
|
||||
*used = 2;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (!t[offsetof(struct mt792x_asar_dyn, enable)])
|
||||
return -EINVAL;
|
||||
|
||||
if (version && *used != version)
|
||||
dev_info(dev->mt76.dev,
|
||||
"MTDS is v%u, MTCL says v%u; using v%u\n",
|
||||
*used, version, *used);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* MTGS : Geo SAR Power Table */
|
||||
static int
|
||||
mt792x_asar_acpi_read_mtgs(struct mt792x_dev *dev, u8 **table, u8 version)
|
||||
mt792x_asar_acpi_read_mtgs(struct mt792x_dev *dev, u8 **table, u8 version,
|
||||
u8 *used)
|
||||
{
|
||||
int len, ret, sarlen, prelen, tblcnt;
|
||||
int len, ret;
|
||||
u8 *t;
|
||||
|
||||
ret = mt792x_acpi_read(dev, MT792x_ACPI_MTGS, table, &len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Table content validation */
|
||||
switch (version) {
|
||||
case 1:
|
||||
sarlen = sizeof(struct mt792x_asar_geo_limit);
|
||||
prelen = sizeof(struct mt792x_asar_geo);
|
||||
break;
|
||||
case 2:
|
||||
sarlen = sizeof(struct mt792x_asar_geo_limit_v2);
|
||||
prelen = sizeof(struct mt792x_asar_geo_v2);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
t = *table;
|
||||
|
||||
tblcnt = (len - prelen) / sarlen;
|
||||
if (tblcnt > MT792x_ASAR_MAX_GEO || tblcnt < MT792x_ASAR_MIN_GEO)
|
||||
/* Table content validation */
|
||||
if (mt792x_asar_fits(t, len, sizeof(struct mt792x_asar_geo),
|
||||
sizeof(struct mt792x_asar_geo_limit),
|
||||
offsetof(struct mt792x_asar_geo, nr_tbl),
|
||||
MT792x_ASAR_MIN_GEO, MT792x_ASAR_MAX_GEO))
|
||||
*used = 1;
|
||||
else if (mt792x_asar_fits(t, len, sizeof(struct mt792x_asar_geo_v2),
|
||||
sizeof(struct mt792x_asar_geo_limit_v2),
|
||||
offsetof(struct mt792x_asar_geo_v2, nr_tbl),
|
||||
MT792x_ASAR_MIN_GEO, MT792x_ASAR_MAX_GEO))
|
||||
*used = 2;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (version && *used != version)
|
||||
dev_info(dev->mt76.dev,
|
||||
"MTGS is v%u, MTCL says v%u; using v%u\n",
|
||||
*used, version, *used);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -205,14 +235,16 @@ int mt792x_init_acpi_sar(struct mt792x_dev *dev)
|
|||
asar->countrylist = NULL;
|
||||
}
|
||||
|
||||
ret = mt792x_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver);
|
||||
ret = mt792x_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver,
|
||||
&asar->dyn_ver);
|
||||
if (ret) {
|
||||
devm_kfree(dev->mt76.dev, asar->dyn);
|
||||
asar->dyn = NULL;
|
||||
}
|
||||
|
||||
/* MTGS is optional */
|
||||
ret = mt792x_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver);
|
||||
ret = mt792x_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver,
|
||||
&asar->geo_ver);
|
||||
if (ret) {
|
||||
devm_kfree(dev->mt76.dev, asar->geo);
|
||||
asar->geo = NULL;
|
||||
|
|
@ -254,7 +286,7 @@ mt792x_asar_get_geo_pwr(struct mt792x_phy *phy,
|
|||
break;
|
||||
}
|
||||
|
||||
if (asar->ver == 1) {
|
||||
if (asar->geo_ver == 1) {
|
||||
band_pwr = &asar->geo->tbl[idx].band[0];
|
||||
max = ARRAY_SIZE(asar->geo->tbl[idx].band);
|
||||
} else {
|
||||
|
|
@ -279,10 +311,18 @@ mt792x_asar_get_geo_pwr(struct mt792x_phy *phy,
|
|||
if (idx >= max)
|
||||
return dyn_power;
|
||||
|
||||
geo_power = (band_pwr + idx)->pwr;
|
||||
dyn_power += (band_pwr + idx)->offset;
|
||||
band_pwr += idx;
|
||||
|
||||
return min(geo_power, dyn_power);
|
||||
/* Some OEM tables carry 0xff here; narrowed to s8 that is -1 and
|
||||
* wins the min() below. Take it as no limit.
|
||||
*/
|
||||
if (band_pwr->pwr == 0xff)
|
||||
return dyn_power;
|
||||
|
||||
geo_power = band_pwr->pwr;
|
||||
|
||||
return min_t(int, geo_power,
|
||||
min_t(int, dyn_power + band_pwr->offset, 127));
|
||||
}
|
||||
|
||||
static s8
|
||||
|
|
@ -297,7 +337,7 @@ mt792x_asar_range_pwr(struct mt792x_phy *phy,
|
|||
if (!capa)
|
||||
return 127;
|
||||
|
||||
if (asar->ver == 1) {
|
||||
if (asar->dyn_ver == 1) {
|
||||
limit = &asar->dyn->tbl[0].frp[0];
|
||||
max = ARRAY_SIZE(asar->dyn->tbl[0].frp);
|
||||
} else {
|
||||
|
|
@ -315,7 +355,9 @@ mt792x_asar_range_pwr(struct mt792x_phy *phy,
|
|||
else
|
||||
band = NL80211_BAND_2GHZ;
|
||||
|
||||
return mt792x_asar_get_geo_pwr(phy, band, limit[idx]);
|
||||
/* 0xff: no dynamic limit, see mt792x_asar_get_geo_pwr() */
|
||||
return mt792x_asar_get_geo_pwr(phy, band,
|
||||
limit[idx] == 0xff ? 127 : limit[idx]);
|
||||
}
|
||||
|
||||
int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default)
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@ struct mt792x_asar_fg {
|
|||
|
||||
struct mt792x_acpi_sar {
|
||||
u8 ver;
|
||||
u8 dyn_ver;
|
||||
u8 geo_ver;
|
||||
union {
|
||||
struct mt792x_asar_dyn *dyn;
|
||||
struct mt792x_asar_dyn_v2 *dyn_v2;
|
||||
|
|
|
|||
|
|
@ -540,6 +540,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
|
|||
ieee80211_hw_set(hw, NO_VIRTUAL_MONITOR);
|
||||
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
|
||||
ieee80211_hw_set(hw, CHANCTX_STA_CSA);
|
||||
ieee80211_hw_set(hw, CONNECTION_MONITOR);
|
||||
|
||||
hw->max_tx_fragments = 4;
|
||||
wiphy->txq_memory_limit = 32 << 20; /* 32 MiB */
|
||||
|
|
@ -1247,7 +1248,7 @@ static int mt7996_variant_fem_init(struct mt7996_dev *dev)
|
|||
adie_ver = u32_get_bits(regval, MT_ADIE_VERSION_MASK);
|
||||
idx = MT7976C_EFUSE_OFFSET % MT7996_EEPROM_BLOCK_SIZE;
|
||||
is_7976c = adie_ver == 0x8a10 || adie_ver == 0x8b00 ||
|
||||
adie_ver == 0x8c10 || buf[idx] == 0xc;
|
||||
adie_ver == 0x8c10 || (!ret && buf[idx] == 0xc);
|
||||
|
||||
adie_id = u32_get_bits(regval, MT_ADIE_CHIP_ID_MASK);
|
||||
if (adie_id == 0x7975 || adie_id == 0x7979 ||
|
||||
|
|
|
|||
|
|
@ -310,7 +310,14 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
|||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
return mt7996_mcu_mld_link_oper(dev, link_conf, link,
|
||||
true);
|
||||
return 0;
|
||||
|
||||
/* update the link address */
|
||||
ret = mt7996_mcu_add_dev_info(phy, vif, link_conf, mlink, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink,
|
||||
msta_link, true);
|
||||
}
|
||||
|
||||
mlink->idx = __ffs64(~dev->mt76.vif_mask);
|
||||
|
|
@ -1426,6 +1433,7 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
|||
else if (sta->mlo && links == BIT(link_id)) /* last link */
|
||||
mt7996_mcu_teardown_mld_sta(dev, link,
|
||||
msta_link);
|
||||
msta_link->wcid.tx_info &= ~MT_WCID_TX_INFO_SET;
|
||||
msta_link->wcid.sta_disabled = 1;
|
||||
msta_link->wcid.sta = 0;
|
||||
links = links & ~BIT(link_id);
|
||||
|
|
|
|||
|
|
@ -284,6 +284,9 @@ struct mt7996_mcu_wed_rro_ba_delete_event {
|
|||
__le16 len;
|
||||
|
||||
__le16 session_id;
|
||||
__le16 wlan_id;
|
||||
u8 tid;
|
||||
u8 __rsv1;
|
||||
u8 __rsv2[2];
|
||||
} __packed;
|
||||
|
||||
|
|
|
|||
|
|
@ -234,6 +234,8 @@ mt76_tx_check_non_aql(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
|||
if (!wcid || info->tx_time_est)
|
||||
return;
|
||||
|
||||
wcid = mt76_wcid_primary(wcid);
|
||||
|
||||
pending = atomic_dec_return(&wcid->non_aql_packets);
|
||||
if (pending < 0)
|
||||
atomic_cmpxchg(&wcid->non_aql_packets, pending, 0);
|
||||
|
|
@ -344,7 +346,8 @@ __mt76_tx_queue_skb(struct mt76_phy *phy, int qid, struct sk_buff *skb,
|
|||
if (!non_aql)
|
||||
return idx;
|
||||
|
||||
pending = atomic_inc_return(&wcid->non_aql_packets);
|
||||
/* the hardware can report the completion on a different link */
|
||||
pending = atomic_inc_return(&mt76_wcid_primary(wcid)->non_aql_packets);
|
||||
if (stop && pending >= MT_MAX_NON_AQL_PKT)
|
||||
*stop = true;
|
||||
|
||||
|
|
@ -506,7 +509,8 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (atomic_read(&wcid->non_aql_packets) >= MT_MAX_NON_AQL_PKT)
|
||||
if (atomic_read(&mt76_wcid_primary(wcid)->non_aql_packets) >=
|
||||
MT_MAX_NON_AQL_PKT)
|
||||
return 0;
|
||||
|
||||
skb = mt76_txq_dequeue(phy, mtxq);
|
||||
|
|
@ -603,7 +607,8 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (atomic_read(&wcid->non_aql_packets) >= MT_MAX_NON_AQL_PKT)
|
||||
if (atomic_read(&mt76_wcid_primary(wcid)->non_aql_packets) >=
|
||||
MT_MAX_NON_AQL_PKT)
|
||||
continue;
|
||||
if (dev->queue_ops->tx_cleanup &&
|
||||
q->queued + 2 * MT_TXQ_FREE_THR >= q->ndesc) {
|
||||
|
|
@ -675,7 +680,8 @@ mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid,
|
|||
if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) &&
|
||||
!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
|
||||
!ieee80211_is_data_present(hdr->frame_control) &&
|
||||
(!ieee80211_is_bufferable_mmpdu(skb) ||
|
||||
(!(wcid->tx_info & MT_WCID_TX_INFO_SET) ||
|
||||
!ieee80211_is_bufferable_mmpdu(skb) ||
|
||||
ieee80211_is_deauth(hdr->frame_control) ||
|
||||
ieee80211_is_disassoc(hdr->frame_control) ||
|
||||
head == &wcid->tx_offchannel))
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user