mt76 patches for 6.17

- firmware recovery improvements for mt7915
 - mlo improvements
 - fixes
 -----BEGIN PGP SIGNATURE-----
 Comment: GPGTools - http://gpgtools.org
 
 iF0EABECAB0WIQR10Rp9kadxD0kAQu/XfRQdAqdu9QUCaGwfmAAKCRDXfRQdAqdu
 9eDNAJ9AHDU0+gDHFOFj7uQeImtXDwLB9QCgoVxFXtOnlGQc8nWJ8l/FIvUEKfw=
 =/5oS
 -----END PGP SIGNATURE-----

Merge tag 'mt76-next-2025-07-07' of https://github.com/nbd168/wireless

Felix Fietkay says:
===================
mt76 patches for 6.17

- firmware recovery improvements for mt7915
- mlo improvements
- fixes
===================

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2025-07-08 09:42:28 +02:00
commit aa49388151
15 changed files with 182 additions and 98 deletions

View File

@ -173,13 +173,13 @@ void mt76_unassign_vif_chanctx(struct ieee80211_hw *hw,
if (!mlink)
goto out;
if (link_conf != &vif->bss_conf)
if (mlink != (struct mt76_vif_link *)vif->drv_priv)
rcu_assign_pointer(mvif->link[link_id], NULL);
dev->drv->vif_link_remove(phy, vif, link_conf, mlink);
mlink->ctx = NULL;
if (link_conf != &vif->bss_conf)
if (mlink != (struct mt76_vif_link *)vif->drv_priv)
kfree_rcu(mlink, rcu_head);
out:

View File

@ -643,10 +643,8 @@ mt76_dma_rx_fill_buf(struct mt76_dev *dev, struct mt76_queue *q,
while (q->queued < q->ndesc - 1) {
struct mt76_queue_buf qbuf = {};
enum dma_data_direction dir;
dma_addr_t addr;
int offset;
void *buf = NULL;
int offset;
if (mt76_queue_is_wed_rro_ind(q))
goto done;
@ -655,11 +653,8 @@ mt76_dma_rx_fill_buf(struct mt76_dev *dev, struct mt76_queue *q,
if (!buf)
break;
addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset;
dir = page_pool_get_dma_dir(q->page_pool);
dma_sync_single_for_device(dev->dma_dev, addr, len, dir);
qbuf.addr = addr + q->buf_offset;
qbuf.addr = page_pool_get_dma_addr(virt_to_head_page(buf)) +
offset + q->buf_offset;
done:
qbuf.len = len - q->buf_offset;
qbuf.skip_unmap = false;

View File

@ -78,6 +78,10 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb,
unsigned long expires;
int ret, seq;
if (mt76_is_sdio(dev))
if (test_bit(MT76_RESET, &dev->phy.state) && atomic_read(&dev->bus_hung))
return -EIO;
if (ret_skb)
*ret_skb = NULL;

View File

@ -983,6 +983,8 @@ struct mt76_dev {
struct mt76_usb usb;
struct mt76_sdio sdio;
};
atomic_t bus_hung;
};
/* per-phy stats. */
@ -1865,6 +1867,9 @@ mt76_vif_link(struct mt76_dev *dev, struct ieee80211_vif *vif, int link_id)
struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
struct mt76_vif_data *mvif = mlink->mvif;
if (!link_id)
return mlink;
return mt76_dereference(mvif->link[link_id], dev);
}
@ -1875,7 +1880,7 @@ mt76_vif_conf_link(struct mt76_dev *dev, struct ieee80211_vif *vif,
struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
struct mt76_vif_data *mvif = mlink->mvif;
if (link_conf == &vif->bss_conf)
if (link_conf == &vif->bss_conf || !link_conf->link_id)
return mlink;
return mt76_dereference(mvif->link[link_conf->link_id], dev);

View File

@ -197,6 +197,8 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
static void
mt7915_mcu_set_timeout(struct mt76_dev *mdev, int cmd)
{
mdev->mcu.timeout = 5 * HZ;
if ((cmd & __MCU_CMD_FIELD_ID) != MCU_CMD_EXT_CID)
return;
@ -208,6 +210,9 @@ mt7915_mcu_set_timeout(struct mt76_dev *mdev, int cmd)
case MCU_EXT_CMD_BSS_INFO_UPDATE:
mdev->mcu.timeout = 2 * HZ;
return;
case MCU_EXT_CMD_EFUSE_BUFFER_MODE:
mdev->mcu.timeout = 10 * HZ;
return;
default:
break;
}
@ -2110,16 +2115,21 @@ static int mt7915_load_firmware(struct mt7915_dev *dev)
{
int ret;
/* make sure fw is download state */
if (mt7915_firmware_state(dev, false)) {
/* restart firmware once */
mt76_connac_mcu_restart(&dev->mt76);
ret = mt7915_firmware_state(dev, false);
if (ret) {
dev_err(dev->mt76.dev,
"Firmware is not ready for download\n");
return ret;
}
/* Release Semaphore if taken by previous failed attempt */
ret = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, false);
if (ret != PATCH_REL_SEM_SUCCESS) {
dev_err(dev->mt76.dev, "Could not release semaphore\n");
/* Continue anyways */
}
/* Always restart MCU firmware */
mt76_connac_mcu_restart(&dev->mt76);
/* Check if MCU is ready */
ret = mt7915_firmware_state(dev, false);
if (ret) {
dev_err(dev->mt76.dev, "Firmware did not enter download state\n");
return ret;
}
ret = mt76_connac2_load_patch(&dev->mt76, fw_name_var(dev, ROM_PATCH));

View File

@ -675,6 +675,8 @@ void mt7921_mac_reset_work(struct work_struct *work)
if (!ret)
break;
}
if (mt76_is_sdio(&dev->mt76) && atomic_read(&dev->mt76.bus_hung))
return;
if (i == 10)
dev_err(dev->mt76.dev, "chip reset failed\n");

View File

@ -150,6 +150,8 @@ static int mt7921s_probe(struct sdio_func *func,
if (ret)
goto error;
atomic_set(&mdev->bus_hung, false);
mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
(mt76_rr(dev, MT_HW_REV) & 0xff);
dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);

View File

@ -6,6 +6,8 @@
#include "mt7921.h"
#include "../mt76_connac2_mac.h"
#include "../sdio.h"
#include <linux/mmc/host.h>
#include <linux/kallsyms.h>
static void mt7921s_enable_irq(struct mt76_dev *dev)
{
@ -35,6 +37,9 @@ int mt7921s_wfsys_reset(struct mt792x_dev *dev)
struct mt76_sdio *sdio = &dev->mt76.sdio;
u32 val, status;
if (atomic_read(&dev->mt76.bus_hung))
return 0;
mt7921s_mcu_drv_pmctrl(dev);
sdio_claim_host(sdio->func);
@ -91,11 +96,64 @@ int mt7921s_init_reset(struct mt792x_dev *dev)
return 0;
}
static struct mt76_sdio *msdio;
static void mt7921s_card_reset(struct work_struct *work)
{
struct mmc_host *sdio_host = msdio->func->card->host;
sdio_claim_host(msdio->func);
sdio_release_irq(msdio->func);
sdio_release_host(msdio->func);
mmc_remove_host(sdio_host);
msleep(50);
mmc_add_host(sdio_host);
}
static DECLARE_WORK(sdio_reset_work, mt7921s_card_reset);
static int mt7921s_check_bus(struct mt76_dev *dev)
{
struct mt76_sdio *sdio = &dev->sdio;
int err;
sdio_claim_host(sdio->func);
sdio_readl(dev->sdio.func, MCR_WHCR, &err);
sdio_release_host(sdio->func);
return err;
}
static int mt7921s_host_reset(struct mt792x_dev *dev)
{
struct mt76_dev *mdev = &dev->mt76;
int err = -1;
if (!atomic_read(&mdev->bus_hung))
err = mt7921s_check_bus(&dev->mt76);
if (err) {
atomic_set(&mdev->bus_hung, true);
msdio = &dev->mt76.sdio;
dev_err(mdev->dev, "SDIO bus problem detected(%d), resetting card!!\n", err);
schedule_work(&sdio_reset_work);
return err;
}
atomic_set(&mdev->bus_hung, false);
return 0;
}
int mt7921s_mac_reset(struct mt792x_dev *dev)
{
int err;
mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
mt7921s_host_reset(dev);
if (atomic_read(&dev->mt76.bus_hung))
return 0;
mt76_txq_schedule_all(&dev->mphy);
mt76_worker_disable(&dev->mt76.tx_worker);
set_bit(MT76_MCU_RESET, &dev->mphy.state);

View File

@ -2866,7 +2866,7 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
for (i = 0; i < sreq->n_ssids; i++) {
if (!sreq->ssids[i].ssid_len)
continue;
if (i > MT7925_RNR_SCAN_MAX_BSSIDS)
if (i >= MT7925_RNR_SCAN_MAX_BSSIDS)
break;
ssid->ssids[i].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len);
@ -2883,7 +2883,7 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
mt76_connac_mcu_build_rnr_scan_param(mdev, sreq);
for (j = 0; j < mdev->rnr.bssid_num; j++) {
if (j > MT7925_RNR_SCAN_MAX_BSSIDS)
if (j >= MT7925_RNR_SCAN_MAX_BSSIDS)
break;
tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_BSSID,

View File

@ -666,6 +666,7 @@ int mt792x_init_wiphy(struct ieee80211_hw *hw)
ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
ieee80211_hw_set(hw, CONNECTION_MONITOR);
ieee80211_hw_set(hw, NO_VIRTUAL_MONITOR);
if (is_mt7921(&dev->mt76))
ieee80211_hw_set(hw, CHANCTX_STA_CSA);

View File

@ -1087,9 +1087,9 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
if (wcid->offchannel)
mlink = rcu_dereference(mvif->mt76.offchannel_link);
if (!mlink)
mlink = &mvif->deflink.mt76;
mlink = rcu_dereference(mvif->mt76.link[wcid->link_id]);
txp->fw.bss_idx = mlink->idx;
txp->fw.bss_idx = mlink ? mlink->idx : mvif->deflink.mt76.idx;
}
txp->fw.token = cpu_to_le16(id);
@ -1129,15 +1129,14 @@ u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
}
static void
mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
mt7996_tx_check_aggr(struct ieee80211_link_sta *link_sta,
struct mt76_wcid *wcid, struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
struct mt7996_sta_link *msta_link;
struct mt7996_sta *msta;
u16 fc, tid;
if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
if (!(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he))
return;
tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
@ -1146,7 +1145,8 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
if (is_8023) {
fc = IEEE80211_FTYPE_DATA |
(sta->wme ? IEEE80211_STYPE_QOS_DATA : IEEE80211_STYPE_DATA);
(link_sta->sta->wme ? IEEE80211_STYPE_QOS_DATA
: IEEE80211_STYPE_DATA);
} else {
/* No need to get precise TID for Action/Management Frame,
* since it will not meet the following Frame Control
@ -1162,19 +1162,16 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
return;
msta = (struct mt7996_sta *)sta->drv_priv;
msta_link = &msta->deflink;
if (!test_and_set_bit(tid, &msta_link->wcid.ampdu_state))
ieee80211_start_tx_ba_session(sta, tid, 0);
if (!test_and_set_bit(tid, &wcid->ampdu_state))
ieee80211_start_tx_ba_session(link_sta->sta, tid, 0);
}
static void
mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t,
struct ieee80211_sta *sta, struct list_head *free_list)
struct ieee80211_link_sta *link_sta,
struct mt76_wcid *wcid, struct list_head *free_list)
{
struct mt76_dev *mdev = &dev->mt76;
struct mt76_wcid *wcid;
__le32 *txwi;
u16 wcid_idx;
@ -1183,12 +1180,10 @@ mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t,
goto out;
txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t);
if (sta) {
wcid = (struct mt76_wcid *)sta->drv_priv;
if (link_sta) {
wcid_idx = wcid->idx;
if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
mt7996_tx_check_aggr(sta, t->skb);
mt7996_tx_check_aggr(link_sta, wcid, t->skb);
} else {
wcid_idx = le32_get_bits(txwi[9], MT_TXD9_WLAN_IDX);
}
@ -1207,8 +1202,8 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
struct mt76_dev *mdev = &dev->mt76;
struct mt76_phy *phy2 = mdev->phys[MT_BAND1];
struct mt76_phy *phy3 = mdev->phys[MT_BAND2];
struct ieee80211_link_sta *link_sta = NULL;
struct mt76_txwi_cache *txwi;
struct ieee80211_sta *sta = NULL;
struct mt76_wcid *wcid = NULL;
LIST_HEAD(free_list);
struct sk_buff *skb, *tmp;
@ -1245,7 +1240,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
*/
info = le32_to_cpu(*cur_info);
if (info & MT_TXFREE_INFO_PAIR) {
struct mt7996_sta_link *msta_link;
struct ieee80211_sta *sta;
u16 idx;
idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info);
@ -1254,9 +1249,11 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
if (!sta)
goto next;
msta_link = container_of(wcid, struct mt7996_sta_link,
wcid);
mt76_wcid_add_poll(&dev->mt76, &msta_link->wcid);
link_sta = rcu_dereference(sta->link[wcid->link_id]);
if (!link_sta)
goto next;
mt76_wcid_add_poll(&dev->mt76, wcid);
next:
/* ver 7 has a new DW with pair = 1, skip it */
if (ver == 7 && ((void *)(cur_info + 1) < end) &&
@ -1289,7 +1286,8 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
if (!txwi)
continue;
mt7996_txwi_free(dev, txwi, sta, &free_list);
mt7996_txwi_free(dev, txwi, link_sta, wcid,
&free_list);
}
}
@ -1748,7 +1746,7 @@ void mt7996_tx_token_put(struct mt7996_dev *dev)
spin_lock_bh(&dev->mt76.token_lock);
idr_for_each_entry(&dev->mt76.token, txwi, id) {
mt7996_txwi_free(dev, txwi, NULL, NULL);
mt7996_txwi_free(dev, txwi, NULL, NULL, NULL);
dev->mt76.token_count--;
}
spin_unlock_bh(&dev->mt76.token_lock);

View File

@ -960,8 +960,8 @@ mt7996_mac_sta_deinit_link(struct mt7996_dev *dev,
}
static void
mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_sta *sta,
unsigned long links)
mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, unsigned long links)
{
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
struct mt76_dev *mdev = &dev->mt76;
@ -969,6 +969,8 @@ mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_sta *sta,
for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
struct mt7996_sta_link *msta_link = NULL;
struct mt7996_vif_link *link;
struct mt76_phy *mphy;
msta_link = rcu_replace_pointer(msta->link[link_id], msta_link,
lockdep_is_held(&mdev->mutex));
@ -976,6 +978,15 @@ mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_sta *sta,
continue;
mt7996_mac_sta_deinit_link(dev, msta_link);
link = mt7996_vif_link(dev, vif, link_id);
if (!link)
continue;
mphy = mt76_vif_link_phy(&link->mt76);
if (!mphy)
continue;
mphy->num_sta--;
if (msta->deflink_id == link_id) {
msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
continue;
@ -997,6 +1008,7 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf;
struct ieee80211_link_sta *link_sta;
struct mt7996_vif_link *link;
struct mt76_phy *mphy;
if (rcu_access_pointer(msta->link[link_id]))
continue;
@ -1023,12 +1035,19 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
link_id);
if (err)
goto error_unlink;
mphy = mt76_vif_link_phy(&link->mt76);
if (!mphy) {
err = -EINVAL;
goto error_unlink;
}
mphy->num_sta++;
}
return 0;
error_unlink:
mt7996_mac_sta_remove_links(dev, sta, new_links);
mt7996_mac_sta_remove_links(dev, vif, sta, new_links);
return err;
}
@ -1045,7 +1064,7 @@ mt7996_mac_sta_change_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mutex_lock(&dev->mt76.mutex);
mt7996_mac_sta_remove_links(dev, sta, rem);
mt7996_mac_sta_remove_links(dev, vif, sta, rem);
ret = mt7996_mac_sta_add_links(dev, vif, sta, add);
mutex_unlock(&dev->mt76.mutex);
@ -1054,25 +1073,21 @@ mt7996_mac_sta_change_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
static int
mt7996_mac_sta_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
mt7996_mac_sta_add(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct mt76_dev *mdev = mphy->dev;
struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
unsigned long links = sta->mlo ? sta->valid_links : BIT(0);
unsigned long links = sta->valid_links ? sta->valid_links : BIT(0);
int err;
mutex_lock(&mdev->mutex);
mutex_lock(&dev->mt76.mutex);
msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
msta->vif = mvif;
err = mt7996_mac_sta_add_links(dev, vif, sta, links);
if (!err)
mphy->num_sta++;
mutex_unlock(&mdev->mutex);
mutex_unlock(&dev->mt76.mutex);
return err;
}
@ -1119,7 +1134,6 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
return err;
msta_link->wcid.tx_info |= MT_WCID_TX_INFO_SET;
msta_link->wcid.sta = 1;
break;
case MT76_STA_EVENT_AUTHORIZE:
err = mt7996_mcu_add_sta(dev, link_conf, link_sta,
@ -1151,19 +1165,14 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
}
static void
mt7996_mac_sta_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
mt7996_mac_sta_remove(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct mt76_dev *mdev = mphy->dev;
struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
unsigned long links = sta->mlo ? sta->valid_links : BIT(0);
unsigned long links = sta->valid_links ? sta->valid_links : BIT(0);
mutex_lock(&mdev->mutex);
mt7996_mac_sta_remove_links(dev, sta, links);
mphy->num_sta--;
mutex_unlock(&mdev->mutex);
mutex_lock(&dev->mt76.mutex);
mt7996_mac_sta_remove_links(dev, vif, sta, links);
mutex_unlock(&dev->mt76.mutex);
}
static int
@ -1171,20 +1180,16 @@ mt7996_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, enum ieee80211_sta_state old_state,
enum ieee80211_sta_state new_state)
{
struct mt76_phy *mphy = mt76_vif_phy(hw, vif);
struct mt7996_dev *dev = mt7996_hw_dev(hw);
enum mt76_sta_event ev;
if (!mphy)
return -EINVAL;
if (old_state == IEEE80211_STA_NOTEXIST &&
new_state == IEEE80211_STA_NONE)
return mt7996_mac_sta_add(mphy, vif, sta);
return mt7996_mac_sta_add(dev, vif, sta);
if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_NOTEXIST)
mt7996_mac_sta_remove(mphy, vif, sta);
mt7996_mac_sta_remove(dev, vif, sta);
if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_ASSOC)
@ -1217,10 +1222,17 @@ static void mt7996_tx(struct ieee80211_hw *hw,
if (vif) {
struct mt7996_vif *mvif = (void *)vif->drv_priv;
struct mt76_vif_link *mlink;
struct mt76_vif_link *mlink = &mvif->deflink.mt76;
mlink = rcu_dereference(mvif->mt76.link[link_id]);
if (mlink && mlink->wcid)
if (link_id < IEEE80211_LINK_UNSPECIFIED)
mlink = rcu_dereference(mvif->mt76.link[link_id]);
if (!mlink) {
ieee80211_free_txskb(hw, skb);
goto unlock;
}
if (mlink->wcid)
wcid = mlink->wcid;
if (mvif->mt76.roc_phy &&
@ -1229,7 +1241,7 @@ static void mt7996_tx(struct ieee80211_hw *hw,
if (mphy->roc_link)
wcid = mphy->roc_link->wcid;
} else {
mphy = mt76_vif_link_phy(&mvif->deflink.mt76);
mphy = mt76_vif_link_phy(mlink);
}
}
@ -1238,7 +1250,7 @@ static void mt7996_tx(struct ieee80211_hw *hw,
goto unlock;
}
if (control->sta) {
if (control->sta && link_id < IEEE80211_LINK_UNSPECIFIED) {
struct mt7996_sta *msta = (void *)control->sta->drv_priv;
struct mt7996_sta_link *msta_link;

View File

@ -2216,15 +2216,15 @@ mt7996_mcu_add_group(struct mt7996_dev *dev, struct ieee80211_vif *vif,
static void
mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
unsigned long links = sta->valid_links;
unsigned int nlinks = hweight16(links);
unsigned int nlinks = hweight16(sta->valid_links);
struct mld_setup_link *mld_setup_link;
struct ieee80211_link_sta *link_sta;
struct sta_rec_mld_setup *mld_setup;
struct mt7996_sta_link *msta_link;
struct ieee80211_vif *vif;
unsigned int link_id;
struct tlv *tlv;
@ -2242,18 +2242,16 @@ mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
mld_setup->primary_id = cpu_to_le16(msta_link->wcid.idx);
if (nlinks > 1) {
link_id = __ffs(links & ~BIT(msta->deflink_id));
msta_link = mt76_dereference(msta->link[msta->deflink_id],
&dev->mt76);
link_id = __ffs(sta->valid_links & ~BIT(msta->deflink_id));
msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
if (!msta_link)
return;
}
mld_setup->seconed_id = cpu_to_le16(msta_link->wcid.idx);
mld_setup->link_num = nlinks;
vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
mld_setup_link = (struct mld_setup_link *)mld_setup->link_info;
for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
for_each_sta_active_link(vif, sta, link_sta, link_id) {
struct mt7996_vif_link *link;
msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
@ -2345,7 +2343,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev,
mt7996_mcu_sta_muru_tlv(dev, skb, link_conf, link_sta);
if (sta->mlo) {
mt7996_mcu_sta_mld_setup_tlv(dev, skb, sta);
mt7996_mcu_sta_mld_setup_tlv(dev, skb, link_conf->vif,
sta);
mt7996_mcu_sta_eht_mld_tlv(dev, skb, sta);
}
}

View File

@ -112,6 +112,7 @@ mt76s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid,
if (err < 0) {
dev_err(dev->dev, "sdio read data failed:%d\n", err);
atomic_set(&dev->bus_hung, true);
put_page(page);
return err;
}
@ -234,9 +235,10 @@ static int __mt76s_xmit_queue(struct mt76_dev *dev, u8 *data, int len)
err = sdio_writesb(sdio->func, MCR_WTDR1, data, len);
sdio_release_host(sdio->func);
if (err)
if (err) {
dev_err(dev->dev, "sdio write failed: %d\n", err);
atomic_set(&dev->bus_hung, true);
}
return err;
}

View File

@ -34,11 +34,10 @@ u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
struct mtk_wed_bm_desc *desc = wed->rx_buf_ring.desc;
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
int i, len = SKB_WITH_OVERHEAD(q->buf_size);
struct mt76_txwi_cache *t = NULL;
int i;
for (i = 0; i < size; i++) {
enum dma_data_direction dir;
dma_addr_t addr;
u32 offset;
int token;
@ -53,9 +52,6 @@ u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
goto unmap;
addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset;
dir = page_pool_get_dma_dir(q->page_pool);
dma_sync_single_for_device(dev->dma_dev, addr, len, dir);
desc->buf0 = cpu_to_le32(addr);
token = mt76_rx_token_consume(dev, buf, t, addr);
if (token < 0) {