Skip to content

Commit 7c236c4

Browse files
Stuart HodgsonBen Hutchings
authored andcommitted
sfc: Add support for IEEE-1588 PTP
Add PTP IEEE-1588 support and make accesible via the PHC subsystem. This work is based on prior code by Andrew Jackson Signed-off-by: Stuart Hodgson <[email protected]> [bwh: - Add byte order conversion in efx_ptp_send_times() - Simplify conversion of PPS event times - Add the built-in vs module check to CONFIG_SFC_PTP dependencies] Signed-off-by: Ben Hutchings <[email protected]>
1 parent 576eda8 commit 7c236c4

File tree

11 files changed

+1562
-1
lines changed

11 files changed

+1562
-1
lines changed

drivers/net/ethernet/sfc/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,10 @@ config SFC_SRIOV
3434
This enables support for the SFC9000 I/O Virtualization
3535
features, allowing accelerated network performance in
3636
virtualized environments.
37+
config SFC_PTP
38+
bool "Solarflare SFC9000-family PTP support"
39+
depends on SFC && PTP_1588_CLOCK && !(SFC=y && PTP_1588_CLOCK=m)
40+
default y
41+
---help---
42+
This enables support for the Precision Time Protocol (PTP)
43+
on SFC9000-family NICs

drivers/net/ethernet/sfc/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \
55
mcdi.o mcdi_phy.o mcdi_mon.o
66
sfc-$(CONFIG_SFC_MTD) += mtd.o
77
sfc-$(CONFIG_SFC_SRIOV) += siena_sriov.o
8+
sfc-$(CONFIG_SFC_PTP) += ptp.o
89

910
obj-$(CONFIG_SFC) += sfc.o

drivers/net/ethernet/sfc/efx.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1779,6 +1779,9 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
17791779
struct efx_nic *efx = netdev_priv(net_dev);
17801780
struct mii_ioctl_data *data = if_mii(ifr);
17811781

1782+
if (cmd == SIOCSHWTSTAMP)
1783+
return efx_ptp_ioctl(efx, ifr, cmd);
1784+
17821785
/* Convert phy_id from older PRTAD/DEVAD format */
17831786
if ((cmd == SIOCGMIIREG || cmd == SIOCSMIIREG) &&
17841787
(data->phy_id & 0xfc00) == 0x0400)

drivers/net/ethernet/sfc/ethtool.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,7 @@ const struct ethtool_ops efx_ethtool_ops = {
11741174
.get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size,
11751175
.get_rxfh_indir = efx_ethtool_get_rxfh_indir,
11761176
.set_rxfh_indir = efx_ethtool_set_rxfh_indir,
1177+
.get_ts_info = efx_ptp_get_ts_info,
11771178
.get_module_info = efx_ethtool_get_module_info,
11781179
.get_module_eeprom = efx_ethtool_get_module_eeprom,
11791180
};

drivers/net/ethernet/sfc/mcdi.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,11 @@ void efx_mcdi_process_event(struct efx_channel *channel,
578578
case MCDI_EVENT_CODE_FLR:
579579
efx_sriov_flr(efx, MCDI_EVENT_FIELD(*event, FLR_VF));
580580
break;
581+
case MCDI_EVENT_CODE_PTP_RX:
582+
case MCDI_EVENT_CODE_PTP_FAULT:
583+
case MCDI_EVENT_CODE_PTP_PPS:
584+
efx_ptp_event(efx, event);
585+
break;
581586

582587
default:
583588
netif_err(efx, hw, efx->net_dev, "Unknown MCDI event 0x%x\n",

drivers/net/ethernet/sfc/mcdi_pcol.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@
289289
#define MCDI_EVENT_CODE_TX_FLUSH 0xc /* enum */
290290
#define MCDI_EVENT_CODE_PTP_RX 0xd /* enum */
291291
#define MCDI_EVENT_CODE_PTP_FAULT 0xe /* enum */
292+
#define MCDI_EVENT_CODE_PTP_PPS 0xf /* enum */
292293
#define MCDI_EVENT_CMDDONE_DATA_OFST 0
293294
#define MCDI_EVENT_CMDDONE_DATA_LBN 0
294295
#define MCDI_EVENT_CMDDONE_DATA_WIDTH 32

drivers/net/ethernet/sfc/net_driver.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@
5656
#define EFX_MAX_CHANNELS 32U
5757
#define EFX_MAX_RX_QUEUES EFX_MAX_CHANNELS
5858
#define EFX_EXTRA_CHANNEL_IOV 0
59-
#define EFX_MAX_EXTRA_CHANNELS 1U
59+
#define EFX_EXTRA_CHANNEL_PTP 1
60+
#define EFX_MAX_EXTRA_CHANNELS 2U
6061

6162
/* Checksum generation is a per-queue option in hardware, so each
6263
* queue visible to the networking core is backed by two hardware TX
@@ -68,6 +69,9 @@
6869
#define EFX_TXQ_TYPES 4
6970
#define EFX_MAX_TX_QUEUES (EFX_TXQ_TYPES * EFX_MAX_CHANNELS)
7071

72+
/* Forward declare Precision Time Protocol (PTP) support structure. */
73+
struct efx_ptp_data;
74+
7175
struct efx_self_tests;
7276

7377
/**
@@ -736,6 +740,7 @@ struct vfdi_status;
736740
* %local_addr_list. Protected by %local_lock.
737741
* @local_lock: Mutex protecting %local_addr_list and %local_page_list.
738742
* @peer_work: Work item to broadcast peer addresses to VMs.
743+
* @ptp_data: PTP state data
739744
* @monitor_work: Hardware monitor workitem
740745
* @biu_lock: BIU (bus interface unit) lock
741746
* @last_irq_cpu: Last CPU to handle a possible test interrupt. This
@@ -863,6 +868,10 @@ struct efx_nic {
863868
struct work_struct peer_work;
864869
#endif
865870

871+
#ifdef CONFIG_SFC_PTP
872+
struct efx_ptp_data *ptp_data;
873+
#endif
874+
866875
/* The following fields may be written more often */
867876

868877
struct delayed_work monitor_work ____cacheline_aligned_in_smp;
@@ -1125,5 +1134,13 @@ static inline void clear_bit_le(unsigned nr, unsigned char *addr)
11251134
#define EFX_MAX_FRAME_LEN(mtu) \
11261135
((((mtu) + ETH_HLEN + VLAN_HLEN + 4/* FCS */ + 7) & ~7) + 16)
11271136

1137+
static inline bool efx_xmit_with_hwtstamp(struct sk_buff *skb)
1138+
{
1139+
return skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP;
1140+
}
1141+
static inline void efx_xmit_hwtstamp_pending(struct sk_buff *skb)
1142+
{
1143+
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
1144+
}
11281145

11291146
#endif /* EFX_NET_DRIVER_H */

drivers/net/ethernet/sfc/nic.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#ifndef EFX_NIC_H
1212
#define EFX_NIC_H
1313

14+
#include <linux/net_tstamp.h>
1415
#include <linux/i2c-algo-bit.h>
1516
#include "net_driver.h"
1617
#include "efx.h"
@@ -250,6 +251,41 @@ extern int efx_sriov_get_vf_config(struct net_device *dev, int vf,
250251
extern int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf,
251252
bool spoofchk);
252253

254+
struct ethtool_ts_info;
255+
#ifdef CONFIG_SFC_PTP
256+
extern void efx_ptp_probe(struct efx_nic *efx);
257+
extern int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd);
258+
extern int efx_ptp_get_ts_info(struct net_device *net_dev,
259+
struct ethtool_ts_info *ts_info);
260+
extern bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
261+
extern int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
262+
extern void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev);
263+
#else
264+
static inline void efx_ptp_probe(struct efx_nic *efx) {}
265+
static inline int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd)
266+
{
267+
return -EOPNOTSUPP;
268+
}
269+
static inline int efx_ptp_get_ts_info(struct net_device *net_dev,
270+
struct ethtool_ts_info *ts_info)
271+
{
272+
ts_info->so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
273+
SOF_TIMESTAMPING_RX_SOFTWARE);
274+
ts_info->phc_index = -1;
275+
276+
return 0;
277+
}
278+
static inline bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb)
279+
{
280+
return false;
281+
}
282+
static inline int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb)
283+
{
284+
return NETDEV_TX_OK;
285+
}
286+
static inline void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev) {}
287+
#endif
288+
253289
extern const struct efx_nic_type falcon_a1_nic_type;
254290
extern const struct efx_nic_type falcon_b0_nic_type;
255291
extern const struct efx_nic_type siena_a0_nic_type;

0 commit comments

Comments
 (0)