Commit 829600ce authored by Shannon Nelson's avatar Shannon Nelson Committed by David S. Miller

ionic: add ts_config replay

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: default avatarShannon Nelson <snelson@pensando.io>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 99b5bea0
...@@ -2993,7 +2993,7 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif) ...@@ -2993,7 +2993,7 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif)
dev_info(ionic->dev, "FW Up: LIFs restarted\n"); dev_info(ionic->dev, "FW Up: LIFs restarted\n");
/* restore the hardware timestamping queues */ /* restore the hardware timestamping queues */
ionic_lif_hwstamp_set(lif, NULL); ionic_lif_hwstamp_replay(lif);
return; return;
......
...@@ -302,6 +302,7 @@ int ionic_lif_identify(struct ionic *ionic, u8 lif_type, ...@@ -302,6 +302,7 @@ int ionic_lif_identify(struct ionic *ionic, u8 lif_type,
int ionic_lif_size(struct ionic *ionic); int ionic_lif_size(struct ionic *ionic);
#if IS_ENABLED(CONFIG_PTP_1588_CLOCK) #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_set(struct ionic_lif *lif, struct ifreq *ifr);
int ionic_lif_hwstamp_get(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); 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); ...@@ -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_alloc_phc(struct ionic_lif *lif);
void ionic_lif_free_phc(struct ionic_lif *lif); void ionic_lif_free_phc(struct ionic_lif *lif);
#else #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) static inline int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
......
...@@ -64,10 +64,12 @@ static u64 ionic_hwstamp_rx_filt(int config_rx_filter) ...@@ -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 ionic *ionic = lif->ionic;
struct hwtstamp_config config; struct hwtstamp_config *config;
struct hwtstamp_config ts;
int tx_mode = 0; int tx_mode = 0;
u64 rx_filt = 0; u64 rx_filt = 0;
int err, err2; int err, err2;
...@@ -77,18 +79,23 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr) ...@@ -77,18 +79,23 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr)
if (!lif->phc || !lif->phc->ptp) if (!lif->phc || !lif->phc->ptp)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (ifr) { if (new_ts) {
if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) config = new_ts;
return -EFAULT;
} else { } else {
/* if called with ifr == NULL, behave as if called with the /* If called with new_ts == NULL, replay the previous request
* current ts_config from the initial cleared state. * 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)); config = &ts;
memset(&lif->phc->ts_config, 0, sizeof(config)); 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) if (tx_mode < 0)
return tx_mode; return tx_mode;
...@@ -96,18 +103,18 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr) ...@@ -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) if ((ionic->ident.lif.eth.hwstamp_tx_modes & mask) != mask)
return -ERANGE; return -ERANGE;
rx_filt = ionic_hwstamp_rx_filt(config.rx_filter); rx_filt = ionic_hwstamp_rx_filt(config->rx_filter);
rx_all = config.rx_filter != HWTSTAMP_FILTER_NONE && !rx_filt; rx_all = config->rx_filter != HWTSTAMP_FILTER_NONE && !rx_filt;
mask = cpu_to_le64(rx_filt); mask = cpu_to_le64(rx_filt);
if ((ionic->ident.lif.eth.hwstamp_rx_filters & mask) != mask) { if ((ionic->ident.lif.eth.hwstamp_rx_filters & mask) != mask) {
rx_filt = 0; rx_filt = 0;
rx_all = true; 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", 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); mutex_lock(&lif->phc->config_lock);
...@@ -141,15 +148,7 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr) ...@@ -141,15 +148,7 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr)
goto err_rxall; goto err_rxall;
} }
if (ifr) { memcpy(&lif->phc->ts_config, config, sizeof(*config));
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));
lif->phc->ts_config_rx_filt = rx_filt; lif->phc->ts_config_rx_filt = rx_filt;
lif->phc->ts_config_tx_mode = tx_mode; lif->phc->ts_config_tx_mode = tx_mode;
...@@ -157,14 +156,6 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr) ...@@ -157,14 +156,6 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr)
return 0; 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: err_rxall:
if (rx_filt != lif->phc->ts_config_rx_filt) { if (rx_filt != lif->phc->ts_config_rx_filt) {
rx_filt = lif->phc->ts_config_rx_filt; rx_filt = lif->phc->ts_config_rx_filt;
...@@ -188,6 +179,37 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr) ...@@ -188,6 +179,37 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr)
return err; 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) int ionic_lif_hwstamp_get(struct ionic_lif *lif, struct ifreq *ifr)
{ {
struct hwtstamp_config config; struct hwtstamp_config config;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment