aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Cooper <jcooper@solarflare.com>2013-11-18 07:54:41 -0500
committerBen Hutchings <bhutchings@solarflare.com>2013-12-12 17:07:13 -0500
commitbd9a265db26cdbfe74a303111381d90e66f56877 (patch)
tree74c54327d245e1c8b2367f9c112264cb055ae2d0
parent2ccd0b192534b1dc6af45ffb81faa44b7ae416bf (diff)
sfc: Add RX packet timestamping for EF10
The EF10 firmware can optionally insert RX timestamps in the packet prefix. These only include the clock minor value. We must also enable periodic time sync events on each event queue which provide the high bits of the clock value. [bwh: Combined and rebased several changes. Added the above description and some sanity checks for inline vs separate timestamps. Changed efx_rx_skb_attach_timestamp() to read the packet prefix from the skb head area.] Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
-rw-r--r--drivers/net/ethernet/sfc/ef10.c123
-rw-r--r--drivers/net/ethernet/sfc/efx.c2
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c3
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h22
-rw-r--r--drivers/net/ethernet/sfc/nic.h9
-rw-r--r--drivers/net/ethernet/sfc/ptp.c131
-rw-r--r--drivers/net/ethernet/sfc/rx.c2
7 files changed, 277 insertions, 15 deletions
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index ca922b958a2e..a3d891764030 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1469,8 +1469,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)); 1469 MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_LABEL, efx_rx_queue_index(rx_queue));
1470 MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_INSTANCE, 1470 MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_INSTANCE,
1471 efx_rx_queue_index(rx_queue)); 1471 efx_rx_queue_index(rx_queue));
1472 MCDI_POPULATE_DWORD_1(inbuf, INIT_RXQ_IN_FLAGS, 1472 MCDI_POPULATE_DWORD_2(inbuf, INIT_RXQ_IN_FLAGS,
1473 INIT_RXQ_IN_FLAG_PREFIX, 1); 1473 INIT_RXQ_IN_FLAG_PREFIX, 1,
1474 INIT_RXQ_IN_FLAG_TIMESTAMP, 1);
1474 MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_OWNER_ID, 0); 1475 MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_OWNER_ID, 0);
1475 MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_PORT_ID, EVB_PORT_ID_ASSIGNED); 1476 MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_PORT_ID, EVB_PORT_ID_ASSIGNED);
1476 1477
@@ -3406,6 +3407,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); 3407 _efx_writed(efx, cpu_to_le32(host_time), ER_DZ_MC_DB_LWRD);
3407} 3408}
3408 3409
3410static int efx_ef10_rx_enable_timestamping(struct efx_channel *channel,
3411 bool temp)
3412{
3413 MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_TIME_EVENT_SUBSCRIBE_LEN);
3414 int rc;
3415
3416 if (channel->sync_events_state == SYNC_EVENTS_REQUESTED ||
3417 channel->sync_events_state == SYNC_EVENTS_VALID ||
3418 (temp && channel->sync_events_state == SYNC_EVENTS_DISABLED))
3419 return 0;
3420 channel->sync_events_state = SYNC_EVENTS_REQUESTED;
3421
3422 MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_TIME_EVENT_SUBSCRIBE);
3423 MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0);
3424 MCDI_SET_DWORD(inbuf, PTP_IN_TIME_EVENT_SUBSCRIBE_QUEUE,
3425 channel->channel);
3426
3427 rc = efx_mcdi_rpc(channel->efx, MC_CMD_PTP,
3428 inbuf, sizeof(inbuf), NULL, 0, NULL);
3429
3430 if (rc != 0)
3431 channel->sync_events_state = temp ? SYNC_EVENTS_QUIESCENT :
3432 SYNC_EVENTS_DISABLED;
3433
3434 return rc;
3435}
3436
3437static int efx_ef10_rx_disable_timestamping(struct efx_channel *channel,
3438 bool temp)
3439{
3440 MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_TIME_EVENT_UNSUBSCRIBE_LEN);
3441 int rc;
3442
3443 if (channel->sync_events_state == SYNC_EVENTS_DISABLED ||
3444 (temp && channel->sync_events_state == SYNC_EVENTS_QUIESCENT))
3445 return 0;
3446 if (channel->sync_events_state == SYNC_EVENTS_QUIESCENT) {
3447 channel->sync_events_state = SYNC_EVENTS_DISABLED;
3448 return 0;
3449 }
3450 channel->sync_events_state = temp ? SYNC_EVENTS_QUIESCENT :
3451 SYNC_EVENTS_DISABLED;
3452
3453 MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_TIME_EVENT_UNSUBSCRIBE);
3454 MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0);
3455 MCDI_SET_DWORD(inbuf, PTP_IN_TIME_EVENT_UNSUBSCRIBE_CONTROL,
3456 MC_CMD_PTP_IN_TIME_EVENT_UNSUBSCRIBE_SINGLE);
3457 MCDI_SET_DWORD(inbuf, PTP_IN_TIME_EVENT_UNSUBSCRIBE_QUEUE,
3458 channel->channel);
3459
3460 rc = efx_mcdi_rpc(channel->efx, MC_CMD_PTP,
3461 inbuf, sizeof(inbuf), NULL, 0, NULL);
3462
3463 return rc;
3464}
3465
3466static int efx_ef10_ptp_set_ts_sync_events(struct efx_nic *efx, bool en,
3467 bool temp)
3468{
3469 int (*set)(struct efx_channel *channel, bool temp);
3470 struct efx_channel *channel;
3471
3472 set = en ?
3473 efx_ef10_rx_enable_timestamping :
3474 efx_ef10_rx_disable_timestamping;
3475
3476 efx_for_each_channel(channel, efx) {
3477 int rc = set(channel, temp);
3478 if (en && rc != 0) {
3479 efx_ef10_ptp_set_ts_sync_events(efx, false, temp);
3480 return rc;
3481 }
3482 }
3483
3484 return 0;
3485}
3486
3487static int efx_ef10_ptp_set_ts_config(struct efx_nic *efx,
3488 struct hwtstamp_config *init)
3489{
3490 int rc;
3491
3492 switch (init->rx_filter) {
3493 case HWTSTAMP_FILTER_NONE:
3494 efx_ef10_ptp_set_ts_sync_events(efx, false, false);
3495 /* if TX timestamping is still requested then leave PTP on */
3496 return efx_ptp_change_mode(efx,
3497 init->tx_type != HWTSTAMP_TX_OFF, 0);
3498 case HWTSTAMP_FILTER_ALL:
3499 case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
3500 case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
3501 case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
3502 case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
3503 case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
3504 case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
3505 case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
3506 case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
3507 case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
3508 case HWTSTAMP_FILTER_PTP_V2_EVENT:
3509 case HWTSTAMP_FILTER_PTP_V2_SYNC:
3510 case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
3511 init->rx_filter = HWTSTAMP_FILTER_ALL;
3512 rc = efx_ptp_change_mode(efx, true, 0);
3513 if (!rc)
3514 rc = efx_ef10_ptp_set_ts_sync_events(efx, true, false);
3515 if (rc)
3516 efx_ptp_change_mode(efx, false, 0);
3517 return rc;
3518 default:
3519 return -ERANGE;
3520 }
3521}
3522
3409const struct efx_nic_type efx_hunt_a0_nic_type = { 3523const struct efx_nic_type efx_hunt_a0_nic_type = {
3410 .mem_map_size = efx_ef10_mem_map_size, 3524 .mem_map_size = efx_ef10_mem_map_size,
3411 .probe = efx_ef10_probe, 3525 .probe = efx_ef10_probe,
@@ -3484,11 +3598,14 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
3484 .mtd_sync = efx_mcdi_mtd_sync, 3598 .mtd_sync = efx_mcdi_mtd_sync,
3485#endif 3599#endif
3486 .ptp_write_host_time = efx_ef10_ptp_write_host_time, 3600 .ptp_write_host_time = efx_ef10_ptp_write_host_time,
3601 .ptp_set_ts_sync_events = efx_ef10_ptp_set_ts_sync_events,
3602 .ptp_set_ts_config = efx_ef10_ptp_set_ts_config,
3487 3603
3488 .revision = EFX_REV_HUNT_A0, 3604 .revision = EFX_REV_HUNT_A0,
3489 .max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH), 3605 .max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH),
3490 .rx_prefix_size = ES_DZ_RX_PREFIX_SIZE, 3606 .rx_prefix_size = ES_DZ_RX_PREFIX_SIZE,
3491 .rx_hash_offset = ES_DZ_RX_PREFIX_HASH_OFST, 3607 .rx_hash_offset = ES_DZ_RX_PREFIX_HASH_OFST,
3608 .rx_ts_offset = ES_DZ_RX_PREFIX_TSTAMP_OFST,
3492 .can_rx_scatter = true, 3609 .can_rx_scatter = true,
3493 .always_rx_scatter = true, 3610 .always_rx_scatter = true,
3494 .max_interrupt_mode = EFX_INT_MODE_MSIX, 3611 .max_interrupt_mode = EFX_INT_MODE_MSIX,
@@ -3497,4 +3614,6 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
3497 NETIF_F_RXHASH | NETIF_F_NTUPLE), 3614 NETIF_F_RXHASH | NETIF_F_NTUPLE),
3498 .mcdi_max_ver = 2, 3615 .mcdi_max_ver = 2,
3499 .max_rx_ip_filters = HUNT_FILTER_TBL_ROWS, 3616 .max_rx_ip_filters = HUNT_FILTER_TBL_ROWS,
3617 .hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE |
3618 1 << HWTSTAMP_FILTER_ALL,
3500}; 3619};
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 893cd78c3a6c..b9929d9ed69d 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -2586,6 +2586,8 @@ static int efx_init_struct(struct efx_nic *efx,
2586 NET_IP_ALIGN ? (efx->rx_prefix_size + NET_IP_ALIGN) % 4 : 0; 2586 NET_IP_ALIGN ? (efx->rx_prefix_size + NET_IP_ALIGN) % 4 : 0;
2587 efx->rx_packet_hash_offset = 2587 efx->rx_packet_hash_offset =
2588 efx->type->rx_hash_offset - efx->type->rx_prefix_size; 2588 efx->type->rx_hash_offset - efx->type->rx_prefix_size;
2589 efx->rx_packet_ts_offset =
2590 efx->type->rx_ts_offset - efx->type->rx_prefix_size;
2589 spin_lock_init(&efx->stats_lock); 2591 spin_lock_init(&efx->stats_lock);
2590 mutex_init(&efx->mac_lock); 2592 mutex_init(&efx->mac_lock);
2591 efx->phy_op = &efx_dummy_phy_operations; 2593 efx->phy_op = &efx_dummy_phy_operations;
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index d608838f6729..540f57915d6f 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -1018,6 +1018,9 @@ void efx_mcdi_process_event(struct efx_channel *channel,
1018 case MCDI_EVENT_CODE_PTP_PPS: 1018 case MCDI_EVENT_CODE_PTP_PPS:
1019 efx_ptp_event(efx, event); 1019 efx_ptp_event(efx, event);
1020 break; 1020 break;
1021 case MCDI_EVENT_CODE_PTP_TIME:
1022 efx_time_sync_event(channel, event);
1023 break;
1021 case MCDI_EVENT_CODE_TX_FLUSH: 1024 case MCDI_EVENT_CODE_TX_FLUSH:
1022 case MCDI_EVENT_CODE_RX_FLUSH: 1025 case MCDI_EVENT_CODE_RX_FLUSH:
1023 /* Two flush events will be sent: one to the same event 1026 /* Two flush events will be sent: one to the same event
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 1a3e4972c68f..0d0e8eb88332 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -369,6 +369,13 @@ enum efx_rx_alloc_method {
369 RX_ALLOC_METHOD_PAGE = 2, 369 RX_ALLOC_METHOD_PAGE = 2,
370}; 370};
371 371
372enum efx_sync_events_state {
373 SYNC_EVENTS_DISABLED = 0,
374 SYNC_EVENTS_QUIESCENT,
375 SYNC_EVENTS_REQUESTED,
376 SYNC_EVENTS_VALID,
377};
378
372/** 379/**
373 * struct efx_channel - An Efx channel 380 * struct efx_channel - An Efx channel
374 * 381 *
@@ -408,6 +415,9 @@ enum efx_rx_alloc_method {
408 * by __efx_rx_packet(), if @rx_pkt_n_frags != 0 415 * by __efx_rx_packet(), if @rx_pkt_n_frags != 0
409 * @rx_queue: RX queue for this channel 416 * @rx_queue: RX queue for this channel
410 * @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
411 */ 421 */
412struct efx_channel { 422struct efx_channel {
413 struct efx_nic *efx; 423 struct efx_nic *efx;
@@ -446,6 +456,10 @@ struct efx_channel {
446 456
447 struct efx_rx_queue rx_queue; 457 struct efx_rx_queue rx_queue;
448 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;
449}; 463};
450 464
451/** 465/**
@@ -686,6 +700,8 @@ struct vfdi_status;
686 * (valid only if @rx_prefix_size != 0; always negative) 700 * (valid only if @rx_prefix_size != 0; always negative)
687 * @rx_packet_len_offset: Offset of RX packet length from start of packet data 701 * @rx_packet_len_offset: Offset of RX packet length from start of packet data
688 * (valid only for NICs that set %EFX_RX_PKT_PREFIX_LEN; always negative) 702 * (valid only for NICs that set %EFX_RX_PKT_PREFIX_LEN; always negative)
703 * @rx_packet_ts_offset: Offset of timestamp from start of packet data
704 * (valid only if channel->sync_timestamps_enabled; always negative)
689 * @rx_hash_key: Toeplitz hash key for RSS 705 * @rx_hash_key: Toeplitz hash key for RSS
690 * @rx_indir_table: Indirection table for RSS 706 * @rx_indir_table: Indirection table for RSS
691 * @rx_scatter: Scatter mode enabled for receives 707 * @rx_scatter: Scatter mode enabled for receives
@@ -820,6 +836,7 @@ struct efx_nic {
820 unsigned int rx_prefix_size; 836 unsigned int rx_prefix_size;
821 int rx_packet_hash_offset; 837 int rx_packet_hash_offset;
822 int rx_packet_len_offset; 838 int rx_packet_len_offset;
839 int rx_packet_ts_offset;
823 u8 rx_hash_key[40]; 840 u8 rx_hash_key[40];
824 u32 rx_indir_table[128]; 841 u32 rx_indir_table[128];
825 bool rx_scatter; 842 bool rx_scatter;
@@ -1035,6 +1052,8 @@ struct efx_mtd_partition {
1035 * also notifies the driver that a writer has finished using this 1052 * also notifies the driver that a writer has finished using this
1036 * partition. 1053 * partition.
1037 * @ptp_write_host_time: Send host time to MC as part of sync protocol 1054 * @ptp_write_host_time: Send host time to MC as part of sync protocol
1055 * @ptp_set_ts_sync_events: Enable or disable sync events for inline RX
1056 * timestamping, possibly only temporarily for the purposes of a reset.
1038 * @ptp_set_ts_config: Set hardware timestamp configuration. The flags 1057 * @ptp_set_ts_config: Set hardware timestamp configuration. The flags
1039 * and tx_type will already have been validated but this operation 1058 * and tx_type will already have been validated but this operation
1040 * must validate and update rx_filter. 1059 * must validate and update rx_filter.
@@ -1047,6 +1066,7 @@ struct efx_mtd_partition {
1047 * @max_dma_mask: Maximum possible DMA mask 1066 * @max_dma_mask: Maximum possible DMA mask
1048 * @rx_prefix_size: Size of RX prefix before packet data 1067 * @rx_prefix_size: Size of RX prefix before packet data
1049 * @rx_hash_offset: Offset of RX flow hash within prefix 1068 * @rx_hash_offset: Offset of RX flow hash within prefix
1069 * @rx_ts_offset: Offset of timestamp within prefix
1050 * @rx_buffer_padding: Size of padding at end of RX packet 1070 * @rx_buffer_padding: Size of padding at end of RX packet
1051 * @can_rx_scatter: NIC is able to scatter packets to multiple buffers 1071 * @can_rx_scatter: NIC is able to scatter packets to multiple buffers
1052 * @always_rx_scatter: NIC will always scatter packets to multiple buffers 1072 * @always_rx_scatter: NIC will always scatter packets to multiple buffers
@@ -1158,6 +1178,7 @@ struct efx_nic_type {
1158 int (*mtd_sync)(struct mtd_info *mtd); 1178 int (*mtd_sync)(struct mtd_info *mtd);
1159#endif 1179#endif
1160 void (*ptp_write_host_time)(struct efx_nic *efx, u32 host_time); 1180 void (*ptp_write_host_time)(struct efx_nic *efx, u32 host_time);
1181 int (*ptp_set_ts_sync_events)(struct efx_nic *efx, bool en, bool temp);
1161 int (*ptp_set_ts_config)(struct efx_nic *efx, 1182 int (*ptp_set_ts_config)(struct efx_nic *efx,
1162 struct hwtstamp_config *init); 1183 struct hwtstamp_config *init);
1163 1184
@@ -1170,6 +1191,7 @@ struct efx_nic_type {
1170 u64 max_dma_mask; 1191 u64 max_dma_mask;
1171 unsigned int rx_prefix_size; 1192 unsigned int rx_prefix_size;
1172 unsigned int rx_hash_offset; 1193 unsigned int rx_hash_offset;
1194 unsigned int rx_ts_offset;
1173 unsigned int rx_buffer_padding; 1195 unsigned int rx_buffer_padding;
1174 bool can_rx_scatter; 1196 bool can_rx_scatter;
1175 bool always_rx_scatter; 1197 bool always_rx_scatter;
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index 999ef285662d..5d9e2dc121f7 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -566,6 +566,15 @@ int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted,
566 unsigned int new_mode); 566 unsigned int new_mode);
567int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); 567int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
568void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev); 568void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev);
569void efx_time_sync_event(struct efx_channel *channel, efx_qword_t *ev);
570void __efx_rx_skb_attach_timestamp(struct efx_channel *channel,
571 struct sk_buff *skb);
572static 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}
569void efx_ptp_start_datapath(struct efx_nic *efx); 578void efx_ptp_start_datapath(struct efx_nic *efx);
570void efx_ptp_stop_datapath(struct efx_nic *efx); 579void efx_ptp_stop_datapath(struct efx_nic *efx);
571 580
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
index 1d1a6f7325da..843e98dfb1b2 100644
--- a/drivers/net/ethernet/sfc/ptp.c
+++ b/drivers/net/ethernet/sfc/ptp.c
@@ -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
@@ -258,6 +260,7 @@ struct efx_ptp_timeset {
258struct efx_ptp_data { 260struct efx_ptp_data {
259 struct efx_nic *efx; 261 struct efx_nic *efx;
260 struct efx_channel *channel; 262 struct efx_channel *channel;
263 bool rx_ts_inline;
261 struct sk_buff_head rxq; 264 struct sk_buff_head rxq;
262 struct sk_buff_head txq; 265 struct sk_buff_head txq;
263 struct list_head evt_list; 266 struct list_head evt_list;
@@ -317,8 +320,8 @@ static void efx_ptp_ns_to_s_ns(s64 ns, u32 *nic_major, u32 *nic_minor)
317 *nic_minor = ts.tv_nsec; 320 *nic_minor = ts.tv_nsec;
318} 321}
319 322
320static ktime_t efx_ptp_s_ns_to_ktime(u32 nic_major, u32 nic_minor, 323static ktime_t efx_ptp_s_ns_to_ktime_correction(u32 nic_major, u32 nic_minor,
321 s32 correction) 324 s32 correction)
322{ 325{
323 ktime_t kt = ktime_set(nic_major, nic_minor); 326 ktime_t kt = ktime_set(nic_major, nic_minor);
324 if (correction >= 0) 327 if (correction >= 0)
@@ -359,11 +362,16 @@ static void efx_ptp_ns_to_s27(s64 ns, u32 *nic_major, u32 *nic_minor)
359 *nic_minor = min; 362 *nic_minor = min;
360} 363}
361 364
362static ktime_t efx_ptp_s27_to_ktime(u32 nic_major, u32 nic_minor, 365static inline ktime_t efx_ptp_s27_to_ktime(u32 nic_major, u32 nic_minor)
363 s32 correction)
364{ 366{
365 u32 ns; 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}
366 371
372static ktime_t efx_ptp_s27_to_ktime_correction(u32 nic_major, u32 nic_minor,
373 s32 correction)
374{
367 /* Apply the correction and deal with carry */ 375 /* Apply the correction and deal with carry */
368 nic_minor += correction; 376 nic_minor += correction;
369 if ((s32)nic_minor < 0) { 377 if ((s32)nic_minor < 0) {
@@ -374,10 +382,7 @@ static ktime_t efx_ptp_s27_to_ktime(u32 nic_major, u32 nic_minor,
374 nic_major++; 382 nic_major++;
375 } 383 }
376 384
377 ns = (u32)(((u64)nic_minor * NSEC_PER_SEC + 385 return efx_ptp_s27_to_ktime(nic_major, nic_minor);
378 (1ULL << (S27_TO_NS_SHIFT - 1))) >> S27_TO_NS_SHIFT);
379
380 return ktime_set(nic_major, ns);
381} 386}
382 387
383/* Get PTP attributes and set up time conversions */ 388/* Get PTP attributes and set up time conversions */
@@ -407,10 +412,10 @@ static int efx_ptp_get_attributes(struct efx_nic *efx)
407 412
408 if (fmt == MC_CMD_PTP_OUT_GET_ATTRIBUTES_SECONDS_27FRACTION) { 413 if (fmt == MC_CMD_PTP_OUT_GET_ATTRIBUTES_SECONDS_27FRACTION) {
409 ptp->ns_to_nic_time = efx_ptp_ns_to_s27; 414 ptp->ns_to_nic_time = efx_ptp_ns_to_s27;
410 ptp->nic_to_kernel_time = efx_ptp_s27_to_ktime; 415 ptp->nic_to_kernel_time = efx_ptp_s27_to_ktime_correction;
411 } else if (fmt == MC_CMD_PTP_OUT_GET_ATTRIBUTES_SECONDS_NANOSECONDS) { 416 } else if (fmt == MC_CMD_PTP_OUT_GET_ATTRIBUTES_SECONDS_NANOSECONDS) {
412 ptp->ns_to_nic_time = efx_ptp_ns_to_s_ns; 417 ptp->ns_to_nic_time = efx_ptp_ns_to_s_ns;
413 ptp->nic_to_kernel_time = efx_ptp_s_ns_to_ktime; 418 ptp->nic_to_kernel_time = efx_ptp_s_ns_to_ktime_correction;
414 } else { 419 } else {
415 return -ERANGE; 420 return -ERANGE;
416 } 421 }
@@ -806,6 +811,9 @@ static void efx_ptp_drop_time_expired_events(struct efx_nic *efx)
806 struct list_head *cursor; 811 struct list_head *cursor;
807 struct list_head *next; 812 struct list_head *next;
808 813
814 if (ptp->rx_ts_inline)
815 return;
816
809 /* Drop time-expired events */ 817 /* Drop time-expired events */
810 spin_lock_bh(&ptp->evt_lock); 818 spin_lock_bh(&ptp->evt_lock);
811 if (!list_empty(&ptp->evt_list)) { 819 if (!list_empty(&ptp->evt_list)) {
@@ -839,6 +847,8 @@ static enum ptp_packet_state efx_ptp_match_rx(struct efx_nic *efx,
839 struct efx_ptp_match *match; 847 struct efx_ptp_match *match;
840 enum ptp_packet_state rc = PTP_PACKET_STATE_UNMATCHED; 848 enum ptp_packet_state rc = PTP_PACKET_STATE_UNMATCHED;
841 849
850 WARN_ON_ONCE(ptp->rx_ts_inline);
851
842 spin_lock_bh(&ptp->evt_lock); 852 spin_lock_bh(&ptp->evt_lock);
843 evts_waiting = !list_empty(&ptp->evt_list); 853 evts_waiting = !list_empty(&ptp->evt_list);
844 spin_unlock_bh(&ptp->evt_lock); 854 spin_unlock_bh(&ptp->evt_lock);
@@ -1061,8 +1071,6 @@ static void efx_ptp_pps_worker(struct work_struct *work)
1061 ptp_clock_event(ptp->phc_clock, &ptp_evt); 1071 ptp_clock_event(ptp->phc_clock, &ptp_evt);
1062} 1072}
1063 1073
1064/* Process any pending transmissions and timestamp any received packets.
1065 */
1066static void efx_ptp_worker(struct work_struct *work) 1074static void efx_ptp_worker(struct work_struct *work)
1067{ 1075{
1068 struct efx_ptp_data *ptp_data = 1076 struct efx_ptp_data *ptp_data =
@@ -1120,6 +1128,7 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel)
1120 1128
1121 ptp->efx = efx; 1129 ptp->efx = efx;
1122 ptp->channel = channel; 1130 ptp->channel = channel;
1131 ptp->rx_ts_inline = efx_nic_rev(efx) >= EFX_REV_HUNT_A0;
1123 1132
1124 rc = efx_nic_alloc_buffer(efx, &ptp->start, sizeof(int), GFP_KERNEL); 1133 rc = efx_nic_alloc_buffer(efx, &ptp->start, sizeof(int), GFP_KERNEL);
1125 if (rc != 0) 1134 if (rc != 0)
@@ -1491,6 +1500,9 @@ static void ptp_event_rx(struct efx_nic *efx, struct efx_ptp_data *ptp)
1491{ 1500{
1492 struct efx_ptp_event_rx *evt = NULL; 1501 struct efx_ptp_event_rx *evt = NULL;
1493 1502
1503 if (WARN_ON_ONCE(ptp->rx_ts_inline))
1504 return;
1505
1494 if (ptp->evt_frag_idx != 3) { 1506 if (ptp->evt_frag_idx != 3) {
1495 ptp_event_failure(efx, 3); 1507 ptp_event_failure(efx, 3);
1496 return; 1508 return;
@@ -1587,6 +1599,93 @@ void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev)
1587 } 1599 }
1588} 1600}
1589 1601
1602void efx_time_sync_event(struct efx_channel *channel, efx_qword_t *ev)
1603{
1604 channel->sync_timestamp_major = MCDI_EVENT_FIELD(*ev, PTP_TIME_MAJOR);
1605 channel->sync_timestamp_minor =
1606 MCDI_EVENT_FIELD(*ev, PTP_TIME_MINOR_26_19) << 19;
1607 /* if sync events have been disabled then we want to silently ignore
1608 * this event, so throw away result.
1609 */
1610 (void) cmpxchg(&channel->sync_events_state, SYNC_EVENTS_REQUESTED,
1611 SYNC_EVENTS_VALID);
1612}
1613
1614/* make some assumptions about the time representation rather than abstract it,
1615 * since we currently only support one type of inline timestamping and only on
1616 * EF10.
1617 */
1618#define MINOR_TICKS_PER_SECOND 0x8000000
1619/* Fuzz factor for sync events to be out of order with RX events */
1620#define FUZZ (MINOR_TICKS_PER_SECOND / 10)
1621#define EXPECTED_SYNC_EVENTS_PER_SECOND 4
1622
1623static inline u32 efx_rx_buf_timestamp_minor(struct efx_nic *efx, const u8 *eh)
1624{
1625#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
1626 return __le32_to_cpup((const __le32 *)(eh + efx->rx_packet_ts_offset));
1627#else
1628 const u8 *data = eh + efx->rx_packet_ts_offset;
1629 return (u32)data[0] |
1630 (u32)data[1] << 8 |
1631 (u32)data[2] << 16 |
1632 (u32)data[3] << 24;
1633#endif
1634}
1635
1636void __efx_rx_skb_attach_timestamp(struct efx_channel *channel,
1637 struct sk_buff *skb)
1638{
1639 struct efx_nic *efx = channel->efx;
1640 u32 pkt_timestamp_major, pkt_timestamp_minor;
1641 u32 diff, carry;
1642 struct skb_shared_hwtstamps *timestamps;
1643
1644 pkt_timestamp_minor = (efx_rx_buf_timestamp_minor(efx,
1645 skb_mac_header(skb)) +
1646 (u32) efx->ptp_data->ts_corrections.rx) &
1647 (MINOR_TICKS_PER_SECOND - 1);
1648
1649 /* get the difference between the packet and sync timestamps,
1650 * modulo one second
1651 */
1652 diff = (pkt_timestamp_minor - channel->sync_timestamp_minor) &
1653 (MINOR_TICKS_PER_SECOND - 1);
1654 /* do we roll over a second boundary and need to carry the one? */
1655 carry = channel->sync_timestamp_minor + diff > MINOR_TICKS_PER_SECOND ?
1656 1 : 0;
1657
1658 if (diff <= MINOR_TICKS_PER_SECOND / EXPECTED_SYNC_EVENTS_PER_SECOND +
1659 FUZZ) {
1660 /* packet is ahead of the sync event by a quarter of a second or
1661 * less (allowing for fuzz)
1662 */
1663 pkt_timestamp_major = channel->sync_timestamp_major + carry;
1664 } else if (diff >= MINOR_TICKS_PER_SECOND - FUZZ) {
1665 /* packet is behind the sync event but within the fuzz factor.
1666 * This means the RX packet and sync event crossed as they were
1667 * placed on the event queue, which can sometimes happen.
1668 */
1669 pkt_timestamp_major = channel->sync_timestamp_major - 1 + carry;
1670 } else {
1671 /* it's outside tolerance in both directions. this might be
1672 * indicative of us missing sync events for some reason, so
1673 * we'll call it an error rather than risk giving a bogus
1674 * timestamp.
1675 */
1676 netif_vdbg(efx, drv, efx->net_dev,
1677 "packet timestamp %x too far from sync event %x:%x\n",
1678 pkt_timestamp_minor, channel->sync_timestamp_major,
1679 channel->sync_timestamp_minor);
1680 return;
1681 }
1682
1683 /* attach the timestamps to the skb */
1684 timestamps = skb_hwtstamps(skb);
1685 timestamps->hwtstamp =
1686 efx_ptp_s27_to_ktime(pkt_timestamp_major, pkt_timestamp_minor);
1687}
1688
1590static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) 1689static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
1591{ 1690{
1592 struct efx_ptp_data *ptp_data = container_of(ptp, 1691 struct efx_ptp_data *ptp_data = container_of(ptp,
@@ -1728,9 +1827,15 @@ void efx_ptp_start_datapath(struct efx_nic *efx)
1728{ 1827{
1729 if (efx_ptp_restart(efx)) 1828 if (efx_ptp_restart(efx))
1730 netif_err(efx, drv, efx->net_dev, "Failed to restart PTP.\n"); 1829 netif_err(efx, drv, efx->net_dev, "Failed to restart PTP.\n");
1830 /* re-enable timestamping if it was previously enabled */
1831 if (efx->type->ptp_set_ts_sync_events)
1832 efx->type->ptp_set_ts_sync_events(efx, true, true);
1731} 1833}
1732 1834
1733void efx_ptp_stop_datapath(struct efx_nic *efx) 1835void efx_ptp_stop_datapath(struct efx_nic *efx)
1734{ 1836{
1837 /* temporarily disable timestamping */
1838 if (efx->type->ptp_set_ts_sync_events)
1839 efx->type->ptp_set_ts_sync_events(efx, false, true);
1735 efx_ptp_stop(efx); 1840 efx_ptp_stop(efx);
1736} 1841}
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index d12abc543975..1fde9b8ac456 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -624,6 +624,8 @@ static void efx_rx_deliver(struct efx_channel *channel, u8 *eh,
624 if (likely(rx_buf->flags & EFX_RX_PKT_CSUMMED)) 624 if (likely(rx_buf->flags & EFX_RX_PKT_CSUMMED))
625 skb->ip_summed = CHECKSUM_UNNECESSARY; 625 skb->ip_summed = CHECKSUM_UNNECESSARY;
626 626
627 efx_rx_skb_attach_timestamp(channel, skb);
628
627 if (channel->type->receive_skb) 629 if (channel->type->receive_skb)
628 if (channel->type->receive_skb(channel, skb)) 630 if (channel->type->receive_skb(channel, skb))
629 return; 631 return;