diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7921')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7921/main.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7921/sdio.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c | 58 |
4 files changed, 73 insertions, 6 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 5dd57de59f27..bce26389ab18 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -465,7 +465,7 @@ void mt7921_mac_add_txs(struct mt792x_dev *dev, void *data) rcu_read_lock(); - wcid = rcu_dereference(dev->mt76.wcid[wcidx]); + wcid = mt76_wcid_ptr(dev, wcidx); if (!wcid) goto out; @@ -516,7 +516,7 @@ static void mt7921_mac_tx_free(struct mt792x_dev *dev, void *data, int len) count++; idx = FIELD_GET(MT_TX_FREE_WLAN_ID, info); - wcid = rcu_dereference(dev->mt76.wcid[idx]); + wcid = mt76_wcid_ptr(dev, idx); sta = wcid_to_sta(wcid); if (!sta) continue; @@ -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"); @@ -816,7 +818,7 @@ void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, u16 idx; idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); - wcid = rcu_dereference(mdev->wcid[idx]); + wcid = __mt76_wcid_ptr(mdev, idx); sta = wcid_to_sta(wcid); if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE))) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 1fffa43379b2..40954e64c7fc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -624,7 +624,7 @@ void mt7921_set_runtime_pm(struct mt792x_dev *dev) mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable); } -static int mt7921_config(struct ieee80211_hw *hw, u32 changed) +static int mt7921_config(struct ieee80211_hw *hw, int radio_idx, u32 changed) { struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt792x_phy *phy = mt792x_hw_phy(hw); @@ -907,7 +907,8 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(mt7921_mac_sta_remove); -static int mt7921_set_rts_threshold(struct ieee80211_hw *hw, u32 val) +static int mt7921_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx, + u32 val) { struct mt792x_dev *dev = mt792x_hw_dev(hw); @@ -1088,7 +1089,8 @@ mt7921_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) } static int -mt7921_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) +mt7921_set_antenna(struct ieee80211_hw *hw, int radio_idx, + u32 tx_ant, u32 rx_ant) { struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt792x_phy *phy = mt792x_hw_phy(hw); @@ -1180,6 +1182,9 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw, struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; struct mt792x_dev *dev = mt792x_hw_dev(hw); + if (!msta->deflink.wcid.sta) + return; + mt792x_mutex_acquire(dev); if (enabled) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c index 45b9f35aab17..d8d36b3c3068 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c @@ -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); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c index 1f77cf71ca70..a9eb6252a904 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c @@ -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); |