Skip to content

Commit af327c0

Browse files
shimodaygregkh
authored andcommitted
net: rswitch: Add jumbo frames handling for TX
[ Upstream commit d2c96b9 ] If the driver would like to transmit a jumbo frame like 2KiB or more, it should be split into multiple queues. In the near future, to support this, add handling specific descriptor types F{START,MID,END}. However, such jumbo frames will not happen yet because the maximum MTU size is still default for now. Signed-off-by: Yoshihiro Shimoda <[email protected]> Signed-off-by: David S. Miller <[email protected]> Stable-dep-of: 0c9547e ("net: renesas: rswitch: fix race window between tx start and complete") Signed-off-by: Sasha Levin <[email protected]>
1 parent 87388cb commit af327c0

File tree

1 file changed

+46
-10
lines changed

1 file changed

+46
-10
lines changed

drivers/net/ethernet/renesas/rswitch.c

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,41 +1561,77 @@ static bool rswitch_ext_desc_set(struct rswitch_device *rdev,
15611561
return true;
15621562
}
15631563

1564+
static u8 rswitch_ext_desc_get_die_dt(unsigned int nr_desc, unsigned int index)
1565+
{
1566+
if (nr_desc == 1)
1567+
return DT_FSINGLE | DIE;
1568+
if (index == 0)
1569+
return DT_FSTART;
1570+
if (nr_desc - 1 == index)
1571+
return DT_FEND | DIE;
1572+
return DT_FMID;
1573+
}
1574+
1575+
static u16 rswitch_ext_desc_get_len(u8 die_dt, unsigned int orig_len)
1576+
{
1577+
switch (die_dt & DT_MASK) {
1578+
case DT_FSINGLE:
1579+
case DT_FEND:
1580+
return (orig_len % RSWITCH_DESC_BUF_SIZE) ?: RSWITCH_DESC_BUF_SIZE;
1581+
case DT_FSTART:
1582+
case DT_FMID:
1583+
return RSWITCH_DESC_BUF_SIZE;
1584+
default:
1585+
return 0;
1586+
}
1587+
}
1588+
15641589
static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *ndev)
15651590
{
15661591
struct rswitch_device *rdev = netdev_priv(ndev);
15671592
struct rswitch_gwca_queue *gq = rdev->tx_queue;
1593+
dma_addr_t dma_addr, dma_addr_orig;
15681594
netdev_tx_t ret = NETDEV_TX_OK;
15691595
struct rswitch_ext_desc *desc;
1570-
dma_addr_t dma_addr;
1596+
unsigned int i, nr_desc;
1597+
u8 die_dt;
1598+
u16 len;
15711599

1572-
if (rswitch_get_num_cur_queues(gq) >= gq->ring_size - 1) {
1600+
nr_desc = (skb->len - 1) / RSWITCH_DESC_BUF_SIZE + 1;
1601+
if (rswitch_get_num_cur_queues(gq) >= gq->ring_size - nr_desc) {
15731602
netif_stop_subqueue(ndev, 0);
15741603
return NETDEV_TX_BUSY;
15751604
}
15761605

15771606
if (skb_put_padto(skb, ETH_ZLEN))
15781607
return ret;
15791608

1580-
dma_addr = dma_map_single(ndev->dev.parent, skb->data, skb->len, DMA_TO_DEVICE);
1581-
if (dma_mapping_error(ndev->dev.parent, dma_addr))
1609+
dma_addr_orig = dma_map_single(ndev->dev.parent, skb->data, skb->len, DMA_TO_DEVICE);
1610+
if (dma_mapping_error(ndev->dev.parent, dma_addr_orig))
15821611
goto err_kfree;
15831612

15841613
gq->skbs[gq->cur] = skb;
1585-
gq->unmap_addrs[gq->cur] = dma_addr;
1586-
desc = &gq->tx_ring[gq->cur];
1587-
if (!rswitch_ext_desc_set(rdev, skb, desc, dma_addr, skb->len, DT_FSINGLE | DIE))
1588-
goto err_unmap;
1614+
gq->unmap_addrs[gq->cur] = dma_addr_orig;
1615+
1616+
/* DT_FSTART should be set at last. So, this is reverse order. */
1617+
for (i = nr_desc; i-- > 0; ) {
1618+
desc = &gq->tx_ring[rswitch_next_queue_index(gq, true, i)];
1619+
die_dt = rswitch_ext_desc_get_die_dt(nr_desc, i);
1620+
dma_addr = dma_addr_orig + i * RSWITCH_DESC_BUF_SIZE;
1621+
len = rswitch_ext_desc_get_len(die_dt, skb->len);
1622+
if (!rswitch_ext_desc_set(rdev, skb, desc, dma_addr, len, die_dt))
1623+
goto err_unmap;
1624+
}
15891625

15901626
wmb(); /* gq->cur must be incremented after die_dt was set */
15911627

1592-
gq->cur = rswitch_next_queue_index(gq, true, 1);
1628+
gq->cur = rswitch_next_queue_index(gq, true, nr_desc);
15931629
rswitch_modify(rdev->addr, GWTRC(gq->index), 0, BIT(gq->index % 32));
15941630

15951631
return ret;
15961632

15971633
err_unmap:
1598-
dma_unmap_single(ndev->dev.parent, dma_addr, skb->len, DMA_TO_DEVICE);
1634+
dma_unmap_single(ndev->dev.parent, dma_addr_orig, skb->len, DMA_TO_DEVICE);
15991635

16001636
err_kfree:
16011637
dev_kfree_skb_any(skb);

0 commit comments

Comments
 (0)