diff options
Diffstat (limited to 'drivers/net/ethernet/sfc/ptp.c')
-rw-r--r-- | drivers/net/ethernet/sfc/ptp.c | 93 |
1 files changed, 39 insertions, 54 deletions
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index d7a36829649a..6b861e3de4b0 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c | |||
@@ -223,7 +223,6 @@ struct efx_ptp_timeset { | |||
223 | * @evt_list: List of MC receive events awaiting packets | 223 | * @evt_list: List of MC receive events awaiting packets |
224 | * @evt_free_list: List of free events | 224 | * @evt_free_list: List of free events |
225 | * @evt_lock: Lock for manipulating evt_list and evt_free_list | 225 | * @evt_lock: Lock for manipulating evt_list and evt_free_list |
226 | * @evt_overflow: Boolean indicating that event list has overflowed | ||
227 | * @rx_evts: Instantiated events (on evt_list and evt_free_list) | 226 | * @rx_evts: Instantiated events (on evt_list and evt_free_list) |
228 | * @workwq: Work queue for processing pending PTP operations | 227 | * @workwq: Work queue for processing pending PTP operations |
229 | * @work: Work task | 228 | * @work: Work task |
@@ -275,7 +274,6 @@ struct efx_ptp_data { | |||
275 | struct list_head evt_list; | 274 | struct list_head evt_list; |
276 | struct list_head evt_free_list; | 275 | struct list_head evt_free_list; |
277 | spinlock_t evt_lock; | 276 | spinlock_t evt_lock; |
278 | bool evt_overflow; | ||
279 | struct efx_ptp_event_rx rx_evts[MAX_RECEIVE_EVENTS]; | 277 | struct efx_ptp_event_rx rx_evts[MAX_RECEIVE_EVENTS]; |
280 | struct workqueue_struct *workwq; | 278 | struct workqueue_struct *workwq; |
281 | struct work_struct work; | 279 | struct work_struct work; |
@@ -768,37 +766,36 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf), | |||
768 | return -EAGAIN; | 766 | return -EAGAIN; |
769 | } | 767 | } |
770 | 768 | ||
771 | /* Convert the NIC time into kernel time. No correction is required- | 769 | /* Calculate delay from last good sync (host time) to last_time. |
772 | * this time is the output of a firmware process. | 770 | * It is possible that the seconds rolled over between taking |
773 | */ | ||
774 | mc_time = ptp->nic_to_kernel_time(ptp->timeset[last_good].major, | ||
775 | ptp->timeset[last_good].minor, 0); | ||
776 | |||
777 | /* Calculate delay from actual PPS to last_time */ | ||
778 | delta = ktime_to_timespec(mc_time); | ||
779 | delta.tv_nsec += | ||
780 | last_time->ts_real.tv_nsec - | ||
781 | (ptp->timeset[last_good].host_start & MC_NANOSECOND_MASK); | ||
782 | |||
783 | /* It is possible that the seconds rolled over between taking | ||
784 | * the start reading and the last value written by the host. The | 771 | * the start reading and the last value written by the host. The |
785 | * timescales are such that a gap of more than one second is never | 772 | * timescales are such that a gap of more than one second is never |
786 | * expected. | 773 | * expected. delta is *not* normalised. |
787 | */ | 774 | */ |
788 | start_sec = ptp->timeset[last_good].host_start >> MC_NANOSECOND_BITS; | 775 | start_sec = ptp->timeset[last_good].host_start >> MC_NANOSECOND_BITS; |
789 | last_sec = last_time->ts_real.tv_sec & MC_SECOND_MASK; | 776 | last_sec = last_time->ts_real.tv_sec & MC_SECOND_MASK; |
790 | if (start_sec != last_sec) { | 777 | if (start_sec != last_sec && |
791 | if (((start_sec + 1) & MC_SECOND_MASK) != last_sec) { | 778 | ((start_sec + 1) & MC_SECOND_MASK) != last_sec) { |
792 | netif_warn(efx, hw, efx->net_dev, | 779 | netif_warn(efx, hw, efx->net_dev, |
793 | "PTP bad synchronisation seconds\n"); | 780 | "PTP bad synchronisation seconds\n"); |
794 | return -EAGAIN; | 781 | return -EAGAIN; |
795 | } else { | ||
796 | delta.tv_sec = 1; | ||
797 | } | ||
798 | } else { | ||
799 | delta.tv_sec = 0; | ||
800 | } | 782 | } |
783 | delta.tv_sec = (last_sec - start_sec) & 1; | ||
784 | delta.tv_nsec = | ||
785 | last_time->ts_real.tv_nsec - | ||
786 | (ptp->timeset[last_good].host_start & MC_NANOSECOND_MASK); | ||
787 | |||
788 | /* Convert the NIC time at last good sync into kernel time. | ||
789 | * No correction is required - this time is the output of a | ||
790 | * firmware process. | ||
791 | */ | ||
792 | mc_time = ptp->nic_to_kernel_time(ptp->timeset[last_good].major, | ||
793 | ptp->timeset[last_good].minor, 0); | ||
794 | |||
795 | /* Calculate delay from NIC top of second to last_time */ | ||
796 | delta.tv_nsec += ktime_to_timespec(mc_time).tv_nsec; | ||
801 | 797 | ||
798 | /* Set PPS timestamp to match NIC top of second */ | ||
802 | ptp->host_time_pps = *last_time; | 799 | ptp->host_time_pps = *last_time; |
803 | pps_sub_ts(&ptp->host_time_pps, delta); | 800 | pps_sub_ts(&ptp->host_time_pps, delta); |
804 | 801 | ||
@@ -941,11 +938,6 @@ static void efx_ptp_drop_time_expired_events(struct efx_nic *efx) | |||
941 | } | 938 | } |
942 | } | 939 | } |
943 | } | 940 | } |
944 | /* If the event overflow flag is set and the event list is now empty | ||
945 | * clear the flag to re-enable the overflow warning message. | ||
946 | */ | ||
947 | if (ptp->evt_overflow && list_empty(&ptp->evt_list)) | ||
948 | ptp->evt_overflow = false; | ||
949 | spin_unlock_bh(&ptp->evt_lock); | 941 | spin_unlock_bh(&ptp->evt_lock); |
950 | } | 942 | } |
951 | 943 | ||
@@ -989,11 +981,6 @@ static enum ptp_packet_state efx_ptp_match_rx(struct efx_nic *efx, | |||
989 | break; | 981 | break; |
990 | } | 982 | } |
991 | } | 983 | } |
992 | /* If the event overflow flag is set and the event list is now empty | ||
993 | * clear the flag to re-enable the overflow warning message. | ||
994 | */ | ||
995 | if (ptp->evt_overflow && list_empty(&ptp->evt_list)) | ||
996 | ptp->evt_overflow = false; | ||
997 | spin_unlock_bh(&ptp->evt_lock); | 984 | spin_unlock_bh(&ptp->evt_lock); |
998 | 985 | ||
999 | return rc; | 986 | return rc; |
@@ -1147,7 +1134,6 @@ static int efx_ptp_stop(struct efx_nic *efx) | |||
1147 | list_for_each_safe(cursor, next, &efx->ptp_data->evt_list) { | 1134 | list_for_each_safe(cursor, next, &efx->ptp_data->evt_list) { |
1148 | list_move(cursor, &efx->ptp_data->evt_free_list); | 1135 | list_move(cursor, &efx->ptp_data->evt_free_list); |
1149 | } | 1136 | } |
1150 | ptp->evt_overflow = false; | ||
1151 | spin_unlock_bh(&efx->ptp_data->evt_lock); | 1137 | spin_unlock_bh(&efx->ptp_data->evt_lock); |
1152 | 1138 | ||
1153 | return rc; | 1139 | return rc; |
@@ -1208,6 +1194,7 @@ static const struct ptp_clock_info efx_phc_clock_info = { | |||
1208 | .n_alarm = 0, | 1194 | .n_alarm = 0, |
1209 | .n_ext_ts = 0, | 1195 | .n_ext_ts = 0, |
1210 | .n_per_out = 0, | 1196 | .n_per_out = 0, |
1197 | .n_pins = 0, | ||
1211 | .pps = 1, | 1198 | .pps = 1, |
1212 | .adjfreq = efx_phc_adjfreq, | 1199 | .adjfreq = efx_phc_adjfreq, |
1213 | .adjtime = efx_phc_adjtime, | 1200 | .adjtime = efx_phc_adjtime, |
@@ -1253,7 +1240,6 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel) | |||
1253 | spin_lock_init(&ptp->evt_lock); | 1240 | spin_lock_init(&ptp->evt_lock); |
1254 | for (pos = 0; pos < MAX_RECEIVE_EVENTS; pos++) | 1241 | for (pos = 0; pos < MAX_RECEIVE_EVENTS; pos++) |
1255 | list_add(&ptp->rx_evts[pos].link, &ptp->evt_free_list); | 1242 | list_add(&ptp->rx_evts[pos].link, &ptp->evt_free_list); |
1256 | ptp->evt_overflow = false; | ||
1257 | 1243 | ||
1258 | /* Get the NIC PTP attributes and set up time conversions */ | 1244 | /* Get the NIC PTP attributes and set up time conversions */ |
1259 | rc = efx_ptp_get_attributes(efx); | 1245 | rc = efx_ptp_get_attributes(efx); |
@@ -1380,6 +1366,7 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb) | |||
1380 | struct efx_ptp_match *match = (struct efx_ptp_match *)skb->cb; | 1366 | struct efx_ptp_match *match = (struct efx_ptp_match *)skb->cb; |
1381 | u8 *match_data_012, *match_data_345; | 1367 | u8 *match_data_012, *match_data_345; |
1382 | unsigned int version; | 1368 | unsigned int version; |
1369 | u8 *data; | ||
1383 | 1370 | ||
1384 | match->expiry = jiffies + msecs_to_jiffies(PKT_EVENT_LIFETIME_MS); | 1371 | match->expiry = jiffies + msecs_to_jiffies(PKT_EVENT_LIFETIME_MS); |
1385 | 1372 | ||
@@ -1388,7 +1375,8 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb) | |||
1388 | if (!pskb_may_pull(skb, PTP_V1_MIN_LENGTH)) { | 1375 | if (!pskb_may_pull(skb, PTP_V1_MIN_LENGTH)) { |
1389 | return false; | 1376 | return false; |
1390 | } | 1377 | } |
1391 | version = ntohs(*(__be16 *)&skb->data[PTP_V1_VERSION_OFFSET]); | 1378 | data = skb->data; |
1379 | version = ntohs(*(__be16 *)&data[PTP_V1_VERSION_OFFSET]); | ||
1392 | if (version != PTP_VERSION_V1) { | 1380 | if (version != PTP_VERSION_V1) { |
1393 | return false; | 1381 | return false; |
1394 | } | 1382 | } |
@@ -1396,13 +1384,14 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb) | |||
1396 | /* PTP V1 uses all six bytes of the UUID to match the packet | 1384 | /* PTP V1 uses all six bytes of the UUID to match the packet |
1397 | * to the timestamp | 1385 | * to the timestamp |
1398 | */ | 1386 | */ |
1399 | match_data_012 = skb->data + PTP_V1_UUID_OFFSET; | 1387 | match_data_012 = data + PTP_V1_UUID_OFFSET; |
1400 | match_data_345 = skb->data + PTP_V1_UUID_OFFSET + 3; | 1388 | match_data_345 = data + PTP_V1_UUID_OFFSET + 3; |
1401 | } else { | 1389 | } else { |
1402 | if (!pskb_may_pull(skb, PTP_V2_MIN_LENGTH)) { | 1390 | if (!pskb_may_pull(skb, PTP_V2_MIN_LENGTH)) { |
1403 | return false; | 1391 | return false; |
1404 | } | 1392 | } |
1405 | version = skb->data[PTP_V2_VERSION_OFFSET]; | 1393 | data = skb->data; |
1394 | version = data[PTP_V2_VERSION_OFFSET]; | ||
1406 | if ((version & PTP_VERSION_V2_MASK) != PTP_VERSION_V2) { | 1395 | if ((version & PTP_VERSION_V2_MASK) != PTP_VERSION_V2) { |
1407 | return false; | 1396 | return false; |
1408 | } | 1397 | } |
@@ -1414,17 +1403,17 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb) | |||
1414 | * enhanced mode fixes this issue and uses bytes 0-2 | 1403 | * enhanced mode fixes this issue and uses bytes 0-2 |
1415 | * and byte 5-7 of the UUID. | 1404 | * and byte 5-7 of the UUID. |
1416 | */ | 1405 | */ |
1417 | match_data_345 = skb->data + PTP_V2_UUID_OFFSET + 5; | 1406 | match_data_345 = data + PTP_V2_UUID_OFFSET + 5; |
1418 | if (ptp->mode == MC_CMD_PTP_MODE_V2) { | 1407 | if (ptp->mode == MC_CMD_PTP_MODE_V2) { |
1419 | match_data_012 = skb->data + PTP_V2_UUID_OFFSET + 2; | 1408 | match_data_012 = data + PTP_V2_UUID_OFFSET + 2; |
1420 | } else { | 1409 | } else { |
1421 | match_data_012 = skb->data + PTP_V2_UUID_OFFSET + 0; | 1410 | match_data_012 = data + PTP_V2_UUID_OFFSET + 0; |
1422 | BUG_ON(ptp->mode != MC_CMD_PTP_MODE_V2_ENHANCED); | 1411 | BUG_ON(ptp->mode != MC_CMD_PTP_MODE_V2_ENHANCED); |
1423 | } | 1412 | } |
1424 | } | 1413 | } |
1425 | 1414 | ||
1426 | /* Does this packet require timestamping? */ | 1415 | /* Does this packet require timestamping? */ |
1427 | if (ntohs(*(__be16 *)&skb->data[PTP_DPORT_OFFSET]) == PTP_EVENT_PORT) { | 1416 | if (ntohs(*(__be16 *)&data[PTP_DPORT_OFFSET]) == PTP_EVENT_PORT) { |
1428 | match->state = PTP_PACKET_STATE_UNMATCHED; | 1417 | match->state = PTP_PACKET_STATE_UNMATCHED; |
1429 | 1418 | ||
1430 | /* We expect the sequence number to be in the same position in | 1419 | /* We expect the sequence number to be in the same position in |
@@ -1440,8 +1429,8 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb) | |||
1440 | (match_data_345[0] << 24)); | 1429 | (match_data_345[0] << 24)); |
1441 | match->words[1] = (match_data_345[1] | | 1430 | match->words[1] = (match_data_345[1] | |
1442 | (match_data_345[2] << 8) | | 1431 | (match_data_345[2] << 8) | |
1443 | (skb->data[PTP_V1_SEQUENCE_OFFSET + | 1432 | (data[PTP_V1_SEQUENCE_OFFSET + |
1444 | PTP_V1_SEQUENCE_LENGTH - 1] << | 1433 | PTP_V1_SEQUENCE_LENGTH - 1] << |
1445 | 16)); | 1434 | 16)); |
1446 | } else { | 1435 | } else { |
1447 | match->state = PTP_PACKET_STATE_MATCH_UNWANTED; | 1436 | match->state = PTP_PACKET_STATE_MATCH_UNWANTED; |
@@ -1635,13 +1624,9 @@ static void ptp_event_rx(struct efx_nic *efx, struct efx_ptp_data *ptp) | |||
1635 | list_add_tail(&evt->link, &ptp->evt_list); | 1624 | list_add_tail(&evt->link, &ptp->evt_list); |
1636 | 1625 | ||
1637 | queue_work(ptp->workwq, &ptp->work); | 1626 | queue_work(ptp->workwq, &ptp->work); |
1638 | } else if (!ptp->evt_overflow) { | 1627 | } else if (net_ratelimit()) { |
1639 | /* Log a warning message and set the event overflow flag. | 1628 | /* Log a rate-limited warning message. */ |
1640 | * The message won't be logged again until the event queue | ||
1641 | * becomes empty. | ||
1642 | */ | ||
1643 | netif_err(efx, rx_err, efx->net_dev, "PTP event queue overflow\n"); | 1629 | netif_err(efx, rx_err, efx->net_dev, "PTP event queue overflow\n"); |
1644 | ptp->evt_overflow = true; | ||
1645 | } | 1630 | } |
1646 | spin_unlock_bh(&ptp->evt_lock); | 1631 | spin_unlock_bh(&ptp->evt_lock); |
1647 | } | 1632 | } |