Skip to content

Commit 30b3fe0

Browse files
author
Paolo Abeni
committed
Merge branch 'enable-rx-hw-timestamp-for-ptp-packets-using-cpts-fifo'
Chintan Vankar says: ==================== Enable RX HW timestamp for PTP packets using CPTS FIFO The CPSW offers two mechanisms for communicating packet ingress timestamp information to the host. The first mechanism is via the CPTS Event FIFO which records timestamp when triggered by certain events. One such event is the reception of an Ethernet packet with a specified EtherType field. This is used to capture ingress timestamps for PTP packets. With this mechanism the host must read the timestamp (from the CPTS FIFO) separately from the packet payload which is delivered via DMA. In the second mechanism of timestamping, CPSW driver enables hardware timestamping for all received packets by setting the TSTAMP_EN bit in CPTS_CONTROL register, which directs the CPTS module to timestamp all received packets, followed by passing timestamp via DMA descriptors. This mechanism is responsible for triggering errata i2401: "CPSW: Host Timestamps Cause CPSW Port to Lock up." The errata affects all K3 SoCs. Link to errata for AM64x: https://www.ti.com/lit/er/sprz457h/sprz457h.pdf As a workaround we can use first mechanism to timestamp received packets. ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents 9b9fd02 + c03a6fd commit 30b3fe0

File tree

4 files changed

+118
-64
lines changed

4 files changed

+118
-64
lines changed

drivers/net/ethernet/ti/am65-cpsw-ethtool.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,17 @@ static int am65_cpsw_get_ethtool_ts_info(struct net_device *ndev,
695695
struct ethtool_ts_info *info)
696696
{
697697
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
698+
unsigned int ptp_v2_filter;
699+
700+
ptp_v2_filter = BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
701+
BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
702+
BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
703+
BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
704+
BIT(HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
705+
BIT(HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
706+
BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) |
707+
BIT(HWTSTAMP_FILTER_PTP_V2_SYNC) |
708+
BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ);
698709

699710
if (!IS_ENABLED(CONFIG_TI_K3_AM65_CPTS))
700711
return ethtool_op_get_ts_info(ndev, info);
@@ -708,7 +719,7 @@ static int am65_cpsw_get_ethtool_ts_info(struct net_device *ndev,
708719
SOF_TIMESTAMPING_RAW_HARDWARE;
709720
info->phc_index = am65_cpts_phc_index(common->cpts);
710721
info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
711-
info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
722+
info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | ptp_v2_filter;
712723
return 0;
713724
}
714725

drivers/net/ethernet/ti/am65-cpsw-nuss.c

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@
103103
#define AM65_CPSW_PN_TS_CTL_TX_HOST_TS_EN BIT(11)
104104
#define AM65_CPSW_PN_TS_CTL_MSG_TYPE_EN_SHIFT 16
105105

106+
#define AM65_CPSW_PN_TS_CTL_RX_ANX_F_EN BIT(0)
107+
#define AM65_CPSW_PN_TS_CTL_RX_VLAN_LT1_EN BIT(1)
108+
#define AM65_CPSW_PN_TS_CTL_RX_VLAN_LT2_EN BIT(2)
109+
#define AM65_CPSW_PN_TS_CTL_RX_ANX_D_EN BIT(3)
110+
#define AM65_CPSW_PN_TS_CTL_RX_ANX_E_EN BIT(9)
111+
106112
/* AM65_CPSW_PORTN_REG_TS_SEQ_LTYPE_REG register fields */
107113
#define AM65_CPSW_PN_TS_SEQ_ID_OFFSET_SHIFT 16
108114

@@ -126,6 +132,11 @@
126132
AM65_CPSW_PN_TS_CTL_TX_ANX_E_EN | \
127133
AM65_CPSW_PN_TS_CTL_TX_ANX_F_EN)
128134

135+
#define AM65_CPSW_TS_RX_ANX_ALL_EN \
136+
(AM65_CPSW_PN_TS_CTL_RX_ANX_D_EN | \
137+
AM65_CPSW_PN_TS_CTL_RX_ANX_E_EN | \
138+
AM65_CPSW_PN_TS_CTL_RX_ANX_F_EN)
139+
129140
#define AM65_CPSW_ALE_AGEOUT_DEFAULT 30
130141
/* Number of TX/RX descriptors */
131142
#define AM65_CPSW_MAX_TX_DESC 500
@@ -1050,18 +1061,6 @@ static int am65_cpsw_run_xdp(struct am65_cpsw_common *common,
10501061
return ret;
10511062
}
10521063

1053-
static void am65_cpsw_nuss_rx_ts(struct sk_buff *skb, u32 *psdata)
1054-
{
1055-
struct skb_shared_hwtstamps *ssh;
1056-
u64 ns;
1057-
1058-
ns = ((u64)psdata[1] << 32) | psdata[0];
1059-
1060-
ssh = skb_hwtstamps(skb);
1061-
memset(ssh, 0, sizeof(*ssh));
1062-
ssh->hwtstamp = ns_to_ktime(ns);
1063-
}
1064-
10651064
/* RX psdata[2] word format - checksum information */
10661065
#define AM65_CPSW_RX_PSD_CSUM_ADD GENMASK(15, 0)
10671066
#define AM65_CPSW_RX_PSD_CSUM_ERR BIT(16)
@@ -1177,13 +1176,11 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_common *common,
11771176
skb_reserve(skb, headroom);
11781177
}
11791178

1180-
/* Pass skb to netstack if no XDP prog or returned XDP_PASS */
1181-
if (port->rx_ts_enabled)
1182-
am65_cpsw_nuss_rx_ts(skb, psdata);
1183-
11841179
ndev_priv = netdev_priv(ndev);
11851180
am65_cpsw_nuss_set_offload_fwd_mark(skb, ndev_priv->offload_fwd_mark);
11861181
skb_put(skb, pkt_len);
1182+
if (port->rx_ts_enabled)
1183+
am65_cpts_rx_timestamp(common->cpts, skb);
11871184
skb_mark_for_recycle(skb);
11881185
skb->protocol = eth_type_trans(skb, ndev);
11891186
am65_cpsw_nuss_rx_csum(skb, csum_info);
@@ -1736,7 +1733,6 @@ static int am65_cpsw_nuss_ndo_slave_set_mac_address(struct net_device *ndev,
17361733
static int am65_cpsw_nuss_hwtstamp_set(struct net_device *ndev,
17371734
struct ifreq *ifr)
17381735
{
1739-
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
17401736
struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
17411737
u32 ts_ctrl, seq_id, ts_ctrl_ltype2, ts_vlan_ltype;
17421738
struct hwtstamp_config cfg;
@@ -1760,11 +1756,6 @@ static int am65_cpsw_nuss_hwtstamp_set(struct net_device *ndev,
17601756
case HWTSTAMP_FILTER_NONE:
17611757
port->rx_ts_enabled = false;
17621758
break;
1763-
case HWTSTAMP_FILTER_ALL:
1764-
case HWTSTAMP_FILTER_SOME:
1765-
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
1766-
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
1767-
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
17681759
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
17691760
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
17701761
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
@@ -1774,10 +1765,13 @@ static int am65_cpsw_nuss_hwtstamp_set(struct net_device *ndev,
17741765
case HWTSTAMP_FILTER_PTP_V2_EVENT:
17751766
case HWTSTAMP_FILTER_PTP_V2_SYNC:
17761767
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
1777-
case HWTSTAMP_FILTER_NTP_ALL:
17781768
port->rx_ts_enabled = true;
1779-
cfg.rx_filter = HWTSTAMP_FILTER_ALL;
1769+
cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
17801770
break;
1771+
case HWTSTAMP_FILTER_ALL:
1772+
case HWTSTAMP_FILTER_SOME:
1773+
case HWTSTAMP_FILTER_NTP_ALL:
1774+
return -EOPNOTSUPP;
17811775
default:
17821776
return -ERANGE;
17831777
}
@@ -1807,16 +1801,17 @@ static int am65_cpsw_nuss_hwtstamp_set(struct net_device *ndev,
18071801
ts_ctrl |= AM65_CPSW_TS_TX_ANX_ALL_EN |
18081802
AM65_CPSW_PN_TS_CTL_TX_VLAN_LT1_EN;
18091803

1804+
if (port->rx_ts_enabled)
1805+
ts_ctrl |= AM65_CPSW_TS_RX_ANX_ALL_EN |
1806+
AM65_CPSW_PN_TS_CTL_RX_VLAN_LT1_EN;
1807+
18101808
writel(seq_id, port->port_base + AM65_CPSW_PORTN_REG_TS_SEQ_LTYPE_REG);
18111809
writel(ts_vlan_ltype, port->port_base +
18121810
AM65_CPSW_PORTN_REG_TS_VLAN_LTYPE_REG);
18131811
writel(ts_ctrl_ltype2, port->port_base +
18141812
AM65_CPSW_PORTN_REG_TS_CTL_LTYPE2);
18151813
writel(ts_ctrl, port->port_base + AM65_CPSW_PORTN_REG_TS_CTL);
18161814

1817-
/* en/dis RX timestamp */
1818-
am65_cpts_rx_enable(common->cpts, port->rx_ts_enabled);
1819-
18201815
return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
18211816
}
18221817

@@ -1833,7 +1828,7 @@ static int am65_cpsw_nuss_hwtstamp_get(struct net_device *ndev,
18331828
cfg.tx_type = port->tx_ts_enabled ?
18341829
HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
18351830
cfg.rx_filter = port->rx_ts_enabled ?
1836-
HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE;
1831+
HWTSTAMP_FILTER_PTP_V2_EVENT : HWTSTAMP_FILTER_NONE;
18371832

18381833
return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
18391834
}

drivers/net/ethernet/ti/am65-cpts.c

Lines changed: 77 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -275,15 +275,13 @@ static bool am65_cpts_fifo_pop_event(struct am65_cpts *cpts,
275275
return true;
276276
}
277277

278-
static int am65_cpts_fifo_read(struct am65_cpts *cpts)
278+
static int __am65_cpts_fifo_read(struct am65_cpts *cpts)
279279
{
280280
struct ptp_clock_event pevent;
281281
struct am65_cpts_event *event;
282282
bool schedule = false;
283283
int i, type, ret = 0;
284-
unsigned long flags;
285284

286-
spin_lock_irqsave(&cpts->lock, flags);
287285
for (i = 0; i < AM65_CPTS_FIFO_DEPTH; i++) {
288286
event = list_first_entry_or_null(&cpts->pool,
289287
struct am65_cpts_event, list);
@@ -312,8 +310,7 @@ static int am65_cpts_fifo_read(struct am65_cpts *cpts)
312310
event->tmo = jiffies +
313311
msecs_to_jiffies(AM65_CPTS_EVENT_RX_TX_TIMEOUT);
314312

315-
list_del_init(&event->list);
316-
list_add_tail(&event->list, &cpts->events);
313+
list_move_tail(&event->list, &cpts->events);
317314

318315
dev_dbg(cpts->dev,
319316
"AM65_CPTS_EV_TX e1:%08x e2:%08x t:%lld\n",
@@ -356,14 +353,24 @@ static int am65_cpts_fifo_read(struct am65_cpts *cpts)
356353
}
357354

358355
out:
359-
spin_unlock_irqrestore(&cpts->lock, flags);
360-
361356
if (schedule)
362357
ptp_schedule_worker(cpts->ptp_clock, 0);
363358

364359
return ret;
365360
}
366361

362+
static int am65_cpts_fifo_read(struct am65_cpts *cpts)
363+
{
364+
unsigned long flags;
365+
int ret = 0;
366+
367+
spin_lock_irqsave(&cpts->lock, flags);
368+
ret = __am65_cpts_fifo_read(cpts);
369+
spin_unlock_irqrestore(&cpts->lock, flags);
370+
371+
return ret;
372+
}
373+
367374
static u64 am65_cpts_gettime(struct am65_cpts *cpts,
368375
struct ptp_system_timestamp *sts)
369376
{
@@ -859,29 +866,6 @@ static long am65_cpts_ts_work(struct ptp_clock_info *ptp)
859866
return delay;
860867
}
861868

862-
/**
863-
* am65_cpts_rx_enable - enable rx timestamping
864-
* @cpts: cpts handle
865-
* @en: enable
866-
*
867-
* This functions enables rx packets timestamping. The CPTS can timestamp all
868-
* rx packets.
869-
*/
870-
void am65_cpts_rx_enable(struct am65_cpts *cpts, bool en)
871-
{
872-
u32 val;
873-
874-
mutex_lock(&cpts->ptp_clk_lock);
875-
val = am65_cpts_read32(cpts, control);
876-
if (en)
877-
val |= AM65_CPTS_CONTROL_TSTAMP_EN;
878-
else
879-
val &= ~AM65_CPTS_CONTROL_TSTAMP_EN;
880-
am65_cpts_write32(cpts, val, control);
881-
mutex_unlock(&cpts->ptp_clk_lock);
882-
}
883-
EXPORT_SYMBOL_GPL(am65_cpts_rx_enable);
884-
885869
static int am65_skb_get_mtype_seqid(struct sk_buff *skb, u32 *mtype_seqid)
886870
{
887871
unsigned int ptp_class = ptp_classify_raw(skb);
@@ -906,6 +890,69 @@ static int am65_skb_get_mtype_seqid(struct sk_buff *skb, u32 *mtype_seqid)
906890
return 1;
907891
}
908892

893+
static u64 am65_cpts_find_rx_ts(struct am65_cpts *cpts, u32 skb_mtype_seqid)
894+
{
895+
struct list_head *this, *next;
896+
struct am65_cpts_event *event;
897+
unsigned long flags;
898+
u32 mtype_seqid;
899+
u64 ns = 0;
900+
901+
spin_lock_irqsave(&cpts->lock, flags);
902+
__am65_cpts_fifo_read(cpts);
903+
list_for_each_safe(this, next, &cpts->events) {
904+
event = list_entry(this, struct am65_cpts_event, list);
905+
if (time_after(jiffies, event->tmo)) {
906+
list_move(&event->list, &cpts->pool);
907+
continue;
908+
}
909+
910+
mtype_seqid = event->event1 &
911+
(AM65_CPTS_EVENT_1_MESSAGE_TYPE_MASK |
912+
AM65_CPTS_EVENT_1_SEQUENCE_ID_MASK |
913+
AM65_CPTS_EVENT_1_EVENT_TYPE_MASK);
914+
915+
if (mtype_seqid == skb_mtype_seqid) {
916+
ns = event->timestamp;
917+
list_move(&event->list, &cpts->pool);
918+
break;
919+
}
920+
}
921+
spin_unlock_irqrestore(&cpts->lock, flags);
922+
923+
return ns;
924+
}
925+
926+
void am65_cpts_rx_timestamp(struct am65_cpts *cpts, struct sk_buff *skb)
927+
{
928+
struct am65_cpts_skb_cb_data *skb_cb = (struct am65_cpts_skb_cb_data *)skb->cb;
929+
struct skb_shared_hwtstamps *ssh;
930+
int ret;
931+
u64 ns;
932+
933+
/* am65_cpts_rx_timestamp() is called before eth_type_trans(), so
934+
* skb MAC Hdr properties are not configured yet. Hence need to
935+
* reset skb MAC header here
936+
*/
937+
skb_reset_mac_header(skb);
938+
ret = am65_skb_get_mtype_seqid(skb, &skb_cb->skb_mtype_seqid);
939+
if (!ret)
940+
return; /* if not PTP class packet */
941+
942+
skb_cb->skb_mtype_seqid |= (AM65_CPTS_EV_RX << AM65_CPTS_EVENT_1_EVENT_TYPE_SHIFT);
943+
944+
dev_dbg(cpts->dev, "%s mtype seqid %08x\n", __func__, skb_cb->skb_mtype_seqid);
945+
946+
ns = am65_cpts_find_rx_ts(cpts, skb_cb->skb_mtype_seqid);
947+
if (!ns)
948+
return;
949+
950+
ssh = skb_hwtstamps(skb);
951+
memset(ssh, 0, sizeof(*ssh));
952+
ssh->hwtstamp = ns_to_ktime(ns);
953+
}
954+
EXPORT_SYMBOL_GPL(am65_cpts_rx_timestamp);
955+
909956
/**
910957
* am65_cpts_tx_timestamp - save tx packet for timestamping
911958
* @cpts: cpts handle

drivers/net/ethernet/ti/am65-cpts.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ void am65_cpts_release(struct am65_cpts *cpts);
2222
struct am65_cpts *am65_cpts_create(struct device *dev, void __iomem *regs,
2323
struct device_node *node);
2424
int am65_cpts_phc_index(struct am65_cpts *cpts);
25+
void am65_cpts_rx_timestamp(struct am65_cpts *cpts, struct sk_buff *skb);
2526
void am65_cpts_tx_timestamp(struct am65_cpts *cpts, struct sk_buff *skb);
2627
void am65_cpts_prep_tx_timestamp(struct am65_cpts *cpts, struct sk_buff *skb);
27-
void am65_cpts_rx_enable(struct am65_cpts *cpts, bool en);
2828
u64 am65_cpts_ns_gettime(struct am65_cpts *cpts);
2929
int am65_cpts_estf_enable(struct am65_cpts *cpts, int idx,
3030
struct am65_cpts_estf_cfg *cfg);
@@ -48,17 +48,18 @@ static inline int am65_cpts_phc_index(struct am65_cpts *cpts)
4848
return -1;
4949
}
5050

51-
static inline void am65_cpts_tx_timestamp(struct am65_cpts *cpts,
51+
static inline void am65_cpts_rx_timestamp(struct am65_cpts *cpts,
5252
struct sk_buff *skb)
5353
{
5454
}
5555

56-
static inline void am65_cpts_prep_tx_timestamp(struct am65_cpts *cpts,
57-
struct sk_buff *skb)
56+
static inline void am65_cpts_tx_timestamp(struct am65_cpts *cpts,
57+
struct sk_buff *skb)
5858
{
5959
}
6060

61-
static inline void am65_cpts_rx_enable(struct am65_cpts *cpts, bool en)
61+
static inline void am65_cpts_prep_tx_timestamp(struct am65_cpts *cpts,
62+
struct sk_buff *skb)
6263
{
6364
}
6465

0 commit comments

Comments
 (0)