Skip to content

Commit 33f5d73

Browse files
shimodaykuba-moo
authored andcommitted
net: renesas: rswitch: Improve TX timestamp accuracy
In the previous code, TX timestamp accuracy was bad because the irq handler got the timestamp from the timestamp register at that time. This hardware has "Timestamp capture" feature which can store each TX timestamp into the timestamp descriptors. To improve TX timestamp accuracy, implement timestamp descriptors' handling. Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Reviewed-by: Alexander Duyck <alexanderduyck@fb.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 48cf0a2 commit 33f5d73

File tree

2 files changed

+179
-22
lines changed

2 files changed

+179
-22
lines changed

drivers/net/ethernet/renesas/rswitch.c

Lines changed: 149 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,6 @@ static void rswitch_fwd_init(struct rswitch_private *priv)
123123
iowrite32(GENMASK(RSWITCH_NUM_PORTS - 1, 0), priv->addr + FWPBFC(priv->gwca.index));
124124
}
125125

126-
/* gPTP timer (gPTP) */
127-
static void rswitch_get_timestamp(struct rswitch_private *priv,
128-
struct timespec64 *ts)
129-
{
130-
priv->ptp_priv->info.gettime64(&priv->ptp_priv->info, ts);
131-
}
132-
133126
/* Gateway CPU agent block (GWCA) */
134127
static int rswitch_gwca_change_mode(struct rswitch_private *priv,
135128
enum rswitch_gwca_mode mode)
@@ -299,6 +292,16 @@ static void rswitch_gwca_queue_free(struct net_device *ndev,
299292
gq->skbs = NULL;
300293
}
301294

295+
static void rswitch_gwca_ts_queue_free(struct rswitch_private *priv)
296+
{
297+
struct rswitch_gwca_queue *gq = &priv->gwca.ts_queue;
298+
299+
dma_free_coherent(&priv->pdev->dev,
300+
sizeof(struct rswitch_ts_desc) * (gq->ring_size + 1),
301+
gq->ts_ring, gq->ring_dma);
302+
gq->ts_ring = NULL;
303+
}
304+
302305
static int rswitch_gwca_queue_alloc(struct net_device *ndev,
303306
struct rswitch_private *priv,
304307
struct rswitch_gwca_queue *gq,
@@ -344,6 +347,17 @@ static int rswitch_gwca_queue_alloc(struct net_device *ndev,
344347
return -ENOMEM;
345348
}
346349

350+
static int rswitch_gwca_ts_queue_alloc(struct rswitch_private *priv)
351+
{
352+
struct rswitch_gwca_queue *gq = &priv->gwca.ts_queue;
353+
354+
gq->ring_size = TS_RING_SIZE;
355+
gq->ts_ring = dma_alloc_coherent(&priv->pdev->dev,
356+
sizeof(struct rswitch_ts_desc) *
357+
(gq->ring_size + 1), &gq->ring_dma, GFP_KERNEL);
358+
return !gq->ts_ring ? -ENOMEM : 0;
359+
}
360+
347361
static void rswitch_desc_set_dptr(struct rswitch_desc *desc, dma_addr_t addr)
348362
{
349363
desc->dptrl = cpu_to_le32(lower_32_bits(addr));
@@ -405,6 +419,20 @@ static int rswitch_gwca_queue_format(struct net_device *ndev,
405419
return -ENOMEM;
406420
}
407421

422+
static void rswitch_gwca_ts_queue_fill(struct rswitch_private *priv,
423+
int start_index, int num)
424+
{
425+
struct rswitch_gwca_queue *gq = &priv->gwca.ts_queue;
426+
struct rswitch_ts_desc *desc;
427+
int i, index;
428+
429+
for (i = 0; i < num; i++) {
430+
index = (i + start_index) % gq->ring_size;
431+
desc = &gq->ts_ring[index];
432+
desc->desc.die_dt = DT_FEMPTY_ND | DIE;
433+
}
434+
}
435+
408436
static int rswitch_gwca_queue_ext_ts_fill(struct net_device *ndev,
409437
struct rswitch_gwca_queue *gq,
410438
int start_index, int num)
@@ -618,6 +646,9 @@ static int rswitch_gwca_hw_init(struct rswitch_private *priv)
618646
iowrite32(0, priv->addr + GWTTFC);
619647
iowrite32(lower_32_bits(priv->gwca.linkfix_table_dma), priv->addr + GWDCBAC1);
620648
iowrite32(upper_32_bits(priv->gwca.linkfix_table_dma), priv->addr + GWDCBAC0);
649+
iowrite32(lower_32_bits(priv->gwca.ts_queue.ring_dma), priv->addr + GWTDCAC10);
650+
iowrite32(upper_32_bits(priv->gwca.ts_queue.ring_dma), priv->addr + GWTDCAC00);
651+
iowrite32(GWCA_TS_IRQ_BIT, priv->addr + GWTSDCC0);
621652
rswitch_gwca_set_rate_limit(priv, priv->gwca.speed);
622653

623654
for (i = 0; i < RSWITCH_NUM_PORTS; i++) {
@@ -744,15 +775,6 @@ static int rswitch_tx_free(struct net_device *ndev, bool free_txed_only)
744775
size = le16_to_cpu(desc->desc.info_ds) & TX_DS;
745776
skb = gq->skbs[gq->dirty];
746777
if (skb) {
747-
if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
748-
struct skb_shared_hwtstamps shhwtstamps;
749-
struct timespec64 ts;
750-
751-
rswitch_get_timestamp(rdev->priv, &ts);
752-
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
753-
shhwtstamps.hwtstamp = timespec64_to_ktime(ts);
754-
skb_tstamp_tx(skb, &shhwtstamps);
755-
}
756778
dma_addr = rswitch_desc_get_dptr(&desc->desc);
757779
dma_unmap_single(ndev->dev.parent, dma_addr,
758780
size, DMA_TO_DEVICE);
@@ -878,6 +900,73 @@ static int rswitch_gwca_request_irqs(struct rswitch_private *priv)
878900
return 0;
879901
}
880902

903+
static void rswitch_ts(struct rswitch_private *priv)
904+
{
905+
struct rswitch_gwca_queue *gq = &priv->gwca.ts_queue;
906+
struct rswitch_gwca_ts_info *ts_info, *ts_info2;
907+
struct skb_shared_hwtstamps shhwtstamps;
908+
struct rswitch_ts_desc *desc;
909+
struct timespec64 ts;
910+
u32 tag, port;
911+
int num;
912+
913+
desc = &gq->ts_ring[gq->cur];
914+
while ((desc->desc.die_dt & DT_MASK) != DT_FEMPTY_ND) {
915+
dma_rmb();
916+
917+
port = TS_DESC_DPN(__le32_to_cpu(desc->desc.dptrl));
918+
tag = TS_DESC_TSUN(__le32_to_cpu(desc->desc.dptrl));
919+
920+
list_for_each_entry_safe(ts_info, ts_info2, &priv->gwca.ts_info_list, list) {
921+
if (!(ts_info->port == port && ts_info->tag == tag))
922+
continue;
923+
924+
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
925+
ts.tv_sec = __le32_to_cpu(desc->ts_sec);
926+
ts.tv_nsec = __le32_to_cpu(desc->ts_nsec & cpu_to_le32(0x3fffffff));
927+
shhwtstamps.hwtstamp = timespec64_to_ktime(ts);
928+
skb_tstamp_tx(ts_info->skb, &shhwtstamps);
929+
dev_consume_skb_irq(ts_info->skb);
930+
list_del(&ts_info->list);
931+
kfree(ts_info);
932+
break;
933+
}
934+
935+
gq->cur = rswitch_next_queue_index(gq, true, 1);
936+
desc = &gq->ts_ring[gq->cur];
937+
}
938+
939+
num = rswitch_get_num_cur_queues(gq);
940+
rswitch_gwca_ts_queue_fill(priv, gq->dirty, num);
941+
gq->dirty = rswitch_next_queue_index(gq, false, num);
942+
}
943+
944+
static irqreturn_t rswitch_gwca_ts_irq(int irq, void *dev_id)
945+
{
946+
struct rswitch_private *priv = dev_id;
947+
948+
if (ioread32(priv->addr + GWTSDIS) & GWCA_TS_IRQ_BIT) {
949+
iowrite32(GWCA_TS_IRQ_BIT, priv->addr + GWTSDIS);
950+
rswitch_ts(priv);
951+
952+
return IRQ_HANDLED;
953+
}
954+
955+
return IRQ_NONE;
956+
}
957+
958+
static int rswitch_gwca_ts_request_irqs(struct rswitch_private *priv)
959+
{
960+
int irq;
961+
962+
irq = platform_get_irq_byname(priv->pdev, GWCA_TS_IRQ_RESOURCE_NAME);
963+
if (irq < 0)
964+
return irq;
965+
966+
return devm_request_irq(&priv->pdev->dev, irq, rswitch_gwca_ts_irq,
967+
0, GWCA_TS_IRQ_NAME, priv);
968+
}
969+
881970
/* Ethernet TSN Agent block (ETHA) and Ethernet MAC IP block (RMAC) */
882971
static int rswitch_etha_change_mode(struct rswitch_etha *etha,
883972
enum rswitch_etha_mode mode)
@@ -1348,15 +1437,28 @@ static int rswitch_open(struct net_device *ndev)
13481437
rswitch_enadis_data_irq(rdev->priv, rdev->tx_queue->index, true);
13491438
rswitch_enadis_data_irq(rdev->priv, rdev->rx_queue->index, true);
13501439

1440+
iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDIE);
1441+
13511442
return 0;
13521443
};
13531444

13541445
static int rswitch_stop(struct net_device *ndev)
13551446
{
13561447
struct rswitch_device *rdev = netdev_priv(ndev);
1448+
struct rswitch_gwca_ts_info *ts_info, *ts_info2;
13571449

13581450
netif_tx_stop_all_queues(ndev);
13591451

1452+
iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDID);
1453+
1454+
list_for_each_entry_safe(ts_info, ts_info2, &rdev->priv->gwca.ts_info_list, list) {
1455+
if (ts_info->port != rdev->port)
1456+
continue;
1457+
dev_kfree_skb_irq(ts_info->skb);
1458+
list_del(&ts_info->list);
1459+
kfree(ts_info);
1460+
}
1461+
13601462
rswitch_enadis_data_irq(rdev->priv, rdev->tx_queue->index, false);
13611463
rswitch_enadis_data_irq(rdev->priv, rdev->rx_queue->index, false);
13621464

@@ -1395,11 +1497,25 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd
13951497

13961498
desc->info1 = cpu_to_le64(INFO1_DV(BIT(rdev->etha->index)) | INFO1_FMT);
13971499
if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
1500+
struct rswitch_gwca_ts_info *ts_info;
1501+
1502+
ts_info = kzalloc(sizeof(*ts_info), GFP_ATOMIC);
1503+
if (!ts_info) {
1504+
dma_unmap_single(ndev->dev.parent, dma_addr, skb->len, DMA_TO_DEVICE);
1505+
return -ENOMEM;
1506+
}
1507+
13981508
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
13991509
rdev->ts_tag++;
14001510
desc->info1 |= cpu_to_le64(INFO1_TSUN(rdev->ts_tag) | INFO1_TXC);
1511+
1512+
ts_info->skb = skb_get(skb);
1513+
ts_info->port = rdev->port;
1514+
ts_info->tag = rdev->ts_tag;
1515+
list_add_tail(&ts_info->list, &rdev->priv->gwca.ts_info_list);
1516+
1517+
skb_tx_timestamp(skb);
14011518
}
1402-
skb_tx_timestamp(skb);
14031519

14041520
dma_wmb();
14051521

@@ -1653,6 +1769,13 @@ static int rswitch_init(struct rswitch_private *priv)
16531769
if (err < 0)
16541770
return -ENOMEM;
16551771

1772+
err = rswitch_gwca_ts_queue_alloc(priv);
1773+
if (err < 0)
1774+
goto err_ts_queue_alloc;
1775+
1776+
rswitch_gwca_ts_queue_fill(priv, 0, TS_RING_SIZE);
1777+
INIT_LIST_HEAD(&priv->gwca.ts_info_list);
1778+
16561779
for (i = 0; i < RSWITCH_NUM_PORTS; i++) {
16571780
err = rswitch_device_alloc(priv, i);
16581781
if (err < 0) {
@@ -1673,6 +1796,10 @@ static int rswitch_init(struct rswitch_private *priv)
16731796
if (err < 0)
16741797
goto err_gwca_request_irq;
16751798

1799+
err = rswitch_gwca_ts_request_irqs(priv);
1800+
if (err < 0)
1801+
goto err_gwca_ts_request_irq;
1802+
16761803
err = rswitch_gwca_hw_init(priv);
16771804
if (err < 0)
16781805
goto err_gwca_hw_init;
@@ -1703,6 +1830,7 @@ static int rswitch_init(struct rswitch_private *priv)
17031830
rswitch_gwca_hw_deinit(priv);
17041831

17051832
err_gwca_hw_init:
1833+
err_gwca_ts_request_irq:
17061834
err_gwca_request_irq:
17071835
rcar_gen4_ptp_unregister(priv->ptp_priv);
17081836

@@ -1711,6 +1839,9 @@ static int rswitch_init(struct rswitch_private *priv)
17111839
rswitch_device_free(priv, i);
17121840

17131841
err_device_alloc:
1842+
rswitch_gwca_ts_queue_free(priv);
1843+
1844+
err_ts_queue_alloc:
17141845
rswitch_gwca_linkfix_free(priv);
17151846

17161847
return err;
@@ -1790,6 +1921,7 @@ static void rswitch_deinit(struct rswitch_private *priv)
17901921
rswitch_device_free(priv, i);
17911922
}
17921923

1924+
rswitch_gwca_ts_queue_free(priv);
17931925
rswitch_gwca_linkfix_free(priv);
17941926

17951927
rswitch_clock_disable(priv);

drivers/net/ethernet/renesas/rswitch.h

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#define TX_RING_SIZE 1024
2929
#define RX_RING_SIZE 1024
30+
#define TS_RING_SIZE (TX_RING_SIZE * RSWITCH_NUM_PORTS)
3031

3132
#define PKT_BUF_SZ 1584
3233
#define RSWITCH_ALIGN 128
@@ -49,6 +50,10 @@
4950
#define AGENT_INDEX_GWCA 3
5051
#define GWRO RSWITCH_GWCA0_OFFSET
5152

53+
#define GWCA_TS_IRQ_RESOURCE_NAME "gwca0_rxts0"
54+
#define GWCA_TS_IRQ_NAME "rswitch: gwca0_rxts0"
55+
#define GWCA_TS_IRQ_BIT BIT(0)
56+
5257
#define FWRO 0
5358
#define TPRO RSWITCH_TOP_OFFSET
5459
#define CARO RSWITCH_COMA_OFFSET
@@ -831,7 +836,7 @@ enum DIE_DT {
831836
DT_FSINGLE = 0x80,
832837
DT_FSTART = 0x90,
833838
DT_FMID = 0xa0,
834-
DT_FEND = 0xb8,
839+
DT_FEND = 0xb0,
835840

836841
/* Chain control */
837842
DT_LEMPTY = 0xc0,
@@ -843,7 +848,7 @@ enum DIE_DT {
843848
DT_FEMPTY = 0x40,
844849
DT_FEMPTY_IS = 0x10,
845850
DT_FEMPTY_IC = 0x20,
846-
DT_FEMPTY_ND = 0x38,
851+
DT_FEMPTY_ND = 0x30,
847852
DT_FEMPTY_START = 0x50,
848853
DT_FEMPTY_MID = 0x60,
849854
DT_FEMPTY_END = 0x70,
@@ -865,6 +870,12 @@ enum DIE_DT {
865870
/* For reception */
866871
#define INFO1_SPN(port) ((u64)(port) << 36ULL)
867872

873+
/* For timestamp descriptor in dptrl (Byte 4 to 7) */
874+
#define TS_DESC_TSUN(dptrl) ((dptrl) & GENMASK(7, 0))
875+
#define TS_DESC_SPN(dptrl) (((dptrl) & GENMASK(10, 8)) >> 8)
876+
#define TS_DESC_DPN(dptrl) (((dptrl) & GENMASK(17, 16)) >> 16)
877+
#define TS_DESC_TN(dptrl) ((dptrl) & BIT(24))
878+
868879
struct rswitch_desc {
869880
__le16 info_ds; /* Descriptor size */
870881
u8 die_dt; /* Descriptor interrupt enable and type */
@@ -911,21 +922,33 @@ struct rswitch_etha {
911922
* name, this driver calls "queue".
912923
*/
913924
struct rswitch_gwca_queue {
914-
int index;
915-
bool dir_tx;
916925
union {
917926
struct rswitch_ext_desc *tx_ring;
918927
struct rswitch_ext_ts_desc *rx_ring;
928+
struct rswitch_ts_desc *ts_ring;
919929
};
930+
931+
/* Common */
920932
dma_addr_t ring_dma;
921933
int ring_size;
922934
int cur;
923935
int dirty;
924-
struct sk_buff **skbs;
925936

937+
/* For [rt]_ring */
938+
int index;
939+
bool dir_tx;
940+
struct sk_buff **skbs;
926941
struct net_device *ndev; /* queue to ndev for irq */
927942
};
928943

944+
struct rswitch_gwca_ts_info {
945+
struct sk_buff *skb;
946+
struct list_head list;
947+
948+
int port;
949+
u8 tag;
950+
};
951+
929952
#define RSWITCH_NUM_IRQ_REGS (RSWITCH_MAX_NUM_QUEUES / BITS_PER_TYPE(u32))
930953
struct rswitch_gwca {
931954
int index;
@@ -934,6 +957,8 @@ struct rswitch_gwca {
934957
u32 linkfix_table_size;
935958
struct rswitch_gwca_queue *queues;
936959
int num_queues;
960+
struct rswitch_gwca_queue ts_queue;
961+
struct list_head ts_info_list;
937962
DECLARE_BITMAP(used, RSWITCH_MAX_NUM_QUEUES);
938963
u32 tx_irq_bits[RSWITCH_NUM_IRQ_REGS];
939964
u32 rx_irq_bits[RSWITCH_NUM_IRQ_REGS];

0 commit comments

Comments
 (0)