Skip to content

Commit daeceb2

Browse files
committed
Merge branch 'ENETC-support-hardware-timestamping'
Y.b. Lu says: ==================== ENETC: support hardware timestamping This patch-set is to support hardware timestamping for ENETC and also to add ENETC 1588 timer device tree node for ls1028a. Because the ENETC RX BD ring dynamic allocation has not been supported and it is too expensive to use extended RX BDs if timestamping is not used, a Kconfig option is used to enable extended RX BDs in order to support hardware timestamping. This option will be removed once RX BD ring dynamic allocation is implemented. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents dfb569f + 4940100 commit daeceb2

File tree

10 files changed

+235
-6
lines changed

10 files changed

+235
-6
lines changed

Documentation/devicetree/bindings/ptp/ptp-qoriq.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ General Properties:
44

55
- compatible Should be "fsl,etsec-ptp" for eTSEC
66
Should be "fsl,fman-ptp-timer" for DPAA FMan
7+
Should be "fsl,enetc-ptp" for ENETC
78
- reg Offset and length of the register set for the device
89
- interrupts There should be at least two interrupts. Some devices
910
have as many as four PTP related interrupts.

arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,12 @@
431431
compatible = "fsl,enetc";
432432
reg = <0x000100 0 0 0 0>;
433433
};
434+
ethernet@0,4 {
435+
compatible = "fsl,enetc-ptp";
436+
reg = <0x000400 0 0 0 0>;
437+
clocks = <&clockgen 4 0>;
438+
little-endian;
439+
};
434440
};
435441
};
436442
};

drivers/net/ethernet/freescale/enetc/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,13 @@ config FSL_ENETC_PTP_CLOCK
2929
packets using the SO_TIMESTAMPING API.
3030

3131
If compiled as module (M), the module name is fsl-enetc-ptp.
32+
33+
config FSL_ENETC_HW_TIMESTAMPING
34+
bool "ENETC hardware timestamping support"
35+
depends on FSL_ENETC || FSL_ENETC_VF
36+
help
37+
Enable hardware timestamping support on the Ethernet packets
38+
using the SO_TIMESTAMPING API. Because the RX BD ring dynamic
39+
allocation has not been supported and it is too expensive to use
40+
extended RX BDs if timestamping is not used, this option enables
41+
extended RX BDs in order to support hardware timestamping.

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

Lines changed: 153 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
#define ENETC_MAX_SKB_FRAGS 13
1414
#define ENETC_TXBDS_MAX_NEEDED ENETC_TXBDS_NEEDED(ENETC_MAX_SKB_FRAGS + 1)
1515

16-
static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb);
16+
static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb,
17+
int active_offloads);
1718

1819
netdev_tx_t enetc_xmit(struct sk_buff *skb, struct net_device *ndev)
1920
{
@@ -33,7 +34,7 @@ netdev_tx_t enetc_xmit(struct sk_buff *skb, struct net_device *ndev)
3334
return NETDEV_TX_BUSY;
3435
}
3536

36-
count = enetc_map_tx_buffs(tx_ring, skb);
37+
count = enetc_map_tx_buffs(tx_ring, skb, priv->active_offloads);
3738
if (unlikely(!count))
3839
goto drop_packet_err;
3940

@@ -105,7 +106,8 @@ static void enetc_free_tx_skb(struct enetc_bdr *tx_ring,
105106
}
106107
}
107108

108-
static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
109+
static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb,
110+
int active_offloads)
109111
{
110112
struct enetc_tx_swbd *tx_swbd;
111113
struct skb_frag_struct *frag;
@@ -137,7 +139,10 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
137139
count++;
138140

139141
do_vlan = skb_vlan_tag_present(skb);
140-
do_tstamp = skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP;
142+
do_tstamp = (active_offloads & ENETC_F_TX_TSTAMP) &&
143+
(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP);
144+
tx_swbd->do_tstamp = do_tstamp;
145+
tx_swbd->check_wb = tx_swbd->do_tstamp;
141146

142147
if (do_vlan || do_tstamp)
143148
flags |= ENETC_TXBD_FLAGS_EX;
@@ -299,24 +304,69 @@ static int enetc_bd_ready_count(struct enetc_bdr *tx_ring, int ci)
299304
return pi >= ci ? pi - ci : tx_ring->bd_count - ci + pi;
300305
}
301306

307+
static void enetc_get_tx_tstamp(struct enetc_hw *hw, union enetc_tx_bd *txbd,
308+
u64 *tstamp)
309+
{
310+
u32 lo, hi;
311+
312+
lo = enetc_rd(hw, ENETC_SICTR0);
313+
hi = enetc_rd(hw, ENETC_SICTR1);
314+
if (lo <= txbd->wb.tstamp)
315+
hi -= 1;
316+
*tstamp = (u64)hi << 32 | txbd->wb.tstamp;
317+
}
318+
319+
static void enetc_tstamp_tx(struct sk_buff *skb, u64 tstamp)
320+
{
321+
struct skb_shared_hwtstamps shhwtstamps;
322+
323+
if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) {
324+
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
325+
shhwtstamps.hwtstamp = ns_to_ktime(tstamp);
326+
skb_tstamp_tx(skb, &shhwtstamps);
327+
}
328+
}
329+
302330
static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
303331
{
304332
struct net_device *ndev = tx_ring->ndev;
305333
int tx_frm_cnt = 0, tx_byte_cnt = 0;
306334
struct enetc_tx_swbd *tx_swbd;
307335
int i, bds_to_clean;
336+
bool do_tstamp;
337+
u64 tstamp = 0;
308338

309339
i = tx_ring->next_to_clean;
310340
tx_swbd = &tx_ring->tx_swbd[i];
311341
bds_to_clean = enetc_bd_ready_count(tx_ring, i);
312342

343+
do_tstamp = false;
344+
313345
while (bds_to_clean && tx_frm_cnt < ENETC_DEFAULT_TX_WORK) {
314346
bool is_eof = !!tx_swbd->skb;
315347

348+
if (unlikely(tx_swbd->check_wb)) {
349+
struct enetc_ndev_priv *priv = netdev_priv(ndev);
350+
union enetc_tx_bd *txbd;
351+
352+
txbd = ENETC_TXBD(*tx_ring, i);
353+
354+
if (txbd->flags & ENETC_TXBD_FLAGS_W &&
355+
tx_swbd->do_tstamp) {
356+
enetc_get_tx_tstamp(&priv->si->hw, txbd,
357+
&tstamp);
358+
do_tstamp = true;
359+
}
360+
}
361+
316362
if (likely(tx_swbd->dma))
317363
enetc_unmap_tx_buff(tx_ring, tx_swbd);
318364

319365
if (is_eof) {
366+
if (unlikely(do_tstamp)) {
367+
enetc_tstamp_tx(tx_swbd->skb, tstamp);
368+
do_tstamp = false;
369+
}
320370
napi_consume_skb(tx_swbd->skb, napi_budget);
321371
tx_swbd->skb = NULL;
322372
}
@@ -425,10 +475,37 @@ static int enetc_refill_rx_ring(struct enetc_bdr *rx_ring, const int buff_cnt)
425475
return j;
426476
}
427477

478+
#ifdef CONFIG_FSL_ENETC_HW_TIMESTAMPING
479+
static void enetc_get_rx_tstamp(struct net_device *ndev,
480+
union enetc_rx_bd *rxbd,
481+
struct sk_buff *skb)
482+
{
483+
struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
484+
struct enetc_ndev_priv *priv = netdev_priv(ndev);
485+
struct enetc_hw *hw = &priv->si->hw;
486+
u32 lo, hi;
487+
u64 tstamp;
488+
489+
if (rxbd->r.flags & ENETC_RXBD_FLAG_TSTMP) {
490+
lo = enetc_rd(hw, ENETC_SICTR0);
491+
hi = enetc_rd(hw, ENETC_SICTR1);
492+
if (lo <= rxbd->r.tstamp)
493+
hi -= 1;
494+
495+
tstamp = (u64)hi << 32 | rxbd->r.tstamp;
496+
memset(shhwtstamps, 0, sizeof(*shhwtstamps));
497+
shhwtstamps->hwtstamp = ns_to_ktime(tstamp);
498+
}
499+
}
500+
#endif
501+
428502
static void enetc_get_offloads(struct enetc_bdr *rx_ring,
429503
union enetc_rx_bd *rxbd, struct sk_buff *skb)
430504
{
431-
/* TODO: add tstamp, hashing */
505+
#ifdef CONFIG_FSL_ENETC_HW_TIMESTAMPING
506+
struct enetc_ndev_priv *priv = netdev_priv(rx_ring->ndev);
507+
#endif
508+
/* TODO: hashing */
432509
if (rx_ring->ndev->features & NETIF_F_RXCSUM) {
433510
u16 inet_csum = le16_to_cpu(rxbd->r.inet_csum);
434511

@@ -442,6 +519,10 @@ static void enetc_get_offloads(struct enetc_bdr *rx_ring,
442519
if (le16_to_cpu(rxbd->r.flags) & ENETC_RXBD_FLAG_VLAN)
443520
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
444521
le16_to_cpu(rxbd->r.vlan_opt));
522+
#ifdef CONFIG_FSL_ENETC_HW_TIMESTAMPING
523+
if (priv->active_offloads & ENETC_F_RX_TSTAMP)
524+
enetc_get_rx_tstamp(rx_ring->ndev, rxbd, skb);
525+
#endif
445526
}
446527

447528
static void enetc_process_skb(struct enetc_bdr *rx_ring,
@@ -1074,6 +1155,9 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
10741155
enetc_rxbdr_wr(hw, idx, ENETC_RBICIR0, ENETC_RBICIR0_ICEN | 0x1);
10751156

10761157
rbmr = ENETC_RBMR_EN;
1158+
#ifdef CONFIG_FSL_ENETC_HW_TIMESTAMPING
1159+
rbmr |= ENETC_RBMR_BDS;
1160+
#endif
10771161
if (rx_ring->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)
10781162
rbmr |= ENETC_RBMR_VTE;
10791163

@@ -1396,6 +1480,70 @@ int enetc_set_features(struct net_device *ndev,
13961480
return 0;
13971481
}
13981482

1483+
#ifdef CONFIG_FSL_ENETC_HW_TIMESTAMPING
1484+
static int enetc_hwtstamp_set(struct net_device *ndev, struct ifreq *ifr)
1485+
{
1486+
struct enetc_ndev_priv *priv = netdev_priv(ndev);
1487+
struct hwtstamp_config config;
1488+
1489+
if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
1490+
return -EFAULT;
1491+
1492+
switch (config.tx_type) {
1493+
case HWTSTAMP_TX_OFF:
1494+
priv->active_offloads &= ~ENETC_F_TX_TSTAMP;
1495+
break;
1496+
case HWTSTAMP_TX_ON:
1497+
priv->active_offloads |= ENETC_F_TX_TSTAMP;
1498+
break;
1499+
default:
1500+
return -ERANGE;
1501+
}
1502+
1503+
switch (config.rx_filter) {
1504+
case HWTSTAMP_FILTER_NONE:
1505+
priv->active_offloads &= ~ENETC_F_RX_TSTAMP;
1506+
break;
1507+
default:
1508+
priv->active_offloads |= ENETC_F_RX_TSTAMP;
1509+
config.rx_filter = HWTSTAMP_FILTER_ALL;
1510+
}
1511+
1512+
return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
1513+
-EFAULT : 0;
1514+
}
1515+
1516+
static int enetc_hwtstamp_get(struct net_device *ndev, struct ifreq *ifr)
1517+
{
1518+
struct enetc_ndev_priv *priv = netdev_priv(ndev);
1519+
struct hwtstamp_config config;
1520+
1521+
config.flags = 0;
1522+
1523+
if (priv->active_offloads & ENETC_F_TX_TSTAMP)
1524+
config.tx_type = HWTSTAMP_TX_ON;
1525+
else
1526+
config.tx_type = HWTSTAMP_TX_OFF;
1527+
1528+
config.rx_filter = (priv->active_offloads & ENETC_F_RX_TSTAMP) ?
1529+
HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE;
1530+
1531+
return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
1532+
-EFAULT : 0;
1533+
}
1534+
#endif
1535+
1536+
int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
1537+
{
1538+
#ifdef CONFIG_FSL_ENETC_HW_TIMESTAMPING
1539+
if (cmd == SIOCSHWTSTAMP)
1540+
return enetc_hwtstamp_set(ndev, rq);
1541+
if (cmd == SIOCGHWTSTAMP)
1542+
return enetc_hwtstamp_get(ndev, rq);
1543+
#endif
1544+
return -EINVAL;
1545+
}
1546+
13991547
int enetc_alloc_msix(struct enetc_ndev_priv *priv)
14001548
{
14011549
struct pci_dev *pdev = priv->si->pdev;

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ struct enetc_tx_swbd {
2121
struct sk_buff *skb;
2222
dma_addr_t dma;
2323
u16 len;
24-
u16 is_dma_page;
24+
u8 is_dma_page:1;
25+
u8 check_wb:1;
26+
u8 do_tstamp:1;
2527
};
2628

2729
#define ENETC_RX_MAXFRM_SIZE ENETC_MAC_MAXFRM_SIZE
@@ -167,6 +169,12 @@ struct enetc_cls_rule {
167169

168170
#define ENETC_MAX_BDR_INT 2 /* fixed to max # of available cpus */
169171

172+
/* TODO: more hardware offloads */
173+
enum enetc_active_offloads {
174+
ENETC_F_RX_TSTAMP = BIT(0),
175+
ENETC_F_TX_TSTAMP = BIT(1),
176+
};
177+
170178
struct enetc_ndev_priv {
171179
struct net_device *ndev;
172180
struct device *dev; /* dma-mapping device */
@@ -178,6 +186,7 @@ struct enetc_ndev_priv {
178186
u16 rx_bd_count, tx_bd_count;
179187

180188
u16 msg_enable;
189+
int active_offloads;
181190

182191
struct enetc_bdr *tx_ring[16];
183192
struct enetc_bdr *rx_ring[16];
@@ -200,6 +209,9 @@ struct enetc_msg_cmd_set_primary_mac {
200209

201210
#define ENETC_CBDR_TIMEOUT 1000 /* usecs */
202211

212+
/* PTP driver exports */
213+
extern int enetc_phc_index;
214+
203215
/* SI common */
204216
int enetc_pci_probe(struct pci_dev *pdev, const char *name, int sizeof_priv);
205217
void enetc_pci_remove(struct pci_dev *pdev);
@@ -216,6 +228,7 @@ netdev_tx_t enetc_xmit(struct sk_buff *skb, struct net_device *ndev);
216228
struct net_device_stats *enetc_get_stats(struct net_device *ndev);
217229
int enetc_set_features(struct net_device *ndev,
218230
netdev_features_t features);
231+
int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd);
219232
/* ethtool */
220233
void enetc_set_ethtool_ops(struct net_device *ndev);
221234

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,35 @@ static void enetc_get_ringparam(struct net_device *ndev,
555555
}
556556
}
557557

558+
static int enetc_get_ts_info(struct net_device *ndev,
559+
struct ethtool_ts_info *info)
560+
{
561+
int *phc_idx;
562+
563+
phc_idx = symbol_get(enetc_phc_index);
564+
if (phc_idx) {
565+
info->phc_index = *phc_idx;
566+
symbol_put(enetc_phc_index);
567+
} else {
568+
info->phc_index = -1;
569+
}
570+
571+
#ifdef CONFIG_FSL_ENETC_HW_TIMESTAMPING
572+
info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
573+
SOF_TIMESTAMPING_RX_HARDWARE |
574+
SOF_TIMESTAMPING_RAW_HARDWARE;
575+
576+
info->tx_types = (1 << HWTSTAMP_TX_OFF) |
577+
(1 << HWTSTAMP_TX_ON);
578+
info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
579+
(1 << HWTSTAMP_FILTER_ALL);
580+
#else
581+
info->so_timestamping = SOF_TIMESTAMPING_RX_SOFTWARE |
582+
SOF_TIMESTAMPING_SOFTWARE;
583+
#endif
584+
return 0;
585+
}
586+
558587
static const struct ethtool_ops enetc_pf_ethtool_ops = {
559588
.get_regs_len = enetc_get_reglen,
560589
.get_regs = enetc_get_regs,
@@ -571,6 +600,7 @@ static const struct ethtool_ops enetc_pf_ethtool_ops = {
571600
.get_link_ksettings = phy_ethtool_get_link_ksettings,
572601
.set_link_ksettings = phy_ethtool_set_link_ksettings,
573602
.get_link = ethtool_op_get_link,
603+
.get_ts_info = enetc_get_ts_info,
574604
};
575605

576606
static const struct ethtool_ops enetc_vf_ethtool_ops = {
@@ -586,6 +616,7 @@ static const struct ethtool_ops enetc_vf_ethtool_ops = {
586616
.set_rxfh = enetc_set_rxfh,
587617
.get_ringparam = enetc_get_ringparam,
588618
.get_link = ethtool_op_get_link,
619+
.get_ts_info = enetc_get_ts_info,
589620
};
590621

591622
void enetc_set_ethtool_ops(struct net_device *ndev)

0 commit comments

Comments
 (0)