Skip to content

Commit b67e191

Browse files
bwallanJeff Kirsher
authored and
Jeff Kirsher
committed
e1000e: add support for hardware timestamping on some devices
On 82574, 82583, 82579, I217 and I218 add support for hardware time stamping of all or no Rx packets and Tx packets which have the SKBTX_HW_TSTAMP flag set. Update the .get_ts_info ethtool operation to report the supported time stamping modes, and enable and disable hardware time stamping with the SIOCSHWTSTAMP ioctl. Signed-off-by: Bruce Allan <[email protected]> Tested-by: Jeff Pieper <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent ffe0b2f commit b67e191

File tree

7 files changed

+462
-8
lines changed

7 files changed

+462
-8
lines changed

drivers/net/ethernet/intel/e1000e/82571.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2044,6 +2044,7 @@ const struct e1000_info e1000_82574_info = {
20442044
| FLAG_HAS_MSIX
20452045
| FLAG_HAS_JUMBO_FRAMES
20462046
| FLAG_HAS_WOL
2047+
| FLAG_HAS_HW_TIMESTAMP
20472048
| FLAG_APME_IN_CTRL3
20482049
| FLAG_HAS_SMART_POWER_DOWN
20492050
| FLAG_HAS_AMT
@@ -2065,6 +2066,7 @@ const struct e1000_info e1000_82583_info = {
20652066
.mac = e1000_82583,
20662067
.flags = FLAG_HAS_HW_VLAN_FILTER
20672068
| FLAG_HAS_WOL
2069+
| FLAG_HAS_HW_TIMESTAMP
20682070
| FLAG_APME_IN_CTRL3
20692071
| FLAG_HAS_SMART_POWER_DOWN
20702072
| FLAG_HAS_AMT

drivers/net/ethernet/intel/e1000e/defines.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */
108108
#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */
109109

110+
#define E1000_RXDEXT_STATERR_TST 0x00000100 /* Time Stamp taken */
110111
#define E1000_RXDEXT_STATERR_CE 0x01000000
111112
#define E1000_RXDEXT_STATERR_SE 0x02000000
112113
#define E1000_RXDEXT_STATERR_SEQ 0x04000000
@@ -318,6 +319,7 @@
318319
#define E1000_TXD_CMD_IP 0x02000000 /* IP packet */
319320
#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */
320321
#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */
322+
#define E1000_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */
321323

322324
/* Transmit Control */
323325
#define E1000_TCTL_EN 0x00000002 /* enable Tx */
@@ -536,6 +538,18 @@
536538
#define E1000_RXCW_C 0x20000000 /* Receive config */
537539
#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */
538540

541+
#define E1000_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */
542+
#define E1000_TSYNCRXCTL_TYPE_ALL 0x08
543+
#define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */
544+
545+
#define E1000_TSYNCRXCTL_VALID 0x00000001 /* Rx timestamp valid */
546+
#define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */
547+
#define E1000_TSYNCRXCTL_ENABLED 0x00000010 /* enable Rx timestamping */
548+
#define E1000_TSYNCRXCTL_SYSCFI 0x00000020 /* Sys clock frequency */
549+
550+
#define E1000_TIMINCA_INCPERIOD_SHIFT 24
551+
#define E1000_TIMINCA_INCVALUE_MASK 0x00FFFFFF
552+
539553
/* PCI Express Control */
540554
#define E1000_GCR_RXD_NO_SNOOP 0x00000001
541555
#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002

drivers/net/ethernet/intel/e1000e/e1000.h

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
#include <linux/pci-aspm.h>
4242
#include <linux/crc32.h>
4343
#include <linux/if_vlan.h>
44+
#include <linux/clocksource.h>
45+
#include <linux/net_tstamp.h>
4446

4547
#include "hw.h"
4648

@@ -353,6 +355,7 @@ struct e1000_adapter {
353355
u64 gorc_old;
354356
u32 alloc_rx_buff_failed;
355357
u32 rx_dma_failed;
358+
u32 rx_hwtstamp_cleared;
356359

357360
unsigned int rx_ps_pages;
358361
u16 rx_ps_bsize0;
@@ -402,6 +405,14 @@ struct e1000_adapter {
402405

403406
u16 tx_ring_count;
404407
u16 rx_ring_count;
408+
409+
struct hwtstamp_config hwtstamp_config;
410+
struct delayed_work systim_overflow_work;
411+
struct sk_buff *tx_hwtstamp_skb;
412+
struct work_struct tx_hwtstamp_work;
413+
spinlock_t systim_lock; /* protects SYSTIML/H regsters */
414+
struct cyclecounter cc;
415+
struct timecounter tc;
405416
};
406417

407418
struct e1000_info {
@@ -416,6 +427,38 @@ struct e1000_info {
416427
const struct e1000_nvm_operations *nvm_ops;
417428
};
418429

430+
/* The system time is maintained by a 64-bit counter comprised of the 32-bit
431+
* SYSTIMH and SYSTIML registers. How the counter increments (and therefore
432+
* its resolution) is based on the contents of the TIMINCA register - it
433+
* increments every incperiod (bits 31:24) clock ticks by incvalue (bits 23:0).
434+
* For the best accuracy, the incperiod should be as small as possible. The
435+
* incvalue is scaled by a factor as large as possible (while still fitting
436+
* in bits 23:0) so that relatively small clock corrections can be made.
437+
*
438+
* As a result, a shift of INCVALUE_SHIFT_n is used to fit a value of
439+
* INCVALUE_n into the TIMINCA register allowing 32+8+(24-INCVALUE_SHIFT_n)
440+
* bits to count nanoseconds leaving the rest for fractional nonseconds.
441+
*/
442+
#define INCVALUE_96MHz 125
443+
#define INCVALUE_SHIFT_96MHz 17
444+
#define INCPERIOD_SHIFT_96MHz 2
445+
#define INCPERIOD_96MHz (12 >> INCPERIOD_SHIFT_96MHz)
446+
447+
#define INCVALUE_25MHz 40
448+
#define INCVALUE_SHIFT_25MHz 18
449+
#define INCPERIOD_25MHz 1
450+
451+
/* Another drawback of scaling the incvalue by a large factor is the
452+
* 64-bit SYSTIM register overflows more quickly. This is dealt with
453+
* by simply reading the clock before it overflows.
454+
*
455+
* Clock ns bits Overflows after
456+
* ~~~~~~ ~~~~~~~ ~~~~~~~~~~~~~~~
457+
* 96MHz 47-bit 2^(47-INCPERIOD_SHIFT_96MHz) / 10^9 / 3600 = 9.77 hrs
458+
* 25MHz 46-bit 2^46 / 10^9 / 3600 = 19.55 hours
459+
*/
460+
#define E1000_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 60 * 4)
461+
419462
/* hardware capability, feature, and workaround flags */
420463
#define FLAG_HAS_AMT (1 << 0)
421464
#define FLAG_HAS_FLASH (1 << 1)
@@ -431,7 +474,7 @@ struct e1000_info {
431474
#define FLAG_HAS_SMART_POWER_DOWN (1 << 11)
432475
#define FLAG_IS_QUAD_PORT_A (1 << 12)
433476
#define FLAG_IS_QUAD_PORT (1 << 13)
434-
/* reserved bit14 */
477+
#define FLAG_HAS_HW_TIMESTAMP (1 << 14)
435478
#define FLAG_APME_IN_WUC (1 << 15)
436479
#define FLAG_APME_IN_CTRL3 (1 << 16)
437480
#define FLAG_APME_CHECK_PORT_B (1 << 17)
@@ -463,6 +506,7 @@ struct e1000_info {
463506
#define FLAG2_NO_DISABLE_RX (1 << 10)
464507
#define FLAG2_PCIM2PCI_ARBITER_WA (1 << 11)
465508
#define FLAG2_DFLT_CRC_STRIPPING (1 << 12)
509+
#define FLAG2_CHECK_RX_HWTSTAMP (1 << 13)
466510

467511
#define E1000_RX_DESC_PS(R, i) \
468512
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))

drivers/net/ethernet/intel/e1000e/ethtool.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
108108
E1000_STAT("dropped_smbus", stats.mgpdc),
109109
E1000_STAT("rx_dma_failed", rx_dma_failed),
110110
E1000_STAT("tx_dma_failed", tx_dma_failed),
111+
E1000_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
111112
};
112113

113114
#define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats)
@@ -2182,6 +2183,28 @@ static int e1000e_set_eee(struct net_device *netdev, struct ethtool_eee *edata)
21822183
return 0;
21832184
}
21842185

2186+
static int e1000e_get_ts_info(struct net_device *netdev,
2187+
struct ethtool_ts_info *info)
2188+
{
2189+
struct e1000_adapter *adapter = netdev_priv(netdev);
2190+
2191+
ethtool_op_get_ts_info(netdev, info);
2192+
2193+
if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP))
2194+
return 0;
2195+
2196+
info->so_timestamping |= (SOF_TIMESTAMPING_TX_HARDWARE |
2197+
SOF_TIMESTAMPING_RX_HARDWARE |
2198+
SOF_TIMESTAMPING_RAW_HARDWARE);
2199+
2200+
info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
2201+
2202+
info->rx_filters = ((1 << HWTSTAMP_FILTER_NONE) |
2203+
(1 << HWTSTAMP_FILTER_ALL));
2204+
2205+
return 0;
2206+
}
2207+
21852208
static const struct ethtool_ops e1000_ethtool_ops = {
21862209
.get_settings = e1000_get_settings,
21872210
.set_settings = e1000_set_settings,
@@ -2209,7 +2232,7 @@ static const struct ethtool_ops e1000_ethtool_ops = {
22092232
.get_coalesce = e1000_get_coalesce,
22102233
.set_coalesce = e1000_set_coalesce,
22112234
.get_rxnfc = e1000_get_rxnfc,
2212-
.get_ts_info = ethtool_op_get_ts_info,
2235+
.get_ts_info = e1000e_get_ts_info,
22132236
.get_eee = e1000e_get_eee,
22142237
.set_eee = e1000e_set_eee,
22152238
};

drivers/net/ethernet/intel/e1000e/hw.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ enum e1e_registers {
6060
E1000_EIAC_82574 = 0x000DC, /* Ext. Interrupt Auto Clear - RW */
6161
E1000_IAM = 0x000E0, /* Interrupt Acknowledge Auto Mask */
6262
E1000_IVAR = 0x000E4, /* Interrupt Vector Allocation - RW */
63+
E1000_FEXTNVM7 = 0x000E4, /* Future Extended NVM 7 - RW */
6364
E1000_EITR_82574_BASE = 0x000E8, /* Interrupt Throttling - RW */
6465
#define E1000_EITR_82574(_n) (E1000_EITR_82574_BASE + (_n << 2))
6566
E1000_LPIC = 0x000FC, /* Low Power Idle Control - RW */
@@ -241,6 +242,15 @@ enum e1e_registers {
241242
#define E1000_PCH_RAICC(_n) (E1000_PCH_RAICC_BASE + ((_n) * 4))
242243
#define E1000_CRC_OFFSET E1000_PCH_RAICC_BASE
243244
E1000_HICR = 0x08F00, /* Host Interface Control */
245+
E1000_SYSTIML = 0x0B600, /* System time register Low - RO */
246+
E1000_SYSTIMH = 0x0B604, /* System time register High - RO */
247+
E1000_TIMINCA = 0x0B608, /* Increment attributes register - RW */
248+
E1000_TSYNCTXCTL = 0x0B614, /* Tx Time Sync Control register - RW */
249+
E1000_TXSTMPL = 0x0B618, /* Tx timestamp value Low - RO */
250+
E1000_TXSTMPH = 0x0B61C, /* Tx timestamp value High - RO */
251+
E1000_TSYNCRXCTL = 0x0B620, /* Rx Time Sync Control register - RW */
252+
E1000_RXSTMPL = 0x0B624, /* Rx timestamp Low - RO */
253+
E1000_RXSTMPH = 0x0B628, /* Rx timestamp High - RO */
244254
};
245255

246256
#define E1000_MAX_PHY_ADDR 4

drivers/net/ethernet/intel/e1000e/ich8lan.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4601,6 +4601,7 @@ const struct e1000_info e1000_pch2_info = {
46014601
.mac = e1000_pch2lan,
46024602
.flags = FLAG_IS_ICH
46034603
| FLAG_HAS_WOL
4604+
| FLAG_HAS_HW_TIMESTAMP
46044605
| FLAG_HAS_CTRLEXT_ON_LOAD
46054606
| FLAG_HAS_AMT
46064607
| FLAG_HAS_FLASH
@@ -4620,6 +4621,7 @@ const struct e1000_info e1000_pch_lpt_info = {
46204621
.mac = e1000_pch_lpt,
46214622
.flags = FLAG_IS_ICH
46224623
| FLAG_HAS_WOL
4624+
| FLAG_HAS_HW_TIMESTAMP
46234625
| FLAG_HAS_CTRLEXT_ON_LOAD
46244626
| FLAG_HAS_AMT
46254627
| FLAG_HAS_FLASH

0 commit comments

Comments
 (0)