diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/dma.c')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/dma.c | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 1847f55e199b..75e659774e07 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -132,6 +132,11 @@ mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) writel(q->ndesc, &q->regs->ring_size); q->head = readl(&q->regs->dma_idx); q->tail = q->head; +} + +static void +mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q) +{ writel(q->head, &q->regs->cpu_idx); } @@ -141,7 +146,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush) struct mt76_sw_queue *sq = &dev->q_tx[qid]; struct mt76_queue *q = sq->q; struct mt76_queue_entry entry; - unsigned int n_swq_queued[4] = {}; + unsigned int n_swq_queued[8] = {}; unsigned int n_queued = 0; bool wake = false; int i, last; @@ -178,15 +183,25 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush) spin_lock_bh(&q->lock); q->queued -= n_queued; - for (i = 0; i < ARRAY_SIZE(n_swq_queued); i++) { + for (i = 0; i < 4; i++) { if (!n_swq_queued[i]) continue; dev->q_tx[i].swq_queued -= n_swq_queued[i]; } - if (flush) + /* ext PHY */ + for (i = 0; i < 4; i++) { + if (!n_swq_queued[i]) + continue; + + dev->q_tx[__MT_TXQ_MAX + i].swq_queued -= n_swq_queued[4 + i]; + } + + if (flush) { mt76_dma_sync_idx(dev, q); + mt76_dma_kick_queue(dev, q); + } wake = wake && q->stopped && qid < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8; @@ -238,7 +253,9 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush, if (!q->queued) return NULL; - if (!flush && !(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE))) + if (flush) + q->desc[idx].ctrl |= cpu_to_le32(MT_DMA_CTL_DMA_DONE); + else if (!(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE))) return NULL; q->tail = (q->tail + 1) % q->ndesc; @@ -247,12 +264,6 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush, return mt76_dma_get_buf(dev, q, idx, len, info, more); } -static void -mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q) -{ - writel(q->head, &q->regs->cpu_idx); -} - static int mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid, struct sk_buff *skb, u32 tx_info) @@ -261,10 +272,13 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid, struct mt76_queue_buf buf; dma_addr_t addr; + if (q->queued + 1 >= q->ndesc - 1) + goto error; + addr = dma_map_single(dev->dev, skb->data, skb->len, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev->dev, addr))) - return -ENOMEM; + goto error; buf.addr = addr; buf.len = skb->len; @@ -275,6 +289,10 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid, spin_unlock_bh(&q->lock); return 0; + +error: + dev_kfree_skb(skb); + return -ENOMEM; } static int @@ -286,6 +304,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, struct mt76_tx_info tx_info = { .skb = skb, }; + struct ieee80211_hw *hw; int len, n = 0, ret = -ENOMEM; struct mt76_queue_entry e; struct mt76_txwi_cache *t; @@ -295,7 +314,8 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, t = mt76_get_txwi(dev); if (!t) { - ieee80211_free_txskb(dev->hw, skb); + hw = mt76_tx_status_get_hw(dev, skb); + ieee80211_free_txskb(hw, skb); return -ENOMEM; } txwi = mt76_get_txwi_ptr(dev, t); @@ -427,7 +447,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid) int i; for (i = 0; i < q->ndesc; i++) - q->desc[i].ctrl &= ~cpu_to_le32(MT_DMA_CTL_DMA_DONE); + q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); mt76_dma_rx_cleanup(dev, q); mt76_dma_sync_idx(dev, q); @@ -531,6 +551,7 @@ mt76_dma_rx_poll(struct napi_struct *napi, int budget) dev = container_of(napi->dev, struct mt76_dev, napi_dev); qid = napi - dev->napi; + local_bh_disable(); rcu_read_lock(); do { @@ -540,6 +561,7 @@ mt76_dma_rx_poll(struct napi_struct *napi, int budget) } while (cur && done < budget); rcu_read_unlock(); + local_bh_enable(); if (done < budget && napi_complete(napi)) dev->drv->rx_poll_complete(dev, qid); @@ -558,7 +580,6 @@ mt76_dma_init(struct mt76_dev *dev) netif_napi_add(&dev->napi_dev, &dev->napi[i], mt76_dma_rx_poll, 64); mt76_dma_rx_fill(dev, &dev->q_rx[i]); - skb_queue_head_init(&dev->rx_skb[i]); napi_enable(&dev->napi[i]); } |