[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