diff mbox series

mt76: mt7921e: fix possible probe failure after reboot

Message ID 70e27cbc652cbdb78277b9c691a3a5ba02653afb.1641540175.git.objelf@gmail.com
State New
Headers show
Series mt76: mt7921e: fix possible probe failure after reboot | expand

Commit Message

Sean Wang Jan. 7, 2022, 7:30 a.m. UTC
From: Sean Wang <sean.wang@mediatek.com>

It doesn't guarantee the mt7921e gets started with ASPM L0 after each
machine reboot on every platform.

If mt7921e gets started with not ASPM L0, it would be possible that the
driver encounters time to time failure in mt7921_pci_probe, like a
weird chip identifier is read

[  215.514503] mt7921e 0000:05:00.0: ASIC revision: feed0000
[  216.604741] mt7921e: probe of 0000:05:00.0 failed with error -110

or failing to init hardware because the driver is not allowed to access the
register until the device is in ASPM L0 state. So, we call
__mt7921e_mcu_drv_pmctrl in early mt7921_pci_probe to force the device
to bring back to the L0 state for we can safely access registers in any
case.

In the patch, we move all functions from dma.c to pci.c and register mt76
bus operation earilier, that is the __mt7921e_mcu_drv_pmctrl depends on.

Fixes: bf3747ae2e25 ("mt76: mt7921: enable aspm by default")
Reported-by: Kai-Chuan Hsieh <kaichuan.hsieh@canonical.com>
Co-developed-by: Deren Wu <deren.wu@mediatek.com>
Signed-off-by: Deren Wu <deren.wu@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 .../net/wireless/mediatek/mt76/mt7921/dma.c   | 119 -----------------
 .../wireless/mediatek/mt76/mt7921/mt7921.h    |   1 +
 .../net/wireless/mediatek/mt76/mt7921/pci.c   | 124 ++++++++++++++++++
 .../wireless/mediatek/mt76/mt7921/pci_mcu.c   |  18 ++-
 4 files changed, 139 insertions(+), 123 deletions(-)

Comments

Khalid Aziz Jan. 18, 2022, 6:16 p.m. UTC | #1
On 1/7/22 12:30 AM, sean.wang@mediatek.com wrote:
> From: Sean Wang <sean.wang@mediatek.com>
>
> It doesn't guarantee the mt7921e gets started with ASPM L0 after each
> machine reboot on every platform.
>
> If mt7921e gets started with not ASPM L0, it would be possible that the
> driver encounters time to time failure in mt7921_pci_probe, like a
> weird chip identifier is read
>
> [  215.514503] mt7921e 0000:05:00.0: ASIC revision: feed0000
> [  216.604741] mt7921e: probe of 0000:05:00.0 failed with error -110
>
> or failing to init hardware because the driver is not allowed to access the
> register until the device is in ASPM L0 state. So, we call
> __mt7921e_mcu_drv_pmctrl in early mt7921_pci_probe to force the device
> to bring back to the L0 state for we can safely access registers in any
> case.
>
> In the patch, we move all functions from dma.c to pci.c and register mt76
> bus operation earilier, that is the __mt7921e_mcu_drv_pmctrl depends on.
>
> Fixes: bf3747ae2e25 ("mt76: mt7921: enable aspm by default")
> Reported-by: Kai-Chuan Hsieh <kaichuan.hsieh@canonical.com>
> Co-developed-by: Deren Wu <deren.wu@mediatek.com>
> Signed-off-by: Deren Wu <deren.wu@mediatek.com>
> Signed-off-by: Sean Wang <sean.wang@mediatek.com>


Tested-by: Khalid Aziz <khalid@gonehiking.org>

--
Khalid
> ---
>   .../net/wireless/mediatek/mt76/mt7921/dma.c   | 119 -----------------
>   .../wireless/mediatek/mt76/mt7921/mt7921.h    |   1 +
>   .../net/wireless/mediatek/mt76/mt7921/pci.c   | 124 ++++++++++++++++++
>   .../wireless/mediatek/mt76/mt7921/pci_mcu.c   |  18 ++-
>   4 files changed, 139 insertions(+), 123 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
> index cdff1fd52d93..39d6ce4ecddd 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
> @@ -78,110 +78,6 @@ static void mt7921_dma_prefetch(struct mt7921_dev *dev)
>   	mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4));
>   }
>   
> -static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr)
> -{
> -	static const struct {
> -		u32 phys;
> -		u32 mapped;
> -		u32 size;
> -	} fixed_map[] = {
> -		{ 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */
> -		{ 0x820ed000, 0x24800, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */
> -		{ 0x820e4000, 0x21000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */
> -		{ 0x820e7000, 0x21e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */
> -		{ 0x820eb000, 0x24200, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */
> -		{ 0x820e2000, 0x20800, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */
> -		{ 0x820e3000, 0x20c00, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */
> -		{ 0x820e5000, 0x21400, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */
> -		{ 0x00400000, 0x80000, 0x10000 }, /* WF_MCU_SYSRAM */
> -		{ 0x00410000, 0x90000, 0x10000 }, /* WF_MCU_SYSRAM (configure register) */
> -		{ 0x40000000, 0x70000, 0x10000 }, /* WF_UMAC_SYSRAM */
> -		{ 0x54000000, 0x02000, 0x1000 }, /* WFDMA PCIE0 MCU DMA0 */
> -		{ 0x55000000, 0x03000, 0x1000 }, /* WFDMA PCIE0 MCU DMA1 */
> -		{ 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */
> -		{ 0x59000000, 0x07000, 0x1000 }, /* WFDMA PCIE1 MCU DMA1 */
> -		{ 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */
> -		{ 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */
> -		{ 0x7c060000, 0xe0000, 0x10000 }, /* CONN_INFRA, conn_host_csr_top */
> -		{ 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */
> -		{ 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */
> -		{ 0x820c0000, 0x08000, 0x4000 }, /* WF_UMAC_TOP (PLE) */
> -		{ 0x820c8000, 0x0c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */
> -		{ 0x820cc000, 0x0e000, 0x1000 }, /* WF_UMAC_TOP (PP) */
> -		{ 0x820cd000, 0x0f000, 0x1000 }, /* WF_MDP_TOP */
> -		{ 0x820ce000, 0x21c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */
> -		{ 0x820cf000, 0x22000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */
> -		{ 0x820e0000, 0x20000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */
> -		{ 0x820e1000, 0x20400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */
> -		{ 0x820e9000, 0x23400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
> -		{ 0x820ea000, 0x24000, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */
> -		{ 0x820ec000, 0x24600, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_INT) */
> -		{ 0x820f0000, 0xa0000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */
> -		{ 0x820f1000, 0xa0600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */
> -		{ 0x820f2000, 0xa0800, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */
> -		{ 0x820f3000, 0xa0c00, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */
> -		{ 0x820f4000, 0xa1000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */
> -		{ 0x820f5000, 0xa1400, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */
> -		{ 0x820f7000, 0xa1e00, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */
> -		{ 0x820f9000, 0xa3400, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
> -		{ 0x820fa000, 0xa4000, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */
> -		{ 0x820fb000, 0xa4200, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */
> -		{ 0x820fc000, 0xa4600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_INT) */
> -		{ 0x820fd000, 0xa4800, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */
> -	};
> -	int i;
> -
> -	if (addr < 0x100000)
> -		return addr;
> -
> -	for (i = 0; i < ARRAY_SIZE(fixed_map); i++) {
> -		u32 ofs;
> -
> -		if (addr < fixed_map[i].phys)
> -			continue;
> -
> -		ofs = addr - fixed_map[i].phys;
> -		if (ofs > fixed_map[i].size)
> -			continue;
> -
> -		return fixed_map[i].mapped + ofs;
> -	}
> -
> -	if ((addr >= 0x18000000 && addr < 0x18c00000) ||
> -	    (addr >= 0x70000000 && addr < 0x78000000) ||
> -	    (addr >= 0x7c000000 && addr < 0x7c400000))
> -		return mt7921_reg_map_l1(dev, addr);
> -
> -	dev_err(dev->mt76.dev, "Access currently unsupported address %08x\n",
> -		addr);
> -
> -	return 0;
> -}
> -
> -static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset)
> -{
> -	struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
> -	u32 addr = __mt7921_reg_addr(dev, offset);
> -
> -	return dev->bus_ops->rr(mdev, addr);
> -}
> -
> -static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val)
> -{
> -	struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
> -	u32 addr = __mt7921_reg_addr(dev, offset);
> -
> -	dev->bus_ops->wr(mdev, addr, val);
> -}
> -
> -static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
> -{
> -	struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
> -	u32 addr = __mt7921_reg_addr(dev, offset);
> -
> -	return dev->bus_ops->rmw(mdev, addr, mask, val);
> -}
> -
>   static int mt7921_dma_disable(struct mt7921_dev *dev, bool force)
>   {
>   	if (force) {
> @@ -341,23 +237,8 @@ int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev)
>   
>   int mt7921_dma_init(struct mt7921_dev *dev)
>   {
> -	struct mt76_bus_ops *bus_ops;
>   	int ret;
>   
> -	dev->phy.dev = dev;
> -	dev->phy.mt76 = &dev->mt76.phy;
> -	dev->mt76.phy.priv = &dev->phy;
> -	dev->bus_ops = dev->mt76.bus;
> -	bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
> -			       GFP_KERNEL);
> -	if (!bus_ops)
> -		return -ENOMEM;
> -
> -	bus_ops->rr = mt7921_rr;
> -	bus_ops->wr = mt7921_wr;
> -	bus_ops->rmw = mt7921_rmw;
> -	dev->mt76.bus = bus_ops;
> -
>   	mt76_dma_attach(&dev->mt76);
>   
>   	ret = mt7921_dma_disable(dev, true);
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> index 8b674e042568..63e3c7ef5e89 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> @@ -443,6 +443,7 @@ int mt7921e_mcu_init(struct mt7921_dev *dev);
>   int mt7921s_wfsys_reset(struct mt7921_dev *dev);
>   int mt7921s_mac_reset(struct mt7921_dev *dev);
>   int mt7921s_init_reset(struct mt7921_dev *dev);
> +int __mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev);
>   int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev);
>   int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev);
>   
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
> index 1ae0d5826ca7..a0c82d19c4d9 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
> @@ -121,6 +121,110 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev)
>   	mt76_free_device(&dev->mt76);
>   }
>   
> +static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr)
> +{
> +	static const struct {
> +		u32 phys;
> +		u32 mapped;
> +		u32 size;
> +	} fixed_map[] = {
> +		{ 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */
> +		{ 0x820ed000, 0x24800, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */
> +		{ 0x820e4000, 0x21000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */
> +		{ 0x820e7000, 0x21e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */
> +		{ 0x820eb000, 0x24200, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */
> +		{ 0x820e2000, 0x20800, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */
> +		{ 0x820e3000, 0x20c00, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */
> +		{ 0x820e5000, 0x21400, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */
> +		{ 0x00400000, 0x80000, 0x10000 }, /* WF_MCU_SYSRAM */
> +		{ 0x00410000, 0x90000, 0x10000 }, /* WF_MCU_SYSRAM (configure register) */
> +		{ 0x40000000, 0x70000, 0x10000 }, /* WF_UMAC_SYSRAM */
> +		{ 0x54000000, 0x02000, 0x1000 }, /* WFDMA PCIE0 MCU DMA0 */
> +		{ 0x55000000, 0x03000, 0x1000 }, /* WFDMA PCIE0 MCU DMA1 */
> +		{ 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */
> +		{ 0x59000000, 0x07000, 0x1000 }, /* WFDMA PCIE1 MCU DMA1 */
> +		{ 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */
> +		{ 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */
> +		{ 0x7c060000, 0xe0000, 0x10000 }, /* CONN_INFRA, conn_host_csr_top */
> +		{ 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */
> +		{ 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */
> +		{ 0x820c0000, 0x08000, 0x4000 }, /* WF_UMAC_TOP (PLE) */
> +		{ 0x820c8000, 0x0c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */
> +		{ 0x820cc000, 0x0e000, 0x1000 }, /* WF_UMAC_TOP (PP) */
> +		{ 0x820cd000, 0x0f000, 0x1000 }, /* WF_MDP_TOP */
> +		{ 0x820ce000, 0x21c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */
> +		{ 0x820cf000, 0x22000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */
> +		{ 0x820e0000, 0x20000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */
> +		{ 0x820e1000, 0x20400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */
> +		{ 0x820e9000, 0x23400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
> +		{ 0x820ea000, 0x24000, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */
> +		{ 0x820ec000, 0x24600, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_INT) */
> +		{ 0x820f0000, 0xa0000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */
> +		{ 0x820f1000, 0xa0600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */
> +		{ 0x820f2000, 0xa0800, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */
> +		{ 0x820f3000, 0xa0c00, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */
> +		{ 0x820f4000, 0xa1000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */
> +		{ 0x820f5000, 0xa1400, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */
> +		{ 0x820f7000, 0xa1e00, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */
> +		{ 0x820f9000, 0xa3400, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
> +		{ 0x820fa000, 0xa4000, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */
> +		{ 0x820fb000, 0xa4200, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */
> +		{ 0x820fc000, 0xa4600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_INT) */
> +		{ 0x820fd000, 0xa4800, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */
> +	};
> +	int i;
> +
> +	if (addr < 0x100000)
> +		return addr;
> +
> +	for (i = 0; i < ARRAY_SIZE(fixed_map); i++) {
> +		u32 ofs;
> +
> +		if (addr < fixed_map[i].phys)
> +			continue;
> +
> +		ofs = addr - fixed_map[i].phys;
> +		if (ofs > fixed_map[i].size)
> +			continue;
> +
> +		return fixed_map[i].mapped + ofs;
> +	}
> +
> +	if ((addr >= 0x18000000 && addr < 0x18c00000) ||
> +	    (addr >= 0x70000000 && addr < 0x78000000) ||
> +	    (addr >= 0x7c000000 && addr < 0x7c400000))
> +		return mt7921_reg_map_l1(dev, addr);
> +
> +	dev_err(dev->mt76.dev, "Access currently unsupported address %08x\n",
> +		addr);
> +
> +	return 0;
> +}
> +
> +static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset)
> +{
> +	struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
> +	u32 addr = __mt7921_reg_addr(dev, offset);
> +
> +	return dev->bus_ops->rr(mdev, addr);
> +}
> +
> +static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val)
> +{
> +	struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
> +	u32 addr = __mt7921_reg_addr(dev, offset);
> +
> +	dev->bus_ops->wr(mdev, addr, val);
> +}
> +
> +static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
> +{
> +	struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
> +	u32 addr = __mt7921_reg_addr(dev, offset);
> +
> +	return dev->bus_ops->rmw(mdev, addr, mask, val);
> +}
> +
>   static int mt7921_pci_probe(struct pci_dev *pdev,
>   			    const struct pci_device_id *id)
>   {
> @@ -152,6 +256,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
>   		.fw_own = mt7921e_mcu_fw_pmctrl,
>   	};
>   
> +	struct mt76_bus_ops *bus_ops;
>   	struct mt7921_dev *dev;
>   	struct mt76_dev *mdev;
>   	int ret;
> @@ -189,6 +294,25 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
>   
>   	mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
>   	tasklet_init(&dev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev);
> +
> +	dev->phy.dev = dev;
> +	dev->phy.mt76 = &dev->mt76.phy;
> +	dev->mt76.phy.priv = &dev->phy;
> +	dev->bus_ops = dev->mt76.bus;
> +	bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
> +			       GFP_KERNEL);
> +	if (!bus_ops)
> +		return -ENOMEM;
> +
> +	bus_ops->rr = mt7921_rr;
> +	bus_ops->wr = mt7921_wr;
> +	bus_ops->rmw = mt7921_rmw;
> +	dev->mt76.bus = bus_ops;
> +
> +	ret = __mt7921e_mcu_drv_pmctrl(dev);
> +	if (ret)
> +		return ret;
> +
>   	mdev->rev = (mt7921_l1_rr(dev, MT_HW_CHIPID) << 16) |
>   		    (mt7921_l1_rr(dev, MT_HW_REV) & 0xff);
>   	dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c
> index f9e350b67fdc..36669e5aeef3 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c
> @@ -59,10 +59,8 @@ int mt7921e_mcu_init(struct mt7921_dev *dev)
>   	return err;
>   }
>   
> -int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev)
> +int __mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev)
>   {
> -	struct mt76_phy *mphy = &dev->mt76.phy;
> -	struct mt76_connac_pm *pm = &dev->pm;
>   	int i, err = 0;
>   
>   	for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) {
> @@ -75,9 +73,21 @@ int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev)
>   	if (i == MT7921_DRV_OWN_RETRY_COUNT) {
>   		dev_err(dev->mt76.dev, "driver own failed\n");
>   		err = -EIO;
> -		goto out;
>   	}
>   
> +	return err;
> +}
> +
> +int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev)
> +{
> +	struct mt76_phy *mphy = &dev->mt76.phy;
> +	struct mt76_connac_pm *pm = &dev->pm;
> +	int err;
> +
> +	err = __mt7921e_mcu_drv_pmctrl(dev);
> +	if (err < 0)
> +		goto out;
> +
>   	mt7921_wpdma_reinit_cond(dev);
>   	clear_bit(MT76_STATE_PM, &mphy->state);
>
Mike Lothian Jan. 20, 2022, 9:56 a.m. UTC | #2
Hi

I get a BUG and the kernel resuses to boot with this patch when mt76 is compiled into the kernel

https://bugzilla.kernel.org/show_bug.cgi?id=214557

I don't see this issue when mt76 is compiled as a module

My .config is at https://github.com/FireBurn/KernelStuff/blob/master/dot_config_tip

Let me know if you'd like any more info

Cheers

Mike
Janusz Dziedzic Jan. 21, 2022, 6:33 a.m. UTC | #3
pt., 21 sty 2022 o 00:23 Khalid Aziz <khalid@gonehiking.org> napisaƂ(a):
>
> On 1/7/22 12:30 AM, sean.wang@mediatek.com wrote:
> > From: Sean Wang <sean.wang@mediatek.com>
> >
> > It doesn't guarantee the mt7921e gets started with ASPM L0 after each
> > machine reboot on every platform.
> >
> > If mt7921e gets started with not ASPM L0, it would be possible that the
> > driver encounters time to time failure in mt7921_pci_probe, like a
> > weird chip identifier is read
> >
> > [  215.514503] mt7921e 0000:05:00.0: ASIC revision: feed0000
> > [  216.604741] mt7921e: probe of 0000:05:00.0 failed with error -110
> >
> > or failing to init hardware because the driver is not allowed to access the
> > register until the device is in ASPM L0 state. So, we call
> > __mt7921e_mcu_drv_pmctrl in early mt7921_pci_probe to force the device
> > to bring back to the L0 state for we can safely access registers in any
> > case.
> >

BTW, probably I see something similar with mt7915e (inside ramips):

Have mt7915e in my mt7621 (mt7621-pci) router (pandora box/ramips).
After fresh start (disconnect/connect power supply/cold reset) works correctly.
After reboot seems to always fail with:
Sat Dec 18 08:43:58 2021 kern.info kernel: [   14.552269] mt7621-pci
1e140000.pcie: bus=3 slot=2 irq=25
Sat Dec 18 08:43:58 2021 kern.info kernel: [   14.557823] pci
0000:00:02.0: enabling device (0000 -> 0003)
Sat Dec 18 08:43:58 2021 kern.info kernel: [   14.563499] mt7915e
0000:03:00.0: enabling device (0000 -> 0002)
Sat Dec 18 08:43:58 2021 kern.err kernel: [   35.094270] mt7915e
0000:03:00.0: Message 00000010 (seq 1) timeout
Sat Dec 18 08:43:58 2021 kern.err kernel: [   35.100457] mt7915e
0000:03:00.0: Failed to get patch semaphore
Sat Dec 18 08:43:58 2021 kern.err kernel: [   55.574220] mt7915e
0000:03:00.0: Message 00000010 (seq 2) timeout
Sat Dec 18 08:43:58 2021 kern.err kernel: [   55.580380] mt7915e
0000:03:00.0: Failed to get patch semaphore
Sat Dec 18 08:43:58 2021 kern.warn kernel: [   55.586529] mt7915e:
probe of 0000:03:00.0 failed with error -11


This is lspci output:
02:00.0 Network controller: MEDIATEK Corp. MT7612E 802.11acbgn PCI
Express Wireless Network Adapter
03:00.0 Unclassified device [0002]: MEDIATEK Corp. MT7915E 802.11ax
PCI Express Wireless Network Adapter

Detection works correctly after disconnect/connect power supply (cold reboot).

I don't see this issue (same HW/card) with.
 - my laptop x86_64
 - banana_pi aarch64

Any idea this could be same/similar issue and there is possible fix for that?

BR
Janusz



> > In the patch, we move all functions from dma.c to pci.c and register mt76
> > bus operation earilier, that is the __mt7921e_mcu_drv_pmctrl depends on.
> >
> > Fixes: bf3747ae2e25 ("mt76: mt7921: enable aspm by default")
> > Reported-by: Kai-Chuan Hsieh <kaichuan.hsieh@canonical.com>
> > Co-developed-by: Deren Wu <deren.wu@mediatek.com>
> > Signed-off-by: Deren Wu <deren.wu@mediatek.com>
> > Signed-off-by: Sean Wang <sean.wang@mediatek.com>
>
>
> Tested-by: Khalid Aziz <khalid@gonehiking.org>
>
> --
> Khalid
> > ---
> >   .../net/wireless/mediatek/mt76/mt7921/dma.c   | 119 -----------------
> >   .../wireless/mediatek/mt76/mt7921/mt7921.h    |   1 +
> >   .../net/wireless/mediatek/mt76/mt7921/pci.c   | 124 ++++++++++++++++++
> >   .../wireless/mediatek/mt76/mt7921/pci_mcu.c   |  18 ++-
> >   4 files changed, 139 insertions(+), 123 deletions(-)
> >
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
> > index cdff1fd52d93..39d6ce4ecddd 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
> > @@ -78,110 +78,6 @@ static void mt7921_dma_prefetch(struct mt7921_dev *dev)
> >       mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4));
> >   }
> >
> > -static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr)
> > -{
> > -     static const struct {
> > -             u32 phys;
> > -             u32 mapped;
> > -             u32 size;
> > -     } fixed_map[] = {
> > -             { 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */
> > -             { 0x820ed000, 0x24800, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */
> > -             { 0x820e4000, 0x21000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */
> > -             { 0x820e7000, 0x21e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */
> > -             { 0x820eb000, 0x24200, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */
> > -             { 0x820e2000, 0x20800, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */
> > -             { 0x820e3000, 0x20c00, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */
> > -             { 0x820e5000, 0x21400, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */
> > -             { 0x00400000, 0x80000, 0x10000 }, /* WF_MCU_SYSRAM */
> > -             { 0x00410000, 0x90000, 0x10000 }, /* WF_MCU_SYSRAM (configure register) */
> > -             { 0x40000000, 0x70000, 0x10000 }, /* WF_UMAC_SYSRAM */
> > -             { 0x54000000, 0x02000, 0x1000 }, /* WFDMA PCIE0 MCU DMA0 */
> > -             { 0x55000000, 0x03000, 0x1000 }, /* WFDMA PCIE0 MCU DMA1 */
> > -             { 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */
> > -             { 0x59000000, 0x07000, 0x1000 }, /* WFDMA PCIE1 MCU DMA1 */
> > -             { 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */
> > -             { 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */
> > -             { 0x7c060000, 0xe0000, 0x10000 }, /* CONN_INFRA, conn_host_csr_top */
> > -             { 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */
> > -             { 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */
> > -             { 0x820c0000, 0x08000, 0x4000 }, /* WF_UMAC_TOP (PLE) */
> > -             { 0x820c8000, 0x0c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */
> > -             { 0x820cc000, 0x0e000, 0x1000 }, /* WF_UMAC_TOP (PP) */
> > -             { 0x820cd000, 0x0f000, 0x1000 }, /* WF_MDP_TOP */
> > -             { 0x820ce000, 0x21c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */
> > -             { 0x820cf000, 0x22000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */
> > -             { 0x820e0000, 0x20000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */
> > -             { 0x820e1000, 0x20400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */
> > -             { 0x820e9000, 0x23400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
> > -             { 0x820ea000, 0x24000, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */
> > -             { 0x820ec000, 0x24600, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_INT) */
> > -             { 0x820f0000, 0xa0000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */
> > -             { 0x820f1000, 0xa0600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */
> > -             { 0x820f2000, 0xa0800, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */
> > -             { 0x820f3000, 0xa0c00, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */
> > -             { 0x820f4000, 0xa1000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */
> > -             { 0x820f5000, 0xa1400, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */
> > -             { 0x820f7000, 0xa1e00, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */
> > -             { 0x820f9000, 0xa3400, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
> > -             { 0x820fa000, 0xa4000, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */
> > -             { 0x820fb000, 0xa4200, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */
> > -             { 0x820fc000, 0xa4600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_INT) */
> > -             { 0x820fd000, 0xa4800, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */
> > -     };
> > -     int i;
> > -
> > -     if (addr < 0x100000)
> > -             return addr;
> > -
> > -     for (i = 0; i < ARRAY_SIZE(fixed_map); i++) {
> > -             u32 ofs;
> > -
> > -             if (addr < fixed_map[i].phys)
> > -                     continue;
> > -
> > -             ofs = addr - fixed_map[i].phys;
> > -             if (ofs > fixed_map[i].size)
> > -                     continue;
> > -
> > -             return fixed_map[i].mapped + ofs;
> > -     }
> > -
> > -     if ((addr >= 0x18000000 && addr < 0x18c00000) ||
> > -         (addr >= 0x70000000 && addr < 0x78000000) ||
> > -         (addr >= 0x7c000000 && addr < 0x7c400000))
> > -             return mt7921_reg_map_l1(dev, addr);
> > -
> > -     dev_err(dev->mt76.dev, "Access currently unsupported address %08x\n",
> > -             addr);
> > -
> > -     return 0;
> > -}
> > -
> > -static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset)
> > -{
> > -     struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
> > -     u32 addr = __mt7921_reg_addr(dev, offset);
> > -
> > -     return dev->bus_ops->rr(mdev, addr);
> > -}
> > -
> > -static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val)
> > -{
> > -     struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
> > -     u32 addr = __mt7921_reg_addr(dev, offset);
> > -
> > -     dev->bus_ops->wr(mdev, addr, val);
> > -}
> > -
> > -static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
> > -{
> > -     struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
> > -     u32 addr = __mt7921_reg_addr(dev, offset);
> > -
> > -     return dev->bus_ops->rmw(mdev, addr, mask, val);
> > -}
> > -
> >   static int mt7921_dma_disable(struct mt7921_dev *dev, bool force)
> >   {
> >       if (force) {
> > @@ -341,23 +237,8 @@ int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev)
> >
> >   int mt7921_dma_init(struct mt7921_dev *dev)
> >   {
> > -     struct mt76_bus_ops *bus_ops;
> >       int ret;
> >
> > -     dev->phy.dev = dev;
> > -     dev->phy.mt76 = &dev->mt76.phy;
> > -     dev->mt76.phy.priv = &dev->phy;
> > -     dev->bus_ops = dev->mt76.bus;
> > -     bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
> > -                            GFP_KERNEL);
> > -     if (!bus_ops)
> > -             return -ENOMEM;
> > -
> > -     bus_ops->rr = mt7921_rr;
> > -     bus_ops->wr = mt7921_wr;
> > -     bus_ops->rmw = mt7921_rmw;
> > -     dev->mt76.bus = bus_ops;
> > -
> >       mt76_dma_attach(&dev->mt76);
> >
> >       ret = mt7921_dma_disable(dev, true);
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> > index 8b674e042568..63e3c7ef5e89 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> > @@ -443,6 +443,7 @@ int mt7921e_mcu_init(struct mt7921_dev *dev);
> >   int mt7921s_wfsys_reset(struct mt7921_dev *dev);
> >   int mt7921s_mac_reset(struct mt7921_dev *dev);
> >   int mt7921s_init_reset(struct mt7921_dev *dev);
> > +int __mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev);
> >   int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev);
> >   int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev);
> >
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
> > index 1ae0d5826ca7..a0c82d19c4d9 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
> > @@ -121,6 +121,110 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev)
> >       mt76_free_device(&dev->mt76);
> >   }
> >
> > +static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr)
> > +{
> > +     static const struct {
> > +             u32 phys;
> > +             u32 mapped;
> > +             u32 size;
> > +     } fixed_map[] = {
> > +             { 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */
> > +             { 0x820ed000, 0x24800, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */
> > +             { 0x820e4000, 0x21000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */
> > +             { 0x820e7000, 0x21e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */
> > +             { 0x820eb000, 0x24200, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */
> > +             { 0x820e2000, 0x20800, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */
> > +             { 0x820e3000, 0x20c00, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */
> > +             { 0x820e5000, 0x21400, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */
> > +             { 0x00400000, 0x80000, 0x10000 }, /* WF_MCU_SYSRAM */
> > +             { 0x00410000, 0x90000, 0x10000 }, /* WF_MCU_SYSRAM (configure register) */
> > +             { 0x40000000, 0x70000, 0x10000 }, /* WF_UMAC_SYSRAM */
> > +             { 0x54000000, 0x02000, 0x1000 }, /* WFDMA PCIE0 MCU DMA0 */
> > +             { 0x55000000, 0x03000, 0x1000 }, /* WFDMA PCIE0 MCU DMA1 */
> > +             { 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */
> > +             { 0x59000000, 0x07000, 0x1000 }, /* WFDMA PCIE1 MCU DMA1 */
> > +             { 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */
> > +             { 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */
> > +             { 0x7c060000, 0xe0000, 0x10000 }, /* CONN_INFRA, conn_host_csr_top */
> > +             { 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */
> > +             { 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */
> > +             { 0x820c0000, 0x08000, 0x4000 }, /* WF_UMAC_TOP (PLE) */
> > +             { 0x820c8000, 0x0c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */
> > +             { 0x820cc000, 0x0e000, 0x1000 }, /* WF_UMAC_TOP (PP) */
> > +             { 0x820cd000, 0x0f000, 0x1000 }, /* WF_MDP_TOP */
> > +             { 0x820ce000, 0x21c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */
> > +             { 0x820cf000, 0x22000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */
> > +             { 0x820e0000, 0x20000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */
> > +             { 0x820e1000, 0x20400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */
> > +             { 0x820e9000, 0x23400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
> > +             { 0x820ea000, 0x24000, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */
> > +             { 0x820ec000, 0x24600, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_INT) */
> > +             { 0x820f0000, 0xa0000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */
> > +             { 0x820f1000, 0xa0600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */
> > +             { 0x820f2000, 0xa0800, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */
> > +             { 0x820f3000, 0xa0c00, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */
> > +             { 0x820f4000, 0xa1000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */
> > +             { 0x820f5000, 0xa1400, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */
> > +             { 0x820f7000, 0xa1e00, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */
> > +             { 0x820f9000, 0xa3400, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
> > +             { 0x820fa000, 0xa4000, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */
> > +             { 0x820fb000, 0xa4200, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */
> > +             { 0x820fc000, 0xa4600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_INT) */
> > +             { 0x820fd000, 0xa4800, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */
> > +     };
> > +     int i;
> > +
> > +     if (addr < 0x100000)
> > +             return addr;
> > +
> > +     for (i = 0; i < ARRAY_SIZE(fixed_map); i++) {
> > +             u32 ofs;
> > +
> > +             if (addr < fixed_map[i].phys)
> > +                     continue;
> > +
> > +             ofs = addr - fixed_map[i].phys;
> > +             if (ofs > fixed_map[i].size)
> > +                     continue;
> > +
> > +             return fixed_map[i].mapped + ofs;
> > +     }
> > +
> > +     if ((addr >= 0x18000000 && addr < 0x18c00000) ||
> > +         (addr >= 0x70000000 && addr < 0x78000000) ||
> > +         (addr >= 0x7c000000 && addr < 0x7c400000))
> > +             return mt7921_reg_map_l1(dev, addr);
> > +
> > +     dev_err(dev->mt76.dev, "Access currently unsupported address %08x\n",
> > +             addr);
> > +
> > +     return 0;
> > +}
> > +
> > +static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset)
> > +{
> > +     struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
> > +     u32 addr = __mt7921_reg_addr(dev, offset);
> > +
> > +     return dev->bus_ops->rr(mdev, addr);
> > +}
> > +
> > +static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val)
> > +{
> > +     struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
> > +     u32 addr = __mt7921_reg_addr(dev, offset);
> > +
> > +     dev->bus_ops->wr(mdev, addr, val);
> > +}
> > +
> > +static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
> > +{
> > +     struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
> > +     u32 addr = __mt7921_reg_addr(dev, offset);
> > +
> > +     return dev->bus_ops->rmw(mdev, addr, mask, val);
> > +}
> > +
> >   static int mt7921_pci_probe(struct pci_dev *pdev,
> >                           const struct pci_device_id *id)
> >   {
> > @@ -152,6 +256,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
> >               .fw_own = mt7921e_mcu_fw_pmctrl,
> >       };
> >
> > +     struct mt76_bus_ops *bus_ops;
> >       struct mt7921_dev *dev;
> >       struct mt76_dev *mdev;
> >       int ret;
> > @@ -189,6 +294,25 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
> >
> >       mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
> >       tasklet_init(&dev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev);
> > +
> > +     dev->phy.dev = dev;
> > +     dev->phy.mt76 = &dev->mt76.phy;
> > +     dev->mt76.phy.priv = &dev->phy;
> > +     dev->bus_ops = dev->mt76.bus;
> > +     bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
> > +                            GFP_KERNEL);
> > +     if (!bus_ops)
> > +             return -ENOMEM;
> > +
> > +     bus_ops->rr = mt7921_rr;
> > +     bus_ops->wr = mt7921_wr;
> > +     bus_ops->rmw = mt7921_rmw;
> > +     dev->mt76.bus = bus_ops;
> > +
> > +     ret = __mt7921e_mcu_drv_pmctrl(dev);
> > +     if (ret)
> > +             return ret;
> > +
> >       mdev->rev = (mt7921_l1_rr(dev, MT_HW_CHIPID) << 16) |
> >                   (mt7921_l1_rr(dev, MT_HW_REV) & 0xff);
> >       dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c
> > index f9e350b67fdc..36669e5aeef3 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c
> > @@ -59,10 +59,8 @@ int mt7921e_mcu_init(struct mt7921_dev *dev)
> >       return err;
> >   }
> >
> > -int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev)
> > +int __mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev)
> >   {
> > -     struct mt76_phy *mphy = &dev->mt76.phy;
> > -     struct mt76_connac_pm *pm = &dev->pm;
> >       int i, err = 0;
> >
> >       for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) {
> > @@ -75,9 +73,21 @@ int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev)
> >       if (i == MT7921_DRV_OWN_RETRY_COUNT) {
> >               dev_err(dev->mt76.dev, "driver own failed\n");
> >               err = -EIO;
> > -             goto out;
> >       }
> >
> > +     return err;
> > +}
> > +
> > +int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev)
> > +{
> > +     struct mt76_phy *mphy = &dev->mt76.phy;
> > +     struct mt76_connac_pm *pm = &dev->pm;
> > +     int err;
> > +
> > +     err = __mt7921e_mcu_drv_pmctrl(dev);
> > +     if (err < 0)
> > +             goto out;
> > +
> >       mt7921_wpdma_reinit_cond(dev);
> >       clear_bit(MT76_STATE_PM, &mphy->state);
> >
>
>


--
Janusz Dziedzic
Mike Lothian Jan. 25, 2022, 2:16 p.m. UTC | #4
On Thu, 20 Jan 2022 at 09:56, Mike Lothian <mike@fireburn.co.uk> wrote:
>
> Hi
>
> I get a BUG and the kernel resuses to boot with this patch when mt76 is compiled into the kernel
>
> https://bugzilla.kernel.org/show_bug.cgi?id=214557
>
> I don't see this issue when mt76 is compiled as a module
>
> My .config is at https://github.com/FireBurn/KernelStuff/blob/master/dot_config_tip
>
> Let me know if you'd like any more info
>
> Cheers
>
> Mike

The bug I was hitting was due to a different change introduced in rc1,
with that reverted your patches work great

Though I am seeing lots of these messages from the bluetooth device:

Bluetooth: hci0: unexpected event 0xff length: 5 > 0

I'll bisect that next

Thanks

Mike
Ben Greear Jan. 25, 2022, 6:09 p.m. UTC | #5
On 1/25/22 6:16 AM, Mike Lothian wrote:
> On Thu, 20 Jan 2022 at 09:56, Mike Lothian <mike@fireburn.co.uk> wrote:
>>
>> Hi
>>
>> I get a BUG and the kernel resuses to boot with this patch when mt76 is compiled into the kernel
>>
>> https://bugzilla.kernel.org/show_bug.cgi?id=214557
>>
>> I don't see this issue when mt76 is compiled as a module
>>
>> My .config is at https://github.com/FireBurn/KernelStuff/blob/master/dot_config_tip
>>
>> Let me know if you'd like any more info
>>
>> Cheers
>>
>> Mike
> 
> The bug I was hitting was due to a different change introduced in rc1,
> with that reverted your patches work great

What patch did you revert?

Thanks,
Ben

> 
> Though I am seeing lots of these messages from the bluetooth device:
> 
> Bluetooth: hci0: unexpected event 0xff length: 5 > 0
> 
> I'll bisect that next
> 
> Thanks
> 
> Mike
>
Mike Lothian Jan. 25, 2022, 10:56 p.m. UTC | #6
On Tue, 25 Jan 2022 at 18:09, Ben Greear <greearb@candelatech.com> wrote:
>
> On 1/25/22 6:16 AM, Mike Lothian wrote:
> > On Thu, 20 Jan 2022 at 09:56, Mike Lothian <mike@fireburn.co.uk> wrote:
> >>
> >> Hi
> >>
> >> I get a BUG and the kernel resuses to boot with this patch when mt76 is compiled into the kernel
> >>
> >> https://bugzilla.kernel.org/show_bug.cgi?id=214557
> >>
> >> I don't see this issue when mt76 is compiled as a module
> >>
> >> My .config is at https://github.com/FireBurn/KernelStuff/blob/master/dot_config_tip
> >>
> >> Let me know if you'd like any more info
> >>
> >> Cheers
> >>
> >> Mike
> >
> > The bug I was hitting was due to a different change introduced in rc1,
> > with that reverted your patches work great
>
> What patch did you revert?
>
> Thanks,
> Ben
>

Hi

I reverted both 730b49aac426e1e8016d3c2dd6b407e500423821 and
510a0bdb2bfcff8d7be822c72adc3add7a97d559

But there's a fix now,
https://patchwork.kernel.org/project/linux-usb/patch/20220124090228.41396-2-heikki.krogerus@linux.intel.com/

I'm able to load mt76 as a module or built in

Cheers

Mike
diff mbox series

Patch

diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
index cdff1fd52d93..39d6ce4ecddd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
@@ -78,110 +78,6 @@  static void mt7921_dma_prefetch(struct mt7921_dev *dev)
 	mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4));
 }
 
-static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr)
-{
-	static const struct {
-		u32 phys;
-		u32 mapped;
-		u32 size;
-	} fixed_map[] = {
-		{ 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */
-		{ 0x820ed000, 0x24800, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */
-		{ 0x820e4000, 0x21000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */
-		{ 0x820e7000, 0x21e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */
-		{ 0x820eb000, 0x24200, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */
-		{ 0x820e2000, 0x20800, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */
-		{ 0x820e3000, 0x20c00, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */
-		{ 0x820e5000, 0x21400, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */
-		{ 0x00400000, 0x80000, 0x10000 }, /* WF_MCU_SYSRAM */
-		{ 0x00410000, 0x90000, 0x10000 }, /* WF_MCU_SYSRAM (configure register) */
-		{ 0x40000000, 0x70000, 0x10000 }, /* WF_UMAC_SYSRAM */
-		{ 0x54000000, 0x02000, 0x1000 }, /* WFDMA PCIE0 MCU DMA0 */
-		{ 0x55000000, 0x03000, 0x1000 }, /* WFDMA PCIE0 MCU DMA1 */
-		{ 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */
-		{ 0x59000000, 0x07000, 0x1000 }, /* WFDMA PCIE1 MCU DMA1 */
-		{ 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */
-		{ 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */
-		{ 0x7c060000, 0xe0000, 0x10000 }, /* CONN_INFRA, conn_host_csr_top */
-		{ 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */
-		{ 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */
-		{ 0x820c0000, 0x08000, 0x4000 }, /* WF_UMAC_TOP (PLE) */
-		{ 0x820c8000, 0x0c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */
-		{ 0x820cc000, 0x0e000, 0x1000 }, /* WF_UMAC_TOP (PP) */
-		{ 0x820cd000, 0x0f000, 0x1000 }, /* WF_MDP_TOP */
-		{ 0x820ce000, 0x21c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */
-		{ 0x820cf000, 0x22000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */
-		{ 0x820e0000, 0x20000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */
-		{ 0x820e1000, 0x20400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */
-		{ 0x820e9000, 0x23400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
-		{ 0x820ea000, 0x24000, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */
-		{ 0x820ec000, 0x24600, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_INT) */
-		{ 0x820f0000, 0xa0000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */
-		{ 0x820f1000, 0xa0600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */
-		{ 0x820f2000, 0xa0800, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */
-		{ 0x820f3000, 0xa0c00, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */
-		{ 0x820f4000, 0xa1000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */
-		{ 0x820f5000, 0xa1400, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */
-		{ 0x820f7000, 0xa1e00, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */
-		{ 0x820f9000, 0xa3400, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
-		{ 0x820fa000, 0xa4000, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */
-		{ 0x820fb000, 0xa4200, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */
-		{ 0x820fc000, 0xa4600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_INT) */
-		{ 0x820fd000, 0xa4800, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */
-	};
-	int i;
-
-	if (addr < 0x100000)
-		return addr;
-
-	for (i = 0; i < ARRAY_SIZE(fixed_map); i++) {
-		u32 ofs;
-
-		if (addr < fixed_map[i].phys)
-			continue;
-
-		ofs = addr - fixed_map[i].phys;
-		if (ofs > fixed_map[i].size)
-			continue;
-
-		return fixed_map[i].mapped + ofs;
-	}
-
-	if ((addr >= 0x18000000 && addr < 0x18c00000) ||
-	    (addr >= 0x70000000 && addr < 0x78000000) ||
-	    (addr >= 0x7c000000 && addr < 0x7c400000))
-		return mt7921_reg_map_l1(dev, addr);
-
-	dev_err(dev->mt76.dev, "Access currently unsupported address %08x\n",
-		addr);
-
-	return 0;
-}
-
-static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset)
-{
-	struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
-	u32 addr = __mt7921_reg_addr(dev, offset);
-
-	return dev->bus_ops->rr(mdev, addr);
-}
-
-static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val)
-{
-	struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
-	u32 addr = __mt7921_reg_addr(dev, offset);
-
-	dev->bus_ops->wr(mdev, addr, val);
-}
-
-static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
-{
-	struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
-	u32 addr = __mt7921_reg_addr(dev, offset);
-
-	return dev->bus_ops->rmw(mdev, addr, mask, val);
-}
-
 static int mt7921_dma_disable(struct mt7921_dev *dev, bool force)
 {
 	if (force) {
@@ -341,23 +237,8 @@  int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev)
 
 int mt7921_dma_init(struct mt7921_dev *dev)
 {
-	struct mt76_bus_ops *bus_ops;
 	int ret;
 
-	dev->phy.dev = dev;
-	dev->phy.mt76 = &dev->mt76.phy;
-	dev->mt76.phy.priv = &dev->phy;
-	dev->bus_ops = dev->mt76.bus;
-	bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
-			       GFP_KERNEL);
-	if (!bus_ops)
-		return -ENOMEM;
-
-	bus_ops->rr = mt7921_rr;
-	bus_ops->wr = mt7921_wr;
-	bus_ops->rmw = mt7921_rmw;
-	dev->mt76.bus = bus_ops;
-
 	mt76_dma_attach(&dev->mt76);
 
 	ret = mt7921_dma_disable(dev, true);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
index 8b674e042568..63e3c7ef5e89 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
@@ -443,6 +443,7 @@  int mt7921e_mcu_init(struct mt7921_dev *dev);
 int mt7921s_wfsys_reset(struct mt7921_dev *dev);
 int mt7921s_mac_reset(struct mt7921_dev *dev);
 int mt7921s_init_reset(struct mt7921_dev *dev);
+int __mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev);
 int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev);
 int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
index 1ae0d5826ca7..a0c82d19c4d9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
@@ -121,6 +121,110 @@  static void mt7921e_unregister_device(struct mt7921_dev *dev)
 	mt76_free_device(&dev->mt76);
 }
 
+static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr)
+{
+	static const struct {
+		u32 phys;
+		u32 mapped;
+		u32 size;
+	} fixed_map[] = {
+		{ 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */
+		{ 0x820ed000, 0x24800, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */
+		{ 0x820e4000, 0x21000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */
+		{ 0x820e7000, 0x21e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */
+		{ 0x820eb000, 0x24200, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */
+		{ 0x820e2000, 0x20800, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */
+		{ 0x820e3000, 0x20c00, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */
+		{ 0x820e5000, 0x21400, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */
+		{ 0x00400000, 0x80000, 0x10000 }, /* WF_MCU_SYSRAM */
+		{ 0x00410000, 0x90000, 0x10000 }, /* WF_MCU_SYSRAM (configure register) */
+		{ 0x40000000, 0x70000, 0x10000 }, /* WF_UMAC_SYSRAM */
+		{ 0x54000000, 0x02000, 0x1000 }, /* WFDMA PCIE0 MCU DMA0 */
+		{ 0x55000000, 0x03000, 0x1000 }, /* WFDMA PCIE0 MCU DMA1 */
+		{ 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */
+		{ 0x59000000, 0x07000, 0x1000 }, /* WFDMA PCIE1 MCU DMA1 */
+		{ 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */
+		{ 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */
+		{ 0x7c060000, 0xe0000, 0x10000 }, /* CONN_INFRA, conn_host_csr_top */
+		{ 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */
+		{ 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */
+		{ 0x820c0000, 0x08000, 0x4000 }, /* WF_UMAC_TOP (PLE) */
+		{ 0x820c8000, 0x0c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */
+		{ 0x820cc000, 0x0e000, 0x1000 }, /* WF_UMAC_TOP (PP) */
+		{ 0x820cd000, 0x0f000, 0x1000 }, /* WF_MDP_TOP */
+		{ 0x820ce000, 0x21c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */
+		{ 0x820cf000, 0x22000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */
+		{ 0x820e0000, 0x20000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */
+		{ 0x820e1000, 0x20400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */
+		{ 0x820e9000, 0x23400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
+		{ 0x820ea000, 0x24000, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */
+		{ 0x820ec000, 0x24600, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_INT) */
+		{ 0x820f0000, 0xa0000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */
+		{ 0x820f1000, 0xa0600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */
+		{ 0x820f2000, 0xa0800, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */
+		{ 0x820f3000, 0xa0c00, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */
+		{ 0x820f4000, 0xa1000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */
+		{ 0x820f5000, 0xa1400, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */
+		{ 0x820f7000, 0xa1e00, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */
+		{ 0x820f9000, 0xa3400, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
+		{ 0x820fa000, 0xa4000, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */
+		{ 0x820fb000, 0xa4200, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */
+		{ 0x820fc000, 0xa4600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_INT) */
+		{ 0x820fd000, 0xa4800, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */
+	};
+	int i;
+
+	if (addr < 0x100000)
+		return addr;
+
+	for (i = 0; i < ARRAY_SIZE(fixed_map); i++) {
+		u32 ofs;
+
+		if (addr < fixed_map[i].phys)
+			continue;
+
+		ofs = addr - fixed_map[i].phys;
+		if (ofs > fixed_map[i].size)
+			continue;
+
+		return fixed_map[i].mapped + ofs;
+	}
+
+	if ((addr >= 0x18000000 && addr < 0x18c00000) ||
+	    (addr >= 0x70000000 && addr < 0x78000000) ||
+	    (addr >= 0x7c000000 && addr < 0x7c400000))
+		return mt7921_reg_map_l1(dev, addr);
+
+	dev_err(dev->mt76.dev, "Access currently unsupported address %08x\n",
+		addr);
+
+	return 0;
+}
+
+static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset)
+{
+	struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
+	u32 addr = __mt7921_reg_addr(dev, offset);
+
+	return dev->bus_ops->rr(mdev, addr);
+}
+
+static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val)
+{
+	struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
+	u32 addr = __mt7921_reg_addr(dev, offset);
+
+	dev->bus_ops->wr(mdev, addr, val);
+}
+
+static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
+{
+	struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
+	u32 addr = __mt7921_reg_addr(dev, offset);
+
+	return dev->bus_ops->rmw(mdev, addr, mask, val);
+}
+
 static int mt7921_pci_probe(struct pci_dev *pdev,
 			    const struct pci_device_id *id)
 {
@@ -152,6 +256,7 @@  static int mt7921_pci_probe(struct pci_dev *pdev,
 		.fw_own = mt7921e_mcu_fw_pmctrl,
 	};
 
+	struct mt76_bus_ops *bus_ops;
 	struct mt7921_dev *dev;
 	struct mt76_dev *mdev;
 	int ret;
@@ -189,6 +294,25 @@  static int mt7921_pci_probe(struct pci_dev *pdev,
 
 	mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
 	tasklet_init(&dev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev);
+
+	dev->phy.dev = dev;
+	dev->phy.mt76 = &dev->mt76.phy;
+	dev->mt76.phy.priv = &dev->phy;
+	dev->bus_ops = dev->mt76.bus;
+	bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
+			       GFP_KERNEL);
+	if (!bus_ops)
+		return -ENOMEM;
+
+	bus_ops->rr = mt7921_rr;
+	bus_ops->wr = mt7921_wr;
+	bus_ops->rmw = mt7921_rmw;
+	dev->mt76.bus = bus_ops;
+
+	ret = __mt7921e_mcu_drv_pmctrl(dev);
+	if (ret)
+		return ret;
+
 	mdev->rev = (mt7921_l1_rr(dev, MT_HW_CHIPID) << 16) |
 		    (mt7921_l1_rr(dev, MT_HW_REV) & 0xff);
 	dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c
index f9e350b67fdc..36669e5aeef3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c
@@ -59,10 +59,8 @@  int mt7921e_mcu_init(struct mt7921_dev *dev)
 	return err;
 }
 
-int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev)
+int __mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev)
 {
-	struct mt76_phy *mphy = &dev->mt76.phy;
-	struct mt76_connac_pm *pm = &dev->pm;
 	int i, err = 0;
 
 	for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) {
@@ -75,9 +73,21 @@  int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev)
 	if (i == MT7921_DRV_OWN_RETRY_COUNT) {
 		dev_err(dev->mt76.dev, "driver own failed\n");
 		err = -EIO;
-		goto out;
 	}
 
+	return err;
+}
+
+int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev)
+{
+	struct mt76_phy *mphy = &dev->mt76.phy;
+	struct mt76_connac_pm *pm = &dev->pm;
+	int err;
+
+	err = __mt7921e_mcu_drv_pmctrl(dev);
+	if (err < 0)
+		goto out;
+
 	mt7921_wpdma_reinit_cond(dev);
 	clear_bit(MT76_STATE_PM, &mphy->state);