mirror of
https://github.com/outbackdingo/mt76.git
synced 2026-10-24 13:26:48 +00:00
Fix the following mt7612e hw hangs during suspend/resume reported on Dell Vostro 3360 mt76x2e 0000:01:00.0: MCU message 2 (seq 11) timed out mt76x2e 0000:01:00.0: MCU message 30 (seq 12) timed out mt76x2e 0000:01:00.0: MCU message 30 (seq 13) timed out mt76x2e 0000:01:00.0: Firmware Version: 0.0.00 mt76x2e 0000:01:00.0: Build: 1 mt76x2e 0000:01:00.0: Build Time: 201507311614____ mt76x2e 0000:01:00.0: Firmware running! ieee80211 phy0: Hardware restart was requested mt76x2e 0000:01:00.0: MCU message 2 (seq 1) timed out mt76x2e 0000:01:00.0: MCU message 30 (seq 2) timed out mt76x2e 0000:01:00.0: MCU message 30 (seq 3) timed out mt76x2e 0000:01:00.0: Firmware Version: 0.0.00 mt76x2e 0000:01:00.0: Build: 1 mt76x2e 0000:01:00.0: Build Time: 201507311614____ mt76x2e 0000:01:00.0: Firmware running! ieee80211 phy0: Hardware restart was requested mt76x2e 0000:01:00.0: MCU message 31 (seq 5) timed out mt76x2e 0000:01:00.0: MCU message 31 (seq 6) timed out mt76x2e 0000:01:00.0: MCU message 31 (seq 7) timed out mt76x2e 0000:01:00.0: MCU message 31 (seq 8) timed out mt76x2e 0000:01:00.0: MCU message 31 (seq 9) timed out mt76x2e 0000:01:00.0: MCU message 31 (seq 10) timed out mt76x2e 0000:01:00.0: MCU message 31 (seq 11) timed out mt76x2e 0000:01:00.0: Firmware Version: 0.0.00 mt76x2e 0000:01:00.0: Build: 1 mt76x2e 0000:01:00.0: Build Time: 201507311614____ mt76x2e 0000:01:00.0: Firmware running! ieee80211 phy0: Hardware restart was requested ------------[ cut here ]----------- CPU: 3 PID: 11956 Comm: kworker/3:1 Not tainted 5.7.0-pf2 #1 Hardware name: Dell Inc. Vostro 3360/0F5DWF, BIOS A18 09/25/2013 Workqueue: events_freezable ieee80211_restart_work [mac80211] RIP: 0010:ieee80211_reconfig+0x234/0x1700 [mac80211] RSP: 0018:ffffb803c23ffdf0 EFLAGS: 00010286 RAX: 00000000fffffff0 RBX: ffff9595a7564900 RCX: 0000000000000008 RDX: 0000000000000000 RSI: 0000000000000100 RDI: 0000000000000100 RBP: ffff9595a7ec07e0 R08: 0000000000000000 R09: 0000000000000001 R10: 0000000000000001 R11: 0000000000000000 R12: ffff9595a7ec18d0 R13: 00000000ffffffff R14: 0000000000000000 R15: 00000000fffffff0 FS: 0000000000000000(0000) GS:ffff9595af2c0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055e56d7de000 CR3: 000000042200a001 CR4: 00000000001706e0 Call Trace: ieee80211_restart_work+0xb7/0xe0 [mac80211] process_one_work+0x1d4/0x3c0 worker_thread+0x228/0x470 ? process_one_work+0x3c0/0x3c0 kthread+0x19c/0x1c0 ? __kthread_init_worker+0x30/0x30 ret_from_fork+0x35/0x40 wlp1s0: Failed check-sdata-in-driver check, flags: 0x0 CPU: 3 PID: 11956 Comm: kworker/3:1 Tainted: G W 5.7.0-pf2 #1 Hardware name: Dell Inc. Vostro 3360/0F5DWF, BIOS A18 09/25/2013 Workqueue: events_freezable ieee80211_restart_work [mac80211] RIP: 0010:drv_remove_interface+0x11f/0x130 [mac80211] RSP: 0018:ffffb803c23ffc80 EFLAGS: 00010282 RAX: 0000000000000000 RBX: ffff9595a7564900 RCX: 0000000000000000 RDX: 0000000000000001 RSI: 0000000000000082 RDI: 00000000ffffffff RBP: ffff9595a7ec1930 R08: 00000000000004b6 R09: 0000000000000001 R10: 0000000000000001 R11: 0000000000006f08 R12: ffff9595a7ec1000 R13: ffff9595a75654b8 R14: ffff9595a7ec0ca0 R15: ffff9595a7ec07e0 FS: 0000000000000000(0000) GS:ffff9595af2c0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055e56d7de000 CR3: 000000042200a001 CR4: 00000000001706e0 Call Trace: ieee80211_do_stop+0x5af/0x8c0 [mac80211] ieee80211_stop+0x16/0x20 [mac80211] __dev_close_many+0xaa/0x120 dev_close_many+0xa1/0x2b0 dev_close+0x6d/0x90 cfg80211_shutdown_all_interfaces+0x71/0xd0 [cfg80211] ieee80211_reconfig+0xa2/0x1700 [mac80211] ieee80211_restart_work+0xb7/0xe0 [mac80211] process_one_work+0x1d4/0x3c0 worker_thread+0x228/0x470 ? process_one_work+0x3c0/0x3c0 kthread+0x19c/0x1c0 ? __kthread_init_worker+0x30/0x30 ret_from_fork+0x35/0x40 Fixes: 7bc04215a66b ("mt76: add driver code for MT76x2e") Tested-by: Oleksandr Natalenko <[email protected]> Signed-off-by: Lorenzo Bianconi <[email protected]> Signed-off-by: Felix Fietkau <[email protected]>
175 lines
3.9 KiB
C
175 lines
3.9 KiB
C
// SPDX-License-Identifier: ISC
|
|
/*
|
|
* Copyright (C) 2016 Felix Fietkau <[email protected]>
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/pci.h>
|
|
|
|
#include "mt76x2.h"
|
|
|
|
static const struct pci_device_id mt76x2e_device_table[] = {
|
|
{ PCI_DEVICE(0x14c3, 0x7662) },
|
|
{ PCI_DEVICE(0x14c3, 0x7612) },
|
|
{ PCI_DEVICE(0x14c3, 0x7602) },
|
|
{ },
|
|
};
|
|
|
|
static int
|
|
mt76x2e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
{
|
|
static const struct mt76_driver_ops drv_ops = {
|
|
.txwi_size = sizeof(struct mt76x02_txwi),
|
|
.drv_flags = MT_DRV_TX_ALIGNED4_SKBS |
|
|
MT_DRV_SW_RX_AIRTIME,
|
|
.survey_flags = SURVEY_INFO_TIME_TX,
|
|
.update_survey = mt76x02_update_channel,
|
|
.tx_prepare_skb = mt76x02_tx_prepare_skb,
|
|
.tx_complete_skb = mt76x02_tx_complete_skb,
|
|
.rx_skb = mt76x02_queue_rx_skb,
|
|
.rx_poll_complete = mt76x02_rx_poll_complete,
|
|
.sta_ps = mt76x02_sta_ps,
|
|
.sta_add = mt76x02_sta_add,
|
|
.sta_remove = mt76x02_sta_remove,
|
|
};
|
|
struct mt76x02_dev *dev;
|
|
struct mt76_dev *mdev;
|
|
int ret;
|
|
|
|
ret = pcim_enable_device(pdev);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
|
|
if (ret)
|
|
return ret;
|
|
|
|
pci_set_master(pdev);
|
|
|
|
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
|
|
if (ret)
|
|
return ret;
|
|
|
|
mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt76x2_ops,
|
|
&drv_ops);
|
|
if (!mdev)
|
|
return -ENOMEM;
|
|
|
|
dev = container_of(mdev, struct mt76x02_dev, mt76);
|
|
mt76_mmio_init(mdev, pcim_iomap_table(pdev)[0]);
|
|
mt76x2_reset_wlan(dev, false);
|
|
|
|
mdev->rev = mt76_rr(dev, MT_ASIC_VERSION);
|
|
dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev);
|
|
|
|
ret = devm_request_irq(mdev->dev, pdev->irq, mt76x02_irq_handler,
|
|
IRQF_SHARED, KBUILD_MODNAME, dev);
|
|
if (ret)
|
|
goto error;
|
|
|
|
ret = mt76x2_register_device(dev);
|
|
if (ret)
|
|
goto error;
|
|
|
|
/* Fix up ASPM configuration */
|
|
|
|
/* RG_SSUSB_G1_CDR_BIR_LTR = 0x9 */
|
|
mt76_rmw_field(dev, 0x15a10, 0x1f << 16, 0x9);
|
|
|
|
/* RG_SSUSB_G1_CDR_BIC_LTR = 0xf */
|
|
mt76_rmw_field(dev, 0x15a0c, 0xf << 28, 0xf);
|
|
|
|
/* RG_SSUSB_CDR_BR_PE1D = 0x3 */
|
|
mt76_rmw_field(dev, 0x15c58, 0x3 << 6, 0x3);
|
|
|
|
mt76_pci_disable_aspm(pdev);
|
|
|
|
return 0;
|
|
|
|
error:
|
|
ieee80211_free_hw(mt76_hw(dev));
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
mt76x2e_remove(struct pci_dev *pdev)
|
|
{
|
|
struct mt76_dev *mdev = pci_get_drvdata(pdev);
|
|
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
|
|
|
|
mt76_unregister_device(mdev);
|
|
mt76x2_cleanup(dev);
|
|
mt76_free_device(mdev);
|
|
}
|
|
|
|
static int __maybe_unused
|
|
mt76x2e_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
{
|
|
struct mt76_dev *mdev = pci_get_drvdata(pdev);
|
|
int i, err;
|
|
|
|
napi_disable(&mdev->tx_napi);
|
|
tasklet_kill(&mdev->pre_tbtt_tasklet);
|
|
tasklet_kill(&mdev->tx_tasklet);
|
|
|
|
mt76_for_each_q_rx(mdev, i)
|
|
napi_disable(&mdev->napi[i]);
|
|
|
|
pci_enable_wake(pdev, pci_choose_state(pdev, state), true);
|
|
pci_save_state(pdev);
|
|
err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
|
|
if (err)
|
|
goto restore;
|
|
|
|
return 0;
|
|
|
|
restore:
|
|
mt76_for_each_q_rx(mdev, i)
|
|
napi_enable(&mdev->napi[i]);
|
|
napi_enable(&mdev->tx_napi);
|
|
|
|
return err;
|
|
}
|
|
|
|
static int __maybe_unused
|
|
mt76x2e_resume(struct pci_dev *pdev)
|
|
{
|
|
struct mt76_dev *mdev = pci_get_drvdata(pdev);
|
|
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
|
|
int i, err;
|
|
|
|
err = pci_set_power_state(pdev, PCI_D0);
|
|
if (err)
|
|
return err;
|
|
|
|
pci_restore_state(pdev);
|
|
|
|
mt76_for_each_q_rx(mdev, i) {
|
|
napi_enable(&mdev->napi[i]);
|
|
napi_schedule(&mdev->napi[i]);
|
|
}
|
|
napi_enable(&mdev->tx_napi);
|
|
napi_schedule(&mdev->tx_napi);
|
|
|
|
return mt76x2_resume_device(dev);
|
|
}
|
|
|
|
MODULE_DEVICE_TABLE(pci, mt76x2e_device_table);
|
|
MODULE_FIRMWARE(MT7662_FIRMWARE);
|
|
MODULE_FIRMWARE(MT7662_ROM_PATCH);
|
|
MODULE_LICENSE("Dual BSD/GPL");
|
|
|
|
static struct pci_driver mt76pci_driver = {
|
|
.name = KBUILD_MODNAME,
|
|
.id_table = mt76x2e_device_table,
|
|
.probe = mt76x2e_probe,
|
|
.remove = mt76x2e_remove,
|
|
#ifdef CONFIG_PM
|
|
.suspend = mt76x2e_suspend,
|
|
.resume = mt76x2e_resume,
|
|
#endif /* CONFIG_PM */
|
|
};
|
|
|
|
module_pci_driver(mt76pci_driver);
|