Skip to content

Commit 7294380

Browse files
yangbolu1991davem330
authored andcommitted
enetc: support PTP Sync packet one-step timestamping
This patch is to add support for PTP Sync packet one-step timestamping. Since ENETC single-step register has to be configured dynamically per packet for correctionField offeset and UDP checksum update, current one-step timestamping packet has to be sent only when the last one completes transmitting on hardware. So, on the TX, this patch handles one-step timestamping packet as below: - Trasmit packet immediately if no other one in transfer, or queue to skb queue if there is already one in transfer. The test_and_set_bit_lock() is used here to lock and check state. - Start a work when complete transfer on hardware, to release the bit lock and to send one skb in skb queue if has. And the configuration for one-step timestamping on ENETC before transmitting is, - Set one-step timestamping flag in extension BD. - Write 30 bits current timestamp in tstamp field of extension BD. - Update PTP Sync packet originTimestamp field with current timestamp. - Configure single-step register for correctionField offeset and UDP checksum update. Signed-off-by: Yangbo Lu <[email protected]> Reviewed-by: Claudiu Manoil <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f768e75 commit 7294380

File tree

4 files changed

+195
-26
lines changed

4 files changed

+195
-26
lines changed

drivers/net/ethernet/freescale/enetc/enetc.c

Lines changed: 171 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <linux/tcp.h>
77
#include <linux/udp.h>
88
#include <linux/vmalloc.h>
9+
#include <linux/ptp_classify.h>
910
#include <net/pkt_sched.h>
1011

1112
static struct sk_buff *enetc_tx_swbd_get_skb(struct enetc_tx_swbd *tx_swbd)
@@ -67,15 +68,52 @@ static void enetc_update_tx_ring_tail(struct enetc_bdr *tx_ring)
6768
enetc_wr_reg_hot(tx_ring->tpir, tx_ring->next_to_use);
6869
}
6970

71+
static int enetc_ptp_parse(struct sk_buff *skb, u8 *udp,
72+
u8 *msgtype, u8 *twostep,
73+
u16 *correction_offset, u16 *body_offset)
74+
{
75+
unsigned int ptp_class;
76+
struct ptp_header *hdr;
77+
unsigned int type;
78+
u8 *base;
79+
80+
ptp_class = ptp_classify_raw(skb);
81+
if (ptp_class == PTP_CLASS_NONE)
82+
return -EINVAL;
83+
84+
hdr = ptp_parse_header(skb, ptp_class);
85+
if (!hdr)
86+
return -EINVAL;
87+
88+
type = ptp_class & PTP_CLASS_PMASK;
89+
if (type == PTP_CLASS_IPV4 || type == PTP_CLASS_IPV6)
90+
*udp = 1;
91+
else
92+
*udp = 0;
93+
94+
*msgtype = ptp_get_msgtype(hdr, ptp_class);
95+
*twostep = hdr->flag_field[0] & 0x2;
96+
97+
base = skb_mac_header(skb);
98+
*correction_offset = (u8 *)&hdr->correction - base;
99+
*body_offset = (u8 *)hdr + sizeof(struct ptp_header) - base;
100+
101+
return 0;
102+
}
103+
70104
static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
71105
{
106+
bool do_vlan, do_onestep_tstamp = false, do_twostep_tstamp = false;
107+
struct enetc_ndev_priv *priv = netdev_priv(tx_ring->ndev);
108+
struct enetc_hw *hw = &priv->si->hw;
72109
struct enetc_tx_swbd *tx_swbd;
73-
skb_frag_t *frag;
74110
int len = skb_headlen(skb);
75111
union enetc_tx_bd temp_bd;
112+
u8 msgtype, twostep, udp;
76113
union enetc_tx_bd *txbd;
77-
bool do_vlan, do_tstamp;
114+
u16 offset1, offset2;
78115
int i, count = 0;
116+
skb_frag_t *frag;
79117
unsigned int f;
80118
dma_addr_t dma;
81119
u8 flags = 0;
@@ -100,12 +138,21 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
100138
count++;
101139

102140
do_vlan = skb_vlan_tag_present(skb);
103-
do_tstamp = (skb->cb[0] & ENETC_F_TX_TSTAMP) &&
104-
(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP);
105-
tx_swbd->do_tstamp = do_tstamp;
106-
tx_swbd->check_wb = tx_swbd->do_tstamp;
141+
if (skb->cb[0] & ENETC_F_TX_ONESTEP_SYNC_TSTAMP) {
142+
if (enetc_ptp_parse(skb, &udp, &msgtype, &twostep, &offset1,
143+
&offset2) ||
144+
msgtype != PTP_MSGTYPE_SYNC || twostep)
145+
WARN_ONCE(1, "Bad packet for one-step timestamping\n");
146+
else
147+
do_onestep_tstamp = true;
148+
} else if (skb->cb[0] & ENETC_F_TX_TSTAMP) {
149+
do_twostep_tstamp = true;
150+
}
151+
152+
tx_swbd->do_twostep_tstamp = do_twostep_tstamp;
153+
tx_swbd->check_wb = tx_swbd->do_twostep_tstamp;
107154

108-
if (do_vlan || do_tstamp)
155+
if (do_vlan || do_onestep_tstamp || do_twostep_tstamp)
109156
flags |= ENETC_TXBD_FLAGS_EX;
110157

111158
if (tx_ring->tsd_enable)
@@ -142,7 +189,40 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
142189
e_flags |= ENETC_TXBD_E_FLAGS_VLAN_INS;
143190
}
144191

145-
if (do_tstamp) {
192+
if (do_onestep_tstamp) {
193+
u32 lo, hi, val;
194+
u64 sec, nsec;
195+
u8 *data;
196+
197+
lo = enetc_rd_hot(hw, ENETC_SICTR0);
198+
hi = enetc_rd_hot(hw, ENETC_SICTR1);
199+
sec = (u64)hi << 32 | lo;
200+
nsec = do_div(sec, 1000000000);
201+
202+
/* Configure extension BD */
203+
temp_bd.ext.tstamp = cpu_to_le32(lo & 0x3fffffff);
204+
e_flags |= ENETC_TXBD_E_FLAGS_ONE_STEP_PTP;
205+
206+
/* Update originTimestamp field of Sync packet
207+
* - 48 bits seconds field
208+
* - 32 bits nanseconds field
209+
*/
210+
data = skb_mac_header(skb);
211+
*(__be16 *)(data + offset2) =
212+
htons((sec >> 32) & 0xffff);
213+
*(__be32 *)(data + offset2 + 2) =
214+
htonl(sec & 0xffffffff);
215+
*(__be32 *)(data + offset2 + 6) = htonl(nsec);
216+
217+
/* Configure single-step register */
218+
val = ENETC_PM0_SINGLE_STEP_EN;
219+
val |= ENETC_SET_SINGLE_STEP_OFFSET(offset1);
220+
if (udp)
221+
val |= ENETC_PM0_SINGLE_STEP_CH;
222+
223+
enetc_port_wr(hw, ENETC_PM0_SINGLE_STEP, val);
224+
enetc_port_wr(hw, ENETC_PM1_SINGLE_STEP, val);
225+
} else if (do_twostep_tstamp) {
146226
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
147227
e_flags |= ENETC_TXBD_E_FLAGS_TWO_STEP_PTP;
148228
}
@@ -214,15 +294,13 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
214294
return 0;
215295
}
216296

217-
netdev_tx_t enetc_xmit(struct sk_buff *skb, struct net_device *ndev)
297+
static netdev_tx_t enetc_start_xmit(struct sk_buff *skb,
298+
struct net_device *ndev)
218299
{
219300
struct enetc_ndev_priv *priv = netdev_priv(ndev);
220301
struct enetc_bdr *tx_ring;
221302
int count;
222303

223-
/* cb[0] used for TX timestamp type */
224-
skb->cb[0] = priv->active_offloads & ENETC_F_TX_TSTAMP_MASK;
225-
226304
tx_ring = priv->tx_ring[skb->queue_mapping];
227305

228306
if (unlikely(skb_shinfo(skb)->nr_frags > ENETC_MAX_SKB_FRAGS))
@@ -252,6 +330,40 @@ netdev_tx_t enetc_xmit(struct sk_buff *skb, struct net_device *ndev)
252330
return NETDEV_TX_OK;
253331
}
254332

333+
netdev_tx_t enetc_xmit(struct sk_buff *skb, struct net_device *ndev)
334+
{
335+
struct enetc_ndev_priv *priv = netdev_priv(ndev);
336+
u8 udp, msgtype, twostep;
337+
u16 offset1, offset2;
338+
339+
/* Mark tx timestamp type on skb->cb[0] if requires */
340+
if ((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
341+
(priv->active_offloads & ENETC_F_TX_TSTAMP_MASK)) {
342+
skb->cb[0] = priv->active_offloads & ENETC_F_TX_TSTAMP_MASK;
343+
} else {
344+
skb->cb[0] = 0;
345+
}
346+
347+
/* Fall back to two-step timestamp if not one-step Sync packet */
348+
if (skb->cb[0] & ENETC_F_TX_ONESTEP_SYNC_TSTAMP) {
349+
if (enetc_ptp_parse(skb, &udp, &msgtype, &twostep,
350+
&offset1, &offset2) ||
351+
msgtype != PTP_MSGTYPE_SYNC || twostep != 0)
352+
skb->cb[0] = ENETC_F_TX_TSTAMP;
353+
}
354+
355+
/* Queue one-step Sync packet if already locked */
356+
if (skb->cb[0] & ENETC_F_TX_ONESTEP_SYNC_TSTAMP) {
357+
if (test_and_set_bit_lock(ENETC_TX_ONESTEP_TSTAMP_IN_PROGRESS,
358+
&priv->flags)) {
359+
skb_queue_tail(&priv->tx_skbs, skb);
360+
return NETDEV_TX_OK;
361+
}
362+
}
363+
364+
return enetc_start_xmit(skb, ndev);
365+
}
366+
255367
static irqreturn_t enetc_msix(int irq, void *data)
256368
{
257369
struct enetc_int_vector *v = data;
@@ -392,18 +504,19 @@ static void enetc_recycle_xdp_tx_buff(struct enetc_bdr *tx_ring,
392504
static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
393505
{
394506
struct net_device *ndev = tx_ring->ndev;
507+
struct enetc_ndev_priv *priv = netdev_priv(ndev);
395508
int tx_frm_cnt = 0, tx_byte_cnt = 0;
396509
struct enetc_tx_swbd *tx_swbd;
397510
int i, bds_to_clean;
398-
bool do_tstamp;
511+
bool do_twostep_tstamp;
399512
u64 tstamp = 0;
400513

401514
i = tx_ring->next_to_clean;
402515
tx_swbd = &tx_ring->tx_swbd[i];
403516

404517
bds_to_clean = enetc_bd_ready_count(tx_ring, i);
405518

406-
do_tstamp = false;
519+
do_twostep_tstamp = false;
407520

408521
while (bds_to_clean && tx_frm_cnt < ENETC_DEFAULT_TX_WORK) {
409522
struct xdp_frame *xdp_frame = enetc_tx_swbd_get_xdp_frame(tx_swbd);
@@ -417,10 +530,10 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
417530
txbd = ENETC_TXBD(*tx_ring, i);
418531

419532
if (txbd->flags & ENETC_TXBD_FLAGS_W &&
420-
tx_swbd->do_tstamp) {
533+
tx_swbd->do_twostep_tstamp) {
421534
enetc_get_tx_tstamp(&priv->si->hw, txbd,
422535
&tstamp);
423-
do_tstamp = true;
536+
do_twostep_tstamp = true;
424537
}
425538
}
426539

@@ -433,9 +546,16 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
433546
xdp_return_frame(xdp_frame);
434547
tx_swbd->xdp_frame = NULL;
435548
} else if (skb) {
436-
if (unlikely(do_tstamp)) {
549+
if (unlikely(tx_swbd->skb->cb[0] &
550+
ENETC_F_TX_ONESTEP_SYNC_TSTAMP)) {
551+
/* Start work to release lock for next one-step
552+
* timestamping packet. And send one skb in
553+
* tx_skbs queue if has.
554+
*/
555+
queue_work(system_wq, &priv->tx_onestep_tstamp);
556+
} else if (unlikely(do_twostep_tstamp)) {
437557
enetc_tstamp_tx(skb, tstamp);
438-
do_tstamp = false;
558+
do_twostep_tstamp = false;
439559
}
440560
napi_consume_skb(skb, napi_budget);
441561
tx_swbd->skb = NULL;
@@ -1864,6 +1984,29 @@ static int enetc_phylink_connect(struct net_device *ndev)
18641984
return 0;
18651985
}
18661986

1987+
static void enetc_tx_onestep_tstamp(struct work_struct *work)
1988+
{
1989+
struct enetc_ndev_priv *priv;
1990+
struct sk_buff *skb;
1991+
1992+
priv = container_of(work, struct enetc_ndev_priv, tx_onestep_tstamp);
1993+
1994+
netif_tx_lock(priv->ndev);
1995+
1996+
clear_bit_unlock(ENETC_TX_ONESTEP_TSTAMP_IN_PROGRESS, &priv->flags);
1997+
skb = skb_dequeue(&priv->tx_skbs);
1998+
if (skb)
1999+
enetc_start_xmit(skb, priv->ndev);
2000+
2001+
netif_tx_unlock(priv->ndev);
2002+
}
2003+
2004+
static void enetc_tx_onestep_tstamp_init(struct enetc_ndev_priv *priv)
2005+
{
2006+
INIT_WORK(&priv->tx_onestep_tstamp, enetc_tx_onestep_tstamp);
2007+
skb_queue_head_init(&priv->tx_skbs);
2008+
}
2009+
18672010
void enetc_start(struct net_device *ndev)
18682011
{
18692012
struct enetc_ndev_priv *priv = netdev_priv(ndev);
@@ -1916,6 +2059,7 @@ int enetc_open(struct net_device *ndev)
19162059
if (err)
19172060
goto err_set_queues;
19182061

2062+
enetc_tx_onestep_tstamp_init(priv);
19192063
enetc_setup_bdrs(priv);
19202064
enetc_start(ndev);
19212065

@@ -2214,11 +2358,16 @@ static int enetc_hwtstamp_set(struct net_device *ndev, struct ifreq *ifr)
22142358

22152359
switch (config.tx_type) {
22162360
case HWTSTAMP_TX_OFF:
2217-
priv->active_offloads &= ~ENETC_F_TX_TSTAMP;
2361+
priv->active_offloads &= ~ENETC_F_TX_TSTAMP_MASK;
22182362
break;
22192363
case HWTSTAMP_TX_ON:
2364+
priv->active_offloads &= ~ENETC_F_TX_TSTAMP_MASK;
22202365
priv->active_offloads |= ENETC_F_TX_TSTAMP;
22212366
break;
2367+
case HWTSTAMP_TX_ONESTEP_SYNC:
2368+
priv->active_offloads &= ~ENETC_F_TX_TSTAMP_MASK;
2369+
priv->active_offloads |= ENETC_F_TX_ONESTEP_SYNC_TSTAMP;
2370+
break;
22222371
default:
22232372
return -ERANGE;
22242373
}
@@ -2249,7 +2398,9 @@ static int enetc_hwtstamp_get(struct net_device *ndev, struct ifreq *ifr)
22492398

22502399
config.flags = 0;
22512400

2252-
if (priv->active_offloads & ENETC_F_TX_TSTAMP)
2401+
if (priv->active_offloads & ENETC_F_TX_ONESTEP_SYNC_TSTAMP)
2402+
config.tx_type = HWTSTAMP_TX_ONESTEP_SYNC;
2403+
else if (priv->active_offloads & ENETC_F_TX_TSTAMP)
22532404
config.tx_type = HWTSTAMP_TX_ON;
22542405
else
22552406
config.tx_type = HWTSTAMP_TX_OFF;

drivers/net/ethernet/freescale/enetc/enetc.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ struct enetc_tx_swbd {
3030
enum dma_data_direction dir;
3131
u8 is_dma_page:1;
3232
u8 check_wb:1;
33-
u8 do_tstamp:1;
33+
u8 do_twostep_tstamp:1;
3434
u8 is_eof:1;
3535
u8 is_xdp_tx:1;
3636
u8 is_xdp_redirect:1;
@@ -275,11 +275,16 @@ struct psfp_cap {
275275
/* TODO: more hardware offloads */
276276
enum enetc_active_offloads {
277277
/* 8 bits reserved for TX timestamp types (hwtstamp_tx_types) */
278-
ENETC_F_TX_TSTAMP = BIT(0),
278+
ENETC_F_TX_TSTAMP = BIT(0),
279+
ENETC_F_TX_ONESTEP_SYNC_TSTAMP = BIT(1),
279280

280-
ENETC_F_RX_TSTAMP = BIT(8),
281-
ENETC_F_QBV = BIT(9),
282-
ENETC_F_QCI = BIT(10),
281+
ENETC_F_RX_TSTAMP = BIT(8),
282+
ENETC_F_QBV = BIT(9),
283+
ENETC_F_QCI = BIT(10),
284+
};
285+
286+
enum enetc_flags_bit {
287+
ENETC_TX_ONESTEP_TSTAMP_IN_PROGRESS = 0,
283288
};
284289

285290
/* interrupt coalescing modes */
@@ -324,6 +329,11 @@ struct enetc_ndev_priv {
324329
u32 tx_ictt;
325330

326331
struct bpf_prog *xdp_prog;
332+
333+
unsigned long flags;
334+
335+
struct work_struct tx_onestep_tstamp;
336+
struct sk_buff_head tx_skbs;
327337
};
328338

329339
/* Messaging */

drivers/net/ethernet/freescale/enetc/enetc_ethtool.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,8 @@ static int enetc_get_ts_info(struct net_device *ndev,
671671
SOF_TIMESTAMPING_RAW_HARDWARE;
672672

673673
info->tx_types = (1 << HWTSTAMP_TX_OFF) |
674-
(1 << HWTSTAMP_TX_ON);
674+
(1 << HWTSTAMP_TX_ON) |
675+
(1 << HWTSTAMP_TX_ONESTEP_SYNC);
675676
info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
676677
(1 << HWTSTAMP_FILTER_ALL);
677678
#else

drivers/net/ethernet/freescale/enetc/enetc_hw.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,12 @@ enum enetc_bdr_type {TX, RX};
239239

240240
#define ENETC_PM_IMDIO_BASE 0x8030
241241

242+
#define ENETC_PM0_SINGLE_STEP 0x80c0
243+
#define ENETC_PM1_SINGLE_STEP 0x90c0
244+
#define ENETC_PM0_SINGLE_STEP_CH BIT(7)
245+
#define ENETC_PM0_SINGLE_STEP_EN BIT(31)
246+
#define ENETC_SET_SINGLE_STEP_OFFSET(v) (((v) & 0xff) << 8)
247+
242248
#define ENETC_PM0_IF_MODE 0x8300
243249
#define ENETC_PM0_IFM_RG BIT(2)
244250
#define ENETC_PM0_IFM_RLP (BIT(5) | BIT(11))
@@ -548,6 +554,7 @@ static inline void enetc_clear_tx_bd(union enetc_tx_bd *txbd)
548554

549555
/* Extension flags */
550556
#define ENETC_TXBD_E_FLAGS_VLAN_INS BIT(0)
557+
#define ENETC_TXBD_E_FLAGS_ONE_STEP_PTP BIT(1)
551558
#define ENETC_TXBD_E_FLAGS_TWO_STEP_PTP BIT(2)
552559

553560
union enetc_rx_bd {

0 commit comments

Comments
 (0)