> On Fri, Jul 26, 2019 at 02:10:56PM +0200, Stanislaw Gruszka wrote: > > Since 41634aa8d6db ("mt76: only schedule txqs from the tx tasklet") > > I can observe firmware hangs on MT7630E on station mode: tx stop > > functioning after minor activity (rx keep working) and on module > > unload device fail to stop with messages: > > > > [ 5446.141413] mt76x0e 0000:06:00.0: TX DMA did not stop > > [ 5449.176764] mt76x0e 0000:06:00.0: TX DMA did not stop > > > > Loading module again results in failure to associate with AP. > > Only machine power off / power on cycle can make device work again. > > > > I have no idea why the commit caused F/W hangs. Most likely some proper > > fix is needed of changing registers programming (or assuring proper order > > of actions), but so far I can not came up with any better fix than > > a partial revert of 41634aa8d6db. > > The difference is that with 41634aa8d6db we can run mt76x02_poll_tx() > and mt76x02_tx_tasklet() in parallel on 2 different CPUs. Without > the commit, since tasklet is not scheduled from mt76_wake_tx_queue(), > it does not happen. > > I'm not quite sure why, but MT7630E does not like when we poll tx status > on 2 cpus at once. Change like below: Hi Stanislaw, have you tried to look at the commit: 6fe533378795f87 ("mt76: mt76x02: remove irqsave/restore in locking for tx status fifo")? Could it be a race between a registermap update and a stats load? (we are using a different lock now) > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c > index 467b28379870..622251faa415 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c > +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c > @@ -170,7 +170,7 @@ static int mt76x02_poll_tx(struct napi_struct *napi, int budget) > mt76.tx_napi); > int i; > > - mt76x02_mac_poll_tx_status(dev, false); > + mt76x02_mac_poll_tx_status(dev, true); I am not sure if we really need mt76x02_mac_poll_tx_status() here since we run it in mt76x02_tx_complete_skb() and in mt76x02_tx_tasklet(). Anyway the only difference doing so is we do not run mt76x02_send_tx_status(). Regards, Lorenzo > > for (i = MT_TXQ_MCU; i >= 0; i--) > mt76_queue_tx_cleanup(dev, i, false); > > is sufficient to avoid the hangs. > > > diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c > > index 5397827668b9..fefe0ee52584 100644 > > --- a/drivers/net/wireless/mediatek/mt76/tx.c > > +++ b/drivers/net/wireless/mediatek/mt76/tx.c > > @@ -598,7 +598,7 @@ void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq) > > if (!test_bit(MT76_STATE_RUNNING, &dev->state)) > > return; > > > > - tasklet_schedule(&dev->tx_tasklet); > > + mt76_txq_schedule(dev, txq->ac); > > However I'm not sure if change to tasklet_schedule() is indeed correct, > since on tasklet we schedule all queues, hence queues that could > possibly be still blocked? And on mt76_wake_tx_queue() we schedule only > one queue. > > Stanislaw