RE: [PATCH 2/5] net/iavf: defer device start when PF VSI not ready

"Loftus, Ciara" <[email protected]>
Newsgroups org.dpdk.dev
Message-ID <IA4PR11MB927865ADBA29A49F57FECA118ED12@IA4PR11MB9278.namprd11.prod.outlook.com>
> Subject: [PATCH 2/5] net/iavf: defer device start when PF VSI not ready
> 
> During reset recovery iavf_dev_start() might fail (typically -EIO
> from VIRTCHNL_OP_CONFIG_VSI_QUEUES) because the PF VSI is not yet
> active, leaving the VF down and requiring manual intervention
> to recover.
> 
> Added a start_pending flag: when device start fails during recovery,
> defer it instead of erroring out and resume it from newly added
> iavf_resume_pending_start() on the next link-up event, so the
> VF comes back automatically.

It sounds like a fix, can you add a Fixes tag?

> 
> Signed-off-by: Anurag Mandal <[email protected]>
> ---
>  drivers/net/intel/iavf/iavf.h        |  2 +
>  drivers/net/intel/iavf/iavf_ethdev.c | 56 ++++++++++++++++++++++++++--
>  drivers/net/intel/iavf/iavf_vchnl.c  | 16 +++++++-
>  3 files changed, 69 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/intel/iavf/iavf.h b/drivers/net/intel/iavf/iavf.h
> index 293adaf6c9..e76c3bb410 100644
> --- a/drivers/net/intel/iavf/iavf.h
> +++ b/drivers/net/intel/iavf/iavf.h
> @@ -293,6 +293,7 @@ struct iavf_info {
>  	bool in_reset_recovery;
>  	bool reset_pending;
>  	bool pf_reset_in_progress;
> +	bool start_pending;
> 
>  	uint32_t ptp_caps;
>  	rte_spinlock_t phc_time_aq_lock;
> @@ -533,4 +534,5 @@ void iavf_handle_hw_reset(struct rte_eth_dev *dev,
> bool vf_initiated_reset);
>  void iavf_set_no_poll(struct iavf_adapter *adapter, bool link_change);
>  bool is_iavf_supported(struct rte_eth_dev *dev);
>  void iavf_hash_uninit(struct iavf_adapter *ad);
> +void iavf_resume_pending_start(struct rte_eth_dev *dev);
>  #endif /* _IAVF_ETHDEV_H_ */
> diff --git a/drivers/net/intel/iavf/iavf_ethdev.c
> b/drivers/net/intel/iavf/iavf_ethdev.c
> index e475b64971..87b826c873 100644
> --- a/drivers/net/intel/iavf/iavf_ethdev.c
> +++ b/drivers/net/intel/iavf/iavf_ethdev.c
> @@ -1093,6 +1093,9 @@ iavf_dev_start(struct rte_eth_dev *dev)
> 
>  	iavf_phc_sync_alarm_start(dev);
> 
> +	/* An explicit start supersedes any pending deferred start */
> +	vf->start_pending = false;
> +
>  	return 0;
> 
>  error:
> @@ -1131,6 +1134,9 @@ iavf_dev_stop(struct rte_eth_dev *dev)
>  	adapter->stopped = 1;
>  	dev->data->dev_started = 0;
> 
> +	/* An explicit stop cancels any pending deferred start */
> +	vf->start_pending = false;
> +
>  	return 0;
>  }
> 
> @@ -3425,6 +3431,7 @@ iavf_handle_hw_reset(struct rte_eth_dev *dev,
> bool vf_initiated_reset)
> 
>  	vf->in_reset_recovery = true;
>  	vf->pf_reset_in_progress = !vf_initiated_reset;
> +	vf->start_pending = false;
>  	iavf_set_no_poll(adapter, false);
> 
>  	/* Call the pre reset callback */
> @@ -3445,10 +3452,17 @@ iavf_handle_hw_reset(struct rte_eth_dev *dev,
> bool vf_initiated_reset)
>  	if (!vf_initiated_reset || restart_device) {
>  		/* start the device */
>  		ret = iavf_dev_start(dev);
> -		if (ret)
> -			goto error;
> -
> -		dev->data->dev_started = 1;
> +		if (ret == 0) {
> +			dev->data->dev_started = 1;
> +		} else {
> +			PMD_DRV_LOG(WARNING,
> +				    "dev_start failed during reset recovery
> (rc=%d);"
> +				    "deferring to next link-up event",
> +				    ret);
> +			vf->start_pending = true;
> +			dev->data->dev_started = 0;
> +			ret = 0;
> +		}
>  	}
> 
>  	/* Restore settings after the reset */
> @@ -3662,6 +3676,40 @@ bool is_iavf_supported(struct rte_eth_dev *dev)
>  	return !strcmp(dev->device->driver->name,
> rte_iavf_pmd.driver.name);
>  }
> 
> +void
> +iavf_resume_pending_start(struct rte_eth_dev *dev)
> +{
> +	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data-
> >dev_private);
> +	int ret;
> +
> +	if (!vf->start_pending)
> +		return;
> +	/*
> +	 * If the application has already (re)started the port itself, the
> +	 * deferred start is stale, the application's action is honoured
> +	 * and resume pending is dropped to avoid starting an
> +	 * already-running port a second time.
> +	 */
> +	if (dev->data->dev_started) {
> +		vf->start_pending = false;
> +		return;
> +	}
> +
> +	if (!vf->link_up)
> +		return;
> +
> +	PMD_DRV_LOG(DEBUG, "PF link back up; resuming deferred
> dev_start");
> +	ret = iavf_dev_start(dev);

This call to iavf_dev_start could result in another nested call to
iavf_resume_pending_start which would be problematic.
iavf_dev_start polls the ARQ eg.

iavf_dev_start -> iavf_configure_queues -> iavf_execute_vf_cmd_safe ->
iavf_wait_for_msg -> iavf_read_msg_from_pf -> iavf_clean_arq_element

If another LSC happens during this time, you could enter
iavf_handle_link_change_event again and end up calling
iavf_resume_pending_start again. It can maybe be prevented by clearing the
pending flag at the beginning of iavf_resume_pending_start and setting it
again if the start fails.

> +	if (ret == 0) {
> +		dev->data->dev_started = 1;
> +		vf->start_pending = false;
> +	} else {
> +		PMD_DRV_LOG(ERR,
> +			    "deferred dev_start failed (ret=%d); will retry on
> next link-up",
> +			    ret);
> +	}
> +}
> +
>  RTE_PMD_REGISTER_PCI(net_iavf, rte_iavf_pmd);
>  RTE_PMD_REGISTER_PCI_TABLE(net_iavf, pci_id_iavf_map);
>  RTE_PMD_REGISTER_KMOD_DEP(net_iavf, "* igb_uio | vfio-pci");
> diff --git a/drivers/net/intel/iavf/iavf_vchnl.c
> b/drivers/net/intel/iavf/iavf_vchnl.c
> index 56918ebcc1..8e102b02aa 100644
> --- a/drivers/net/intel/iavf/iavf_vchnl.c
> +++ b/drivers/net/intel/iavf/iavf_vchnl.c
> @@ -260,7 +260,7 @@ iavf_handle_link_change_event(struct rte_eth_dev
> *dev,
>  	 * (link is down or a VF reset is in progress); the watchdog drives
>  	 * auto-reset recovery, so it must remain armed in those cases.
>  	 */
> -	if (vf->link_up && !vf->vf_reset)
> +	if (vf->link_up && !vf->vf_reset && !vf->in_reset_recovery)

Is this change relevant to the rest of this patch?

>  		iavf_dev_watchdog_disable(adapter);
>  	else
>  		iavf_dev_watchdog_enable(adapter);
> @@ -271,6 +271,20 @@ iavf_handle_link_change_event(struct rte_eth_dev
> *dev,
>  			    adapter->no_poll ? "on" : "off");
>  	}
> 
> +	/*
> +	 * Resume a deferred dev_start.
> +	 * iavf_handle_hw_reset() sets vf->start_pending when
> +	 * reset recovery completed dev_init() but iavf_dev_start()
> +	 * itself failed (typically -EIO from
> VIRTCHNL_OP_CONFIG_VSI_QUEUES
> +	 * when the PF VSI was inactive).
> +	 * A link-up event implies the PF VSI is active again, so retry now.
> +	 * Run before the LSC event post so the port is ready to accept Tx
> +	 * by the time the app's link-up callback fires; no_poll has already
> +	 * been cleared above so bursts go through as soon as
> +	 * dev_start sets dev_started=1.
> +	 */

I think this comment is verbose, consider shortening it.

> +	iavf_resume_pending_start(dev);
> +
>  	iavf_dev_event_post(dev, RTE_ETH_EVENT_INTR_LSC, NULL, 0);
> 
>  	PMD_DRV_LOG(INFO, "Link status update:%s",
> --
> 2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.