[PATCH v3 2/4] wifi: mt76: mt7915: enable full system reset support

Ryder Lee Ryder.Lee at mediatek.com
Sat Nov 12 13:48:43 PST 2022


On Sat, 2022-11-12 at 17:13 +0100, Lorenzo Bianconi wrote:
> > > From: Bo Jiao <bo.jiao at mediatek.com>
> > > 
> > > Add mt7915_reset() and refactor mt7915_mac_reset_work() to
> > > support
> > > full system recovery.
> > > 
> > > Co-developed-by: Ryder Lee <ryder.lee at mediatek.com>
> > > Signed-off-by: Ryder Lee <ryder.lee at mediatek.com>
> > > Signed-off-by: Bo Jiao <bo.jiao at mediatek.com>
> > > ---
> > > change since v2 - change dev_info to make it easier to see that
> > > firmware crashed while looking at dmesg.
> > > ---
> > >  .../net/wireless/mediatek/mt76/mt7915/init.c  |  11 +-
> > >  .../net/wireless/mediatek/mt76/mt7915/mac.c   | 214
> > > +++++++++++++++++-
> > >  .../net/wireless/mediatek/mt76/mt7915/main.c  |  18 +-
> > >  .../net/wireless/mediatek/mt76/mt7915/mcu.c   |  24 +-
> > >  .../net/wireless/mediatek/mt76/mt7915/mmio.c  |   7 +-
> > >  .../wireless/mediatek/mt76/mt7915/mt7915.h    |  15 +-
> > >  .../net/wireless/mediatek/mt76/mt7915/regs.h  |   4 +
> > >  7 files changed, 267 insertions(+), 26 deletions(-)
> > > 
> > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
> > > b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
> > > index 324db5291c85..1f39aa3e3f3d 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
> > > @@ -262,9 +262,8 @@ static void mt7915_led_set_brightness(struct
> > > led_classdev *led_cdev,
> > >  		mt7915_led_set_config(led_cdev, 0xff, 0);
> > >  }
> > >  
> > > -static void
> > > -mt7915_init_txpower(struct mt7915_dev *dev,
> > > -		    struct ieee80211_supported_band *sband)
> > > +void mt7915_init_txpower(struct mt7915_dev *dev,
> > > +			 struct ieee80211_supported_band *sband)
> > >  {
> > >  	int i, n_chains = hweight8(dev->mphy.antenna_mask);
> > >  	int nss_delta = mt76_tx_power_nss_delta(n_chains);
> > > @@ -446,7 +445,7 @@ mt7915_mac_init_band(struct mt7915_dev *dev,
> > > u8 band)
> > >  	mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
> > >  }
> > >  
> > > -static void mt7915_mac_init(struct mt7915_dev *dev)
> > > +void mt7915_mac_init(struct mt7915_dev *dev)
> > >  {
> > >  	int i;
> > >  	u32 rx_len = is_mt7915(&dev->mt76) ? 0x400 : 0x680;
> > > @@ -476,7 +475,7 @@ static void mt7915_mac_init(struct mt7915_dev
> > > *dev)
> > >  	}
> > >  }
> > >  
> > > -static int mt7915_txbf_init(struct mt7915_dev *dev)
> > > +int mt7915_txbf_init(struct mt7915_dev *dev)
> > >  {
> > >  	int ret;
> > >  
> > > @@ -1117,6 +1116,8 @@ int mt7915_register_device(struct
> > > mt7915_dev *dev)
> > >  			goto unreg_thermal;
> > >  	}
> > >  
> > > +	dev->recovery.hw_init_done = true;
> > > +
> > >  	mt7915_init_debugfs(&dev->phy);
> > >  
> > >  	return 0;
> > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
> > > b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
> > > index 3b1259f14de6..69ce3b39aa53 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
> > > @@ -1265,7 +1265,7 @@ mt7915_wait_reset_state(struct mt7915_dev
> > > *dev, u32 state)
> > >  	bool ret;
> > >  
> > >  	ret = wait_event_timeout(dev->reset_wait,
> > > -				 (READ_ONCE(dev->reset_state) & state),
> > > +				 (READ_ONCE(dev->recovery.state) &
> > > state),
> > >  				 MT7915_RESET_TIMEOUT);
> > >  
> > >  	WARN(!ret, "Timeout waiting for MCU reset state %x\n", state);
> > > @@ -1320,6 +1320,171 @@ void mt7915_tx_token_put(struct
> > > mt7915_dev *dev)
> > >  	idr_destroy(&dev->mt76.token);
> > >  }
> > >  
> > > +static int
> > > +mt7915_mac_restart(struct mt7915_dev *dev)
> > > +{
> > > +	struct mt7915_phy *phy2;
> > > +	struct mt76_phy *ext_phy;
> > > +	struct mt76_dev *mdev = &dev->mt76;
> > > +	int i, ret;
> > > +	u32 irq_mask;
> > > +
> > > +	ext_phy = dev->mt76.phys[MT_BAND1];
> > > +	phy2 = ext_phy ? ext_phy->priv : NULL;
> > > +
> > > +	if (dev->hif2) {
> > > +		mt76_wr(dev, MT_INT1_MASK_CSR, 0x0);
> > > +		mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
> > > +	}
> > > +
> > > +	if (dev_is_pci(mdev->dev)) {
> > > +		mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
> > > +		if (dev->hif2)
> > > +			mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0);
> > > +	}
> > > +
> > > +	set_bit(MT76_RESET, &dev->mphy.state);
> > > +	set_bit(MT76_MCU_RESET, &dev->mphy.state);
> > > +	wake_up(&dev->mt76.mcu.wait);
> > > +	if (ext_phy) {
> > > +		set_bit(MT76_RESET, &ext_phy->state);
> > > +		set_bit(MT76_MCU_RESET, &ext_phy->state);
> > > +	}
> > > +
> > > +	/* lock/unlock all queues to ensure that no tx is pending */
> > > +	mt76_txq_schedule_all(&dev->mphy);
> > > +	if (ext_phy)
> > > +		mt76_txq_schedule_all(ext_phy);
> > > +
> > > +	/* disable all tx/rx napi */
> > > +	mt76_worker_disable(&dev->mt76.tx_worker);
> > > +	mt76_for_each_q_rx(mdev, i) {
> > > +		if (mdev->q_rx[i].ndesc)
> > > +			napi_disable(&dev->mt76.napi[i]);
> > > +	}
> > > +	napi_disable(&dev->mt76.tx_napi);
> > > +
> > > +	/* token reinit */
> > > +	mt7915_tx_token_put(dev);
> > > +	idr_init(&dev->mt76.token);
> > > +
> > > +	mt7915_dma_reset(dev, true);
> > > +
> > > +	local_bh_disable();
> > > +	mt76_for_each_q_rx(mdev, i) {
> > > +		if (mdev->q_rx[i].ndesc) {
> > > +			napi_enable(&dev->mt76.napi[i]);
> > > +			napi_schedule(&dev->mt76.napi[i]);
> > > +		}
> > > +	}
> > > +	local_bh_enable();
> > > +	clear_bit(MT76_MCU_RESET, &dev->mphy.state);
> > > +	clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
> > > +
> > > +	mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask);
> > > +	mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
> > > +
> > > +	if (dev->hif2) {
> > > +		mt76_wr(dev, MT_INT1_MASK_CSR, irq_mask);
> > 
> > irq_mask is used uninitialized here.
> > Moreover is mt7915_mac_restart() and full-reset compatible with wed
> > support?
> > it seems in mt7915_dual_hif_set_irq_mask() we took a different
> > approach.
> > 
> > Regards,
> > Lorenzo
> 
> should we do something similar to the patch below?
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c 
b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
> index c76c5cc398e9..9c99c3014a79 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
> @@ -1386,7 +1386,6 @@ mt7915_mac_restart(struct mt7915_dev *dev)
>  	struct mt76_phy *ext_phy;
>  	struct mt76_dev *mdev = &dev->mt76;
>  	int i, ret;
> -	u32 irq_mask;
>  
>  	ext_phy = dev->mt76.phys[MT_BAND1];
>  	phy2 = ext_phy ? ext_phy->priv : NULL;
> @@ -1440,11 +1439,17 @@ mt7915_mac_restart(struct mt7915_dev *dev)
>  	clear_bit(MT76_MCU_RESET, &dev->mphy.state);
>  	clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
>  
> -	mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask);
> -	mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
> +	if (mtk_wed_device_active(&mdev->mmio.wed)) {
> +		mtk_wed_device_irq_set_mask(&mdev->mmio.wed,
> +					    mdev->mmio.irqmask);
> +		mtk_wed_device_irq_get(wed, ~0);
> +	} else {
> +		mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask);
> +		mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
> +	}
>  
>  	if (dev->hif2) {
> -		mt76_wr(dev, MT_INT1_MASK_CSR, irq_mask);
> +		mt76_wr(dev, MT_INT1_MASK_CSR, dev->mt76.mmio.irqmask);
>  		mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);

Yes we should use dev->mt76.mmio.irqmask...somehow we added irq_mask
here. @Felix, could you help to fold this?

As for wed_device I think we need another patch to suppor its SER as it
needs to take mtk_eth into account, and actually there's a patch in
MTK's git01 repo.

Ryder


More information about the Linux-mediatek mailing list