ionic: add ts_config replay
authorShannon Nelson <snelson@pensando.io>
Wed, 7 Apr 2021 23:20:00 +0000 (16:20 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 8 Apr 2021 20:18:49 +0000 (13:18 -0700)
Split the call into ionic_lif_hwstamp_set() to have two
separate interfaces, one from the ioctl() for changing the
configuration and one for replaying the current configuration
after a FW RESET.

Signed-off-by: Shannon Nelson <snelson@pensando.io>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/pensando/ionic/ionic_lif.c
drivers/net/ethernet/pensando/ionic/ionic_lif.h
drivers/net/ethernet/pensando/ionic/ionic_phc.c

index eae774c..af3a536 100644 (file)
@@ -2993,7 +2993,7 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif)
        dev_info(ionic->dev, "FW Up: LIFs restarted\n");
 
        /* restore the hardware timestamping queues */
-       ionic_lif_hwstamp_set(lif, NULL);
+       ionic_lif_hwstamp_replay(lif);
 
        return;
 
index ea3b086..346506f 100644 (file)
@@ -302,6 +302,7 @@ int ionic_lif_identify(struct ionic *ionic, u8 lif_type,
 int ionic_lif_size(struct ionic *ionic);
 
 #if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+int ionic_lif_hwstamp_replay(struct ionic_lif *lif);
 int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr);
 int ionic_lif_hwstamp_get(struct ionic_lif *lif, struct ifreq *ifr);
 ktime_t ionic_lif_phc_ktime(struct ionic_lif *lif, u64 counter);
@@ -310,6 +311,11 @@ void ionic_lif_unregister_phc(struct ionic_lif *lif);
 void ionic_lif_alloc_phc(struct ionic_lif *lif);
 void ionic_lif_free_phc(struct ionic_lif *lif);
 #else
+static inline int ionic_lif_hwstamp_replay(struct ionic_lif *lif)
+{
+       return -EOPNOTSUPP;
+}
+
 static inline int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr)
 {
        return -EOPNOTSUPP;
index 5d5da61..2bb7490 100644 (file)
@@ -64,10 +64,12 @@ static u64 ionic_hwstamp_rx_filt(int config_rx_filter)
        }
 }
 
-int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr)
+static int ionic_lif_hwstamp_set_ts_config(struct ionic_lif *lif,
+                                          struct hwtstamp_config *new_ts)
 {
        struct ionic *ionic = lif->ionic;
-       struct hwtstamp_config config;
+       struct hwtstamp_config *config;
+       struct hwtstamp_config ts;
        int tx_mode = 0;
        u64 rx_filt = 0;
        int err, err2;
@@ -77,18 +79,23 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr)
        if (!lif->phc || !lif->phc->ptp)
                return -EOPNOTSUPP;
 
-       if (ifr) {
-               if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
-                       return -EFAULT;
+       if (new_ts) {
+               config = new_ts;
        } else {
-               /* if called with ifr == NULL, behave as if called with the
-                * current ts_config from the initial cleared state.
+               /* If called with new_ts == NULL, replay the previous request
+                * primarily for recovery after a FW_RESET.
+                * We saved the previous configuration request info, so copy
+                * the previous request for reference, clear the current state
+                * to match the device's reset state, and run with it.
                 */
-               memcpy(&config, &lif->phc->ts_config, sizeof(config));
-               memset(&lif->phc->ts_config, 0, sizeof(config));
+               config = &ts;
+               memcpy(config, &lif->phc->ts_config, sizeof(*config));
+               memset(&lif->phc->ts_config, 0, sizeof(lif->phc->ts_config));
+               lif->phc->ts_config_tx_mode = 0;
+               lif->phc->ts_config_rx_filt = 0;
        }
 
-       tx_mode = ionic_hwstamp_tx_mode(config.tx_type);
+       tx_mode = ionic_hwstamp_tx_mode(config->tx_type);
        if (tx_mode < 0)
                return tx_mode;
 
@@ -96,18 +103,18 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr)
        if ((ionic->ident.lif.eth.hwstamp_tx_modes & mask) != mask)
                return -ERANGE;
 
-       rx_filt = ionic_hwstamp_rx_filt(config.rx_filter);
-       rx_all = config.rx_filter != HWTSTAMP_FILTER_NONE && !rx_filt;
+       rx_filt = ionic_hwstamp_rx_filt(config->rx_filter);
+       rx_all = config->rx_filter != HWTSTAMP_FILTER_NONE && !rx_filt;
 
        mask = cpu_to_le64(rx_filt);
        if ((ionic->ident.lif.eth.hwstamp_rx_filters & mask) != mask) {
                rx_filt = 0;
                rx_all = true;
-               config.rx_filter = HWTSTAMP_FILTER_ALL;
+               config->rx_filter = HWTSTAMP_FILTER_ALL;
        }
 
        dev_dbg(ionic->dev, "config_rx_filter %d rx_filt %#llx rx_all %d\n",
-               config.rx_filter, rx_filt, rx_all);
+               config->rx_filter, rx_filt, rx_all);
 
        mutex_lock(&lif->phc->config_lock);
 
@@ -141,15 +148,7 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr)
                        goto err_rxall;
        }
 
-       if (ifr) {
-               err = copy_to_user(ifr->ifr_data, &config, sizeof(config));
-               if (err) {
-                       err = -EFAULT;
-                       goto err_final;
-               }
-       }
-
-       memcpy(&lif->phc->ts_config, &config, sizeof(config));
+       memcpy(&lif->phc->ts_config, config, sizeof(*config));
        lif->phc->ts_config_rx_filt = rx_filt;
        lif->phc->ts_config_tx_mode = tx_mode;
 
@@ -157,14 +156,6 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr)
 
        return 0;
 
-err_final:
-       if (rx_all != (lif->phc->ts_config.rx_filter == HWTSTAMP_FILTER_ALL)) {
-               rx_all = lif->phc->ts_config.rx_filter == HWTSTAMP_FILTER_ALL;
-               err2 = ionic_lif_config_hwstamp_rxq_all(lif, rx_all);
-               if (err2)
-                       dev_err(ionic->dev,
-                               "Failed to revert all-rxq timestamp config: %d\n", err2);
-       }
 err_rxall:
        if (rx_filt != lif->phc->ts_config_rx_filt) {
                rx_filt = lif->phc->ts_config_rx_filt;
@@ -188,6 +179,37 @@ err_queues:
        return err;
 }
 
+int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr)
+{
+       struct hwtstamp_config config;
+       int err;
+
+       if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+               return -EFAULT;
+
+       err = ionic_lif_hwstamp_set_ts_config(lif, &config);
+       if (err) {
+               netdev_info(lif->netdev, "hwstamp set failed: %d\n", err);
+               return err;
+       }
+
+       if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
+               return -EFAULT;
+
+       return 0;
+}
+
+int ionic_lif_hwstamp_replay(struct ionic_lif *lif)
+{
+       int err;
+
+       err = ionic_lif_hwstamp_set_ts_config(lif, NULL);
+       if (err)
+               netdev_info(lif->netdev, "hwstamp replay failed: %d\n", err);
+
+       return err;
+}
+
 int ionic_lif_hwstamp_get(struct ionic_lif *lif, struct ifreq *ifr)
 {
        struct hwtstamp_config config;