Skip to content

Commit 99ee2eb

Browse files
shimodaygregkh
authored andcommitted
net: rswitch: Use build_skb() for RX
[ Upstream commit 6a203cb ] If this hardware receives a jumbo frame like 2KiB or more, it will be split into multiple queues. In the near future, to support this, use build_skb() instead of netdev_alloc_skb_ip_align(). 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 ad4bd2c commit 99ee2eb

File tree

2 files changed

+59
-33
lines changed

2 files changed

+59
-33
lines changed

drivers/net/ethernet/renesas/rswitch.c

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -234,19 +234,18 @@ static bool rswitch_is_queue_rxed(struct rswitch_gwca_queue *gq)
234234
return false;
235235
}
236236

237-
static int rswitch_gwca_queue_alloc_skb(struct rswitch_gwca_queue *gq,
238-
unsigned int start_index,
239-
unsigned int num)
237+
static int rswitch_gwca_queue_alloc_rx_buf(struct rswitch_gwca_queue *gq,
238+
unsigned int start_index,
239+
unsigned int num)
240240
{
241241
unsigned int i, index;
242242

243243
for (i = 0; i < num; i++) {
244244
index = (i + start_index) % gq->ring_size;
245-
if (gq->skbs[index])
245+
if (gq->rx_bufs[index])
246246
continue;
247-
gq->skbs[index] = netdev_alloc_skb_ip_align(gq->ndev,
248-
PKT_BUF_SZ + RSWITCH_ALIGN - 1);
249-
if (!gq->skbs[index])
247+
gq->rx_bufs[index] = netdev_alloc_frag(RSWITCH_BUF_SIZE);
248+
if (!gq->rx_bufs[index])
250249
goto err;
251250
}
252251

@@ -255,8 +254,8 @@ static int rswitch_gwca_queue_alloc_skb(struct rswitch_gwca_queue *gq,
255254
err:
256255
for (; i-- > 0; ) {
257256
index = (i + start_index) % gq->ring_size;
258-
dev_kfree_skb(gq->skbs[index]);
259-
gq->skbs[index] = NULL;
257+
skb_free_frag(gq->rx_bufs[index]);
258+
gq->rx_bufs[index] = NULL;
260259
}
261260

262261
return -ENOMEM;
@@ -274,16 +273,17 @@ static void rswitch_gwca_queue_free(struct net_device *ndev,
274273
gq->rx_ring = NULL;
275274

276275
for (i = 0; i < gq->ring_size; i++)
277-
dev_kfree_skb(gq->skbs[i]);
276+
skb_free_frag(gq->rx_bufs[i]);
277+
kfree(gq->rx_bufs);
278+
gq->rx_bufs = NULL;
278279
} else {
279280
dma_free_coherent(ndev->dev.parent,
280281
sizeof(struct rswitch_ext_desc) *
281282
(gq->ring_size + 1), gq->tx_ring, gq->ring_dma);
282283
gq->tx_ring = NULL;
284+
kfree(gq->skbs);
285+
gq->skbs = NULL;
283286
}
284-
285-
kfree(gq->skbs);
286-
gq->skbs = NULL;
287287
}
288288

289289
static void rswitch_gwca_ts_queue_free(struct rswitch_private *priv)
@@ -307,17 +307,20 @@ static int rswitch_gwca_queue_alloc(struct net_device *ndev,
307307
gq->ring_size = ring_size;
308308
gq->ndev = ndev;
309309

310-
gq->skbs = kcalloc(gq->ring_size, sizeof(*gq->skbs), GFP_KERNEL);
311-
if (!gq->skbs)
312-
return -ENOMEM;
313-
314310
if (!dir_tx) {
315-
rswitch_gwca_queue_alloc_skb(gq, 0, gq->ring_size);
311+
gq->rx_bufs = kcalloc(gq->ring_size, sizeof(*gq->rx_bufs), GFP_KERNEL);
312+
if (!gq->rx_bufs)
313+
return -ENOMEM;
314+
if (rswitch_gwca_queue_alloc_rx_buf(gq, 0, gq->ring_size) < 0)
315+
goto out;
316316

317317
gq->rx_ring = dma_alloc_coherent(ndev->dev.parent,
318318
sizeof(struct rswitch_ext_ts_desc) *
319319
(gq->ring_size + 1), &gq->ring_dma, GFP_KERNEL);
320320
} else {
321+
gq->skbs = kcalloc(gq->ring_size, sizeof(*gq->skbs), GFP_KERNEL);
322+
if (!gq->skbs)
323+
return -ENOMEM;
321324
gq->tx_ring = dma_alloc_coherent(ndev->dev.parent,
322325
sizeof(struct rswitch_ext_desc) *
323326
(gq->ring_size + 1), &gq->ring_dma, GFP_KERNEL);
@@ -366,12 +369,13 @@ static int rswitch_gwca_queue_format(struct net_device *ndev,
366369
for (i = 0, desc = gq->tx_ring; i < gq->ring_size; i++, desc++) {
367370
if (!gq->dir_tx) {
368371
dma_addr = dma_map_single(ndev->dev.parent,
369-
gq->skbs[i]->data, PKT_BUF_SZ,
372+
gq->rx_bufs[i] + RSWITCH_HEADROOM,
373+
RSWITCH_MAP_BUF_SIZE,
370374
DMA_FROM_DEVICE);
371375
if (dma_mapping_error(ndev->dev.parent, dma_addr))
372376
goto err;
373377

374-
desc->desc.info_ds = cpu_to_le16(PKT_BUF_SZ);
378+
desc->desc.info_ds = cpu_to_le16(RSWITCH_DESC_BUF_SIZE);
375379
rswitch_desc_set_dptr(&desc->desc, dma_addr);
376380
desc->desc.die_dt = DT_FEMPTY | DIE;
377381
} else {
@@ -394,8 +398,8 @@ static int rswitch_gwca_queue_format(struct net_device *ndev,
394398
if (!gq->dir_tx) {
395399
for (desc = gq->tx_ring; i-- > 0; desc++) {
396400
dma_addr = rswitch_desc_get_dptr(&desc->desc);
397-
dma_unmap_single(ndev->dev.parent, dma_addr, PKT_BUF_SZ,
398-
DMA_FROM_DEVICE);
401+
dma_unmap_single(ndev->dev.parent, dma_addr,
402+
RSWITCH_MAP_BUF_SIZE, DMA_FROM_DEVICE);
399403
}
400404
}
401405

@@ -432,12 +436,13 @@ static int rswitch_gwca_queue_ext_ts_fill(struct net_device *ndev,
432436
desc = &gq->rx_ring[index];
433437
if (!gq->dir_tx) {
434438
dma_addr = dma_map_single(ndev->dev.parent,
435-
gq->skbs[index]->data, PKT_BUF_SZ,
439+
gq->rx_bufs[index] + RSWITCH_HEADROOM,
440+
RSWITCH_MAP_BUF_SIZE,
436441
DMA_FROM_DEVICE);
437442
if (dma_mapping_error(ndev->dev.parent, dma_addr))
438443
goto err;
439444

440-
desc->desc.info_ds = cpu_to_le16(PKT_BUF_SZ);
445+
desc->desc.info_ds = cpu_to_le16(RSWITCH_DESC_BUF_SIZE);
441446
rswitch_desc_set_dptr(&desc->desc, dma_addr);
442447
dma_wmb();
443448
desc->desc.die_dt = DT_FEMPTY | DIE;
@@ -455,8 +460,8 @@ static int rswitch_gwca_queue_ext_ts_fill(struct net_device *ndev,
455460
index = (i + start_index) % gq->ring_size;
456461
desc = &gq->rx_ring[index];
457462
dma_addr = rswitch_desc_get_dptr(&desc->desc);
458-
dma_unmap_single(ndev->dev.parent, dma_addr, PKT_BUF_SZ,
459-
DMA_FROM_DEVICE);
463+
dma_unmap_single(ndev->dev.parent, dma_addr,
464+
RSWITCH_MAP_BUF_SIZE, DMA_FROM_DEVICE);
460465
}
461466
}
462467

@@ -723,10 +728,15 @@ static bool rswitch_rx(struct net_device *ndev, int *quota)
723728
while ((desc->desc.die_dt & DT_MASK) != DT_FEMPTY) {
724729
dma_rmb();
725730
pkt_len = le16_to_cpu(desc->desc.info_ds) & RX_DS;
726-
skb = gq->skbs[gq->cur];
727-
gq->skbs[gq->cur] = NULL;
728731
dma_addr = rswitch_desc_get_dptr(&desc->desc);
729-
dma_unmap_single(ndev->dev.parent, dma_addr, PKT_BUF_SZ, DMA_FROM_DEVICE);
732+
dma_unmap_single(ndev->dev.parent, dma_addr,
733+
RSWITCH_MAP_BUF_SIZE, DMA_FROM_DEVICE);
734+
skb = build_skb(gq->rx_bufs[gq->cur], RSWITCH_BUF_SIZE);
735+
if (!skb)
736+
goto out;
737+
skb_reserve(skb, RSWITCH_HEADROOM);
738+
skb_put(skb, pkt_len);
739+
730740
get_ts = rdev->priv->ptp_priv->tstamp_rx_ctrl & RCAR_GEN4_RXTSTAMP_TYPE_V2_L2_EVENT;
731741
if (get_ts) {
732742
struct skb_shared_hwtstamps *shhwtstamps;
@@ -738,12 +748,13 @@ static bool rswitch_rx(struct net_device *ndev, int *quota)
738748
ts.tv_nsec = __le32_to_cpu(desc->ts_nsec & cpu_to_le32(0x3fffffff));
739749
shhwtstamps->hwtstamp = timespec64_to_ktime(ts);
740750
}
741-
skb_put(skb, pkt_len);
742751
skb->protocol = eth_type_trans(skb, ndev);
743752
napi_gro_receive(&rdev->napi, skb);
744753
rdev->ndev->stats.rx_packets++;
745754
rdev->ndev->stats.rx_bytes += pkt_len;
746755

756+
out:
757+
gq->rx_bufs[gq->cur] = NULL;
747758
gq->cur = rswitch_next_queue_index(gq, true, 1);
748759
desc = &gq->rx_ring[gq->cur];
749760

@@ -752,7 +763,7 @@ static bool rswitch_rx(struct net_device *ndev, int *quota)
752763
}
753764

754765
num = rswitch_get_num_cur_queues(gq);
755-
ret = rswitch_gwca_queue_alloc_skb(gq, gq->dirty, num);
766+
ret = rswitch_gwca_queue_alloc_rx_buf(gq, gq->dirty, num);
756767
if (ret < 0)
757768
goto err;
758769
ret = rswitch_gwca_queue_ext_ts_fill(ndev, gq, gq->dirty, num);

drivers/net/ethernet/renesas/rswitch.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,13 @@
2929
#define RX_RING_SIZE 1024
3030
#define TS_RING_SIZE (TX_RING_SIZE * RSWITCH_NUM_PORTS)
3131

32-
#define PKT_BUF_SZ 1584
32+
#define RSWITCH_HEADROOM (NET_SKB_PAD + NET_IP_ALIGN)
33+
#define RSWITCH_DESC_BUF_SIZE 2048
34+
#define RSWITCH_TAILROOM SKB_DATA_ALIGN(sizeof(struct skb_shared_info))
3335
#define RSWITCH_ALIGN 128
36+
#define RSWITCH_BUF_SIZE (RSWITCH_HEADROOM + RSWITCH_DESC_BUF_SIZE + \
37+
RSWITCH_TAILROOM + RSWITCH_ALIGN)
38+
#define RSWITCH_MAP_BUF_SIZE (RSWITCH_BUF_SIZE - RSWITCH_HEADROOM)
3439
#define RSWITCH_MAX_CTAG_PCP 7
3540

3641
#define RSWITCH_TIMEOUT_US 100000
@@ -945,8 +950,18 @@ struct rswitch_gwca_queue {
945950
/* For [rt]x_ring */
946951
unsigned int index;
947952
bool dir_tx;
948-
struct sk_buff **skbs;
949953
struct net_device *ndev; /* queue to ndev for irq */
954+
955+
union {
956+
/* For TX */
957+
struct {
958+
struct sk_buff **skbs;
959+
};
960+
/* For RX */
961+
struct {
962+
void **rx_bufs;
963+
};
964+
};
950965
};
951966

952967
struct rswitch_gwca_ts_info {

0 commit comments

Comments
 (0)