diff options
author | David S. Miller <davem@davemloft.net> | 2013-12-14 22:33:45 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-12-14 22:33:45 -0500 |
commit | 7ed2a0d0d473482df490b7c44f875f5eefede6aa (patch) | |
tree | 45865c0e43164ed55880990104d7b1665953ac56 | |
parent | f52d81dc27c3456c702e83183035142c222acdc7 (diff) | |
parent | bbbe7149bf0bd14432373de39315505e7a133acc (diff) |
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>
-rw-r--r-- | drivers/net/ethernet/sfc/ef10.c | 128 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/efx.c | 117 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/falcon.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi.c | 25 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/net_driver.h | 53 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/nic.h | 12 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/ptp.c | 594 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/rx.c | 12 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/siena.c | 69 |
10 files changed, 797 insertions, 217 deletions
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index ca922b958a2e..dfff8e7a55e2 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c | |||
@@ -264,6 +264,8 @@ static int efx_ef10_probe(struct efx_nic *efx) | |||
264 | if (rc) | 264 | if (rc) |
265 | goto fail3; | 265 | goto fail3; |
266 | 266 | ||
267 | efx_ptp_probe(efx, NULL); | ||
268 | |||
267 | return 0; | 269 | return 0; |
268 | 270 | ||
269 | fail3: | 271 | fail3: |
@@ -472,9 +474,10 @@ static void efx_ef10_remove(struct efx_nic *efx) | |||
472 | struct efx_ef10_nic_data *nic_data = efx->nic_data; | 474 | struct efx_ef10_nic_data *nic_data = efx->nic_data; |
473 | int rc; | 475 | int rc; |
474 | 476 | ||
477 | efx_ptp_remove(efx); | ||
478 | |||
475 | efx_mcdi_mon_remove(efx); | 479 | efx_mcdi_mon_remove(efx); |
476 | 480 | ||
477 | /* This needs to be after efx_ptp_remove_channel() with no filters */ | ||
478 | efx_ef10_rx_free_indir_table(efx); | 481 | efx_ef10_rx_free_indir_table(efx); |
479 | 482 | ||
480 | if (nic_data->wc_membase) | 483 | if (nic_data->wc_membase) |
@@ -1469,8 +1472,9 @@ static void efx_ef10_rx_init(struct efx_rx_queue *rx_queue) | |||
1469 | MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_LABEL, efx_rx_queue_index(rx_queue)); | 1472 | MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_LABEL, efx_rx_queue_index(rx_queue)); |
1470 | MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_INSTANCE, | 1473 | MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_INSTANCE, |
1471 | efx_rx_queue_index(rx_queue)); | 1474 | efx_rx_queue_index(rx_queue)); |
1472 | MCDI_POPULATE_DWORD_1(inbuf, INIT_RXQ_IN_FLAGS, | 1475 | MCDI_POPULATE_DWORD_2(inbuf, INIT_RXQ_IN_FLAGS, |
1473 | INIT_RXQ_IN_FLAG_PREFIX, 1); | 1476 | INIT_RXQ_IN_FLAG_PREFIX, 1, |
1477 | INIT_RXQ_IN_FLAG_TIMESTAMP, 1); | ||
1474 | MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_OWNER_ID, 0); | 1478 | MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_OWNER_ID, 0); |
1475 | MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_PORT_ID, EVB_PORT_ID_ASSIGNED); | 1479 | MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_PORT_ID, EVB_PORT_ID_ASSIGNED); |
1476 | 1480 | ||
@@ -3406,6 +3410,119 @@ static void efx_ef10_ptp_write_host_time(struct efx_nic *efx, u32 host_time) | |||
3406 | _efx_writed(efx, cpu_to_le32(host_time), ER_DZ_MC_DB_LWRD); | 3410 | _efx_writed(efx, cpu_to_le32(host_time), ER_DZ_MC_DB_LWRD); |
3407 | } | 3411 | } |
3408 | 3412 | ||
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 | |||
3409 | const struct efx_nic_type efx_hunt_a0_nic_type = { | 3526 | const struct efx_nic_type efx_hunt_a0_nic_type = { |
3410 | .mem_map_size = efx_ef10_mem_map_size, | 3527 | .mem_map_size = efx_ef10_mem_map_size, |
3411 | .probe = efx_ef10_probe, | 3528 | .probe = efx_ef10_probe, |
@@ -3484,11 +3601,14 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { | |||
3484 | .mtd_sync = efx_mcdi_mtd_sync, | 3601 | .mtd_sync = efx_mcdi_mtd_sync, |
3485 | #endif | 3602 | #endif |
3486 | .ptp_write_host_time = efx_ef10_ptp_write_host_time, | 3603 | .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, | ||
3487 | 3606 | ||
3488 | .revision = EFX_REV_HUNT_A0, | 3607 | .revision = EFX_REV_HUNT_A0, |
3489 | .max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH), | 3608 | .max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH), |
3490 | .rx_prefix_size = ES_DZ_RX_PREFIX_SIZE, | 3609 | .rx_prefix_size = ES_DZ_RX_PREFIX_SIZE, |
3491 | .rx_hash_offset = ES_DZ_RX_PREFIX_HASH_OFST, | 3610 | .rx_hash_offset = ES_DZ_RX_PREFIX_HASH_OFST, |
3611 | .rx_ts_offset = ES_DZ_RX_PREFIX_TSTAMP_OFST, | ||
3492 | .can_rx_scatter = true, | 3612 | .can_rx_scatter = true, |
3493 | .always_rx_scatter = true, | 3613 | .always_rx_scatter = true, |
3494 | .max_interrupt_mode = EFX_INT_MODE_MSIX, | 3614 | .max_interrupt_mode = EFX_INT_MODE_MSIX, |
@@ -3497,4 +3617,6 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { | |||
3497 | NETIF_F_RXHASH | NETIF_F_NTUPLE), | 3617 | NETIF_F_RXHASH | NETIF_F_NTUPLE), |
3498 | .mcdi_max_ver = 2, | 3618 | .mcdi_max_ver = 2, |
3499 | .max_rx_ip_filters = HUNT_FILTER_TBL_ROWS, | 3619 | .max_rx_ip_filters = HUNT_FILTER_TBL_ROWS, |
3620 | .hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE | | ||
3621 | 1 << HWTSTAMP_FILTER_ALL, | ||
3500 | }; | 3622 | }; |
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 191ac8378eff..3b5dca97ec0e 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c | |||
@@ -1117,6 +1117,77 @@ static void efx_remove_port(struct efx_nic *efx) | |||
1117 | * | 1117 | * |
1118 | **************************************************************************/ | 1118 | **************************************************************************/ |
1119 | 1119 | ||
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 | |||
1120 | /* This configures the PCI device to enable I/O and DMA. */ | 1191 | /* This configures the PCI device to enable I/O and DMA. */ |
1121 | static int efx_init_io(struct efx_nic *efx) | 1192 | static int efx_init_io(struct efx_nic *efx) |
1122 | { | 1193 | { |
@@ -2214,6 +2285,8 @@ static int efx_register_netdev(struct efx_nic *efx) | |||
2214 | efx_init_tx_queue_core_txq(tx_queue); | 2285 | efx_init_tx_queue_core_txq(tx_queue); |
2215 | } | 2286 | } |
2216 | 2287 | ||
2288 | efx_associate(efx); | ||
2289 | |||
2217 | rtnl_unlock(); | 2290 | rtnl_unlock(); |
2218 | 2291 | ||
2219 | rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type); | 2292 | 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) | |||
2227 | 2300 | ||
2228 | fail_registered: | 2301 | fail_registered: |
2229 | rtnl_lock(); | 2302 | rtnl_lock(); |
2303 | efx_dissociate(efx); | ||
2230 | unregister_netdevice(net_dev); | 2304 | unregister_netdevice(net_dev); |
2231 | fail_locked: | 2305 | fail_locked: |
2232 | efx->state = STATE_UNINIT; | 2306 | efx->state = STATE_UNINIT; |
@@ -2568,6 +2642,8 @@ static int efx_init_struct(struct efx_nic *efx, | |||
2568 | int i; | 2642 | int i; |
2569 | 2643 | ||
2570 | /* Initialise common structures */ | 2644 | /* Initialise common structures */ |
2645 | INIT_LIST_HEAD(&efx->node); | ||
2646 | INIT_LIST_HEAD(&efx->secondary_list); | ||
2571 | spin_lock_init(&efx->biu_lock); | 2647 | spin_lock_init(&efx->biu_lock); |
2572 | #ifdef CONFIG_SFC_MTD | 2648 | #ifdef CONFIG_SFC_MTD |
2573 | INIT_LIST_HEAD(&efx->mtd_list); | 2649 | INIT_LIST_HEAD(&efx->mtd_list); |
@@ -2586,6 +2662,8 @@ static int efx_init_struct(struct efx_nic *efx, | |||
2586 | NET_IP_ALIGN ? (efx->rx_prefix_size + NET_IP_ALIGN) % 4 : 0; | 2662 | NET_IP_ALIGN ? (efx->rx_prefix_size + NET_IP_ALIGN) % 4 : 0; |
2587 | efx->rx_packet_hash_offset = | 2663 | efx->rx_packet_hash_offset = |
2588 | efx->type->rx_hash_offset - efx->type->rx_prefix_size; | 2664 | 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; | ||
2589 | spin_lock_init(&efx->stats_lock); | 2667 | spin_lock_init(&efx->stats_lock); |
2590 | mutex_init(&efx->mac_lock); | 2668 | mutex_init(&efx->mac_lock); |
2591 | efx->phy_op = &efx_dummy_phy_operations; | 2669 | efx->phy_op = &efx_dummy_phy_operations; |
@@ -2626,6 +2704,8 @@ static void efx_fini_struct(struct efx_nic *efx) | |||
2626 | for (i = 0; i < EFX_MAX_CHANNELS; i++) | 2704 | for (i = 0; i < EFX_MAX_CHANNELS; i++) |
2627 | kfree(efx->channel[i]); | 2705 | kfree(efx->channel[i]); |
2628 | 2706 | ||
2707 | kfree(efx->vpd_sn); | ||
2708 | |||
2629 | if (efx->workqueue) { | 2709 | if (efx->workqueue) { |
2630 | destroy_workqueue(efx->workqueue); | 2710 | destroy_workqueue(efx->workqueue); |
2631 | efx->workqueue = NULL; | 2711 | efx->workqueue = NULL; |
@@ -2670,6 +2750,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev) | |||
2670 | 2750 | ||
2671 | /* Mark the NIC as fini, then stop the interface */ | 2751 | /* Mark the NIC as fini, then stop the interface */ |
2672 | rtnl_lock(); | 2752 | rtnl_lock(); |
2753 | efx_dissociate(efx); | ||
2673 | dev_close(efx->net_dev); | 2754 | dev_close(efx->net_dev); |
2674 | efx_disable_interrupts(efx); | 2755 | efx_disable_interrupts(efx); |
2675 | rtnl_unlock(); | 2756 | rtnl_unlock(); |
@@ -2696,12 +2777,12 @@ static void efx_pci_remove(struct pci_dev *pci_dev) | |||
2696 | * always appear within the first 512 bytes. | 2777 | * always appear within the first 512 bytes. |
2697 | */ | 2778 | */ |
2698 | #define SFC_VPD_LEN 512 | 2779 | #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) |
2700 | { | 2781 | { |
2701 | struct pci_dev *dev = efx->pci_dev; | 2782 | struct pci_dev *dev = efx->pci_dev; |
2702 | char vpd_data[SFC_VPD_LEN]; | 2783 | char vpd_data[SFC_VPD_LEN]; |
2703 | ssize_t vpd_size; | 2784 | ssize_t vpd_size; |
2704 | int i, j; | 2785 | int ro_start, ro_size, i, j; |
2705 | 2786 | ||
2706 | /* Get the vpd data from the device */ | 2787 | /* Get the vpd data from the device */ |
2707 | vpd_size = pci_read_vpd(dev, 0, sizeof(vpd_data), vpd_data); | 2788 | 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) | |||
2711 | } | 2792 | } |
2712 | 2793 | ||
2713 | /* Get the Read only section */ | 2794 | /* Get the Read only section */ |
2714 | i = pci_vpd_find_tag(vpd_data, 0, vpd_size, PCI_VPD_LRDT_RO_DATA); | 2795 | ro_start = pci_vpd_find_tag(vpd_data, 0, vpd_size, PCI_VPD_LRDT_RO_DATA); |
2715 | if (i < 0) { | 2796 | if (ro_start < 0) { |
2716 | netif_err(efx, drv, efx->net_dev, "VPD Read-only not found\n"); | 2797 | netif_err(efx, drv, efx->net_dev, "VPD Read-only not found\n"); |
2717 | return; | 2798 | return; |
2718 | } | 2799 | } |
2719 | 2800 | ||
2720 | j = pci_vpd_lrdt_size(&vpd_data[i]); | 2801 | ro_size = pci_vpd_lrdt_size(&vpd_data[ro_start]); |
2721 | i += PCI_VPD_LRDT_TAG_SIZE; | 2802 | j = ro_size; |
2803 | i = ro_start + PCI_VPD_LRDT_TAG_SIZE; | ||
2722 | if (i + j > vpd_size) | 2804 | if (i + j > vpd_size) |
2723 | j = vpd_size - i; | 2805 | j = vpd_size - i; |
2724 | 2806 | ||
@@ -2738,6 +2820,27 @@ static void efx_print_product_vpd(struct efx_nic *efx) | |||
2738 | 2820 | ||
2739 | netif_info(efx, drv, efx->net_dev, | 2821 | netif_info(efx, drv, efx->net_dev, |
2740 | "Part Number : %.*s\n", j, &vpd_data[i]); | 2822 | "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]); | ||
2741 | } | 2844 | } |
2742 | 2845 | ||
2743 | 2846 | ||
@@ -2834,7 +2937,7 @@ static int efx_pci_probe(struct pci_dev *pci_dev, | |||
2834 | netif_info(efx, probe, efx->net_dev, | 2937 | netif_info(efx, probe, efx->net_dev, |
2835 | "Solarflare NIC detected\n"); | 2938 | "Solarflare NIC detected\n"); |
2836 | 2939 | ||
2837 | efx_print_product_vpd(efx); | 2940 | efx_probe_vpd_strings(efx); |
2838 | 2941 | ||
2839 | /* Set up basic I/O (BAR mappings etc) */ | 2942 | /* Set up basic I/O (BAR mappings etc) */ |
2840 | rc = efx_init_io(efx); | 2943 | rc = efx_init_io(efx); |
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 4a9e05c82e2a..76699f4e6e04 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c | |||
@@ -2247,6 +2247,8 @@ static int falcon_probe_nic(struct efx_nic *efx) | |||
2247 | struct falcon_board *board; | 2247 | struct falcon_board *board; |
2248 | int rc; | 2248 | int rc; |
2249 | 2249 | ||
2250 | efx->primary = efx; /* only one usable function per controller */ | ||
2251 | |||
2250 | /* Allocate storage for hardware specific data */ | 2252 | /* Allocate storage for hardware specific data */ |
2251 | nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL); | 2253 | nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL); |
2252 | if (!nic_data) | 2254 | if (!nic_data) |
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index d317dfdee845..0d5d7b5325e8 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c | |||
@@ -102,6 +102,10 @@ int efx_mcdi_init(struct efx_nic *efx) | |||
102 | netif_err(efx, probe, efx->net_dev, | 102 | netif_err(efx, probe, efx->net_dev, |
103 | "Host already registered with MCPU\n"); | 103 | "Host already registered with MCPU\n"); |
104 | 104 | ||
105 | if (efx->mcdi->fn_flags & | ||
106 | (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_PRIMARY)) | ||
107 | efx->primary = efx; | ||
108 | |||
105 | return 0; | 109 | return 0; |
106 | } | 110 | } |
107 | 111 | ||
@@ -1018,6 +1022,9 @@ void efx_mcdi_process_event(struct efx_channel *channel, | |||
1018 | case MCDI_EVENT_CODE_PTP_PPS: | 1022 | case MCDI_EVENT_CODE_PTP_PPS: |
1019 | efx_ptp_event(efx, event); | 1023 | efx_ptp_event(efx, event); |
1020 | break; | 1024 | break; |
1025 | case MCDI_EVENT_CODE_PTP_TIME: | ||
1026 | efx_time_sync_event(channel, event); | ||
1027 | break; | ||
1021 | case MCDI_EVENT_CODE_TX_FLUSH: | 1028 | case MCDI_EVENT_CODE_TX_FLUSH: |
1022 | case MCDI_EVENT_CODE_RX_FLUSH: | 1029 | case MCDI_EVENT_CODE_RX_FLUSH: |
1023 | /* Two flush events will be sent: one to the same event | 1030 | /* Two flush events will be sent: one to the same event |
@@ -1132,13 +1139,27 @@ static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating, | |||
1132 | goto fail; | 1139 | goto fail; |
1133 | } | 1140 | } |
1134 | 1141 | ||
1142 | if (driver_operating) { | ||
1143 | if (outlen >= MC_CMD_DRV_ATTACH_EXT_OUT_LEN) { | ||
1144 | efx->mcdi->fn_flags = | ||
1145 | MCDI_DWORD(outbuf, | ||
1146 | DRV_ATTACH_EXT_OUT_FUNC_FLAGS); | ||
1147 | } else { | ||
1148 | /* Synthesise flags for Siena */ | ||
1149 | efx->mcdi->fn_flags = | ||
1150 | 1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL | | ||
1151 | 1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_TRUSTED | | ||
1152 | (efx_port_num(efx) == 0) << | ||
1153 | MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_PRIMARY; | ||
1154 | } | ||
1155 | } | ||
1156 | |||
1135 | /* We currently assume we have control of the external link | 1157 | /* We currently assume we have control of the external link |
1136 | * and are completely trusted by firmware. Abort probing | 1158 | * and are completely trusted by firmware. Abort probing |
1137 | * if that's not true for this function. | 1159 | * if that's not true for this function. |
1138 | */ | 1160 | */ |
1139 | if (driver_operating && | 1161 | if (driver_operating && |
1140 | outlen >= MC_CMD_DRV_ATTACH_EXT_OUT_LEN && | 1162 | (efx->mcdi->fn_flags & |
1141 | (MCDI_DWORD(outbuf, DRV_ATTACH_EXT_OUT_FUNC_FLAGS) & | ||
1142 | (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL | | 1163 | (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL | |
1143 | 1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_TRUSTED)) != | 1164 | 1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_TRUSTED)) != |
1144 | (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL | | 1165 | (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL | |
diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index 171f5f58f84a..52931aebf3c3 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h | |||
@@ -94,12 +94,14 @@ struct efx_mcdi_mtd_partition { | |||
94 | * struct efx_mcdi_data - extra state for NICs that implement MCDI | 94 | * struct efx_mcdi_data - extra state for NICs that implement MCDI |
95 | * @iface: Interface/protocol state | 95 | * @iface: Interface/protocol state |
96 | * @hwmon: Hardware monitor state | 96 | * @hwmon: Hardware monitor state |
97 | * @fn_flags: Flags for this function, as returned by %MC_CMD_DRV_ATTACH. | ||
97 | */ | 98 | */ |
98 | struct efx_mcdi_data { | 99 | struct efx_mcdi_data { |
99 | struct efx_mcdi_iface iface; | 100 | struct efx_mcdi_iface iface; |
100 | #ifdef CONFIG_SFC_MCDI_MON | 101 | #ifdef CONFIG_SFC_MCDI_MON |
101 | struct efx_mcdi_mon hwmon; | 102 | struct efx_mcdi_mon hwmon; |
102 | #endif | 103 | #endif |
104 | u32 fn_flags; | ||
103 | }; | 105 | }; |
104 | 106 | ||
105 | #ifdef CONFIG_SFC_MCDI_MON | 107 | #ifdef CONFIG_SFC_MCDI_MON |
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index f47bac78b92c..653b8782c956 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h | |||
@@ -91,6 +91,7 @@ | |||
91 | 91 | ||
92 | /* Forward declare Precision Time Protocol (PTP) support structure. */ | 92 | /* Forward declare Precision Time Protocol (PTP) support structure. */ |
93 | struct efx_ptp_data; | 93 | struct efx_ptp_data; |
94 | struct hwtstamp_config; | ||
94 | 95 | ||
95 | struct efx_self_tests; | 96 | struct efx_self_tests; |
96 | 97 | ||
@@ -368,6 +369,13 @@ enum efx_rx_alloc_method { | |||
368 | RX_ALLOC_METHOD_PAGE = 2, | 369 | RX_ALLOC_METHOD_PAGE = 2, |
369 | }; | 370 | }; |
370 | 371 | ||
372 | enum efx_sync_events_state { | ||
373 | SYNC_EVENTS_DISABLED = 0, | ||
374 | SYNC_EVENTS_QUIESCENT, | ||
375 | SYNC_EVENTS_REQUESTED, | ||
376 | SYNC_EVENTS_VALID, | ||
377 | }; | ||
378 | |||
371 | /** | 379 | /** |
372 | * struct efx_channel - An Efx channel | 380 | * struct efx_channel - An Efx channel |
373 | * | 381 | * |
@@ -407,6 +415,9 @@ enum efx_rx_alloc_method { | |||
407 | * by __efx_rx_packet(), if @rx_pkt_n_frags != 0 | 415 | * by __efx_rx_packet(), if @rx_pkt_n_frags != 0 |
408 | * @rx_queue: RX queue for this channel | 416 | * @rx_queue: RX queue for this channel |
409 | * @tx_queue: TX queues for this channel | 417 | * @tx_queue: TX queues for this channel |
418 | * @sync_events_state: Current state of sync events on this channel | ||
419 | * @sync_timestamp_major: Major part of the last ptp sync event | ||
420 | * @sync_timestamp_minor: Minor part of the last ptp sync event | ||
410 | */ | 421 | */ |
411 | struct efx_channel { | 422 | struct efx_channel { |
412 | struct efx_nic *efx; | 423 | struct efx_nic *efx; |
@@ -445,6 +456,10 @@ struct efx_channel { | |||
445 | 456 | ||
446 | struct efx_rx_queue rx_queue; | 457 | struct efx_rx_queue rx_queue; |
447 | struct efx_tx_queue tx_queue[EFX_TXQ_TYPES]; | 458 | struct efx_tx_queue tx_queue[EFX_TXQ_TYPES]; |
459 | |||
460 | enum efx_sync_events_state sync_events_state; | ||
461 | u32 sync_timestamp_major; | ||
462 | u32 sync_timestamp_minor; | ||
448 | }; | 463 | }; |
449 | 464 | ||
450 | /** | 465 | /** |
@@ -520,15 +535,6 @@ enum nic_state { | |||
520 | STATE_RECOVERY = 3, /* device recovering from PCI error */ | 535 | STATE_RECOVERY = 3, /* device recovering from PCI error */ |
521 | }; | 536 | }; |
522 | 537 | ||
523 | /* | ||
524 | * Alignment of the skb->head which wraps a page-allocated RX buffer | ||
525 | * | ||
526 | * The skb allocated to wrap an rx_buffer can have this alignment. Since | ||
527 | * the data is memcpy'd from the rx_buf, it does not need to be equal to | ||
528 | * NET_IP_ALIGN. | ||
529 | */ | ||
530 | #define EFX_PAGE_SKB_ALIGN 2 | ||
531 | |||
532 | /* Forward declaration */ | 538 | /* Forward declaration */ |
533 | struct efx_nic; | 539 | struct efx_nic; |
534 | 540 | ||
@@ -651,6 +657,13 @@ struct vfdi_status; | |||
651 | * struct efx_nic - an Efx NIC | 657 | * struct efx_nic - an Efx NIC |
652 | * @name: Device name (net device name or bus id before net device registered) | 658 | * @name: Device name (net device name or bus id before net device registered) |
653 | * @pci_dev: The PCI device | 659 | * @pci_dev: The PCI device |
660 | * @node: List node for maintaning primary/secondary function lists | ||
661 | * @primary: &struct efx_nic instance for the primary function of this | ||
662 | * controller. May be the same structure, and may be %NULL if no | ||
663 | * primary function is bound. Serialised by rtnl_lock. | ||
664 | * @secondary_list: List of &struct efx_nic instances for the secondary PCI | ||
665 | * functions of the controller, if this is for the primary function. | ||
666 | * Serialised by rtnl_lock. | ||
654 | * @type: Controller type attributes | 667 | * @type: Controller type attributes |
655 | * @legacy_irq: IRQ number | 668 | * @legacy_irq: IRQ number |
656 | * @workqueue: Workqueue for port reconfigures and the HW monitor. | 669 | * @workqueue: Workqueue for port reconfigures and the HW monitor. |
@@ -694,6 +707,8 @@ struct vfdi_status; | |||
694 | * (valid only if @rx_prefix_size != 0; always negative) | 707 | * (valid only if @rx_prefix_size != 0; always negative) |
695 | * @rx_packet_len_offset: Offset of RX packet length from start of packet data | 708 | * @rx_packet_len_offset: Offset of RX packet length from start of packet data |
696 | * (valid only for NICs that set %EFX_RX_PKT_PREFIX_LEN; always negative) | 709 | * (valid only for NICs that set %EFX_RX_PKT_PREFIX_LEN; always negative) |
710 | * @rx_packet_ts_offset: Offset of timestamp from start of packet data | ||
711 | * (valid only if channel->sync_timestamps_enabled; always negative) | ||
697 | * @rx_hash_key: Toeplitz hash key for RSS | 712 | * @rx_hash_key: Toeplitz hash key for RSS |
698 | * @rx_indir_table: Indirection table for RSS | 713 | * @rx_indir_table: Indirection table for RSS |
699 | * @rx_scatter: Scatter mode enabled for receives | 714 | * @rx_scatter: Scatter mode enabled for receives |
@@ -763,6 +778,7 @@ struct vfdi_status; | |||
763 | * @local_lock: Mutex protecting %local_addr_list and %local_page_list. | 778 | * @local_lock: Mutex protecting %local_addr_list and %local_page_list. |
764 | * @peer_work: Work item to broadcast peer addresses to VMs. | 779 | * @peer_work: Work item to broadcast peer addresses to VMs. |
765 | * @ptp_data: PTP state data | 780 | * @ptp_data: PTP state data |
781 | * @vpd_sn: Serial number read from VPD | ||
766 | * @monitor_work: Hardware monitor workitem | 782 | * @monitor_work: Hardware monitor workitem |
767 | * @biu_lock: BIU (bus interface unit) lock | 783 | * @biu_lock: BIU (bus interface unit) lock |
768 | * @last_irq_cpu: Last CPU to handle a possible test interrupt. This | 784 | * @last_irq_cpu: Last CPU to handle a possible test interrupt. This |
@@ -777,6 +793,9 @@ struct efx_nic { | |||
777 | /* The following fields should be written very rarely */ | 793 | /* The following fields should be written very rarely */ |
778 | 794 | ||
779 | char name[IFNAMSIZ]; | 795 | char name[IFNAMSIZ]; |
796 | struct list_head node; | ||
797 | struct efx_nic *primary; | ||
798 | struct list_head secondary_list; | ||
780 | struct pci_dev *pci_dev; | 799 | struct pci_dev *pci_dev; |
781 | unsigned int port_num; | 800 | unsigned int port_num; |
782 | const struct efx_nic_type *type; | 801 | const struct efx_nic_type *type; |
@@ -828,6 +847,7 @@ struct efx_nic { | |||
828 | unsigned int rx_prefix_size; | 847 | unsigned int rx_prefix_size; |
829 | int rx_packet_hash_offset; | 848 | int rx_packet_hash_offset; |
830 | int rx_packet_len_offset; | 849 | int rx_packet_len_offset; |
850 | int rx_packet_ts_offset; | ||
831 | u8 rx_hash_key[40]; | 851 | u8 rx_hash_key[40]; |
832 | u32 rx_indir_table[128]; | 852 | u32 rx_indir_table[128]; |
833 | bool rx_scatter; | 853 | bool rx_scatter; |
@@ -911,6 +931,8 @@ struct efx_nic { | |||
911 | 931 | ||
912 | struct efx_ptp_data *ptp_data; | 932 | struct efx_ptp_data *ptp_data; |
913 | 933 | ||
934 | char *vpd_sn; | ||
935 | |||
914 | /* The following fields may be written more often */ | 936 | /* The following fields may be written more often */ |
915 | 937 | ||
916 | struct delayed_work monitor_work ____cacheline_aligned_in_smp; | 938 | struct delayed_work monitor_work ____cacheline_aligned_in_smp; |
@@ -1042,6 +1064,12 @@ struct efx_mtd_partition { | |||
1042 | * @mtd_sync: Wait for write-back to complete on MTD partition. This | 1064 | * @mtd_sync: Wait for write-back to complete on MTD partition. This |
1043 | * also notifies the driver that a writer has finished using this | 1065 | * also notifies the driver that a writer has finished using this |
1044 | * partition. | 1066 | * partition. |
1067 | * @ptp_write_host_time: Send host time to MC as part of sync protocol | ||
1068 | * @ptp_set_ts_sync_events: Enable or disable sync events for inline RX | ||
1069 | * timestamping, possibly only temporarily for the purposes of a reset. | ||
1070 | * @ptp_set_ts_config: Set hardware timestamp configuration. The flags | ||
1071 | * and tx_type will already have been validated but this operation | ||
1072 | * must validate and update rx_filter. | ||
1045 | * @revision: Hardware architecture revision | 1073 | * @revision: Hardware architecture revision |
1046 | * @txd_ptr_tbl_base: TX descriptor ring base address | 1074 | * @txd_ptr_tbl_base: TX descriptor ring base address |
1047 | * @rxd_ptr_tbl_base: RX descriptor ring base address | 1075 | * @rxd_ptr_tbl_base: RX descriptor ring base address |
@@ -1051,6 +1079,7 @@ struct efx_mtd_partition { | |||
1051 | * @max_dma_mask: Maximum possible DMA mask | 1079 | * @max_dma_mask: Maximum possible DMA mask |
1052 | * @rx_prefix_size: Size of RX prefix before packet data | 1080 | * @rx_prefix_size: Size of RX prefix before packet data |
1053 | * @rx_hash_offset: Offset of RX flow hash within prefix | 1081 | * @rx_hash_offset: Offset of RX flow hash within prefix |
1082 | * @rx_ts_offset: Offset of timestamp within prefix | ||
1054 | * @rx_buffer_padding: Size of padding at end of RX packet | 1083 | * @rx_buffer_padding: Size of padding at end of RX packet |
1055 | * @can_rx_scatter: NIC is able to scatter packets to multiple buffers | 1084 | * @can_rx_scatter: NIC is able to scatter packets to multiple buffers |
1056 | * @always_rx_scatter: NIC will always scatter packets to multiple buffers | 1085 | * @always_rx_scatter: NIC will always scatter packets to multiple buffers |
@@ -1060,6 +1089,7 @@ struct efx_mtd_partition { | |||
1060 | * @offload_features: net_device feature flags for protocol offload | 1089 | * @offload_features: net_device feature flags for protocol offload |
1061 | * features implemented in hardware | 1090 | * features implemented in hardware |
1062 | * @mcdi_max_ver: Maximum MCDI version supported | 1091 | * @mcdi_max_ver: Maximum MCDI version supported |
1092 | * @hwtstamp_filters: Mask of hardware timestamp filter types supported | ||
1063 | */ | 1093 | */ |
1064 | struct efx_nic_type { | 1094 | struct efx_nic_type { |
1065 | unsigned int (*mem_map_size)(struct efx_nic *efx); | 1095 | unsigned int (*mem_map_size)(struct efx_nic *efx); |
@@ -1161,6 +1191,9 @@ struct efx_nic_type { | |||
1161 | int (*mtd_sync)(struct mtd_info *mtd); | 1191 | int (*mtd_sync)(struct mtd_info *mtd); |
1162 | #endif | 1192 | #endif |
1163 | void (*ptp_write_host_time)(struct efx_nic *efx, u32 host_time); | 1193 | void (*ptp_write_host_time)(struct efx_nic *efx, u32 host_time); |
1194 | int (*ptp_set_ts_sync_events)(struct efx_nic *efx, bool en, bool temp); | ||
1195 | int (*ptp_set_ts_config)(struct efx_nic *efx, | ||
1196 | struct hwtstamp_config *init); | ||
1164 | 1197 | ||
1165 | int revision; | 1198 | int revision; |
1166 | unsigned int txd_ptr_tbl_base; | 1199 | unsigned int txd_ptr_tbl_base; |
@@ -1171,6 +1204,7 @@ struct efx_nic_type { | |||
1171 | u64 max_dma_mask; | 1204 | u64 max_dma_mask; |
1172 | unsigned int rx_prefix_size; | 1205 | unsigned int rx_prefix_size; |
1173 | unsigned int rx_hash_offset; | 1206 | unsigned int rx_hash_offset; |
1207 | unsigned int rx_ts_offset; | ||
1174 | unsigned int rx_buffer_padding; | 1208 | unsigned int rx_buffer_padding; |
1175 | bool can_rx_scatter; | 1209 | bool can_rx_scatter; |
1176 | bool always_rx_scatter; | 1210 | bool always_rx_scatter; |
@@ -1179,6 +1213,7 @@ struct efx_nic_type { | |||
1179 | netdev_features_t offload_features; | 1213 | netdev_features_t offload_features; |
1180 | int mcdi_max_ver; | 1214 | int mcdi_max_ver; |
1181 | unsigned int max_rx_ip_filters; | 1215 | unsigned int max_rx_ip_filters; |
1216 | u32 hwtstamp_filters; | ||
1182 | }; | 1217 | }; |
1183 | 1218 | ||
1184 | /************************************************************************** | 1219 | /************************************************************************** |
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 25178536f053..5d9e2dc121f7 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h | |||
@@ -561,8 +561,20 @@ int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr); | |||
561 | int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr); | 561 | int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr); |
562 | void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info); | 562 | void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info); |
563 | bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); | 563 | bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); |
564 | int efx_ptp_get_mode(struct efx_nic *efx); | ||
565 | int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted, | ||
566 | unsigned int new_mode); | ||
564 | int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); | 567 | int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); |
565 | void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev); | 568 | void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev); |
569 | void efx_time_sync_event(struct efx_channel *channel, efx_qword_t *ev); | ||
570 | void __efx_rx_skb_attach_timestamp(struct efx_channel *channel, | ||
571 | struct sk_buff *skb); | ||
572 | static inline void efx_rx_skb_attach_timestamp(struct efx_channel *channel, | ||
573 | struct sk_buff *skb) | ||
574 | { | ||
575 | if (channel->sync_events_state == SYNC_EVENTS_VALID) | ||
576 | __efx_rx_skb_attach_timestamp(channel, skb); | ||
577 | } | ||
566 | void efx_ptp_start_datapath(struct efx_nic *efx); | 578 | void efx_ptp_start_datapath(struct efx_nic *efx); |
567 | void efx_ptp_stop_datapath(struct efx_nic *efx); | 579 | void efx_ptp_stop_datapath(struct efx_nic *efx); |
568 | 580 | ||
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index aa4876edaac6..084e2d44790f 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c | |||
@@ -62,7 +62,7 @@ | |||
62 | #define SYNCHRONISATION_GRANULARITY_NS 200 | 62 | #define SYNCHRONISATION_GRANULARITY_NS 200 |
63 | 63 | ||
64 | /* Minimum permitted length of a (corrected) synchronisation time */ | 64 | /* Minimum permitted length of a (corrected) synchronisation time */ |
65 | #define MIN_SYNCHRONISATION_NS 120 | 65 | #define DEFAULT_MIN_SYNCHRONISATION_NS 120 |
66 | 66 | ||
67 | /* Maximum permitted length of a (corrected) synchronisation time */ | 67 | /* Maximum permitted length of a (corrected) synchronisation time */ |
68 | #define MAX_SYNCHRONISATION_NS 1000 | 68 | #define MAX_SYNCHRONISATION_NS 1000 |
@@ -195,20 +195,20 @@ struct efx_ptp_event_rx { | |||
195 | /** | 195 | /** |
196 | * struct efx_ptp_timeset - Synchronisation between host and MC | 196 | * struct efx_ptp_timeset - Synchronisation between host and MC |
197 | * @host_start: Host time immediately before hardware timestamp taken | 197 | * @host_start: Host time immediately before hardware timestamp taken |
198 | * @seconds: Hardware timestamp, seconds | 198 | * @major: Hardware timestamp, major |
199 | * @nanoseconds: Hardware timestamp, nanoseconds | 199 | * @minor: Hardware timestamp, minor |
200 | * @host_end: Host time immediately after hardware timestamp taken | 200 | * @host_end: Host time immediately after hardware timestamp taken |
201 | * @waitns: Number of nanoseconds between hardware timestamp being read and | 201 | * @wait: Number of NIC clock ticks between hardware timestamp being read and |
202 | * host end time being seen | 202 | * host end time being seen |
203 | * @window: Difference of host_end and host_start | 203 | * @window: Difference of host_end and host_start |
204 | * @valid: Whether this timeset is valid | 204 | * @valid: Whether this timeset is valid |
205 | */ | 205 | */ |
206 | struct efx_ptp_timeset { | 206 | struct efx_ptp_timeset { |
207 | u32 host_start; | 207 | u32 host_start; |
208 | u32 seconds; | 208 | u32 major; |
209 | u32 nanoseconds; | 209 | u32 minor; |
210 | u32 host_end; | 210 | u32 host_end; |
211 | u32 waitns; | 211 | u32 wait; |
212 | u32 window; /* Derived: end - start, allowing for wrap */ | 212 | u32 window; /* Derived: end - start, allowing for wrap */ |
213 | }; | 213 | }; |
214 | 214 | ||
@@ -216,6 +216,8 @@ struct efx_ptp_timeset { | |||
216 | * struct efx_ptp_data - Precision Time Protocol (PTP) state | 216 | * struct efx_ptp_data - Precision Time Protocol (PTP) state |
217 | * @efx: The NIC context | 217 | * @efx: The NIC context |
218 | * @channel: The PTP channel (Siena only) | 218 | * @channel: The PTP channel (Siena only) |
219 | * @rx_ts_inline: Flag for whether RX timestamps are inline (else they are | ||
220 | * separate events) | ||
219 | * @rxq: Receive queue (awaiting timestamps) | 221 | * @rxq: Receive queue (awaiting timestamps) |
220 | * @txq: Transmit queue | 222 | * @txq: Transmit queue |
221 | * @evt_list: List of MC receive events awaiting packets | 223 | * @evt_list: List of MC receive events awaiting packets |
@@ -232,42 +234,33 @@ struct efx_ptp_timeset { | |||
232 | * @config: Current timestamp configuration | 234 | * @config: Current timestamp configuration |
233 | * @enabled: PTP operation enabled | 235 | * @enabled: PTP operation enabled |
234 | * @mode: Mode in which PTP operating (PTP version) | 236 | * @mode: Mode in which PTP operating (PTP version) |
237 | * @time_format: Time format supported by this NIC | ||
238 | * @ns_to_nic_time: Function to convert from scalar nanoseconds to NIC time | ||
239 | * @nic_to_kernel_time: Function to convert from NIC to kernel time | ||
240 | * @min_synchronisation_ns: Minimum acceptable corrected sync window | ||
241 | * @ts_corrections.tx: Required driver correction of transmit timestamps | ||
242 | * @ts_corrections.rx: Required driver correction of receive timestamps | ||
243 | * @ts_corrections.pps_out: PPS output error (information only) | ||
244 | * @ts_corrections.pps_in: Required driver correction of PPS input timestamps | ||
235 | * @evt_frags: Partly assembled PTP events | 245 | * @evt_frags: Partly assembled PTP events |
236 | * @evt_frag_idx: Current fragment number | 246 | * @evt_frag_idx: Current fragment number |
237 | * @evt_code: Last event code | 247 | * @evt_code: Last event code |
238 | * @start: Address at which MC indicates ready for synchronisation | 248 | * @start: Address at which MC indicates ready for synchronisation |
239 | * @host_time_pps: Host time at last PPS | 249 | * @host_time_pps: Host time at last PPS |
240 | * @last_sync_ns: Last number of nanoseconds between readings when synchronising | ||
241 | * @base_sync_ns: Number of nanoseconds for last synchronisation. | ||
242 | * @base_sync_valid: Whether base_sync_time is valid. | ||
243 | * @current_adjfreq: Current ppb adjustment. | 250 | * @current_adjfreq: Current ppb adjustment. |
244 | * @phc_clock: Pointer to registered phc device | 251 | * @phc_clock: Pointer to registered phc device (if primary function) |
245 | * @phc_clock_info: Registration structure for phc device | 252 | * @phc_clock_info: Registration structure for phc device |
246 | * @pps_work: pps work task for handling pps events | 253 | * @pps_work: pps work task for handling pps events |
247 | * @pps_workwq: pps work queue | 254 | * @pps_workwq: pps work queue |
248 | * @nic_ts_enabled: Flag indicating if NIC generated TS events are handled | 255 | * @nic_ts_enabled: Flag indicating if NIC generated TS events are handled |
249 | * @txbuf: Buffer for use when transmitting (PTP) packets to MC (avoids | 256 | * @txbuf: Buffer for use when transmitting (PTP) packets to MC (avoids |
250 | * allocations in main data path). | 257 | * allocations in main data path). |
251 | * @debug_ptp_dir: PTP debugfs directory | ||
252 | * @missed_rx_sync: Number of packets received without syncrhonisation. | ||
253 | * @good_syncs: Number of successful synchronisations. | ||
254 | * @no_time_syncs: Number of synchronisations with no good times. | ||
255 | * @bad_sync_durations: Number of synchronisations with bad durations. | ||
256 | * @bad_syncs: Number of failed synchronisations. | ||
257 | * @last_sync_time: Number of nanoseconds for last synchronisation. | ||
258 | * @sync_timeouts: Number of synchronisation timeouts | ||
259 | * @fast_syncs: Number of synchronisations requiring short delay | ||
260 | * @min_sync_delta: Minimum time between event and synchronisation | ||
261 | * @max_sync_delta: Maximum time between event and synchronisation | ||
262 | * @average_sync_delta: Average time between event and synchronisation. | ||
263 | * Modified moving average. | ||
264 | * @last_sync_delta: Last time between event and synchronisation | ||
265 | * @mc_stats: Context value for MC statistics | ||
266 | * @timeset: Last set of synchronisation statistics. | 258 | * @timeset: Last set of synchronisation statistics. |
267 | */ | 259 | */ |
268 | struct efx_ptp_data { | 260 | struct efx_ptp_data { |
269 | struct efx_nic *efx; | 261 | struct efx_nic *efx; |
270 | struct efx_channel *channel; | 262 | struct efx_channel *channel; |
263 | bool rx_ts_inline; | ||
271 | struct sk_buff_head rxq; | 264 | struct sk_buff_head rxq; |
272 | struct sk_buff_head txq; | 265 | struct sk_buff_head txq; |
273 | struct list_head evt_list; | 266 | struct list_head evt_list; |
@@ -284,14 +277,22 @@ struct efx_ptp_data { | |||
284 | struct hwtstamp_config config; | 277 | struct hwtstamp_config config; |
285 | bool enabled; | 278 | bool enabled; |
286 | unsigned int mode; | 279 | unsigned int mode; |
280 | unsigned int time_format; | ||
281 | void (*ns_to_nic_time)(s64 ns, u32 *nic_major, u32 *nic_minor); | ||
282 | ktime_t (*nic_to_kernel_time)(u32 nic_major, u32 nic_minor, | ||
283 | s32 correction); | ||
284 | unsigned int min_synchronisation_ns; | ||
285 | struct { | ||
286 | s32 tx; | ||
287 | s32 rx; | ||
288 | s32 pps_out; | ||
289 | s32 pps_in; | ||
290 | } ts_corrections; | ||
287 | efx_qword_t evt_frags[MAX_EVENT_FRAGS]; | 291 | efx_qword_t evt_frags[MAX_EVENT_FRAGS]; |
288 | int evt_frag_idx; | 292 | int evt_frag_idx; |
289 | int evt_code; | 293 | int evt_code; |
290 | struct efx_buffer start; | 294 | struct efx_buffer start; |
291 | struct pps_event_time host_time_pps; | 295 | struct pps_event_time host_time_pps; |
292 | unsigned last_sync_ns; | ||
293 | unsigned base_sync_ns; | ||
294 | bool base_sync_valid; | ||
295 | s64 current_adjfreq; | 296 | s64 current_adjfreq; |
296 | struct ptp_clock *phc_clock; | 297 | struct ptp_clock *phc_clock; |
297 | struct ptp_clock_info phc_clock_info; | 298 | struct ptp_clock_info phc_clock_info; |
@@ -311,6 +312,169 @@ static int efx_phc_settime(struct ptp_clock_info *ptp, | |||
311 | static int efx_phc_enable(struct ptp_clock_info *ptp, | 312 | static int efx_phc_enable(struct ptp_clock_info *ptp, |
312 | struct ptp_clock_request *request, int on); | 313 | struct ptp_clock_request *request, int on); |
313 | 314 | ||
315 | /* For Siena platforms NIC time is s and ns */ | ||
316 | static void efx_ptp_ns_to_s_ns(s64 ns, u32 *nic_major, u32 *nic_minor) | ||
317 | { | ||
318 | struct timespec ts = ns_to_timespec(ns); | ||
319 | *nic_major = ts.tv_sec; | ||
320 | *nic_minor = ts.tv_nsec; | ||
321 | } | ||
322 | |||
323 | static ktime_t efx_ptp_s_ns_to_ktime_correction(u32 nic_major, u32 nic_minor, | ||
324 | s32 correction) | ||
325 | { | ||
326 | ktime_t kt = ktime_set(nic_major, nic_minor); | ||
327 | if (correction >= 0) | ||
328 | kt = ktime_add_ns(kt, (u64)correction); | ||
329 | else | ||
330 | kt = ktime_sub_ns(kt, (u64)-correction); | ||
331 | return kt; | ||
332 | } | ||
333 | |||
334 | /* To convert from s27 format to ns we multiply then divide by a power of 2. | ||
335 | * For the conversion from ns to s27, the operation is also converted to a | ||
336 | * multiply and shift. | ||
337 | */ | ||
338 | #define S27_TO_NS_SHIFT (27) | ||
339 | #define NS_TO_S27_MULT (((1ULL << 63) + NSEC_PER_SEC / 2) / NSEC_PER_SEC) | ||
340 | #define NS_TO_S27_SHIFT (63 - S27_TO_NS_SHIFT) | ||
341 | #define S27_MINOR_MAX (1 << S27_TO_NS_SHIFT) | ||
342 | |||
343 | /* For Huntington platforms NIC time is in seconds and fractions of a second | ||
344 | * where the minor register only uses 27 bits in units of 2^-27s. | ||
345 | */ | ||
346 | static void efx_ptp_ns_to_s27(s64 ns, u32 *nic_major, u32 *nic_minor) | ||
347 | { | ||
348 | struct timespec ts = ns_to_timespec(ns); | ||
349 | u32 maj = ts.tv_sec; | ||
350 | u32 min = (u32)(((u64)ts.tv_nsec * NS_TO_S27_MULT + | ||
351 | (1ULL << (NS_TO_S27_SHIFT - 1))) >> NS_TO_S27_SHIFT); | ||
352 | |||
353 | /* The conversion can result in the minor value exceeding the maximum. | ||
354 | * In this case, round up to the next second. | ||
355 | */ | ||
356 | if (min >= S27_MINOR_MAX) { | ||
357 | min -= S27_MINOR_MAX; | ||
358 | maj++; | ||
359 | } | ||
360 | |||
361 | *nic_major = maj; | ||
362 | *nic_minor = min; | ||
363 | } | ||
364 | |||
365 | static inline ktime_t efx_ptp_s27_to_ktime(u32 nic_major, u32 nic_minor) | ||
366 | { | ||
367 | u32 ns = (u32)(((u64)nic_minor * NSEC_PER_SEC + | ||
368 | (1ULL << (S27_TO_NS_SHIFT - 1))) >> S27_TO_NS_SHIFT); | ||
369 | return ktime_set(nic_major, ns); | ||
370 | } | ||
371 | |||
372 | static ktime_t efx_ptp_s27_to_ktime_correction(u32 nic_major, u32 nic_minor, | ||
373 | s32 correction) | ||
374 | { | ||
375 | /* Apply the correction and deal with carry */ | ||
376 | nic_minor += correction; | ||
377 | if ((s32)nic_minor < 0) { | ||
378 | nic_minor += S27_MINOR_MAX; | ||
379 | nic_major--; | ||
380 | } else if (nic_minor >= S27_MINOR_MAX) { | ||
381 | nic_minor -= S27_MINOR_MAX; | ||
382 | nic_major++; | ||
383 | } | ||
384 | |||
385 | return efx_ptp_s27_to_ktime(nic_major, nic_minor); | ||
386 | } | ||
387 | |||
388 | /* Get PTP attributes and set up time conversions */ | ||
389 | static int efx_ptp_get_attributes(struct efx_nic *efx) | ||
390 | { | ||
391 | MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_GET_ATTRIBUTES_LEN); | ||
392 | MCDI_DECLARE_BUF(outbuf, MC_CMD_PTP_OUT_GET_ATTRIBUTES_LEN); | ||
393 | struct efx_ptp_data *ptp = efx->ptp_data; | ||
394 | int rc; | ||
395 | u32 fmt; | ||
396 | size_t out_len; | ||
397 | |||
398 | /* Get the PTP attributes. If the NIC doesn't support the operation we | ||
399 | * use the default format for compatibility with older NICs i.e. | ||
400 | * seconds and nanoseconds. | ||
401 | */ | ||
402 | MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_GET_ATTRIBUTES); | ||
403 | MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); | ||
404 | rc = efx_mcdi_rpc(efx, MC_CMD_PTP, inbuf, sizeof(inbuf), | ||
405 | outbuf, sizeof(outbuf), &out_len); | ||
406 | if (rc == 0) | ||
407 | fmt = MCDI_DWORD(outbuf, PTP_OUT_GET_ATTRIBUTES_TIME_FORMAT); | ||
408 | else if (rc == -EINVAL) | ||
409 | fmt = MC_CMD_PTP_OUT_GET_ATTRIBUTES_SECONDS_NANOSECONDS; | ||
410 | else | ||
411 | return rc; | ||
412 | |||
413 | if (fmt == MC_CMD_PTP_OUT_GET_ATTRIBUTES_SECONDS_27FRACTION) { | ||
414 | ptp->ns_to_nic_time = efx_ptp_ns_to_s27; | ||
415 | ptp->nic_to_kernel_time = efx_ptp_s27_to_ktime_correction; | ||
416 | } else if (fmt == MC_CMD_PTP_OUT_GET_ATTRIBUTES_SECONDS_NANOSECONDS) { | ||
417 | ptp->ns_to_nic_time = efx_ptp_ns_to_s_ns; | ||
418 | ptp->nic_to_kernel_time = efx_ptp_s_ns_to_ktime_correction; | ||
419 | } else { | ||
420 | return -ERANGE; | ||
421 | } | ||
422 | |||
423 | ptp->time_format = fmt; | ||
424 | |||
425 | /* MC_CMD_PTP_OP_GET_ATTRIBUTES is an extended version of an older | ||
426 | * operation MC_CMD_PTP_OP_GET_TIME_FORMAT that also returns a value | ||
427 | * to use for the minimum acceptable corrected synchronization window. | ||
428 | * If we have the extra information store it. For older firmware that | ||
429 | * does not implement the extended command use the default value. | ||
430 | */ | ||
431 | if (rc == 0 && out_len >= MC_CMD_PTP_OUT_GET_ATTRIBUTES_LEN) | ||
432 | ptp->min_synchronisation_ns = | ||
433 | MCDI_DWORD(outbuf, | ||
434 | PTP_OUT_GET_ATTRIBUTES_SYNC_WINDOW_MIN); | ||
435 | else | ||
436 | ptp->min_synchronisation_ns = DEFAULT_MIN_SYNCHRONISATION_NS; | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | /* Get PTP timestamp corrections */ | ||
442 | static int efx_ptp_get_timestamp_corrections(struct efx_nic *efx) | ||
443 | { | ||
444 | MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_GET_TIMESTAMP_CORRECTIONS_LEN); | ||
445 | MCDI_DECLARE_BUF(outbuf, MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS_LEN); | ||
446 | int rc; | ||
447 | |||
448 | /* Get the timestamp corrections from the NIC. If this operation is | ||
449 | * not supported (older NICs) then no correction is required. | ||
450 | */ | ||
451 | MCDI_SET_DWORD(inbuf, PTP_IN_OP, | ||
452 | MC_CMD_PTP_OP_GET_TIMESTAMP_CORRECTIONS); | ||
453 | MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); | ||
454 | |||
455 | rc = efx_mcdi_rpc(efx, MC_CMD_PTP, inbuf, sizeof(inbuf), | ||
456 | outbuf, sizeof(outbuf), NULL); | ||
457 | if (rc == 0) { | ||
458 | efx->ptp_data->ts_corrections.tx = MCDI_DWORD(outbuf, | ||
459 | PTP_OUT_GET_TIMESTAMP_CORRECTIONS_TRANSMIT); | ||
460 | efx->ptp_data->ts_corrections.rx = MCDI_DWORD(outbuf, | ||
461 | PTP_OUT_GET_TIMESTAMP_CORRECTIONS_RECEIVE); | ||
462 | efx->ptp_data->ts_corrections.pps_out = MCDI_DWORD(outbuf, | ||
463 | PTP_OUT_GET_TIMESTAMP_CORRECTIONS_PPS_OUT); | ||
464 | efx->ptp_data->ts_corrections.pps_in = MCDI_DWORD(outbuf, | ||
465 | PTP_OUT_GET_TIMESTAMP_CORRECTIONS_PPS_IN); | ||
466 | } else if (rc == -EINVAL) { | ||
467 | efx->ptp_data->ts_corrections.tx = 0; | ||
468 | efx->ptp_data->ts_corrections.rx = 0; | ||
469 | efx->ptp_data->ts_corrections.pps_out = 0; | ||
470 | efx->ptp_data->ts_corrections.pps_in = 0; | ||
471 | } else { | ||
472 | return rc; | ||
473 | } | ||
474 | |||
475 | return 0; | ||
476 | } | ||
477 | |||
314 | /* Enable MCDI PTP support. */ | 478 | /* Enable MCDI PTP support. */ |
315 | static int efx_ptp_enable(struct efx_nic *efx) | 479 | static int efx_ptp_enable(struct efx_nic *efx) |
316 | { | 480 | { |
@@ -423,11 +587,10 @@ static void efx_ptp_read_timeset(MCDI_DECLARE_STRUCT_PTR(data), | |||
423 | unsigned start_ns, end_ns; | 587 | unsigned start_ns, end_ns; |
424 | 588 | ||
425 | timeset->host_start = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_HOSTSTART); | 589 | timeset->host_start = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_HOSTSTART); |
426 | timeset->seconds = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_SECONDS); | 590 | timeset->major = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_MAJOR); |
427 | timeset->nanoseconds = MCDI_DWORD(data, | 591 | timeset->minor = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_MINOR); |
428 | PTP_OUT_SYNCHRONIZE_NANOSECONDS); | ||
429 | timeset->host_end = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_HOSTEND), | 592 | timeset->host_end = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_HOSTEND), |
430 | timeset->waitns = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_WAITNS); | 593 | timeset->wait = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_WAITNS); |
431 | 594 | ||
432 | /* Ignore seconds */ | 595 | /* Ignore seconds */ |
433 | start_ns = timeset->host_start & MC_NANOSECOND_MASK; | 596 | start_ns = timeset->host_start & MC_NANOSECOND_MASK; |
@@ -456,62 +619,68 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf), | |||
456 | MCDI_VAR_ARRAY_LEN(response_length, | 619 | MCDI_VAR_ARRAY_LEN(response_length, |
457 | PTP_OUT_SYNCHRONIZE_TIMESET); | 620 | PTP_OUT_SYNCHRONIZE_TIMESET); |
458 | unsigned i; | 621 | unsigned i; |
459 | unsigned total; | ||
460 | unsigned ngood = 0; | 622 | unsigned ngood = 0; |
461 | unsigned last_good = 0; | 623 | unsigned last_good = 0; |
462 | struct efx_ptp_data *ptp = efx->ptp_data; | 624 | struct efx_ptp_data *ptp = efx->ptp_data; |
463 | u32 last_sec; | 625 | u32 last_sec; |
464 | u32 start_sec; | 626 | u32 start_sec; |
465 | struct timespec delta; | 627 | struct timespec delta; |
628 | ktime_t mc_time; | ||
466 | 629 | ||
467 | if (number_readings == 0) | 630 | if (number_readings == 0) |
468 | return -EAGAIN; | 631 | return -EAGAIN; |
469 | 632 | ||
470 | /* Read the set of results and increment stats for any results that | 633 | /* Read the set of results and find the last good host-MC |
471 | * appera to be erroneous. | 634 | * synchronization result. The MC times when it finishes reading the |
635 | * host time so the corrected window time should be fairly constant | ||
636 | * for a given platform. | ||
472 | */ | 637 | */ |
473 | for (i = 0; i < number_readings; i++) { | 638 | for (i = 0; i < number_readings; i++) { |
639 | s32 window, corrected; | ||
640 | struct timespec wait; | ||
641 | |||
474 | efx_ptp_read_timeset( | 642 | efx_ptp_read_timeset( |
475 | MCDI_ARRAY_STRUCT_PTR(synch_buf, | 643 | MCDI_ARRAY_STRUCT_PTR(synch_buf, |
476 | PTP_OUT_SYNCHRONIZE_TIMESET, i), | 644 | PTP_OUT_SYNCHRONIZE_TIMESET, i), |
477 | &ptp->timeset[i]); | 645 | &ptp->timeset[i]); |
478 | } | ||
479 | 646 | ||
480 | /* Find the last good host-MC synchronization result. The MC times | 647 | wait = ktime_to_timespec( |
481 | * when it finishes reading the host time so the corrected window time | 648 | ptp->nic_to_kernel_time(0, ptp->timeset[i].wait, 0)); |
482 | * should be fairly constant for a given platform. | 649 | window = ptp->timeset[i].window; |
483 | */ | 650 | corrected = window - wait.tv_nsec; |
484 | total = 0; | 651 | |
485 | for (i = 0; i < number_readings; i++) | 652 | /* We expect the uncorrected synchronization window to be at |
486 | if (ptp->timeset[i].window > ptp->timeset[i].waitns) { | 653 | * least as large as the interval between host start and end |
487 | unsigned win; | 654 | * times. If it is smaller than this then this is mostly likely |
488 | 655 | * to be a consequence of the host's time being adjusted. | |
489 | win = ptp->timeset[i].window - ptp->timeset[i].waitns; | 656 | * Check that the corrected sync window is in a reasonable |
490 | if (win >= MIN_SYNCHRONISATION_NS && | 657 | * range. If it is out of range it is likely to be because an |
491 | win < MAX_SYNCHRONISATION_NS) { | 658 | * interrupt or other delay occurred between reading the system |
492 | total += ptp->timeset[i].window; | 659 | * time and writing it to MC memory. |
493 | ngood++; | 660 | */ |
494 | last_good = i; | 661 | if (window >= SYNCHRONISATION_GRANULARITY_NS && |
495 | } | 662 | corrected < MAX_SYNCHRONISATION_NS && |
663 | corrected >= ptp->min_synchronisation_ns) { | ||
664 | ngood++; | ||
665 | last_good = i; | ||
496 | } | 666 | } |
667 | } | ||
497 | 668 | ||
498 | if (ngood == 0) { | 669 | if (ngood == 0) { |
499 | netif_warn(efx, drv, efx->net_dev, | 670 | netif_warn(efx, drv, efx->net_dev, |
500 | "PTP no suitable synchronisations %dns\n", | 671 | "PTP no suitable synchronisations\n"); |
501 | ptp->base_sync_ns); | ||
502 | return -EAGAIN; | 672 | return -EAGAIN; |
503 | } | 673 | } |
504 | 674 | ||
505 | /* Average minimum this synchronisation */ | 675 | /* Convert the NIC time into kernel time. No correction is required- |
506 | ptp->last_sync_ns = DIV_ROUND_UP(total, ngood); | 676 | * this time is the output of a firmware process. |
507 | if (!ptp->base_sync_valid || (ptp->last_sync_ns < ptp->base_sync_ns)) { | 677 | */ |
508 | ptp->base_sync_valid = true; | 678 | mc_time = ptp->nic_to_kernel_time(ptp->timeset[last_good].major, |
509 | ptp->base_sync_ns = ptp->last_sync_ns; | 679 | ptp->timeset[last_good].minor, 0); |
510 | } | ||
511 | 680 | ||
512 | /* Calculate delay from actual PPS to last_time */ | 681 | /* Calculate delay from actual PPS to last_time */ |
513 | delta.tv_nsec = | 682 | delta = ktime_to_timespec(mc_time); |
514 | ptp->timeset[last_good].nanoseconds + | 683 | delta.tv_nsec += |
515 | last_time->ts_real.tv_nsec - | 684 | last_time->ts_real.tv_nsec - |
516 | (ptp->timeset[last_good].host_start & MC_NANOSECOND_MASK); | 685 | (ptp->timeset[last_good].host_start & MC_NANOSECOND_MASK); |
517 | 686 | ||
@@ -621,9 +790,10 @@ static int efx_ptp_xmit_skb(struct efx_nic *efx, struct sk_buff *skb) | |||
621 | goto fail; | 790 | goto fail; |
622 | 791 | ||
623 | memset(×tamps, 0, sizeof(timestamps)); | 792 | memset(×tamps, 0, sizeof(timestamps)); |
624 | timestamps.hwtstamp = ktime_set( | 793 | timestamps.hwtstamp = ptp_data->nic_to_kernel_time( |
625 | MCDI_DWORD(txtime, PTP_OUT_TRANSMIT_SECONDS), | 794 | MCDI_DWORD(txtime, PTP_OUT_TRANSMIT_MAJOR), |
626 | MCDI_DWORD(txtime, PTP_OUT_TRANSMIT_NANOSECONDS)); | 795 | MCDI_DWORD(txtime, PTP_OUT_TRANSMIT_MINOR), |
796 | ptp_data->ts_corrections.tx); | ||
627 | 797 | ||
628 | skb_tstamp_tx(skb, ×tamps); | 798 | skb_tstamp_tx(skb, ×tamps); |
629 | 799 | ||
@@ -641,6 +811,9 @@ static void efx_ptp_drop_time_expired_events(struct efx_nic *efx) | |||
641 | struct list_head *cursor; | 811 | struct list_head *cursor; |
642 | struct list_head *next; | 812 | struct list_head *next; |
643 | 813 | ||
814 | if (ptp->rx_ts_inline) | ||
815 | return; | ||
816 | |||
644 | /* Drop time-expired events */ | 817 | /* Drop time-expired events */ |
645 | spin_lock_bh(&ptp->evt_lock); | 818 | spin_lock_bh(&ptp->evt_lock); |
646 | if (!list_empty(&ptp->evt_list)) { | 819 | if (!list_empty(&ptp->evt_list)) { |
@@ -674,6 +847,8 @@ static enum ptp_packet_state efx_ptp_match_rx(struct efx_nic *efx, | |||
674 | struct efx_ptp_match *match; | 847 | struct efx_ptp_match *match; |
675 | enum ptp_packet_state rc = PTP_PACKET_STATE_UNMATCHED; | 848 | enum ptp_packet_state rc = PTP_PACKET_STATE_UNMATCHED; |
676 | 849 | ||
850 | WARN_ON_ONCE(ptp->rx_ts_inline); | ||
851 | |||
677 | spin_lock_bh(&ptp->evt_lock); | 852 | spin_lock_bh(&ptp->evt_lock); |
678 | evts_waiting = !list_empty(&ptp->evt_list); | 853 | evts_waiting = !list_empty(&ptp->evt_list); |
679 | spin_unlock_bh(&ptp->evt_lock); | 854 | spin_unlock_bh(&ptp->evt_lock); |
@@ -715,13 +890,10 @@ static enum ptp_packet_state efx_ptp_match_rx(struct efx_nic *efx, | |||
715 | /* Process any queued receive events and corresponding packets | 890 | /* Process any queued receive events and corresponding packets |
716 | * | 891 | * |
717 | * q is returned with all the packets that are ready for delivery. | 892 | * q is returned with all the packets that are ready for delivery. |
718 | * true is returned if at least one of those packets requires | ||
719 | * synchronisation. | ||
720 | */ | 893 | */ |
721 | static bool efx_ptp_process_events(struct efx_nic *efx, struct sk_buff_head *q) | 894 | static void efx_ptp_process_events(struct efx_nic *efx, struct sk_buff_head *q) |
722 | { | 895 | { |
723 | struct efx_ptp_data *ptp = efx->ptp_data; | 896 | struct efx_ptp_data *ptp = efx->ptp_data; |
724 | bool rc = false; | ||
725 | struct sk_buff *skb; | 897 | struct sk_buff *skb; |
726 | 898 | ||
727 | while ((skb = skb_dequeue(&ptp->rxq))) { | 899 | while ((skb = skb_dequeue(&ptp->rxq))) { |
@@ -732,7 +904,6 @@ static bool efx_ptp_process_events(struct efx_nic *efx, struct sk_buff_head *q) | |||
732 | __skb_queue_tail(q, skb); | 904 | __skb_queue_tail(q, skb); |
733 | } else if (efx_ptp_match_rx(efx, skb) == | 905 | } else if (efx_ptp_match_rx(efx, skb) == |
734 | PTP_PACKET_STATE_MATCHED) { | 906 | PTP_PACKET_STATE_MATCHED) { |
735 | rc = true; | ||
736 | __skb_queue_tail(q, skb); | 907 | __skb_queue_tail(q, skb); |
737 | } else if (time_after(jiffies, match->expiry)) { | 908 | } else if (time_after(jiffies, match->expiry)) { |
738 | match->state = PTP_PACKET_STATE_TIMED_OUT; | 909 | match->state = PTP_PACKET_STATE_TIMED_OUT; |
@@ -746,8 +917,6 @@ static bool efx_ptp_process_events(struct efx_nic *efx, struct sk_buff_head *q) | |||
746 | break; | 917 | break; |
747 | } | 918 | } |
748 | } | 919 | } |
749 | |||
750 | return rc; | ||
751 | } | 920 | } |
752 | 921 | ||
753 | /* Complete processing of a received packet */ | 922 | /* Complete processing of a received packet */ |
@@ -896,8 +1065,6 @@ static void efx_ptp_pps_worker(struct work_struct *work) | |||
896 | ptp_clock_event(ptp->phc_clock, &ptp_evt); | 1065 | ptp_clock_event(ptp->phc_clock, &ptp_evt); |
897 | } | 1066 | } |
898 | 1067 | ||
899 | /* Process any pending transmissions and timestamp any received packets. | ||
900 | */ | ||
901 | static void efx_ptp_worker(struct work_struct *work) | 1068 | static void efx_ptp_worker(struct work_struct *work) |
902 | { | 1069 | { |
903 | struct efx_ptp_data *ptp_data = | 1070 | struct efx_ptp_data *ptp_data = |
@@ -915,17 +1082,30 @@ static void efx_ptp_worker(struct work_struct *work) | |||
915 | efx_ptp_drop_time_expired_events(efx); | 1082 | efx_ptp_drop_time_expired_events(efx); |
916 | 1083 | ||
917 | __skb_queue_head_init(&tempq); | 1084 | __skb_queue_head_init(&tempq); |
918 | if (efx_ptp_process_events(efx, &tempq) || | 1085 | efx_ptp_process_events(efx, &tempq); |
919 | !skb_queue_empty(&ptp_data->txq)) { | ||
920 | 1086 | ||
921 | while ((skb = skb_dequeue(&ptp_data->txq))) | 1087 | while ((skb = skb_dequeue(&ptp_data->txq))) |
922 | efx_ptp_xmit_skb(efx, skb); | 1088 | efx_ptp_xmit_skb(efx, skb); |
923 | } | ||
924 | 1089 | ||
925 | while ((skb = __skb_dequeue(&tempq))) | 1090 | while ((skb = __skb_dequeue(&tempq))) |
926 | efx_ptp_process_rx(efx, skb); | 1091 | efx_ptp_process_rx(efx, skb); |
927 | } | 1092 | } |
928 | 1093 | ||
1094 | static const struct ptp_clock_info efx_phc_clock_info = { | ||
1095 | .owner = THIS_MODULE, | ||
1096 | .name = "sfc", | ||
1097 | .max_adj = MAX_PPB, | ||
1098 | .n_alarm = 0, | ||
1099 | .n_ext_ts = 0, | ||
1100 | .n_per_out = 0, | ||
1101 | .pps = 1, | ||
1102 | .adjfreq = efx_phc_adjfreq, | ||
1103 | .adjtime = efx_phc_adjtime, | ||
1104 | .gettime = efx_phc_gettime, | ||
1105 | .settime = efx_phc_settime, | ||
1106 | .enable = efx_phc_enable, | ||
1107 | }; | ||
1108 | |||
929 | /* Initialise PTP state. */ | 1109 | /* Initialise PTP state. */ |
930 | int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel) | 1110 | int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel) |
931 | { | 1111 | { |
@@ -940,6 +1120,7 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel) | |||
940 | 1120 | ||
941 | ptp->efx = efx; | 1121 | ptp->efx = efx; |
942 | ptp->channel = channel; | 1122 | ptp->channel = channel; |
1123 | ptp->rx_ts_inline = efx_nic_rev(efx) >= EFX_REV_HUNT_A0; | ||
943 | 1124 | ||
944 | rc = efx_nic_alloc_buffer(efx, &ptp->start, sizeof(int), GFP_KERNEL); | 1125 | rc = efx_nic_alloc_buffer(efx, &ptp->start, sizeof(int), GFP_KERNEL); |
945 | if (rc != 0) | 1126 | if (rc != 0) |
@@ -964,33 +1145,32 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel) | |||
964 | list_add(&ptp->rx_evts[pos].link, &ptp->evt_free_list); | 1145 | list_add(&ptp->rx_evts[pos].link, &ptp->evt_free_list); |
965 | ptp->evt_overflow = false; | 1146 | ptp->evt_overflow = false; |
966 | 1147 | ||
967 | ptp->phc_clock_info.owner = THIS_MODULE; | 1148 | /* Get the NIC PTP attributes and set up time conversions */ |
968 | snprintf(ptp->phc_clock_info.name, | 1149 | rc = efx_ptp_get_attributes(efx); |
969 | sizeof(ptp->phc_clock_info.name), | 1150 | if (rc < 0) |
970 | "%pm", efx->net_dev->perm_addr); | ||
971 | ptp->phc_clock_info.max_adj = MAX_PPB; | ||
972 | ptp->phc_clock_info.n_alarm = 0; | ||
973 | ptp->phc_clock_info.n_ext_ts = 0; | ||
974 | ptp->phc_clock_info.n_per_out = 0; | ||
975 | ptp->phc_clock_info.pps = 1; | ||
976 | ptp->phc_clock_info.adjfreq = efx_phc_adjfreq; | ||
977 | ptp->phc_clock_info.adjtime = efx_phc_adjtime; | ||
978 | ptp->phc_clock_info.gettime = efx_phc_gettime; | ||
979 | ptp->phc_clock_info.settime = efx_phc_settime; | ||
980 | ptp->phc_clock_info.enable = efx_phc_enable; | ||
981 | |||
982 | ptp->phc_clock = ptp_clock_register(&ptp->phc_clock_info, | ||
983 | &efx->pci_dev->dev); | ||
984 | if (IS_ERR(ptp->phc_clock)) { | ||
985 | rc = PTR_ERR(ptp->phc_clock); | ||
986 | goto fail3; | 1151 | goto fail3; |
987 | } | ||
988 | 1152 | ||
989 | INIT_WORK(&ptp->pps_work, efx_ptp_pps_worker); | 1153 | /* Get the timestamp corrections */ |
990 | ptp->pps_workwq = create_singlethread_workqueue("sfc_pps"); | 1154 | rc = efx_ptp_get_timestamp_corrections(efx); |
991 | if (!ptp->pps_workwq) { | 1155 | if (rc < 0) |
992 | rc = -ENOMEM; | 1156 | goto fail3; |
993 | goto fail4; | 1157 | |
1158 | if (efx->mcdi->fn_flags & | ||
1159 | (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_PRIMARY)) { | ||
1160 | ptp->phc_clock_info = efx_phc_clock_info; | ||
1161 | ptp->phc_clock = ptp_clock_register(&ptp->phc_clock_info, | ||
1162 | &efx->pci_dev->dev); | ||
1163 | if (IS_ERR(ptp->phc_clock)) { | ||
1164 | rc = PTR_ERR(ptp->phc_clock); | ||
1165 | goto fail3; | ||
1166 | } | ||
1167 | |||
1168 | INIT_WORK(&ptp->pps_work, efx_ptp_pps_worker); | ||
1169 | ptp->pps_workwq = create_singlethread_workqueue("sfc_pps"); | ||
1170 | if (!ptp->pps_workwq) { | ||
1171 | rc = -ENOMEM; | ||
1172 | goto fail4; | ||
1173 | } | ||
994 | } | 1174 | } |
995 | ptp->nic_ts_enabled = false; | 1175 | ptp->nic_ts_enabled = false; |
996 | 1176 | ||
@@ -1039,10 +1219,12 @@ void efx_ptp_remove(struct efx_nic *efx) | |||
1039 | skb_queue_purge(&efx->ptp_data->rxq); | 1219 | skb_queue_purge(&efx->ptp_data->rxq); |
1040 | skb_queue_purge(&efx->ptp_data->txq); | 1220 | skb_queue_purge(&efx->ptp_data->txq); |
1041 | 1221 | ||
1042 | ptp_clock_unregister(efx->ptp_data->phc_clock); | 1222 | if (efx->ptp_data->phc_clock) { |
1223 | destroy_workqueue(efx->ptp_data->pps_workwq); | ||
1224 | ptp_clock_unregister(efx->ptp_data->phc_clock); | ||
1225 | } | ||
1043 | 1226 | ||
1044 | destroy_workqueue(efx->ptp_data->workwq); | 1227 | destroy_workqueue(efx->ptp_data->workwq); |
1045 | destroy_workqueue(efx->ptp_data->pps_workwq); | ||
1046 | 1228 | ||
1047 | efx_nic_free_buffer(efx, &efx->ptp_data->start); | 1229 | efx_nic_free_buffer(efx, &efx->ptp_data->start); |
1048 | kfree(efx->ptp_data); | 1230 | kfree(efx->ptp_data); |
@@ -1133,14 +1315,8 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb) | |||
1133 | 1315 | ||
1134 | /* Does this packet require timestamping? */ | 1316 | /* Does this packet require timestamping? */ |
1135 | if (ntohs(*(__be16 *)&skb->data[PTP_DPORT_OFFSET]) == PTP_EVENT_PORT) { | 1317 | if (ntohs(*(__be16 *)&skb->data[PTP_DPORT_OFFSET]) == PTP_EVENT_PORT) { |
1136 | struct skb_shared_hwtstamps *timestamps; | ||
1137 | |||
1138 | match->state = PTP_PACKET_STATE_UNMATCHED; | 1318 | match->state = PTP_PACKET_STATE_UNMATCHED; |
1139 | 1319 | ||
1140 | /* Clear all timestamps held: filled in later */ | ||
1141 | timestamps = skb_hwtstamps(skb); | ||
1142 | memset(timestamps, 0, sizeof(*timestamps)); | ||
1143 | |||
1144 | /* We expect the sequence number to be in the same position in | 1320 | /* We expect the sequence number to be in the same position in |
1145 | * the packet for PTP V1 and V2 | 1321 | * the packet for PTP V1 and V2 |
1146 | */ | 1322 | */ |
@@ -1185,8 +1361,13 @@ int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb) | |||
1185 | return NETDEV_TX_OK; | 1361 | return NETDEV_TX_OK; |
1186 | } | 1362 | } |
1187 | 1363 | ||
1188 | static int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted, | 1364 | int efx_ptp_get_mode(struct efx_nic *efx) |
1189 | unsigned int new_mode) | 1365 | { |
1366 | return efx->ptp_data->mode; | ||
1367 | } | ||
1368 | |||
1369 | int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted, | ||
1370 | unsigned int new_mode) | ||
1190 | { | 1371 | { |
1191 | if ((enable_wanted != efx->ptp_data->enabled) || | 1372 | if ((enable_wanted != efx->ptp_data->enabled) || |
1192 | (enable_wanted && (efx->ptp_data->mode != new_mode))) { | 1373 | (enable_wanted && (efx->ptp_data->mode != new_mode))) { |
@@ -1230,8 +1411,6 @@ static int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted, | |||
1230 | 1411 | ||
1231 | static int efx_ptp_ts_init(struct efx_nic *efx, struct hwtstamp_config *init) | 1412 | static int efx_ptp_ts_init(struct efx_nic *efx, struct hwtstamp_config *init) |
1232 | { | 1413 | { |
1233 | bool enable_wanted = false; | ||
1234 | unsigned int new_mode; | ||
1235 | int rc; | 1414 | int rc; |
1236 | 1415 | ||
1237 | if (init->flags) | 1416 | if (init->flags) |
@@ -1241,63 +1420,20 @@ static int efx_ptp_ts_init(struct efx_nic *efx, struct hwtstamp_config *init) | |||
1241 | (init->tx_type != HWTSTAMP_TX_ON)) | 1420 | (init->tx_type != HWTSTAMP_TX_ON)) |
1242 | return -ERANGE; | 1421 | return -ERANGE; |
1243 | 1422 | ||
1244 | new_mode = efx->ptp_data->mode; | 1423 | rc = efx->type->ptp_set_ts_config(efx, init); |
1245 | /* Determine whether any PTP HW operations are required */ | 1424 | if (rc) |
1246 | switch (init->rx_filter) { | ||
1247 | case HWTSTAMP_FILTER_NONE: | ||
1248 | break; | ||
1249 | case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: | ||
1250 | case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: | ||
1251 | case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: | ||
1252 | init->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; | ||
1253 | new_mode = MC_CMD_PTP_MODE_V1; | ||
1254 | enable_wanted = true; | ||
1255 | break; | ||
1256 | case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: | ||
1257 | case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: | ||
1258 | case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: | ||
1259 | /* Although these three are accepted only IPV4 packets will be | ||
1260 | * timestamped | ||
1261 | */ | ||
1262 | init->rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; | ||
1263 | new_mode = MC_CMD_PTP_MODE_V2_ENHANCED; | ||
1264 | enable_wanted = true; | ||
1265 | break; | ||
1266 | case HWTSTAMP_FILTER_PTP_V2_EVENT: | ||
1267 | case HWTSTAMP_FILTER_PTP_V2_SYNC: | ||
1268 | case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: | ||
1269 | case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: | ||
1270 | case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: | ||
1271 | case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: | ||
1272 | /* Non-IP + IPv6 timestamping not supported */ | ||
1273 | return -ERANGE; | ||
1274 | break; | ||
1275 | default: | ||
1276 | return -ERANGE; | ||
1277 | } | ||
1278 | |||
1279 | if (init->tx_type != HWTSTAMP_TX_OFF) | ||
1280 | enable_wanted = true; | ||
1281 | |||
1282 | /* Old versions of the firmware do not support the improved | ||
1283 | * UUID filtering option (SF bug 33070). If the firmware does | ||
1284 | * not accept the enhanced mode, fall back to the standard PTP | ||
1285 | * v2 UUID filtering. | ||
1286 | */ | ||
1287 | rc = efx_ptp_change_mode(efx, enable_wanted, new_mode); | ||
1288 | if ((rc != 0) && (new_mode == MC_CMD_PTP_MODE_V2_ENHANCED)) | ||
1289 | rc = efx_ptp_change_mode(efx, enable_wanted, MC_CMD_PTP_MODE_V2); | ||
1290 | if (rc != 0) | ||
1291 | return rc; | 1425 | return rc; |
1292 | 1426 | ||
1293 | efx->ptp_data->config = *init; | 1427 | efx->ptp_data->config = *init; |
1294 | |||
1295 | return 0; | 1428 | return 0; |
1296 | } | 1429 | } |
1297 | 1430 | ||
1298 | void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info) | 1431 | void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info) |
1299 | { | 1432 | { |
1300 | struct efx_ptp_data *ptp = efx->ptp_data; | 1433 | struct efx_ptp_data *ptp = efx->ptp_data; |
1434 | struct efx_nic *primary = efx->primary; | ||
1435 | |||
1436 | ASSERT_RTNL(); | ||
1301 | 1437 | ||
1302 | if (!ptp) | 1438 | if (!ptp) |
1303 | return; | 1439 | return; |
@@ -1305,15 +1441,11 @@ void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info) | |||
1305 | ts_info->so_timestamping |= (SOF_TIMESTAMPING_TX_HARDWARE | | 1441 | ts_info->so_timestamping |= (SOF_TIMESTAMPING_TX_HARDWARE | |
1306 | SOF_TIMESTAMPING_RX_HARDWARE | | 1442 | SOF_TIMESTAMPING_RX_HARDWARE | |
1307 | SOF_TIMESTAMPING_RAW_HARDWARE); | 1443 | SOF_TIMESTAMPING_RAW_HARDWARE); |
1308 | ts_info->phc_index = ptp_clock_index(ptp->phc_clock); | 1444 | if (primary && primary->ptp_data && primary->ptp_data->phc_clock) |
1445 | ts_info->phc_index = | ||
1446 | ptp_clock_index(primary->ptp_data->phc_clock); | ||
1309 | ts_info->tx_types = 1 << HWTSTAMP_TX_OFF | 1 << HWTSTAMP_TX_ON; | 1447 | ts_info->tx_types = 1 << HWTSTAMP_TX_OFF | 1 << HWTSTAMP_TX_ON; |
1310 | ts_info->rx_filters = (1 << HWTSTAMP_FILTER_NONE | | 1448 | ts_info->rx_filters = ptp->efx->type->hwtstamp_filters; |
1311 | 1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT | | ||
1312 | 1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC | | ||
1313 | 1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ | | ||
1314 | 1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT | | ||
1315 | 1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC | | ||
1316 | 1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ); | ||
1317 | } | 1449 | } |
1318 | 1450 | ||
1319 | int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr) | 1451 | int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr) |
@@ -1364,6 +1496,9 @@ static void ptp_event_rx(struct efx_nic *efx, struct efx_ptp_data *ptp) | |||
1364 | { | 1496 | { |
1365 | struct efx_ptp_event_rx *evt = NULL; | 1497 | struct efx_ptp_event_rx *evt = NULL; |
1366 | 1498 | ||
1499 | if (WARN_ON_ONCE(ptp->rx_ts_inline)) | ||
1500 | return; | ||
1501 | |||
1367 | if (ptp->evt_frag_idx != 3) { | 1502 | if (ptp->evt_frag_idx != 3) { |
1368 | ptp_event_failure(efx, 3); | 1503 | ptp_event_failure(efx, 3); |
1369 | return; | 1504 | return; |
@@ -1382,9 +1517,10 @@ static void ptp_event_rx(struct efx_nic *efx, struct efx_ptp_data *ptp) | |||
1382 | MCDI_EVENT_SRC) << 8) | | 1517 | MCDI_EVENT_SRC) << 8) | |
1383 | (EFX_QWORD_FIELD(ptp->evt_frags[0], | 1518 | (EFX_QWORD_FIELD(ptp->evt_frags[0], |
1384 | MCDI_EVENT_SRC) << 16)); | 1519 | MCDI_EVENT_SRC) << 16)); |
1385 | evt->hwtimestamp = ktime_set( | 1520 | evt->hwtimestamp = efx->ptp_data->nic_to_kernel_time( |
1386 | EFX_QWORD_FIELD(ptp->evt_frags[0], MCDI_EVENT_DATA), | 1521 | EFX_QWORD_FIELD(ptp->evt_frags[0], MCDI_EVENT_DATA), |
1387 | EFX_QWORD_FIELD(ptp->evt_frags[1], MCDI_EVENT_DATA)); | 1522 | EFX_QWORD_FIELD(ptp->evt_frags[1], MCDI_EVENT_DATA), |
1523 | ptp->ts_corrections.rx); | ||
1388 | evt->expiry = jiffies + msecs_to_jiffies(PKT_EVENT_LIFETIME_MS); | 1524 | evt->expiry = jiffies + msecs_to_jiffies(PKT_EVENT_LIFETIME_MS); |
1389 | list_add_tail(&evt->link, &ptp->evt_list); | 1525 | list_add_tail(&evt->link, &ptp->evt_list); |
1390 | 1526 | ||
@@ -1459,6 +1595,93 @@ void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev) | |||
1459 | } | 1595 | } |
1460 | } | 1596 | } |
1461 | 1597 | ||
1598 | void efx_time_sync_event(struct efx_channel *channel, efx_qword_t *ev) | ||
1599 | { | ||
1600 | channel->sync_timestamp_major = MCDI_EVENT_FIELD(*ev, PTP_TIME_MAJOR); | ||
1601 | channel->sync_timestamp_minor = | ||
1602 | MCDI_EVENT_FIELD(*ev, PTP_TIME_MINOR_26_19) << 19; | ||
1603 | /* if sync events have been disabled then we want to silently ignore | ||
1604 | * this event, so throw away result. | ||
1605 | */ | ||
1606 | (void) cmpxchg(&channel->sync_events_state, SYNC_EVENTS_REQUESTED, | ||
1607 | SYNC_EVENTS_VALID); | ||
1608 | } | ||
1609 | |||
1610 | /* make some assumptions about the time representation rather than abstract it, | ||
1611 | * since we currently only support one type of inline timestamping and only on | ||
1612 | * EF10. | ||
1613 | */ | ||
1614 | #define MINOR_TICKS_PER_SECOND 0x8000000 | ||
1615 | /* Fuzz factor for sync events to be out of order with RX events */ | ||
1616 | #define FUZZ (MINOR_TICKS_PER_SECOND / 10) | ||
1617 | #define EXPECTED_SYNC_EVENTS_PER_SECOND 4 | ||
1618 | |||
1619 | static inline u32 efx_rx_buf_timestamp_minor(struct efx_nic *efx, const u8 *eh) | ||
1620 | { | ||
1621 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) | ||
1622 | return __le32_to_cpup((const __le32 *)(eh + efx->rx_packet_ts_offset)); | ||
1623 | #else | ||
1624 | const u8 *data = eh + efx->rx_packet_ts_offset; | ||
1625 | return (u32)data[0] | | ||
1626 | (u32)data[1] << 8 | | ||
1627 | (u32)data[2] << 16 | | ||
1628 | (u32)data[3] << 24; | ||
1629 | #endif | ||
1630 | } | ||
1631 | |||
1632 | void __efx_rx_skb_attach_timestamp(struct efx_channel *channel, | ||
1633 | struct sk_buff *skb) | ||
1634 | { | ||
1635 | struct efx_nic *efx = channel->efx; | ||
1636 | u32 pkt_timestamp_major, pkt_timestamp_minor; | ||
1637 | u32 diff, carry; | ||
1638 | struct skb_shared_hwtstamps *timestamps; | ||
1639 | |||
1640 | pkt_timestamp_minor = (efx_rx_buf_timestamp_minor(efx, | ||
1641 | skb_mac_header(skb)) + | ||
1642 | (u32) efx->ptp_data->ts_corrections.rx) & | ||
1643 | (MINOR_TICKS_PER_SECOND - 1); | ||
1644 | |||
1645 | /* get the difference between the packet and sync timestamps, | ||
1646 | * modulo one second | ||
1647 | */ | ||
1648 | diff = (pkt_timestamp_minor - channel->sync_timestamp_minor) & | ||
1649 | (MINOR_TICKS_PER_SECOND - 1); | ||
1650 | /* do we roll over a second boundary and need to carry the one? */ | ||
1651 | carry = channel->sync_timestamp_minor + diff > MINOR_TICKS_PER_SECOND ? | ||
1652 | 1 : 0; | ||
1653 | |||
1654 | if (diff <= MINOR_TICKS_PER_SECOND / EXPECTED_SYNC_EVENTS_PER_SECOND + | ||
1655 | FUZZ) { | ||
1656 | /* packet is ahead of the sync event by a quarter of a second or | ||
1657 | * less (allowing for fuzz) | ||
1658 | */ | ||
1659 | pkt_timestamp_major = channel->sync_timestamp_major + carry; | ||
1660 | } else if (diff >= MINOR_TICKS_PER_SECOND - FUZZ) { | ||
1661 | /* packet is behind the sync event but within the fuzz factor. | ||
1662 | * This means the RX packet and sync event crossed as they were | ||
1663 | * placed on the event queue, which can sometimes happen. | ||
1664 | */ | ||
1665 | pkt_timestamp_major = channel->sync_timestamp_major - 1 + carry; | ||
1666 | } else { | ||
1667 | /* it's outside tolerance in both directions. this might be | ||
1668 | * indicative of us missing sync events for some reason, so | ||
1669 | * we'll call it an error rather than risk giving a bogus | ||
1670 | * timestamp. | ||
1671 | */ | ||
1672 | netif_vdbg(efx, drv, efx->net_dev, | ||
1673 | "packet timestamp %x too far from sync event %x:%x\n", | ||
1674 | pkt_timestamp_minor, channel->sync_timestamp_major, | ||
1675 | channel->sync_timestamp_minor); | ||
1676 | return; | ||
1677 | } | ||
1678 | |||
1679 | /* attach the timestamps to the skb */ | ||
1680 | timestamps = skb_hwtstamps(skb); | ||
1681 | timestamps->hwtstamp = | ||
1682 | efx_ptp_s27_to_ktime(pkt_timestamp_major, pkt_timestamp_minor); | ||
1683 | } | ||
1684 | |||
1462 | static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) | 1685 | static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) |
1463 | { | 1686 | { |
1464 | struct efx_ptp_data *ptp_data = container_of(ptp, | 1687 | struct efx_ptp_data *ptp_data = container_of(ptp, |
@@ -1494,18 +1717,20 @@ static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) | |||
1494 | 1717 | ||
1495 | static int efx_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) | 1718 | static int efx_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) |
1496 | { | 1719 | { |
1720 | u32 nic_major, nic_minor; | ||
1497 | struct efx_ptp_data *ptp_data = container_of(ptp, | 1721 | struct efx_ptp_data *ptp_data = container_of(ptp, |
1498 | struct efx_ptp_data, | 1722 | struct efx_ptp_data, |
1499 | phc_clock_info); | 1723 | phc_clock_info); |
1500 | struct efx_nic *efx = ptp_data->efx; | 1724 | struct efx_nic *efx = ptp_data->efx; |
1501 | struct timespec delta_ts = ns_to_timespec(delta); | ||
1502 | MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_ADJUST_LEN); | 1725 | MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_ADJUST_LEN); |
1503 | 1726 | ||
1727 | efx->ptp_data->ns_to_nic_time(delta, &nic_major, &nic_minor); | ||
1728 | |||
1504 | MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_ADJUST); | 1729 | MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_ADJUST); |
1505 | MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); | 1730 | MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); |
1506 | MCDI_SET_QWORD(inbuf, PTP_IN_ADJUST_FREQ, ptp_data->current_adjfreq); | 1731 | MCDI_SET_QWORD(inbuf, PTP_IN_ADJUST_FREQ, ptp_data->current_adjfreq); |
1507 | MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_SECONDS, (u32)delta_ts.tv_sec); | 1732 | MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_MAJOR, nic_major); |
1508 | MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_NANOSECONDS, (u32)delta_ts.tv_nsec); | 1733 | MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_MINOR, nic_minor); |
1509 | return efx_mcdi_rpc(efx, MC_CMD_PTP, inbuf, sizeof(inbuf), | 1734 | return efx_mcdi_rpc(efx, MC_CMD_PTP, inbuf, sizeof(inbuf), |
1510 | NULL, 0, NULL); | 1735 | NULL, 0, NULL); |
1511 | } | 1736 | } |
@@ -1519,6 +1744,7 @@ static int efx_phc_gettime(struct ptp_clock_info *ptp, struct timespec *ts) | |||
1519 | MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_READ_NIC_TIME_LEN); | 1744 | MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_READ_NIC_TIME_LEN); |
1520 | MCDI_DECLARE_BUF(outbuf, MC_CMD_PTP_OUT_READ_NIC_TIME_LEN); | 1745 | MCDI_DECLARE_BUF(outbuf, MC_CMD_PTP_OUT_READ_NIC_TIME_LEN); |
1521 | int rc; | 1746 | int rc; |
1747 | ktime_t kt; | ||
1522 | 1748 | ||
1523 | MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_READ_NIC_TIME); | 1749 | MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_READ_NIC_TIME); |
1524 | MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); | 1750 | MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); |
@@ -1528,8 +1754,10 @@ static int efx_phc_gettime(struct ptp_clock_info *ptp, struct timespec *ts) | |||
1528 | if (rc != 0) | 1754 | if (rc != 0) |
1529 | return rc; | 1755 | return rc; |
1530 | 1756 | ||
1531 | ts->tv_sec = MCDI_DWORD(outbuf, PTP_OUT_READ_NIC_TIME_SECONDS); | 1757 | kt = ptp_data->nic_to_kernel_time( |
1532 | ts->tv_nsec = MCDI_DWORD(outbuf, PTP_OUT_READ_NIC_TIME_NANOSECONDS); | 1758 | MCDI_DWORD(outbuf, PTP_OUT_READ_NIC_TIME_MAJOR), |
1759 | MCDI_DWORD(outbuf, PTP_OUT_READ_NIC_TIME_MINOR), 0); | ||
1760 | *ts = ktime_to_timespec(kt); | ||
1533 | return 0; | 1761 | return 0; |
1534 | } | 1762 | } |
1535 | 1763 | ||
@@ -1595,9 +1823,15 @@ void efx_ptp_start_datapath(struct efx_nic *efx) | |||
1595 | { | 1823 | { |
1596 | if (efx_ptp_restart(efx)) | 1824 | if (efx_ptp_restart(efx)) |
1597 | netif_err(efx, drv, efx->net_dev, "Failed to restart PTP.\n"); | 1825 | netif_err(efx, drv, efx->net_dev, "Failed to restart PTP.\n"); |
1826 | /* re-enable timestamping if it was previously enabled */ | ||
1827 | if (efx->type->ptp_set_ts_sync_events) | ||
1828 | efx->type->ptp_set_ts_sync_events(efx, true, true); | ||
1598 | } | 1829 | } |
1599 | 1830 | ||
1600 | void efx_ptp_stop_datapath(struct efx_nic *efx) | 1831 | void efx_ptp_stop_datapath(struct efx_nic *efx) |
1601 | { | 1832 | { |
1833 | /* temporarily disable timestamping */ | ||
1834 | if (efx->type->ptp_set_ts_sync_events) | ||
1835 | efx->type->ptp_set_ts_sync_events(efx, false, true); | ||
1602 | efx_ptp_stop(efx); | 1836 | efx_ptp_stop(efx); |
1603 | } | 1837 | } |
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index 8671bc199a9d..1fde9b8ac456 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c | |||
@@ -476,14 +476,18 @@ static struct sk_buff *efx_rx_mk_skb(struct efx_channel *channel, | |||
476 | struct sk_buff *skb; | 476 | struct sk_buff *skb; |
477 | 477 | ||
478 | /* Allocate an SKB to store the headers */ | 478 | /* Allocate an SKB to store the headers */ |
479 | skb = netdev_alloc_skb(efx->net_dev, hdr_len + EFX_PAGE_SKB_ALIGN); | 479 | skb = netdev_alloc_skb(efx->net_dev, |
480 | efx->rx_ip_align + efx->rx_prefix_size + | ||
481 | hdr_len); | ||
480 | if (unlikely(skb == NULL)) | 482 | if (unlikely(skb == NULL)) |
481 | return NULL; | 483 | return NULL; |
482 | 484 | ||
483 | EFX_BUG_ON_PARANOID(rx_buf->len < hdr_len); | 485 | EFX_BUG_ON_PARANOID(rx_buf->len < hdr_len); |
484 | 486 | ||
485 | skb_reserve(skb, EFX_PAGE_SKB_ALIGN); | 487 | memcpy(skb->data + efx->rx_ip_align, eh - efx->rx_prefix_size, |
486 | memcpy(__skb_put(skb, hdr_len), eh, hdr_len); | 488 | efx->rx_prefix_size + hdr_len); |
489 | skb_reserve(skb, efx->rx_ip_align + efx->rx_prefix_size); | ||
490 | __skb_put(skb, hdr_len); | ||
487 | 491 | ||
488 | /* Append the remaining page(s) onto the frag list */ | 492 | /* Append the remaining page(s) onto the frag list */ |
489 | if (rx_buf->len > hdr_len) { | 493 | if (rx_buf->len > hdr_len) { |
@@ -620,6 +624,8 @@ static void efx_rx_deliver(struct efx_channel *channel, u8 *eh, | |||
620 | if (likely(rx_buf->flags & EFX_RX_PKT_CSUMMED)) | 624 | if (likely(rx_buf->flags & EFX_RX_PKT_CSUMMED)) |
621 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 625 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
622 | 626 | ||
627 | efx_rx_skb_attach_timestamp(channel, skb); | ||
628 | |||
623 | if (channel->type->receive_skb) | 629 | if (channel->type->receive_skb) |
624 | if (channel->type->receive_skb(channel, skb)) | 630 | if (channel->type->receive_skb(channel, skb)) |
625 | return; | 631 | return; |
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index 53b4ce67be0e..f65db356fe09 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c | |||
@@ -118,6 +118,54 @@ out: | |||
118 | 118 | ||
119 | /************************************************************************** | 119 | /************************************************************************** |
120 | * | 120 | * |
121 | * PTP | ||
122 | * | ||
123 | ************************************************************************** | ||
124 | */ | ||
125 | |||
126 | static void siena_ptp_write_host_time(struct efx_nic *efx, u32 host_time) | ||
127 | { | ||
128 | _efx_writed(efx, cpu_to_le32(host_time), | ||
129 | FR_CZ_MC_TREG_SMEM + MC_SMEM_P0_PTP_TIME_OFST); | ||
130 | } | ||
131 | |||
132 | static int siena_ptp_set_ts_config(struct efx_nic *efx, | ||
133 | struct hwtstamp_config *init) | ||
134 | { | ||
135 | int rc; | ||
136 | |||
137 | switch (init->rx_filter) { | ||
138 | case HWTSTAMP_FILTER_NONE: | ||
139 | /* if TX timestamping is still requested then leave PTP on */ | ||
140 | return efx_ptp_change_mode(efx, | ||
141 | init->tx_type != HWTSTAMP_TX_OFF, | ||
142 | efx_ptp_get_mode(efx)); | ||
143 | case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: | ||
144 | case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: | ||
145 | case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: | ||
146 | init->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; | ||
147 | return efx_ptp_change_mode(efx, true, MC_CMD_PTP_MODE_V1); | ||
148 | case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: | ||
149 | case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: | ||
150 | case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: | ||
151 | init->rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; | ||
152 | rc = efx_ptp_change_mode(efx, true, | ||
153 | MC_CMD_PTP_MODE_V2_ENHANCED); | ||
154 | /* bug 33070 - old versions of the firmware do not support the | ||
155 | * improved UUID filtering option. Similarly old versions of the | ||
156 | * application do not expect it to be enabled. If the firmware | ||
157 | * does not accept the enhanced mode, fall back to the standard | ||
158 | * PTP v2 UUID filtering. */ | ||
159 | if (rc != 0) | ||
160 | rc = efx_ptp_change_mode(efx, true, MC_CMD_PTP_MODE_V2); | ||
161 | return rc; | ||
162 | default: | ||
163 | return -ERANGE; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | /************************************************************************** | ||
168 | * | ||
121 | * Device reset | 169 | * Device reset |
122 | * | 170 | * |
123 | ************************************************************************** | 171 | ************************************************************************** |
@@ -839,19 +887,6 @@ fail: | |||
839 | 887 | ||
840 | /************************************************************************** | 888 | /************************************************************************** |
841 | * | 889 | * |
842 | * PTP | ||
843 | * | ||
844 | ************************************************************************** | ||
845 | */ | ||
846 | |||
847 | static void siena_ptp_write_host_time(struct efx_nic *efx, u32 host_time) | ||
848 | { | ||
849 | _efx_writed(efx, cpu_to_le32(host_time), | ||
850 | FR_CZ_MC_TREG_SMEM + MC_SMEM_P0_PTP_TIME_OFST); | ||
851 | } | ||
852 | |||
853 | /************************************************************************** | ||
854 | * | ||
855 | * Revision-dependent attributes used by efx.c and nic.c | 890 | * Revision-dependent attributes used by efx.c and nic.c |
856 | * | 891 | * |
857 | ************************************************************************** | 892 | ************************************************************************** |
@@ -942,6 +977,7 @@ const struct efx_nic_type siena_a0_nic_type = { | |||
942 | .mtd_sync = efx_mcdi_mtd_sync, | 977 | .mtd_sync = efx_mcdi_mtd_sync, |
943 | #endif | 978 | #endif |
944 | .ptp_write_host_time = siena_ptp_write_host_time, | 979 | .ptp_write_host_time = siena_ptp_write_host_time, |
980 | .ptp_set_ts_config = siena_ptp_set_ts_config, | ||
945 | 981 | ||
946 | .revision = EFX_REV_SIENA_A0, | 982 | .revision = EFX_REV_SIENA_A0, |
947 | .txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL, | 983 | .txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL, |
@@ -960,4 +996,11 @@ const struct efx_nic_type siena_a0_nic_type = { | |||
960 | NETIF_F_RXHASH | NETIF_F_NTUPLE), | 996 | NETIF_F_RXHASH | NETIF_F_NTUPLE), |
961 | .mcdi_max_ver = 1, | 997 | .mcdi_max_ver = 1, |
962 | .max_rx_ip_filters = FR_BZ_RX_FILTER_TBL0_ROWS, | 998 | .max_rx_ip_filters = FR_BZ_RX_FILTER_TBL0_ROWS, |
999 | .hwtstamp_filters = (1 << HWTSTAMP_FILTER_NONE | | ||
1000 | 1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT | | ||
1001 | 1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC | | ||
1002 | 1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ | | ||
1003 | 1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT | | ||
1004 | 1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC | | ||
1005 | 1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ), | ||
963 | }; | 1006 | }; |