xref: /freebsd/sys/contrib/dev/mediatek/mt76/mt76x0/pci.c (revision 8ba4d145d351db26e07695b8e90697398c5dfec2)
16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC
26c92544dSBjoern A. Zeeb /*
36c92544dSBjoern A. Zeeb  * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
46c92544dSBjoern A. Zeeb  */
56c92544dSBjoern A. Zeeb 
66c92544dSBjoern A. Zeeb #include <linux/kernel.h>
76c92544dSBjoern A. Zeeb #include <linux/module.h>
86c92544dSBjoern A. Zeeb #include <linux/pci.h>
96c92544dSBjoern A. Zeeb 
106c92544dSBjoern A. Zeeb #include "mt76x0.h"
116c92544dSBjoern A. Zeeb #include "mcu.h"
126c92544dSBjoern A. Zeeb 
mt76x0e_start(struct ieee80211_hw * hw)136c92544dSBjoern A. Zeeb static int mt76x0e_start(struct ieee80211_hw *hw)
146c92544dSBjoern A. Zeeb {
156c92544dSBjoern A. Zeeb 	struct mt76x02_dev *dev = hw->priv;
166c92544dSBjoern A. Zeeb 
176c92544dSBjoern A. Zeeb 	mt76x02_mac_start(dev);
186c92544dSBjoern A. Zeeb 	mt76x0_phy_calibrate(dev, true);
196c92544dSBjoern A. Zeeb 	ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mphy.mac_work,
206c92544dSBjoern A. Zeeb 				     MT_MAC_WORK_INTERVAL);
216c92544dSBjoern A. Zeeb 	ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
226c92544dSBjoern A. Zeeb 				     MT_CALIBRATE_INTERVAL);
236c92544dSBjoern A. Zeeb 	set_bit(MT76_STATE_RUNNING, &dev->mphy.state);
246c92544dSBjoern A. Zeeb 
256c92544dSBjoern A. Zeeb 	return 0;
266c92544dSBjoern A. Zeeb }
276c92544dSBjoern A. Zeeb 
mt76x0e_stop_hw(struct mt76x02_dev * dev)286c92544dSBjoern A. Zeeb static void mt76x0e_stop_hw(struct mt76x02_dev *dev)
296c92544dSBjoern A. Zeeb {
306c92544dSBjoern A. Zeeb 	cancel_delayed_work_sync(&dev->cal_work);
316c92544dSBjoern A. Zeeb 	cancel_delayed_work_sync(&dev->mphy.mac_work);
326c92544dSBjoern A. Zeeb 	clear_bit(MT76_RESTART, &dev->mphy.state);
336c92544dSBjoern A. Zeeb 
346c92544dSBjoern A. Zeeb 	if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY,
356c92544dSBjoern A. Zeeb 		       0, 1000))
366c92544dSBjoern A. Zeeb 		dev_warn(dev->mt76.dev, "TX DMA did not stop\n");
376c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN);
386c92544dSBjoern A. Zeeb 
396c92544dSBjoern A. Zeeb 	mt76x0_mac_stop(dev);
406c92544dSBjoern A. Zeeb 
416c92544dSBjoern A. Zeeb 	if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_RX_DMA_BUSY,
426c92544dSBjoern A. Zeeb 		       0, 1000))
436c92544dSBjoern A. Zeeb 		dev_warn(dev->mt76.dev, "TX DMA did not stop\n");
446c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_RX_DMA_EN);
456c92544dSBjoern A. Zeeb }
466c92544dSBjoern A. Zeeb 
mt76x0e_stop(struct ieee80211_hw * hw,bool suspend)47*8ba4d145SBjoern A. Zeeb static void mt76x0e_stop(struct ieee80211_hw *hw, bool suspend)
486c92544dSBjoern A. Zeeb {
496c92544dSBjoern A. Zeeb 	struct mt76x02_dev *dev = hw->priv;
506c92544dSBjoern A. Zeeb 
516c92544dSBjoern A. Zeeb 	clear_bit(MT76_STATE_RUNNING, &dev->mphy.state);
526c92544dSBjoern A. Zeeb 	mt76x0e_stop_hw(dev);
536c92544dSBjoern A. Zeeb }
546c92544dSBjoern A. Zeeb 
556c92544dSBjoern A. Zeeb static void
mt76x0e_flush(struct ieee80211_hw * hw,struct ieee80211_vif * vif,u32 queues,bool drop)566c92544dSBjoern A. Zeeb mt76x0e_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
576c92544dSBjoern A. Zeeb 	      u32 queues, bool drop)
586c92544dSBjoern A. Zeeb {
596c92544dSBjoern A. Zeeb }
606c92544dSBjoern A. Zeeb 
616c92544dSBjoern A. Zeeb static const struct ieee80211_ops mt76x0e_ops = {
62*8ba4d145SBjoern A. Zeeb 	.add_chanctx = ieee80211_emulate_add_chanctx,
63*8ba4d145SBjoern A. Zeeb 	.remove_chanctx = ieee80211_emulate_remove_chanctx,
64*8ba4d145SBjoern A. Zeeb 	.change_chanctx = ieee80211_emulate_change_chanctx,
65*8ba4d145SBjoern A. Zeeb 	.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
666c92544dSBjoern A. Zeeb 	.tx = mt76x02_tx,
676c92544dSBjoern A. Zeeb 	.start = mt76x0e_start,
686c92544dSBjoern A. Zeeb 	.stop = mt76x0e_stop,
696c92544dSBjoern A. Zeeb 	.add_interface = mt76x02_add_interface,
706c92544dSBjoern A. Zeeb 	.remove_interface = mt76x02_remove_interface,
716c92544dSBjoern A. Zeeb 	.config = mt76x0_config,
726c92544dSBjoern A. Zeeb 	.configure_filter = mt76x02_configure_filter,
736c92544dSBjoern A. Zeeb 	.bss_info_changed = mt76x02_bss_info_changed,
746c92544dSBjoern A. Zeeb 	.sta_state = mt76_sta_state,
756c92544dSBjoern A. Zeeb 	.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
766c92544dSBjoern A. Zeeb 	.set_key = mt76x02_set_key,
776c92544dSBjoern A. Zeeb 	.conf_tx = mt76x02_conf_tx,
786c92544dSBjoern A. Zeeb 	.sw_scan_start = mt76_sw_scan,
796c92544dSBjoern A. Zeeb 	.sw_scan_complete = mt76x02_sw_scan_complete,
806c92544dSBjoern A. Zeeb 	.ampdu_action = mt76x02_ampdu_action,
816c92544dSBjoern A. Zeeb 	.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
826c92544dSBjoern A. Zeeb 	.wake_tx_queue = mt76_wake_tx_queue,
836c92544dSBjoern A. Zeeb 	.get_survey = mt76_get_survey,
846c92544dSBjoern A. Zeeb 	.get_txpower = mt76_get_txpower,
856c92544dSBjoern A. Zeeb 	.flush = mt76x0e_flush,
866c92544dSBjoern A. Zeeb 	.set_tim = mt76_set_tim,
876c92544dSBjoern A. Zeeb 	.release_buffered_frames = mt76_release_buffered_frames,
886c92544dSBjoern A. Zeeb 	.set_coverage_class = mt76x02_set_coverage_class,
896c92544dSBjoern A. Zeeb 	.set_rts_threshold = mt76x02_set_rts_threshold,
906c92544dSBjoern A. Zeeb 	.get_antenna = mt76_get_antenna,
916c92544dSBjoern A. Zeeb 	.reconfig_complete = mt76x02_reconfig_complete,
926c92544dSBjoern A. Zeeb 	.set_sar_specs = mt76x0_set_sar_specs,
936c92544dSBjoern A. Zeeb };
946c92544dSBjoern A. Zeeb 
mt76x0e_init_hardware(struct mt76x02_dev * dev,bool resume)956c92544dSBjoern A. Zeeb static int mt76x0e_init_hardware(struct mt76x02_dev *dev, bool resume)
966c92544dSBjoern A. Zeeb {
976c92544dSBjoern A. Zeeb 	int err;
986c92544dSBjoern A. Zeeb 
996c92544dSBjoern A. Zeeb 	mt76x0_chip_onoff(dev, true, false);
1006c92544dSBjoern A. Zeeb 	if (!mt76x02_wait_for_mac(&dev->mt76))
1016c92544dSBjoern A. Zeeb 		return -ETIMEDOUT;
1026c92544dSBjoern A. Zeeb 
1036c92544dSBjoern A. Zeeb 	mt76x02_dma_disable(dev);
1046c92544dSBjoern A. Zeeb 	err = mt76x0e_mcu_init(dev);
1056c92544dSBjoern A. Zeeb 	if (err < 0)
1066c92544dSBjoern A. Zeeb 		return err;
1076c92544dSBjoern A. Zeeb 
1086c92544dSBjoern A. Zeeb 	if (!resume) {
1096c92544dSBjoern A. Zeeb 		err = mt76x02_dma_init(dev);
1106c92544dSBjoern A. Zeeb 		if (err < 0)
1116c92544dSBjoern A. Zeeb 			return err;
1126c92544dSBjoern A. Zeeb 	}
1136c92544dSBjoern A. Zeeb 
1146c92544dSBjoern A. Zeeb 	err = mt76x0_init_hardware(dev);
1156c92544dSBjoern A. Zeeb 	if (err < 0)
1166c92544dSBjoern A. Zeeb 		return err;
1176c92544dSBjoern A. Zeeb 
1186c92544dSBjoern A. Zeeb 	mt76x02e_init_beacon_config(dev);
1196c92544dSBjoern A. Zeeb 
1206c92544dSBjoern A. Zeeb 	if (mt76_chip(&dev->mt76) == 0x7610) {
1216c92544dSBjoern A. Zeeb 		u16 val;
1226c92544dSBjoern A. Zeeb 
1236c92544dSBjoern A. Zeeb 		mt76_clear(dev, MT_COEXCFG0, BIT(0));
1246c92544dSBjoern A. Zeeb 
1256c92544dSBjoern A. Zeeb 		val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0);
1266c92544dSBjoern A. Zeeb 		if (!(val & MT_EE_NIC_CONF_0_PA_IO_CURRENT))
1276c92544dSBjoern A. Zeeb 			mt76_set(dev, MT_XO_CTRL7, 0xc03);
1286c92544dSBjoern A. Zeeb 	}
1296c92544dSBjoern A. Zeeb 
1306c92544dSBjoern A. Zeeb 	mt76_clear(dev, 0x110, BIT(9));
1316c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_MAX_LEN_CFG, BIT(13));
1326c92544dSBjoern A. Zeeb 
1336c92544dSBjoern A. Zeeb 	return 0;
1346c92544dSBjoern A. Zeeb }
1356c92544dSBjoern A. Zeeb 
mt76x0e_register_device(struct mt76x02_dev * dev)1366c92544dSBjoern A. Zeeb static int mt76x0e_register_device(struct mt76x02_dev *dev)
1376c92544dSBjoern A. Zeeb {
1386c92544dSBjoern A. Zeeb 	int err;
1396c92544dSBjoern A. Zeeb 
1406c92544dSBjoern A. Zeeb 	err = mt76x0e_init_hardware(dev, false);
1416c92544dSBjoern A. Zeeb 	if (err < 0)
1426c92544dSBjoern A. Zeeb 		return err;
1436c92544dSBjoern A. Zeeb 
1446c92544dSBjoern A. Zeeb 	err = mt76x0_register_device(dev);
1456c92544dSBjoern A. Zeeb 	if (err < 0)
1466c92544dSBjoern A. Zeeb 		return err;
1476c92544dSBjoern A. Zeeb 
1486c92544dSBjoern A. Zeeb 	set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
1496c92544dSBjoern A. Zeeb 
1506c92544dSBjoern A. Zeeb 	return 0;
1516c92544dSBjoern A. Zeeb }
1526c92544dSBjoern A. Zeeb 
1536c92544dSBjoern A. Zeeb static int
mt76x0e_probe(struct pci_dev * pdev,const struct pci_device_id * id)1546c92544dSBjoern A. Zeeb mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1556c92544dSBjoern A. Zeeb {
1566c92544dSBjoern A. Zeeb 	static const struct mt76_driver_ops drv_ops = {
1576c92544dSBjoern A. Zeeb 		.txwi_size = sizeof(struct mt76x02_txwi),
1586c92544dSBjoern A. Zeeb 		.drv_flags = MT_DRV_TX_ALIGNED4_SKBS |
1596c92544dSBjoern A. Zeeb 			     MT_DRV_SW_RX_AIRTIME,
1606c92544dSBjoern A. Zeeb 		.survey_flags = SURVEY_INFO_TIME_TX,
1616c92544dSBjoern A. Zeeb 		.update_survey = mt76x02_update_channel,
162*8ba4d145SBjoern A. Zeeb 		.set_channel = mt76x0_set_channel,
1636c92544dSBjoern A. Zeeb 		.tx_prepare_skb = mt76x02_tx_prepare_skb,
1646c92544dSBjoern A. Zeeb 		.tx_complete_skb = mt76x02_tx_complete_skb,
1656c92544dSBjoern A. Zeeb 		.rx_skb = mt76x02_queue_rx_skb,
1666c92544dSBjoern A. Zeeb 		.rx_poll_complete = mt76x02_rx_poll_complete,
1676c92544dSBjoern A. Zeeb 		.sta_ps = mt76x02_sta_ps,
1686c92544dSBjoern A. Zeeb 		.sta_add = mt76x02_sta_add,
1696c92544dSBjoern A. Zeeb 		.sta_remove = mt76x02_sta_remove,
1706c92544dSBjoern A. Zeeb 	};
1716c92544dSBjoern A. Zeeb 	struct mt76x02_dev *dev;
1726c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev;
1736c92544dSBjoern A. Zeeb 	int ret;
1746c92544dSBjoern A. Zeeb 
1756c92544dSBjoern A. Zeeb 	ret = pcim_enable_device(pdev);
1766c92544dSBjoern A. Zeeb 	if (ret)
1776c92544dSBjoern A. Zeeb 		return ret;
1786c92544dSBjoern A. Zeeb 
1796c92544dSBjoern A. Zeeb 	ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
1806c92544dSBjoern A. Zeeb 	if (ret)
1816c92544dSBjoern A. Zeeb 		return ret;
1826c92544dSBjoern A. Zeeb 
1836c92544dSBjoern A. Zeeb 	pci_set_master(pdev);
1846c92544dSBjoern A. Zeeb 
1856c92544dSBjoern A. Zeeb 	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
1866c92544dSBjoern A. Zeeb 	if (ret)
1876c92544dSBjoern A. Zeeb 		return ret;
1886c92544dSBjoern A. Zeeb 
1896c92544dSBjoern A. Zeeb 	mt76_pci_disable_aspm(pdev);
1906c92544dSBjoern A. Zeeb 
1916c92544dSBjoern A. Zeeb 	mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt76x0e_ops,
1926c92544dSBjoern A. Zeeb 				 &drv_ops);
1936c92544dSBjoern A. Zeeb 	if (!mdev)
1946c92544dSBjoern A. Zeeb 		return -ENOMEM;
1956c92544dSBjoern A. Zeeb 
1966c92544dSBjoern A. Zeeb 	dev = container_of(mdev, struct mt76x02_dev, mt76);
1976c92544dSBjoern A. Zeeb 	mutex_init(&dev->phy_mutex);
1986c92544dSBjoern A. Zeeb 
1996c92544dSBjoern A. Zeeb 	mt76_mmio_init(mdev, pcim_iomap_table(pdev)[0]);
2006c92544dSBjoern A. Zeeb 
2016c92544dSBjoern A. Zeeb 	mdev->rev = mt76_rr(dev, MT_ASIC_VERSION);
2026c92544dSBjoern A. Zeeb 	dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev);
2036c92544dSBjoern A. Zeeb 
2046c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_INT_MASK_CSR, 0);
2056c92544dSBjoern A. Zeeb 
2066c92544dSBjoern A. Zeeb 	ret = devm_request_irq(mdev->dev, pdev->irq, mt76x02_irq_handler,
2076c92544dSBjoern A. Zeeb 			       IRQF_SHARED, KBUILD_MODNAME, dev);
2086c92544dSBjoern A. Zeeb 	if (ret)
2096c92544dSBjoern A. Zeeb 		goto error;
2106c92544dSBjoern A. Zeeb 
2116c92544dSBjoern A. Zeeb 	ret = mt76x0e_register_device(dev);
2126c92544dSBjoern A. Zeeb 	if (ret < 0)
2136c92544dSBjoern A. Zeeb 		goto error;
2146c92544dSBjoern A. Zeeb 
2156c92544dSBjoern A. Zeeb 	return 0;
2166c92544dSBjoern A. Zeeb 
2176c92544dSBjoern A. Zeeb error:
2186c92544dSBjoern A. Zeeb 	mt76_free_device(&dev->mt76);
2196c92544dSBjoern A. Zeeb 
2206c92544dSBjoern A. Zeeb 	return ret;
2216c92544dSBjoern A. Zeeb }
2226c92544dSBjoern A. Zeeb 
mt76x0e_cleanup(struct mt76x02_dev * dev)2236c92544dSBjoern A. Zeeb static void mt76x0e_cleanup(struct mt76x02_dev *dev)
2246c92544dSBjoern A. Zeeb {
2256c92544dSBjoern A. Zeeb 	clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
2266c92544dSBjoern A. Zeeb 	tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
2276c92544dSBjoern A. Zeeb 	mt76x0_chip_onoff(dev, false, false);
2286c92544dSBjoern A. Zeeb 	mt76x0e_stop_hw(dev);
2296c92544dSBjoern A. Zeeb 	mt76_dma_cleanup(&dev->mt76);
2306c92544dSBjoern A. Zeeb 	mt76x02_mcu_cleanup(dev);
2316c92544dSBjoern A. Zeeb }
2326c92544dSBjoern A. Zeeb 
2336c92544dSBjoern A. Zeeb static void
mt76x0e_remove(struct pci_dev * pdev)2346c92544dSBjoern A. Zeeb mt76x0e_remove(struct pci_dev *pdev)
2356c92544dSBjoern A. Zeeb {
2366c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev = pci_get_drvdata(pdev);
2376c92544dSBjoern A. Zeeb 	struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
2386c92544dSBjoern A. Zeeb 
2396c92544dSBjoern A. Zeeb 	mt76_unregister_device(mdev);
2406c92544dSBjoern A. Zeeb 	mt76x0e_cleanup(dev);
2416c92544dSBjoern A. Zeeb 	mt76_free_device(mdev);
2426c92544dSBjoern A. Zeeb }
2436c92544dSBjoern A. Zeeb 
2446c92544dSBjoern A. Zeeb #ifdef CONFIG_PM
mt76x0e_suspend(struct pci_dev * pdev,pm_message_t state)2456c92544dSBjoern A. Zeeb static int mt76x0e_suspend(struct pci_dev *pdev, pm_message_t state)
2466c92544dSBjoern A. Zeeb {
2476c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev = pci_get_drvdata(pdev);
2486c92544dSBjoern A. Zeeb 	struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
2496c92544dSBjoern A. Zeeb 	int i;
2506c92544dSBjoern A. Zeeb 
2516c92544dSBjoern A. Zeeb 	mt76_worker_disable(&mdev->tx_worker);
2526c92544dSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(mdev->phy.q_tx); i++)
2536c92544dSBjoern A. Zeeb 		mt76_queue_tx_cleanup(dev, mdev->phy.q_tx[i], true);
2546c92544dSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(mdev->q_mcu); i++)
2556c92544dSBjoern A. Zeeb 		mt76_queue_tx_cleanup(dev, mdev->q_mcu[i], true);
2566c92544dSBjoern A. Zeeb 	napi_disable(&mdev->tx_napi);
2576c92544dSBjoern A. Zeeb 
2586c92544dSBjoern A. Zeeb 	mt76_for_each_q_rx(mdev, i)
2596c92544dSBjoern A. Zeeb 		napi_disable(&mdev->napi[i]);
2606c92544dSBjoern A. Zeeb 
2616c92544dSBjoern A. Zeeb 	mt76x02_dma_disable(dev);
2626c92544dSBjoern A. Zeeb 	mt76x02_mcu_cleanup(dev);
2636c92544dSBjoern A. Zeeb 	mt76x0_chip_onoff(dev, false, false);
2646c92544dSBjoern A. Zeeb 
2656c92544dSBjoern A. Zeeb 	pci_enable_wake(pdev, pci_choose_state(pdev, state), true);
2666c92544dSBjoern A. Zeeb 	pci_save_state(pdev);
2676c92544dSBjoern A. Zeeb 
2686c92544dSBjoern A. Zeeb 	return pci_set_power_state(pdev, pci_choose_state(pdev, state));
2696c92544dSBjoern A. Zeeb }
2706c92544dSBjoern A. Zeeb 
mt76x0e_resume(struct pci_dev * pdev)2716c92544dSBjoern A. Zeeb static int mt76x0e_resume(struct pci_dev *pdev)
2726c92544dSBjoern A. Zeeb {
2736c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev = pci_get_drvdata(pdev);
2746c92544dSBjoern A. Zeeb 	struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
2756c92544dSBjoern A. Zeeb 	int err, i;
2766c92544dSBjoern A. Zeeb 
2776c92544dSBjoern A. Zeeb 	err = pci_set_power_state(pdev, PCI_D0);
2786c92544dSBjoern A. Zeeb 	if (err)
2796c92544dSBjoern A. Zeeb 		return err;
2806c92544dSBjoern A. Zeeb 
2816c92544dSBjoern A. Zeeb 	pci_restore_state(pdev);
2826c92544dSBjoern A. Zeeb 
2836c92544dSBjoern A. Zeeb 	mt76_worker_enable(&mdev->tx_worker);
2846c92544dSBjoern A. Zeeb 
2856c92544dSBjoern A. Zeeb 	mt76_for_each_q_rx(mdev, i) {
2866c92544dSBjoern A. Zeeb 		mt76_queue_rx_reset(dev, i);
2876c92544dSBjoern A. Zeeb 		napi_enable(&mdev->napi[i]);
288*8ba4d145SBjoern A. Zeeb 	}
289*8ba4d145SBjoern A. Zeeb 	napi_enable(&mdev->tx_napi);
290*8ba4d145SBjoern A. Zeeb 
291*8ba4d145SBjoern A. Zeeb 	local_bh_disable();
292*8ba4d145SBjoern A. Zeeb 	mt76_for_each_q_rx(mdev, i) {
2936c92544dSBjoern A. Zeeb 		napi_schedule(&mdev->napi[i]);
2946c92544dSBjoern A. Zeeb 	}
2956c92544dSBjoern A. Zeeb 	napi_schedule(&mdev->tx_napi);
2966c92544dSBjoern A. Zeeb 	local_bh_enable();
2976c92544dSBjoern A. Zeeb 
2986c92544dSBjoern A. Zeeb 	return mt76x0e_init_hardware(dev, true);
2996c92544dSBjoern A. Zeeb }
3006c92544dSBjoern A. Zeeb #endif /* CONFIG_PM */
3016c92544dSBjoern A. Zeeb 
3026c92544dSBjoern A. Zeeb static const struct pci_device_id mt76x0e_device_table[] = {
3036c92544dSBjoern A. Zeeb 	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7610) },
3046c92544dSBjoern A. Zeeb 	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7630) },
3056c92544dSBjoern A. Zeeb 	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7650) },
3066c92544dSBjoern A. Zeeb 	{ },
3076c92544dSBjoern A. Zeeb };
3086c92544dSBjoern A. Zeeb 
3096c92544dSBjoern A. Zeeb MODULE_DEVICE_TABLE(pci, mt76x0e_device_table);
3106c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7610E_FIRMWARE);
3116c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7650E_FIRMWARE);
312*8ba4d145SBjoern A. Zeeb MODULE_DESCRIPTION("MediaTek MT76x0E (PCIe) wireless driver");
3136c92544dSBjoern A. Zeeb MODULE_LICENSE("Dual BSD/GPL");
3146c92544dSBjoern A. Zeeb 
3156c92544dSBjoern A. Zeeb static struct pci_driver mt76x0e_driver = {
3166c92544dSBjoern A. Zeeb 	.name		= KBUILD_MODNAME,
3176c92544dSBjoern A. Zeeb 	.id_table	= mt76x0e_device_table,
3186c92544dSBjoern A. Zeeb 	.probe		= mt76x0e_probe,
3196c92544dSBjoern A. Zeeb 	.remove		= mt76x0e_remove,
3206c92544dSBjoern A. Zeeb #ifdef CONFIG_PM
3216c92544dSBjoern A. Zeeb 	.suspend	= mt76x0e_suspend,
3226c92544dSBjoern A. Zeeb 	.resume		= mt76x0e_resume,
3236c92544dSBjoern A. Zeeb #endif /* CONFIG_PM */
3246c92544dSBjoern A. Zeeb };
3256c92544dSBjoern A. Zeeb 
3266c92544dSBjoern A. Zeeb module_pci_driver(mt76x0e_driver);
327