Skip to content

Commit 7ed2a0d

Browse files
committed
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next
Ben Hutchings says: ==================== 1. Change PTP clock name to 'sfc'. 2. Complete support for hardware timestamping and PTP clock on the SFC9100 family. 3. Various cleanups for the PTP code. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents f52d81d + bbbe714 commit 7ed2a0d

File tree

10 files changed

+797
-217
lines changed

10 files changed

+797
-217
lines changed

drivers/net/ethernet/sfc/ef10.c

Lines changed: 125 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@ static int efx_ef10_probe(struct efx_nic *efx)
264264
if (rc)
265265
goto fail3;
266266

267+
efx_ptp_probe(efx, NULL);
268+
267269
return 0;
268270

269271
fail3:
@@ -472,9 +474,10 @@ static void efx_ef10_remove(struct efx_nic *efx)
472474
struct efx_ef10_nic_data *nic_data = efx->nic_data;
473475
int rc;
474476

477+
efx_ptp_remove(efx);
478+
475479
efx_mcdi_mon_remove(efx);
476480

477-
/* This needs to be after efx_ptp_remove_channel() with no filters */
478481
efx_ef10_rx_free_indir_table(efx);
479482

480483
if (nic_data->wc_membase)
@@ -1469,8 +1472,9 @@ static void efx_ef10_rx_init(struct efx_rx_queue *rx_queue)
14691472
MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_LABEL, efx_rx_queue_index(rx_queue));
14701473
MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_INSTANCE,
14711474
efx_rx_queue_index(rx_queue));
1472-
MCDI_POPULATE_DWORD_1(inbuf, INIT_RXQ_IN_FLAGS,
1473-
INIT_RXQ_IN_FLAG_PREFIX, 1);
1475+
MCDI_POPULATE_DWORD_2(inbuf, INIT_RXQ_IN_FLAGS,
1476+
INIT_RXQ_IN_FLAG_PREFIX, 1,
1477+
INIT_RXQ_IN_FLAG_TIMESTAMP, 1);
14741478
MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_OWNER_ID, 0);
14751479
MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_PORT_ID, EVB_PORT_ID_ASSIGNED);
14761480

@@ -3406,6 +3410,119 @@ static void efx_ef10_ptp_write_host_time(struct efx_nic *efx, u32 host_time)
34063410
_efx_writed(efx, cpu_to_le32(host_time), ER_DZ_MC_DB_LWRD);
34073411
}
34083412

3413+
static int efx_ef10_rx_enable_timestamping(struct efx_channel *channel,
3414+
bool temp)
3415+
{
3416+
MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_TIME_EVENT_SUBSCRIBE_LEN);
3417+
int rc;
3418+
3419+
if (channel->sync_events_state == SYNC_EVENTS_REQUESTED ||
3420+
channel->sync_events_state == SYNC_EVENTS_VALID ||
3421+
(temp && channel->sync_events_state == SYNC_EVENTS_DISABLED))
3422+
return 0;
3423+
channel->sync_events_state = SYNC_EVENTS_REQUESTED;
3424+
3425+
MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_TIME_EVENT_SUBSCRIBE);
3426+
MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0);
3427+
MCDI_SET_DWORD(inbuf, PTP_IN_TIME_EVENT_SUBSCRIBE_QUEUE,
3428+
channel->channel);
3429+
3430+
rc = efx_mcdi_rpc(channel->efx, MC_CMD_PTP,
3431+
inbuf, sizeof(inbuf), NULL, 0, NULL);
3432+
3433+
if (rc != 0)
3434+
channel->sync_events_state = temp ? SYNC_EVENTS_QUIESCENT :
3435+
SYNC_EVENTS_DISABLED;
3436+
3437+
return rc;
3438+
}
3439+
3440+
static int efx_ef10_rx_disable_timestamping(struct efx_channel *channel,
3441+
bool temp)
3442+
{
3443+
MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_TIME_EVENT_UNSUBSCRIBE_LEN);
3444+
int rc;
3445+
3446+
if (channel->sync_events_state == SYNC_EVENTS_DISABLED ||
3447+
(temp && channel->sync_events_state == SYNC_EVENTS_QUIESCENT))
3448+
return 0;
3449+
if (channel->sync_events_state == SYNC_EVENTS_QUIESCENT) {
3450+
channel->sync_events_state = SYNC_EVENTS_DISABLED;
3451+
return 0;
3452+
}
3453+
channel->sync_events_state = temp ? SYNC_EVENTS_QUIESCENT :
3454+
SYNC_EVENTS_DISABLED;
3455+
3456+
MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_TIME_EVENT_UNSUBSCRIBE);
3457+
MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0);
3458+
MCDI_SET_DWORD(inbuf, PTP_IN_TIME_EVENT_UNSUBSCRIBE_CONTROL,
3459+
MC_CMD_PTP_IN_TIME_EVENT_UNSUBSCRIBE_SINGLE);
3460+
MCDI_SET_DWORD(inbuf, PTP_IN_TIME_EVENT_UNSUBSCRIBE_QUEUE,
3461+
channel->channel);
3462+
3463+
rc = efx_mcdi_rpc(channel->efx, MC_CMD_PTP,
3464+
inbuf, sizeof(inbuf), NULL, 0, NULL);
3465+
3466+
return rc;
3467+
}
3468+
3469+
static int efx_ef10_ptp_set_ts_sync_events(struct efx_nic *efx, bool en,
3470+
bool temp)
3471+
{
3472+
int (*set)(struct efx_channel *channel, bool temp);
3473+
struct efx_channel *channel;
3474+
3475+
set = en ?
3476+
efx_ef10_rx_enable_timestamping :
3477+
efx_ef10_rx_disable_timestamping;
3478+
3479+
efx_for_each_channel(channel, efx) {
3480+
int rc = set(channel, temp);
3481+
if (en && rc != 0) {
3482+
efx_ef10_ptp_set_ts_sync_events(efx, false, temp);
3483+
return rc;
3484+
}
3485+
}
3486+
3487+
return 0;
3488+
}
3489+
3490+
static int efx_ef10_ptp_set_ts_config(struct efx_nic *efx,
3491+
struct hwtstamp_config *init)
3492+
{
3493+
int rc;
3494+
3495+
switch (init->rx_filter) {
3496+
case HWTSTAMP_FILTER_NONE:
3497+
efx_ef10_ptp_set_ts_sync_events(efx, false, false);
3498+
/* if TX timestamping is still requested then leave PTP on */
3499+
return efx_ptp_change_mode(efx,
3500+
init->tx_type != HWTSTAMP_TX_OFF, 0);
3501+
case HWTSTAMP_FILTER_ALL:
3502+
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
3503+
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
3504+
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
3505+
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
3506+
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
3507+
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
3508+
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
3509+
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
3510+
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
3511+
case HWTSTAMP_FILTER_PTP_V2_EVENT:
3512+
case HWTSTAMP_FILTER_PTP_V2_SYNC:
3513+
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
3514+
init->rx_filter = HWTSTAMP_FILTER_ALL;
3515+
rc = efx_ptp_change_mode(efx, true, 0);
3516+
if (!rc)
3517+
rc = efx_ef10_ptp_set_ts_sync_events(efx, true, false);
3518+
if (rc)
3519+
efx_ptp_change_mode(efx, false, 0);
3520+
return rc;
3521+
default:
3522+
return -ERANGE;
3523+
}
3524+
}
3525+
34093526
const struct efx_nic_type efx_hunt_a0_nic_type = {
34103527
.mem_map_size = efx_ef10_mem_map_size,
34113528
.probe = efx_ef10_probe,
@@ -3484,11 +3601,14 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
34843601
.mtd_sync = efx_mcdi_mtd_sync,
34853602
#endif
34863603
.ptp_write_host_time = efx_ef10_ptp_write_host_time,
3604+
.ptp_set_ts_sync_events = efx_ef10_ptp_set_ts_sync_events,
3605+
.ptp_set_ts_config = efx_ef10_ptp_set_ts_config,
34873606

34883607
.revision = EFX_REV_HUNT_A0,
34893608
.max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH),
34903609
.rx_prefix_size = ES_DZ_RX_PREFIX_SIZE,
34913610
.rx_hash_offset = ES_DZ_RX_PREFIX_HASH_OFST,
3611+
.rx_ts_offset = ES_DZ_RX_PREFIX_TSTAMP_OFST,
34923612
.can_rx_scatter = true,
34933613
.always_rx_scatter = true,
34943614
.max_interrupt_mode = EFX_INT_MODE_MSIX,
@@ -3497,4 +3617,6 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
34973617
NETIF_F_RXHASH | NETIF_F_NTUPLE),
34983618
.mcdi_max_ver = 2,
34993619
.max_rx_ip_filters = HUNT_FILTER_TBL_ROWS,
3620+
.hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE |
3621+
1 << HWTSTAMP_FILTER_ALL,
35003622
};

drivers/net/ethernet/sfc/efx.c

Lines changed: 110 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,77 @@ static void efx_remove_port(struct efx_nic *efx)
11171117
*
11181118
**************************************************************************/
11191119

1120+
static LIST_HEAD(efx_primary_list);
1121+
static LIST_HEAD(efx_unassociated_list);
1122+
1123+
static bool efx_same_controller(struct efx_nic *left, struct efx_nic *right)
1124+
{
1125+
return left->type == right->type &&
1126+
left->vpd_sn && right->vpd_sn &&
1127+
!strcmp(left->vpd_sn, right->vpd_sn);
1128+
}
1129+
1130+
static void efx_associate(struct efx_nic *efx)
1131+
{
1132+
struct efx_nic *other, *next;
1133+
1134+
if (efx->primary == efx) {
1135+
/* Adding primary function; look for secondaries */
1136+
1137+
netif_dbg(efx, probe, efx->net_dev, "adding to primary list\n");
1138+
list_add_tail(&efx->node, &efx_primary_list);
1139+
1140+
list_for_each_entry_safe(other, next, &efx_unassociated_list,
1141+
node) {
1142+
if (efx_same_controller(efx, other)) {
1143+
list_del(&other->node);
1144+
netif_dbg(other, probe, other->net_dev,
1145+
"moving to secondary list of %s %s\n",
1146+
pci_name(efx->pci_dev),
1147+
efx->net_dev->name);
1148+
list_add_tail(&other->node,
1149+
&efx->secondary_list);
1150+
other->primary = efx;
1151+
}
1152+
}
1153+
} else {
1154+
/* Adding secondary function; look for primary */
1155+
1156+
list_for_each_entry(other, &efx_primary_list, node) {
1157+
if (efx_same_controller(efx, other)) {
1158+
netif_dbg(efx, probe, efx->net_dev,
1159+
"adding to secondary list of %s %s\n",
1160+
pci_name(other->pci_dev),
1161+
other->net_dev->name);
1162+
list_add_tail(&efx->node,
1163+
&other->secondary_list);
1164+
efx->primary = other;
1165+
return;
1166+
}
1167+
}
1168+
1169+
netif_dbg(efx, probe, efx->net_dev,
1170+
"adding to unassociated list\n");
1171+
list_add_tail(&efx->node, &efx_unassociated_list);
1172+
}
1173+
}
1174+
1175+
static void efx_dissociate(struct efx_nic *efx)
1176+
{
1177+
struct efx_nic *other, *next;
1178+
1179+
list_del(&efx->node);
1180+
efx->primary = NULL;
1181+
1182+
list_for_each_entry_safe(other, next, &efx->secondary_list, node) {
1183+
list_del(&other->node);
1184+
netif_dbg(other, probe, other->net_dev,
1185+
"moving to unassociated list\n");
1186+
list_add_tail(&other->node, &efx_unassociated_list);
1187+
other->primary = NULL;
1188+
}
1189+
}
1190+
11201191
/* This configures the PCI device to enable I/O and DMA. */
11211192
static int efx_init_io(struct efx_nic *efx)
11221193
{
@@ -2214,6 +2285,8 @@ static int efx_register_netdev(struct efx_nic *efx)
22142285
efx_init_tx_queue_core_txq(tx_queue);
22152286
}
22162287

2288+
efx_associate(efx);
2289+
22172290
rtnl_unlock();
22182291

22192292
rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type);
@@ -2227,6 +2300,7 @@ static int efx_register_netdev(struct efx_nic *efx)
22272300

22282301
fail_registered:
22292302
rtnl_lock();
2303+
efx_dissociate(efx);
22302304
unregister_netdevice(net_dev);
22312305
fail_locked:
22322306
efx->state = STATE_UNINIT;
@@ -2568,6 +2642,8 @@ static int efx_init_struct(struct efx_nic *efx,
25682642
int i;
25692643

25702644
/* Initialise common structures */
2645+
INIT_LIST_HEAD(&efx->node);
2646+
INIT_LIST_HEAD(&efx->secondary_list);
25712647
spin_lock_init(&efx->biu_lock);
25722648
#ifdef CONFIG_SFC_MTD
25732649
INIT_LIST_HEAD(&efx->mtd_list);
@@ -2586,6 +2662,8 @@ static int efx_init_struct(struct efx_nic *efx,
25862662
NET_IP_ALIGN ? (efx->rx_prefix_size + NET_IP_ALIGN) % 4 : 0;
25872663
efx->rx_packet_hash_offset =
25882664
efx->type->rx_hash_offset - efx->type->rx_prefix_size;
2665+
efx->rx_packet_ts_offset =
2666+
efx->type->rx_ts_offset - efx->type->rx_prefix_size;
25892667
spin_lock_init(&efx->stats_lock);
25902668
mutex_init(&efx->mac_lock);
25912669
efx->phy_op = &efx_dummy_phy_operations;
@@ -2626,6 +2704,8 @@ static void efx_fini_struct(struct efx_nic *efx)
26262704
for (i = 0; i < EFX_MAX_CHANNELS; i++)
26272705
kfree(efx->channel[i]);
26282706

2707+
kfree(efx->vpd_sn);
2708+
26292709
if (efx->workqueue) {
26302710
destroy_workqueue(efx->workqueue);
26312711
efx->workqueue = NULL;
@@ -2670,6 +2750,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
26702750

26712751
/* Mark the NIC as fini, then stop the interface */
26722752
rtnl_lock();
2753+
efx_dissociate(efx);
26732754
dev_close(efx->net_dev);
26742755
efx_disable_interrupts(efx);
26752756
rtnl_unlock();
@@ -2696,12 +2777,12 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
26962777
* always appear within the first 512 bytes.
26972778
*/
26982779
#define SFC_VPD_LEN 512
2699-
static void efx_print_product_vpd(struct efx_nic *efx)
2780+
static void efx_probe_vpd_strings(struct efx_nic *efx)
27002781
{
27012782
struct pci_dev *dev = efx->pci_dev;
27022783
char vpd_data[SFC_VPD_LEN];
27032784
ssize_t vpd_size;
2704-
int i, j;
2785+
int ro_start, ro_size, i, j;
27052786

27062787
/* Get the vpd data from the device */
27072788
vpd_size = pci_read_vpd(dev, 0, sizeof(vpd_data), vpd_data);
@@ -2711,14 +2792,15 @@ static void efx_print_product_vpd(struct efx_nic *efx)
27112792
}
27122793

27132794
/* Get the Read only section */
2714-
i = pci_vpd_find_tag(vpd_data, 0, vpd_size, PCI_VPD_LRDT_RO_DATA);
2715-
if (i < 0) {
2795+
ro_start = pci_vpd_find_tag(vpd_data, 0, vpd_size, PCI_VPD_LRDT_RO_DATA);
2796+
if (ro_start < 0) {
27162797
netif_err(efx, drv, efx->net_dev, "VPD Read-only not found\n");
27172798
return;
27182799
}
27192800

2720-
j = pci_vpd_lrdt_size(&vpd_data[i]);
2721-
i += PCI_VPD_LRDT_TAG_SIZE;
2801+
ro_size = pci_vpd_lrdt_size(&vpd_data[ro_start]);
2802+
j = ro_size;
2803+
i = ro_start + PCI_VPD_LRDT_TAG_SIZE;
27222804
if (i + j > vpd_size)
27232805
j = vpd_size - i;
27242806

@@ -2738,6 +2820,27 @@ static void efx_print_product_vpd(struct efx_nic *efx)
27382820

27392821
netif_info(efx, drv, efx->net_dev,
27402822
"Part Number : %.*s\n", j, &vpd_data[i]);
2823+
2824+
i = ro_start + PCI_VPD_LRDT_TAG_SIZE;
2825+
j = ro_size;
2826+
i = pci_vpd_find_info_keyword(vpd_data, i, j, "SN");
2827+
if (i < 0) {
2828+
netif_err(efx, drv, efx->net_dev, "Serial number not found\n");
2829+
return;
2830+
}
2831+
2832+
j = pci_vpd_info_field_size(&vpd_data[i]);
2833+
i += PCI_VPD_INFO_FLD_HDR_SIZE;
2834+
if (i + j > vpd_size) {
2835+
netif_err(efx, drv, efx->net_dev, "Incomplete serial number\n");
2836+
return;
2837+
}
2838+
2839+
efx->vpd_sn = kmalloc(j + 1, GFP_KERNEL);
2840+
if (!efx->vpd_sn)
2841+
return;
2842+
2843+
snprintf(efx->vpd_sn, j + 1, "%s", &vpd_data[i]);
27412844
}
27422845

27432846

@@ -2834,7 +2937,7 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
28342937
netif_info(efx, probe, efx->net_dev,
28352938
"Solarflare NIC detected\n");
28362939

2837-
efx_print_product_vpd(efx);
2940+
efx_probe_vpd_strings(efx);
28382941

28392942
/* Set up basic I/O (BAR mappings etc) */
28402943
rc = efx_init_io(efx);

drivers/net/ethernet/sfc/falcon.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2247,6 +2247,8 @@ static int falcon_probe_nic(struct efx_nic *efx)
22472247
struct falcon_board *board;
22482248
int rc;
22492249

2250+
efx->primary = efx; /* only one usable function per controller */
2251+
22502252
/* Allocate storage for hardware specific data */
22512253
nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL);
22522254
if (!nic_data)

0 commit comments

Comments
 (0)