mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
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: Shannon Nelson <snelson@pensando.io> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
99b5bea04f
commit
829600ce5e
3 changed files with 60 additions and 32 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr)
|
|||
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;
|
||||
|
|
Loading…
Reference in a new issue