diff options
author | Alexandre Rames <arames@solarflare.com> | 2013-11-08 05:20:31 -0500 |
---|---|---|
committer | Ben Hutchings <bhutchings@solarflare.com> | 2013-12-06 17:27:41 -0500 |
commit | 2ea4dc28a5bcec408e01a8772763871638a5ec79 (patch) | |
tree | bb96ff4fdc285aa0ae708b22d2d7d31da2b0b1a9 | |
parent | 35f9a7a380728a94d417e5824a866f969423ac83 (diff) |
sfc: Stop/re-start PTP when stopping/starting the datapath.
This disables PTP when we bring the interface down to avoid getting
unmatched RX timestamp events, and tries to re-enable it when bringing
the interface up.
[bwh: Make efx_ptp_stop() safe on Falcon. Introduce
efx_ptp_{start,stop}_datapath() functions; we'll expand them later.]
Fixes: 7c236c43b838 ('sfc: Add support for IEEE-1588 PTP')
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
-rw-r--r-- | drivers/net/ethernet/sfc/efx.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/nic.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/ptp.c | 30 |
3 files changed, 33 insertions, 3 deletions
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 2e27837ce6a2..8bd5b485f1bc 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c | |||
@@ -645,6 +645,8 @@ static void efx_start_datapath(struct efx_nic *efx) | |||
645 | WARN_ON(channel->rx_pkt_n_frags); | 645 | WARN_ON(channel->rx_pkt_n_frags); |
646 | } | 646 | } |
647 | 647 | ||
648 | efx_ptp_start_datapath(efx); | ||
649 | |||
648 | if (netif_device_present(efx->net_dev)) | 650 | if (netif_device_present(efx->net_dev)) |
649 | netif_tx_wake_all_queues(efx->net_dev); | 651 | netif_tx_wake_all_queues(efx->net_dev); |
650 | } | 652 | } |
@@ -659,6 +661,8 @@ static void efx_stop_datapath(struct efx_nic *efx) | |||
659 | EFX_ASSERT_RESET_SERIALISED(efx); | 661 | EFX_ASSERT_RESET_SERIALISED(efx); |
660 | BUG_ON(efx->port_enabled); | 662 | BUG_ON(efx->port_enabled); |
661 | 663 | ||
664 | efx_ptp_stop_datapath(efx); | ||
665 | |||
662 | /* Stop RX refill */ | 666 | /* Stop RX refill */ |
663 | efx_for_each_channel(channel, efx) { | 667 | efx_for_each_channel(channel, efx) { |
664 | efx_for_each_channel_rx_queue(rx_queue, channel) | 668 | efx_for_each_channel_rx_queue(rx_queue, channel) |
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 11b6112d9249..91c63ec79c5f 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h | |||
@@ -560,6 +560,8 @@ void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info); | |||
560 | bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); | 560 | bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); |
561 | int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); | 561 | int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); |
562 | void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev); | 562 | void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev); |
563 | void efx_ptp_start_datapath(struct efx_nic *efx); | ||
564 | void efx_ptp_stop_datapath(struct efx_nic *efx); | ||
563 | 565 | ||
564 | extern const struct efx_nic_type falcon_a1_nic_type; | 566 | extern const struct efx_nic_type falcon_a1_nic_type; |
565 | extern const struct efx_nic_type falcon_b0_nic_type; | 567 | extern const struct efx_nic_type falcon_b0_nic_type; |
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 8c665f1b5480..9bd99edf3f95 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c | |||
@@ -801,9 +801,14 @@ fail: | |||
801 | static int efx_ptp_stop(struct efx_nic *efx) | 801 | static int efx_ptp_stop(struct efx_nic *efx) |
802 | { | 802 | { |
803 | struct efx_ptp_data *ptp = efx->ptp_data; | 803 | struct efx_ptp_data *ptp = efx->ptp_data; |
804 | int rc = efx_ptp_disable(efx); | ||
805 | struct list_head *cursor; | 804 | struct list_head *cursor; |
806 | struct list_head *next; | 805 | struct list_head *next; |
806 | int rc; | ||
807 | |||
808 | if (ptp == NULL) | ||
809 | return 0; | ||
810 | |||
811 | rc = efx_ptp_disable(efx); | ||
807 | 812 | ||
808 | if (ptp->rxfilter_installed) { | 813 | if (ptp->rxfilter_installed) { |
809 | efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, | 814 | efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, |
@@ -828,6 +833,13 @@ static int efx_ptp_stop(struct efx_nic *efx) | |||
828 | return rc; | 833 | return rc; |
829 | } | 834 | } |
830 | 835 | ||
836 | static int efx_ptp_restart(struct efx_nic *efx) | ||
837 | { | ||
838 | if (efx->ptp_data && efx->ptp_data->enabled) | ||
839 | return efx_ptp_start(efx); | ||
840 | return 0; | ||
841 | } | ||
842 | |||
831 | static void efx_ptp_pps_worker(struct work_struct *work) | 843 | static void efx_ptp_pps_worker(struct work_struct *work) |
832 | { | 844 | { |
833 | struct efx_ptp_data *ptp = | 845 | struct efx_ptp_data *ptp = |
@@ -1125,7 +1137,7 @@ static int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted, | |||
1125 | { | 1137 | { |
1126 | if ((enable_wanted != efx->ptp_data->enabled) || | 1138 | if ((enable_wanted != efx->ptp_data->enabled) || |
1127 | (enable_wanted && (efx->ptp_data->mode != new_mode))) { | 1139 | (enable_wanted && (efx->ptp_data->mode != new_mode))) { |
1128 | int rc; | 1140 | int rc = 0; |
1129 | 1141 | ||
1130 | if (enable_wanted) { | 1142 | if (enable_wanted) { |
1131 | /* Change of mode requires disable */ | 1143 | /* Change of mode requires disable */ |
@@ -1142,7 +1154,8 @@ static int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted, | |||
1142 | * succeed. | 1154 | * succeed. |
1143 | */ | 1155 | */ |
1144 | efx->ptp_data->mode = new_mode; | 1156 | efx->ptp_data->mode = new_mode; |
1145 | rc = efx_ptp_start(efx); | 1157 | if (netif_running(efx->net_dev)) |
1158 | rc = efx_ptp_start(efx); | ||
1146 | if (rc == 0) { | 1159 | if (rc == 0) { |
1147 | rc = efx_ptp_synchronize(efx, | 1160 | rc = efx_ptp_synchronize(efx, |
1148 | PTP_SYNC_ATTEMPTS * 2); | 1161 | PTP_SYNC_ATTEMPTS * 2); |
@@ -1515,3 +1528,14 @@ void efx_ptp_probe(struct efx_nic *efx) | |||
1515 | efx->extra_channel_type[EFX_EXTRA_CHANNEL_PTP] = | 1528 | efx->extra_channel_type[EFX_EXTRA_CHANNEL_PTP] = |
1516 | &efx_ptp_channel_type; | 1529 | &efx_ptp_channel_type; |
1517 | } | 1530 | } |
1531 | |||
1532 | void efx_ptp_start_datapath(struct efx_nic *efx) | ||
1533 | { | ||
1534 | if (efx_ptp_restart(efx)) | ||
1535 | netif_err(efx, drv, efx->net_dev, "Failed to restart PTP.\n"); | ||
1536 | } | ||
1537 | |||
1538 | void efx_ptp_stop_datapath(struct efx_nic *efx) | ||
1539 | { | ||
1540 | efx_ptp_stop(efx); | ||
1541 | } | ||