From 33c252e1ba8b9ba00831bc520f7017c816429179 Mon Sep 17 00:00:00 2001 From: Shannon Nelson <snelson@pensando.io> Date: Wed, 7 Apr 2021 16:19:54 -0700 Subject: [PATCH 1/8] ionic: fix up a couple of code style nits Clean up variable declarations. 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 | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index ee56fed12e07..4e22e50922cd 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -2015,9 +2015,8 @@ static void ionic_txrx_free(struct ionic_lif *lif) static int ionic_txrx_alloc(struct ionic_lif *lif) { - unsigned int num_desc, desc_sz, comp_sz, sg_desc_sz; - unsigned int flags; - unsigned int i; + unsigned int comp_sz, desc_sz, num_desc, sg_desc_sz; + unsigned int flags, i; int err = 0; num_desc = lif->ntxq_descs; @@ -2584,12 +2583,11 @@ static void ionic_swap_queues(struct ionic_qcq *a, struct ionic_qcq *b) int ionic_reconfigure_queues(struct ionic_lif *lif, struct ionic_queue_params *qparam) { - unsigned int num_desc, desc_sz, comp_sz, sg_desc_sz; + unsigned int comp_sz, desc_sz, num_desc, sg_desc_sz; struct ionic_qcq **tx_qcqs = NULL; struct ionic_qcq **rx_qcqs = NULL; - unsigned int flags; + unsigned int flags, i; int err = -ENOMEM; - unsigned int i; /* allocate temporary qcq arrays to hold new queue structs */ if (qparam->nxqs != lif->nxqs || qparam->ntxq_descs != lif->ntxq_descs) { From e1edcc966ae8579b76db720a94084866bd7dcd6c Mon Sep 17 00:00:00 2001 From: Shannon Nelson <snelson@pensando.io> Date: Wed, 7 Apr 2021 16:19:55 -0700 Subject: [PATCH 2/8] ionic: remove unnecessary compat ifdef We don't need to look for HAVE_HWSTAMP_TX_ONESTEP_P2P in the upstream kernel. Signed-off-by: Shannon Nelson <snelson@pensando.io> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/ethernet/pensando/ionic/ionic_phc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_phc.c b/drivers/net/ethernet/pensando/ionic/ionic_phc.c index 86ae5011ac9b..5d5da61284e7 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_phc.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_phc.c @@ -18,10 +18,8 @@ static int ionic_hwstamp_tx_mode(int config_tx_type) return IONIC_TXSTAMP_ON; case HWTSTAMP_TX_ONESTEP_SYNC: return IONIC_TXSTAMP_ONESTEP_SYNC; -#ifdef HAVE_HWSTAMP_TX_ONESTEP_P2P case HWTSTAMP_TX_ONESTEP_P2P: return IONIC_TXSTAMP_ONESTEP_P2P; -#endif default: return -ERANGE; } From e2ce148e948e7cf6267351ea407ac45a6b561a54 Mon Sep 17 00:00:00 2001 From: Shannon Nelson <snelson@pensando.io> Date: Wed, 7 Apr 2021 16:19:56 -0700 Subject: [PATCH 3/8] ionic: check for valid tx_mode on SKBTX_HW_TSTAMP xmit Make sure the device is in a Tx offload mode before calling the hwstamp offload xmit. Signed-off-by: Shannon Nelson <snelson@pensando.io> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/ethernet/pensando/ionic/ionic_txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c index 3478b0f2495f..765050a5f7a8 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c @@ -1233,7 +1233,7 @@ netdev_tx_t ionic_start_xmit(struct sk_buff *skb, struct net_device *netdev) } if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) - if (lif->hwstamp_txq) + if (lif->hwstamp_txq && lif->phc->ts_config_tx_mode) return ionic_start_hwstamp_xmit(skb, netdev); if (unlikely(queue_index >= lif->nxqs)) From bd7856bcd498498a91b275904b9aa43882cf85a0 Mon Sep 17 00:00:00 2001 From: Shannon Nelson <snelson@pensando.io> Date: Wed, 7 Apr 2021 16:19:57 -0700 Subject: [PATCH 4/8] ionic: add SKBTX_IN_PROGRESS Set the SKBTX_IN_PROGRESS when offloading the Tx timestamp. Signed-off-by: Shannon Nelson <snelson@pensando.io> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/ethernet/pensando/ionic/ionic_txrx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c index 765050a5f7a8..08934888575c 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c @@ -1203,6 +1203,7 @@ static netdev_tx_t ionic_start_hwstamp_xmit(struct sk_buff *skb, if (unlikely(!ionic_q_has_space(q, ndescs))) goto err_out_drop; + skb_shinfo(skb)->tx_flags |= SKBTX_HW_TSTAMP; if (skb_is_gso(skb)) err = ionic_tx_tso(q, skb); else From 51117874554d7883c9b8051d361cb6a5c847c31a Mon Sep 17 00:00:00 2001 From: Shannon Nelson <snelson@pensando.io> Date: Wed, 7 Apr 2021 16:19:58 -0700 Subject: [PATCH 5/8] ionic: re-start ptp after queues up When returning after a firmware reset, re-start the PTP after we've restarted the general queues. 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 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index 4e22e50922cd..8cf6477b9899 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -2987,14 +2987,14 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif) goto err_txrx_free; } - /* restore the hardware timestamping queues */ - ionic_lif_hwstamp_set(lif, NULL); - clear_bit(IONIC_LIF_F_FW_RESET, lif->state); ionic_link_status_check_request(lif, CAN_SLEEP); netif_device_attach(lif->netdev); dev_info(ionic->dev, "FW Up: LIFs restarted\n"); + /* restore the hardware timestamping queues */ + ionic_lif_hwstamp_set(lif, NULL); + return; err_txrx_free: From 99b5bea04f0f0dc9e6278536a269e1f4795b73e1 Mon Sep 17 00:00:00 2001 From: Shannon Nelson <snelson@pensando.io> Date: Wed, 7 Apr 2021 16:19:59 -0700 Subject: [PATCH 6/8] ionic: ignore EBUSY on queue start When starting the queues in the link-check, don't go into the BROKEN state if the return was EBUSY. 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 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index 8cf6477b9899..eae774c0a2d9 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -135,7 +135,7 @@ static void ionic_link_status_check(struct ionic_lif *lif) if (netdev->flags & IFF_UP && netif_running(netdev)) { mutex_lock(&lif->queue_lock); err = ionic_start_queues(lif); - if (err) { + if (err && err != -EBUSY) { netdev_err(lif->netdev, "Failed to start queues: %d\n", err); set_bit(IONIC_LIF_F_BROKEN, lif->state); From 829600ce5e4e985a8a49c445c5e5c72ca613ce41 Mon Sep 17 00:00:00 2001 From: Shannon Nelson <snelson@pensando.io> Date: Wed, 7 Apr 2021 16:20:00 -0700 Subject: [PATCH 7/8] 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> --- .../net/ethernet/pensando/ionic/ionic_lif.c | 2 +- .../net/ethernet/pensando/ionic/ionic_lif.h | 6 ++ .../net/ethernet/pensando/ionic/ionic_phc.c | 84 ++++++++++++------- 3 files changed, 60 insertions(+), 32 deletions(-) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index eae774c0a2d9..af3a5368529c 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -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; diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h index ea3b086af179..346506f01715 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h @@ -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; diff --git a/drivers/net/ethernet/pensando/ionic/ionic_phc.c b/drivers/net/ethernet/pensando/ionic/ionic_phc.c index 5d5da61284e7..2bb749097d9e 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_phc.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_phc.c @@ -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; From f3318099658edcc899b95cdf54257edd428e7fbb Mon Sep 17 00:00:00 2001 From: Shannon Nelson <snelson@pensando.io> Date: Wed, 7 Apr 2021 16:20:01 -0700 Subject: [PATCH 8/8] ionic: extend ts_config set locking Make sure the configuration is locked before operating on it for the replay. Signed-off-by: Shannon Nelson <snelson@pensando.io> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/ethernet/pensando/ionic/ionic_phc.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_phc.c b/drivers/net/ethernet/pensando/ionic/ionic_phc.c index 2bb749097d9e..177dbf89affd 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_phc.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_phc.c @@ -79,6 +79,8 @@ static int ionic_lif_hwstamp_set_ts_config(struct ionic_lif *lif, if (!lif->phc || !lif->phc->ptp) return -EOPNOTSUPP; + mutex_lock(&lif->phc->config_lock); + if (new_ts) { config = new_ts; } else { @@ -96,12 +98,16 @@ static int ionic_lif_hwstamp_set_ts_config(struct ionic_lif *lif, } tx_mode = ionic_hwstamp_tx_mode(config->tx_type); - if (tx_mode < 0) - return tx_mode; + if (tx_mode < 0) { + err = tx_mode; + goto err_queues; + } mask = cpu_to_le64(BIT_ULL(tx_mode)); - if ((ionic->ident.lif.eth.hwstamp_tx_modes & mask) != mask) - return -ERANGE; + if ((ionic->ident.lif.eth.hwstamp_tx_modes & mask) != mask) { + err = -ERANGE; + goto err_queues; + } rx_filt = ionic_hwstamp_rx_filt(config->rx_filter); rx_all = config->rx_filter != HWTSTAMP_FILTER_NONE && !rx_filt; @@ -116,8 +122,6 @@ static int ionic_lif_hwstamp_set_ts_config(struct ionic_lif *lif, dev_dbg(ionic->dev, "config_rx_filter %d rx_filt %#llx rx_all %d\n", config->rx_filter, rx_filt, rx_all); - mutex_lock(&lif->phc->config_lock); - if (tx_mode) { err = ionic_lif_create_hwstamp_txq(lif); if (err)