Skip to content

Commit 89e1afc

Browse files
Mintz, Yuvaldavem330
authored andcommitted
qede: Correct XDP forward unmapping
Driver is currently using dma_unmap_single() with the address it passed to device for the purpose of forwarding, but the XDP transmission buffer was originally a page allocated for the rx-queue. The mapped address is likely to differ from the original mapped address due to the placement offset. This difference is going to get even bigger once we support headroom. Cache the original mapped address of the page, and use it for unmapping of the buffer when completion arrives for the XDP forwarded packet. Signed-off-by: Yuval Mintz <Yuval.Mintz@cavium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 10a0176 commit 89e1afc

File tree

3 files changed

+20
-14
lines changed

3 files changed

+20
-14
lines changed

drivers/net/ethernet/qlogic/qede/qede.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,11 @@ struct sw_tx_bd {
349349
#define QEDE_TSO_SPLIT_BD BIT(0)
350350
};
351351

352+
struct sw_tx_xdp {
353+
struct page *page;
354+
dma_addr_t mapping;
355+
};
356+
352357
struct qede_tx_queue {
353358
u8 is_xdp;
354359
bool is_legacy;
@@ -372,11 +377,11 @@ struct qede_tx_queue {
372377
#define QEDE_TXQ_IDX_TO_XDP(edev, idx) ((idx) + QEDE_MAX_TSS_CNT(edev))
373378

374379
/* Regular Tx requires skb + metadata for release purpose,
375-
* while XDP requires only the pages themselves.
380+
* while XDP requires the pages and the mapped address.
376381
*/
377382
union {
378383
struct sw_tx_bd *skbs;
379-
struct page **pages;
384+
struct sw_tx_xdp *xdp;
380385
} sw_tx_ring;
381386

382387
struct qed_chain tx_pbl;

drivers/net/ethernet/qlogic/qede/qede_fp.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,8 @@ static int qede_xdp_xmit(struct qede_dev *edev, struct qede_fastpath *fp,
360360
metadata->mapping + padding,
361361
length, PCI_DMA_TODEVICE);
362362

363-
txq->sw_tx_ring.pages[idx] = metadata->data;
363+
txq->sw_tx_ring.xdp[idx].page = metadata->data;
364+
txq->sw_tx_ring.xdp[idx].mapping = metadata->mapping;
364365
txq->sw_tx_prod++;
365366

366367
/* Mark the fastpath for future XDP doorbell */
@@ -384,19 +385,19 @@ int qede_txq_has_work(struct qede_tx_queue *txq)
384385

385386
static void qede_xdp_tx_int(struct qede_dev *edev, struct qede_tx_queue *txq)
386387
{
387-
struct eth_tx_1st_bd *bd;
388-
u16 hw_bd_cons;
388+
u16 hw_bd_cons, idx;
389389

390390
hw_bd_cons = le16_to_cpu(*txq->hw_cons_ptr);
391391
barrier();
392392

393393
while (hw_bd_cons != qed_chain_get_cons_idx(&txq->tx_pbl)) {
394-
bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl);
394+
qed_chain_consume(&txq->tx_pbl);
395+
idx = txq->sw_tx_cons & NUM_TX_BDS_MAX;
395396

396-
dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(bd),
397-
PAGE_SIZE, DMA_BIDIRECTIONAL);
398-
__free_page(txq->sw_tx_ring.pages[txq->sw_tx_cons &
399-
NUM_TX_BDS_MAX]);
397+
dma_unmap_page(&edev->pdev->dev,
398+
txq->sw_tx_ring.xdp[idx].mapping,
399+
PAGE_SIZE, DMA_BIDIRECTIONAL);
400+
__free_page(txq->sw_tx_ring.xdp[idx].page);
400401

401402
txq->sw_tx_cons++;
402403
txq->xmit_pkts++;

drivers/net/ethernet/qlogic/qede/qede_main.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,7 +1251,7 @@ static void qede_free_mem_txq(struct qede_dev *edev, struct qede_tx_queue *txq)
12511251
{
12521252
/* Free the parallel SW ring */
12531253
if (txq->is_xdp)
1254-
kfree(txq->sw_tx_ring.pages);
1254+
kfree(txq->sw_tx_ring.xdp);
12551255
else
12561256
kfree(txq->sw_tx_ring.skbs);
12571257

@@ -1269,9 +1269,9 @@ static int qede_alloc_mem_txq(struct qede_dev *edev, struct qede_tx_queue *txq)
12691269

12701270
/* Allocate the parallel driver ring for Tx buffers */
12711271
if (txq->is_xdp) {
1272-
size = sizeof(*txq->sw_tx_ring.pages) * TX_RING_SIZE;
1273-
txq->sw_tx_ring.pages = kzalloc(size, GFP_KERNEL);
1274-
if (!txq->sw_tx_ring.pages)
1272+
size = sizeof(*txq->sw_tx_ring.xdp) * TX_RING_SIZE;
1273+
txq->sw_tx_ring.xdp = kzalloc(size, GFP_KERNEL);
1274+
if (!txq->sw_tx_ring.xdp)
12751275
goto err;
12761276
} else {
12771277
size = sizeof(*txq->sw_tx_ring.skbs) * TX_RING_SIZE;

0 commit comments

Comments
 (0)