mirror of
https://github.com/torvalds/linux.git
synced 2026-05-22 22:22:08 +02:00
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:
commit
aa49388151
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user