sfc: Stop/re-start PTP when stopping/starting the datapath.
authorAlexandre Rames <arames@solarflare.com>
Fri, 8 Nov 2013 10:20:31 +0000 (10:20 +0000)
committerBen Hutchings <bhutchings@solarflare.com>
Fri, 6 Dec 2013 22:27:41 +0000 (22:27 +0000)
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>
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/nic.h
drivers/net/ethernet/sfc/ptp.c

index 2e27837ce6a289dc033c806e613f8dbca42496b9..8bd5b485f1bc1fef2bb76548abb9e8fda20414e0 100644 (file)
@@ -645,6 +645,8 @@ static void efx_start_datapath(struct efx_nic *efx)
                WARN_ON(channel->rx_pkt_n_frags);
        }
 
+       efx_ptp_start_datapath(efx);
+
        if (netif_device_present(efx->net_dev))
                netif_tx_wake_all_queues(efx->net_dev);
 }
@@ -659,6 +661,8 @@ static void efx_stop_datapath(struct efx_nic *efx)
        EFX_ASSERT_RESET_SERIALISED(efx);
        BUG_ON(efx->port_enabled);
 
+       efx_ptp_stop_datapath(efx);
+
        /* Stop RX refill */
        efx_for_each_channel(channel, efx) {
                efx_for_each_channel_rx_queue(rx_queue, channel)
index 11b6112d9249a734701eebe66414bd039702bcdd..91c63ec79c5fcb21d96545c0a6bad98e58cce5b9 100644 (file)
@@ -560,6 +560,8 @@ void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info);
 bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
 int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
 void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev);
+void efx_ptp_start_datapath(struct efx_nic *efx);
+void efx_ptp_stop_datapath(struct efx_nic *efx);
 
 extern const struct efx_nic_type falcon_a1_nic_type;
 extern const struct efx_nic_type falcon_b0_nic_type;
index 8c665f1b54804db1c3c1203160a5a246d7a5858f..9bd99edf3f95627c109365b5bfb4783c5a89cefe 100644 (file)
@@ -801,9 +801,14 @@ fail:
 static int efx_ptp_stop(struct efx_nic *efx)
 {
        struct efx_ptp_data *ptp = efx->ptp_data;
-       int rc = efx_ptp_disable(efx);
        struct list_head *cursor;
        struct list_head *next;
+       int rc;
+
+       if (ptp == NULL)
+               return 0;
+
+       rc = efx_ptp_disable(efx);
 
        if (ptp->rxfilter_installed) {
                efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED,
@@ -828,6 +833,13 @@ static int efx_ptp_stop(struct efx_nic *efx)
        return rc;
 }
 
+static int efx_ptp_restart(struct efx_nic *efx)
+{
+       if (efx->ptp_data && efx->ptp_data->enabled)
+               return efx_ptp_start(efx);
+       return 0;
+}
+
 static void efx_ptp_pps_worker(struct work_struct *work)
 {
        struct efx_ptp_data *ptp =
@@ -1125,7 +1137,7 @@ static int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted,
 {
        if ((enable_wanted != efx->ptp_data->enabled) ||
            (enable_wanted && (efx->ptp_data->mode != new_mode))) {
-               int rc;
+               int rc = 0;
 
                if (enable_wanted) {
                        /* Change of mode requires disable */
@@ -1142,7 +1154,8 @@ static int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted,
                         * succeed.
                         */
                        efx->ptp_data->mode = new_mode;
-                       rc = efx_ptp_start(efx);
+                       if (netif_running(efx->net_dev))
+                               rc = efx_ptp_start(efx);
                        if (rc == 0) {
                                rc = efx_ptp_synchronize(efx,
                                                         PTP_SYNC_ATTEMPTS * 2);
@@ -1515,3 +1528,14 @@ void efx_ptp_probe(struct efx_nic *efx)
                efx->extra_channel_type[EFX_EXTRA_CHANNEL_PTP] =
                        &efx_ptp_channel_type;
 }
+
+void efx_ptp_start_datapath(struct efx_nic *efx)
+{
+       if (efx_ptp_restart(efx))
+               netif_err(efx, drv, efx->net_dev, "Failed to restart PTP.\n");
+}
+
+void efx_ptp_stop_datapath(struct efx_nic *efx)
+{
+       efx_ptp_stop(efx);
+}