Skip to content

Commit

Permalink
mt76: page_pool: keep pages dma mapped
Browse files Browse the repository at this point in the history
For mmio devices rely on page_pool capabilty to keep rx buffers DMA
mapped and just sync rx buffers before accessing them.
  • Loading branch information
LorenzoBianconi committed Dec 22, 2022
1 parent 61ce8e9 commit f54eefc
Show file tree
Hide file tree
Showing 11 changed files with 60 additions and 54 deletions.
34 changes: 16 additions & 18 deletions drivers/net/wireless/mediatek/mt76/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,9 +406,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
if (!t)
return NULL;

dma_unmap_single(dev->dma_dev, t->dma_addr,
SKB_WITH_OVERHEAD(q->buf_size),
DMA_FROM_DEVICE);
dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr,
SKB_WITH_OVERHEAD(q->buf_size),
page_pool_get_dma_dir(dev->pp.pool));

buf = t->ptr;
t->dma_addr = 0;
Expand All @@ -425,9 +425,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
} else {
buf = e->buf;
e->buf = NULL;
dma_unmap_single(dev->dma_dev, e->dma_addr[0],
SKB_WITH_OVERHEAD(q->buf_size),
DMA_FROM_DEVICE);
dma_sync_single_for_cpu(dev->dma_dev, e->dma_addr[0],
SKB_WITH_OVERHEAD(q->buf_size),
page_pool_get_dma_dir(dev->pp.pool));
}

return buf;
Expand Down Expand Up @@ -583,8 +583,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
bool allow_direct)
{
int len = SKB_WITH_OVERHEAD(q->buf_size);
int frames = 0, offset = q->buf_offset;
dma_addr_t addr;
int frames = 0;

if (!q->ndesc)
return 0;
Expand All @@ -593,27 +592,26 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,

while (q->queued < q->ndesc - 1) {
struct mt76_queue_buf qbuf;
dma_addr_t addr;
int offset;
void *buf;

buf = mt76_get_page_pool_buf(dev, q->buf_size);
buf = mt76_get_page_pool_buf(dev, &offset, q->buf_size);
if (!buf)
break;

addr = dma_map_single(dev->dma_dev, buf, len, DMA_FROM_DEVICE);
if (unlikely(dma_mapping_error(dev->dma_dev, addr))) {
mt76_put_page_pool_buf(dev, buf, allow_direct);
break;
}
addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset;
dma_sync_single_for_device(dev->dma_dev, addr, len,
page_pool_get_dma_dir(dev->pp.pool));

qbuf.addr = addr + offset;
qbuf.len = len - offset;
qbuf.addr = addr + q->buf_offset;
qbuf.len = len - q->buf_offset;
qbuf.skip_unmap = false;
if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) {
dma_unmap_single(dev->dma_dev, addr, len,
DMA_FROM_DEVICE);
mt76_put_page_pool_buf(dev, buf, allow_direct);
break;
}

frames++;
}

Expand Down
22 changes: 14 additions & 8 deletions drivers/net/wireless/mediatek/mt76/mac80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -557,18 +557,24 @@ void mt76_unregister_phy(struct mt76_phy *phy)
}
EXPORT_SYMBOL_GPL(mt76_unregister_phy);

static int
mt76_create_page_pool(struct mt76_dev *dev)
int mt76_create_page_pool(struct mt76_dev *dev)
{
struct page_pool_params pp_params = {
.order = 0,
.pool_size = 32768, /* max page pool ring size */
.flags = PP_FLAG_PAGE_FRAG,
.nid = NUMA_NO_NODE,
.dev = dev->dev,
.dma_dir = DMA_FROM_DEVICE,
.dev = dev->dma_dev,
};

if (dev->drv->drv_flags & MT_DRV_PP_DMA_MAP) {
/* rely on page_pool for DMA mapping */
pp_params.flags |= PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV;
pp_params.dma_dir = DMA_FROM_DEVICE;
pp_params.max_len = PAGE_SIZE;
pp_params.offset = 0;
}

spin_lock_init(&dev->pp.lock);
dev->pp.pool = page_pool_create(&pp_params);
if (IS_ERR(dev->pp.pool)) {
Expand All @@ -580,20 +586,20 @@ mt76_create_page_pool(struct mt76_dev *dev)

return 0;
}
EXPORT_SYMBOL_GPL(mt76_create_page_pool);

void *mt76_get_page_pool_buf(struct mt76_dev *dev, u32 size)
void *mt76_get_page_pool_buf(struct mt76_dev *dev, u32 *offset, u32 size)
{
struct page *page;
u32 offset;

if (!dev->pp.pool)
return NULL;

spin_lock_bh(&dev->pp.lock);
page = page_pool_dev_alloc_frag(dev->pp.pool, &offset, size);
page = page_pool_dev_alloc_frag(dev->pp.pool, offset, size);
spin_unlock_bh(&dev->pp.lock);

return page ? page_address(page) + offset : NULL;
return page ? page_address(page) + *offset : NULL;
}
EXPORT_SYMBOL_GPL(mt76_get_page_pool_buf);

Expand Down
4 changes: 3 additions & 1 deletion drivers/net/wireless/mediatek/mt76/mt76.h
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ struct mt76_hw_cap {
#define MT_DRV_RX_DMA_HDR BIT(3)
#define MT_DRV_HW_MGMT_TXQ BIT(4)
#define MT_DRV_AMSDU_OFFLOAD BIT(5)
#define MT_DRV_PP_DMA_MAP BIT(6)

struct mt76_driver_ops {
u32 drv_flags;
Expand Down Expand Up @@ -1426,7 +1427,8 @@ void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked);
struct mt76_txwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token);
int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr,
struct mt76_txwi_cache *r, dma_addr_t phys);
void *mt76_get_page_pool_buf(struct mt76_dev *dev, u32 size);
int mt76_create_page_pool(struct mt76_dev *dev);
void *mt76_get_page_pool_buf(struct mt76_dev *dev, u32 *offset, u32 size);
void mt76_put_page_pool_buf(struct mt76_dev *dev, void *buf,
bool allow_direct);

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/mediatek/mt76/mt7603/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

const struct mt76_driver_ops mt7603_drv_ops = {
.txwi_size = MT_TXD_SIZE,
.drv_flags = MT_DRV_SW_RX_AIRTIME,
.drv_flags = MT_DRV_SW_RX_AIRTIME | MT_DRV_PP_DMA_MAP,
.survey_flags = SURVEY_INFO_TIME_TX,
.tx_prepare_skb = mt7603_tx_prepare_skb,
.tx_complete_skb = mt7603_tx_complete_skb,
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/wireless/mediatek/mt76/mt7615/mmio.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
static const struct mt76_driver_ops drv_ops = {
/* txwi_size = txd size + txp size */
.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_txp_common),
.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ,
.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ |
MT_DRV_PP_DMA_MAP,
.survey_flags = SURVEY_INFO_TIME_TX |
SURVEY_INFO_TIME_RX |
SURVEY_INFO_TIME_BSS_RX,
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
static const struct mt76_driver_ops drv_ops = {
.txwi_size = sizeof(struct mt76x02_txwi),
.drv_flags = MT_DRV_TX_ALIGNED4_SKBS |
MT_DRV_SW_RX_AIRTIME,
MT_DRV_SW_RX_AIRTIME | MT_DRV_PP_DMA_MAP,
.survey_flags = SURVEY_INFO_TIME_TX,
.update_survey = mt76x02_update_channel,
.tx_prepare_skb = mt76x02_tx_prepare_skb,
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ mt76x2e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
static const struct mt76_driver_ops drv_ops = {
.txwi_size = sizeof(struct mt76x02_txwi),
.drv_flags = MT_DRV_TX_ALIGNED4_SKBS |
MT_DRV_SW_RX_AIRTIME,
MT_DRV_SW_RX_AIRTIME | MT_DRV_PP_DMA_MAP,
.survey_flags = SURVEY_INFO_TIME_TX,
.update_survey = mt76x02_update_channel,
.tx_prepare_skb = mt76x02_tx_prepare_skb,
Expand Down
29 changes: 14 additions & 15 deletions drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
Original file line number Diff line number Diff line change
Expand Up @@ -604,8 +604,6 @@ static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
if (!t || !t->ptr)
continue;

dma_unmap_single(dev->mt76.dma_dev, t->dma_addr,
wed->wlan.rx_size, DMA_FROM_DEVICE);
mt76_put_page_pool_buf(&dev->mt76, t->ptr, false);
t->ptr = NULL;

Expand All @@ -627,26 +625,19 @@ static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
for (i = 0; i < size; i++) {
struct mt76_txwi_cache *t = mt76_get_rxwi(&dev->mt76);
dma_addr_t phy_addr;
int token;
int token, offset;
void *ptr;

ptr = mt76_get_page_pool_buf(&dev->mt76, length);
ptr = mt76_get_page_pool_buf(&dev->mt76, &offset, length);
if (!ptr)
goto unmap;

phy_addr = dma_map_single(dev->mt76.dma_dev, ptr,
wed->wlan.rx_size,
DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(dev->mt76.dev, phy_addr))) {
mt76_put_page_pool_buf(&dev->mt76, ptr, false);
goto unmap;
}

phy_addr = page_pool_get_dma_addr(virt_to_head_page(ptr)) +
offset;
desc->buf0 = cpu_to_le32(phy_addr);

token = mt76_rx_token_consume(&dev->mt76, ptr, t, phy_addr);
if (token < 0) {
dma_unmap_single(dev->mt76.dma_dev, phy_addr,
wed->wlan.rx_size, DMA_TO_DEVICE);
mt76_put_page_pool_buf(&dev->mt76, ptr, false);
goto unmap;
}
Expand Down Expand Up @@ -778,6 +769,14 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
*irq = wed->irq;
dev->mt76.dma_dev = wed->dev;

/* we need to recreate the page_pool since dma_dev
* pointer has changed
*/
page_pool_destroy(dev->mt76.pp.pool);
ret = mt76_create_page_pool(&dev->mt76);
if (ret)
return ret;

ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32));
if (ret)
return ret;
Expand Down Expand Up @@ -970,7 +969,7 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
/* txwi_size = txd size + txp size */
.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp),
.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ |
MT_DRV_AMSDU_OFFLOAD,
MT_DRV_AMSDU_OFFLOAD | MT_DRV_PP_DMA_MAP,
.survey_flags = SURVEY_INFO_TIME_TX |
SURVEY_INFO_TIME_RX |
SURVEY_INFO_TIME_BSS_RX,
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/mediatek/mt76/mt7921/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
/* txwi_size = txd size + txp size */
.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_hw_txp),
.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ |
MT_DRV_AMSDU_OFFLOAD,
MT_DRV_AMSDU_OFFLOAD | MT_DRV_PP_DMA_MAP,
.survey_flags = SURVEY_INFO_TIME_TX |
SURVEY_INFO_TIME_RX |
SURVEY_INFO_TIME_BSS_RX,
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
/* txwi_size = txd size + txp size */
.txwi_size = MT_TXD_SIZE + sizeof(struct mt7996_txp),
.drv_flags = MT_DRV_TXWI_NO_FREE |
MT_DRV_HW_MGMT_TXQ,
MT_DRV_HW_MGMT_TXQ | MT_DRV_PP_DMA_MAP,
.survey_flags = SURVEY_INFO_TIME_TX |
SURVEY_INFO_TIME_RX |
SURVEY_INFO_TIME_BSS_RX,
Expand Down
12 changes: 6 additions & 6 deletions drivers/net/wireless/mediatek/mt76/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,17 +324,15 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue *q, struct urb *urb,
int i;

for (i = 0; i < nsgs; i++) {
struct page *page;
void *data;
int offset;

data = mt76_get_page_pool_buf(dev, q->buf_size);
data = mt76_get_page_pool_buf(dev, &offset, q->buf_size);
if (!data)
break;

page = virt_to_head_page(data);
offset = data - page_address(page);
sg_set_page(&urb->sg[i], page, q->buf_size, offset);
sg_set_page(&urb->sg[i], virt_to_head_page(data), q->buf_size,
offset);
}

if (i < nsgs) {
Expand All @@ -358,12 +356,14 @@ mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q,
struct urb *urb, int nsgs)
{
enum mt76_rxq_id qid = q - &dev->q_rx[MT_RXQ_MAIN];
int offset;

if (qid == MT_RXQ_MAIN && dev->usb.sg_en)
return mt76u_fill_rx_sg(dev, q, urb, nsgs);

urb->transfer_buffer_length = q->buf_size;
urb->transfer_buffer = mt76_get_page_pool_buf(dev, q->buf_size);
urb->transfer_buffer = mt76_get_page_pool_buf(dev, &offset,
q->buf_size);

return urb->transfer_buffer ? 0 : -ENOMEM;
}
Expand Down

0 comments on commit f54eefc

Please sign in to comment.