> Subject: [PATCH 5/5] net/iavf: improve VF reset detection on fast ARQ flip
> 
> During PF-initiated reset or a remote/ToR switch link-flap,
> the PF toggles the admin receive queue enable bit (ARQLEN1)
> so quickly around a VF reset that the VF's sampling window
> misses it, leaving the PF and the VF states out of sync
> and the data path stalled.
> 
> Complement the ARQLEN1 check with VFGEN_RSTAT
> (VIRTCHNL_VFR_INPROGRESS) and shorten the poll interval to
> 5 ms (with a proportionally larger count, keeping the ~10 s
> budget), matching the Linux kernel iavf driver.
> When the VFR is still not observed, proceed with recovery
> instead of bailing out so the PF and  the VF states converge.
> 
> Fixes: ada64daa1a5b ("net/iavf: fix VF reset for flow director rule")
> Fixes: 80fb3c920458 ("net/iavf: fix crash on VF start")
> Cc: [email protected]
> 
> Signed-off-by: Anurag Mandal <[email protected]>
> ---
>  drivers/net/intel/iavf/iavf.h        |  1 +
>  drivers/net/intel/iavf/iavf_ethdev.c | 41 +++++++++++++++++++++-------
>  2 files changed, 32 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/net/intel/iavf/iavf.h b/drivers/net/intel/iavf/iavf.h
> index 037bc8436f..5e49e81447 100644
> --- a/drivers/net/intel/iavf/iavf.h
> +++ b/drivers/net/intel/iavf/iavf.h
> @@ -21,6 +21,7 @@
>  #define IAVF_AQ_BUF_SZ            4096
>  #define IAVF_RESET_WAIT_CNT       2000
>  #define IAVF_RESET_DETECTED_CNT   500
> +#define IAVF_RESET_POLL_SCALE     4  /* Poll-interval scale for reset 
> detection
> */
>  #define IAVF_BUF_SIZE_MIN         1024
>  #define IAVF_FRAME_SIZE_MAX       9728
>  #define IAVF_QUEUE_BASE_ADDR_UNIT 128
> diff --git a/drivers/net/intel/iavf/iavf_ethdev.c
> b/drivers/net/intel/iavf/iavf_ethdev.c
> index f6ce339b0c..21bac51467 100644
> --- a/drivers/net/intel/iavf/iavf_ethdev.c
> +++ b/drivers/net/intel/iavf/iavf_ethdev.c
> @@ -3235,7 +3235,9 @@ iavf_dev_close(struct rte_eth_dev *dev)
>       /* remove RSS configuration */
>       iavf_hash_uninit(adapter);
> 
> -     iavf_flow_flush(dev, NULL);
> +     /* Skip the virtchnl-emitting teardown on a PF-initiated reset */
> +     if (!vf->pf_reset_in_progress)
> +             iavf_flow_flush(dev, NULL);

This seems like a valid change but unrelated to the rest of the commit.
Consider splitting it out.

>       iavf_flow_uninit(adapter);
> 
>       /*
> @@ -3358,8 +3360,26 @@ iavf_dev_reset(struct rte_eth_dev *dev)
>  static inline bool
>  iavf_is_reset(struct iavf_hw *hw)
>  {
> -     return !(IAVF_READ_REG(hw, IAVF_VF_ARQLEN1) &
> -             IAVF_VF_ARQLEN1_ARQENABLE_MASK);
> +     uint32_t rstat;
> +
> +     /* ARQ has been disabled by the PF as part of the VFR. */
> +     if (!(IAVF_READ_REG(hw, IAVF_VF_ARQLEN1) &
> +             IAVF_VF_ARQLEN1_ARQENABLE_MASK))
> +             return true;
> +
> +     /*
> +      * VFGEN_RSTAT reports VIRTCHNL_VFR_INPROGRESS.
> +      * At times, the PF flips ARQENABLE so quickly
> +      * around a VFR that the ARQLEN1 sample window
> +      * misses it. Using VFGEN_RSTAT, as a
> +      * complementary indicator, prevents from
> +      * missing a reset that really did happen.
> +      */
> +     rstat = (IAVF_READ_REG(hw, IAVF_VFGEN_RSTAT) &
> +              IAVF_VFGEN_RSTAT_VFR_STATE_MASK) >>
> +             IAVF_VFGEN_RSTAT_VFR_STATE_SHIFT;
> +
> +     return rstat == VIRTCHNL_VFR_INPROGRESS;
>  }
> 
>  static bool
> @@ -3368,11 +3388,14 @@ iavf_is_reset_detected(struct iavf_adapter
> *adapter)
>       struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(adapter);
>       int i;
> 
> -     /* poll until we see the reset actually happen */
> -     for (i = 0; i < IAVF_RESET_DETECTED_CNT; i++) {
> +     /*
> +      * Poll until the reset actually happen.
> +      * Poll every 5 ms to catch the fast ARQ flips.
> +      */
> +     for (i = 0; i < IAVF_RESET_DETECTED_CNT * IAVF_RESET_POLL_SCALE;
> i++) {
>               if (iavf_is_reset(hw))
>                       return true;
> -             rte_delay_ms(20);
> +             rte_delay_us(5000);
>       }
> 
>       return false;
> @@ -3423,10 +3446,8 @@ iavf_handle_hw_reset(struct rte_eth_dev *dev,
> bool vf_initiated_reset)
>               if (!dev->data->dev_started)
>                       return;
> 
> -             if (!iavf_is_reset_detected(adapter)) {
> -                     PMD_DRV_LOG(DEBUG, "reset not start");
> -                     return;
> -             }
> +             if (!iavf_is_reset_detected(adapter))
> +                     PMD_DRV_LOG(WARNING, "VFR not observed;
> recovering anyway");
>       }
> 
>       vf->in_reset_recovery = true;
> --
> 2.34.1

Reply via email to