Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: ethernet: ti: am65-cpts: Enable RX HW timestamp for PTP packets using CPTS FIFO

Add a new function "am65_cpts_rx_timestamp()" which checks for PTP
packets from header and timestamps them.

Add another function "am65_cpts_find_rx_ts()" which finds CPTS FIFO
Event to get the timestamp of received PTP packet.

Signed-off-by: Chintan Vankar <c-vankar@ti.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Chintan Vankar and committed by
Paolo Abeni
c459f606 9b9fd023

+83 -7
+77 -7
drivers/net/ethernet/ti/am65-cpts.c
··· 275 275 return true; 276 276 } 277 277 278 - static int am65_cpts_fifo_read(struct am65_cpts *cpts) 278 + static int __am65_cpts_fifo_read(struct am65_cpts *cpts) 279 279 { 280 280 struct ptp_clock_event pevent; 281 281 struct am65_cpts_event *event; 282 282 bool schedule = false; 283 283 int i, type, ret = 0; 284 - unsigned long flags; 285 284 286 - spin_lock_irqsave(&cpts->lock, flags); 287 285 for (i = 0; i < AM65_CPTS_FIFO_DEPTH; i++) { 288 286 event = list_first_entry_or_null(&cpts->pool, 289 287 struct am65_cpts_event, list); ··· 310 312 event->tmo = jiffies + 311 313 msecs_to_jiffies(AM65_CPTS_EVENT_RX_TX_TIMEOUT); 312 314 313 - list_del_init(&event->list); 314 - list_add_tail(&event->list, &cpts->events); 315 + list_move_tail(&event->list, &cpts->events); 315 316 316 317 dev_dbg(cpts->dev, 317 318 "AM65_CPTS_EV_TX e1:%08x e2:%08x t:%lld\n", ··· 353 356 } 354 357 355 358 out: 356 - spin_unlock_irqrestore(&cpts->lock, flags); 357 - 358 359 if (schedule) 359 360 ptp_schedule_worker(cpts->ptp_clock, 0); 361 + 362 + return ret; 363 + } 364 + 365 + static int am65_cpts_fifo_read(struct am65_cpts *cpts) 366 + { 367 + unsigned long flags; 368 + int ret = 0; 369 + 370 + spin_lock_irqsave(&cpts->lock, flags); 371 + ret = __am65_cpts_fifo_read(cpts); 372 + spin_unlock_irqrestore(&cpts->lock, flags); 360 373 361 374 return ret; 362 375 } ··· 912 905 913 906 return 1; 914 907 } 908 + 909 + static u64 am65_cpts_find_rx_ts(struct am65_cpts *cpts, u32 skb_mtype_seqid) 910 + { 911 + struct list_head *this, *next; 912 + struct am65_cpts_event *event; 913 + unsigned long flags; 914 + u32 mtype_seqid; 915 + u64 ns = 0; 916 + 917 + spin_lock_irqsave(&cpts->lock, flags); 918 + __am65_cpts_fifo_read(cpts); 919 + list_for_each_safe(this, next, &cpts->events) { 920 + event = list_entry(this, struct am65_cpts_event, list); 921 + if (time_after(jiffies, event->tmo)) { 922 + list_move(&event->list, &cpts->pool); 923 + continue; 924 + } 925 + 926 + mtype_seqid = event->event1 & 927 + (AM65_CPTS_EVENT_1_MESSAGE_TYPE_MASK | 928 + AM65_CPTS_EVENT_1_SEQUENCE_ID_MASK | 929 + AM65_CPTS_EVENT_1_EVENT_TYPE_MASK); 930 + 931 + if (mtype_seqid == skb_mtype_seqid) { 932 + ns = event->timestamp; 933 + list_move(&event->list, &cpts->pool); 934 + break; 935 + } 936 + } 937 + spin_unlock_irqrestore(&cpts->lock, flags); 938 + 939 + return ns; 940 + } 941 + 942 + void am65_cpts_rx_timestamp(struct am65_cpts *cpts, struct sk_buff *skb) 943 + { 944 + struct am65_cpts_skb_cb_data *skb_cb = (struct am65_cpts_skb_cb_data *)skb->cb; 945 + struct skb_shared_hwtstamps *ssh; 946 + int ret; 947 + u64 ns; 948 + 949 + /* am65_cpts_rx_timestamp() is called before eth_type_trans(), so 950 + * skb MAC Hdr properties are not configured yet. Hence need to 951 + * reset skb MAC header here 952 + */ 953 + skb_reset_mac_header(skb); 954 + ret = am65_skb_get_mtype_seqid(skb, &skb_cb->skb_mtype_seqid); 955 + if (!ret) 956 + return; /* if not PTP class packet */ 957 + 958 + skb_cb->skb_mtype_seqid |= (AM65_CPTS_EV_RX << AM65_CPTS_EVENT_1_EVENT_TYPE_SHIFT); 959 + 960 + dev_dbg(cpts->dev, "%s mtype seqid %08x\n", __func__, skb_cb->skb_mtype_seqid); 961 + 962 + ns = am65_cpts_find_rx_ts(cpts, skb_cb->skb_mtype_seqid); 963 + if (!ns) 964 + return; 965 + 966 + ssh = skb_hwtstamps(skb); 967 + memset(ssh, 0, sizeof(*ssh)); 968 + ssh->hwtstamp = ns_to_ktime(ns); 969 + } 970 + EXPORT_SYMBOL_GPL(am65_cpts_rx_timestamp); 915 971 916 972 /** 917 973 * am65_cpts_tx_timestamp - save tx packet for timestamping
+6
drivers/net/ethernet/ti/am65-cpts.h
··· 22 22 struct am65_cpts *am65_cpts_create(struct device *dev, void __iomem *regs, 23 23 struct device_node *node); 24 24 int am65_cpts_phc_index(struct am65_cpts *cpts); 25 + void am65_cpts_rx_timestamp(struct am65_cpts *cpts, struct sk_buff *skb); 25 26 void am65_cpts_tx_timestamp(struct am65_cpts *cpts, struct sk_buff *skb); 26 27 void am65_cpts_prep_tx_timestamp(struct am65_cpts *cpts, struct sk_buff *skb); 27 28 void am65_cpts_rx_enable(struct am65_cpts *cpts, bool en); ··· 47 46 static inline int am65_cpts_phc_index(struct am65_cpts *cpts) 48 47 { 49 48 return -1; 49 + } 50 + 51 + static inline void am65_cpts_rx_timestamp(struct am65_cpts *cpts, 52 + struct sk_buff *skb) 53 + { 50 54 } 51 55 52 56 static inline void am65_cpts_tx_timestamp(struct am65_cpts *cpts,