Re: [PATCH v2] PCI SRIOV device enable and disable via sysfs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 17 Dec 2012 16:24:39 -0700
Bjorn Helgaas <bhelgaas@xxxxxxxxxx> wrote:

> On Mon, Dec 17, 2012 at 02:59:15PM -0500, Don Dutile wrote:
> > On 12/14/2012 01:19 PM, Greg Rose wrote:
> > >pci: Fix return code
> > >
> > >From: Greg Rose<gregory.v.rose@xxxxxxxxx>
> > >
> > >The return code from the sriov configure function was only
> > >returned if it was less than zero indicating an error.  This
> > >caused the code to fall through to the default return of an error
> > >code even though the sriov configure function has returned the
> > >number of VFs it created - a positive number indicating success.
> > >
> > >
> > >Signed-off-by: Greg Rose<gregory.v.rose@xxxxxxxxx>
> > 
> > Actually, it returned the number of VFs enabled if it exactly
> > equalled the number to be enabled.  Otherwise, the basic testing
> > would have failed. If the number of vf's enabled was positive but
> > not the same as the number requested-to-be-enabled, then it
> > incorrectly returned.
> > 
> > But, the patch corrects the base problem, so
> > Acked-by: Donald Dutile <ddutile@xxxxxxxxxx>
> 
> Alternate proposal below.  The patch is ugly; it might be easier to
> compare the before (http://pastebin.com/zneG8AuD) and after
> (http://pastebin.com/BEXEE8kc) versions.
> 
> commit fae71e5dc9064dcb3077b8da6e0ed9d800c1f527
> Author: Bjorn Helgaas <bhelgaas@xxxxxxxxxx>
> Date:   Thu Dec 13 20:22:44 2012 -0700
> 
>     PCI: Cleanup sriov_numvfs_show() and handle common case without
> error 
>     If we request "num_vfs" and the driver's sriov_configure() method
> enables exactly that number ("num_vfs_enabled"), we complain "Invalid
> value for number of VFs to enable" and return an error.  We should
> silently return success instead.
>     
>     Also, use kstrtou16() since numVFs is defined to be a 16-bit
> field and rework to simplify control flow.
>     
>     Reported-by: Greg Rose <gregory.v.rose@xxxxxxxxx>
>     Link: http://lkml.kernel.org/r/20121214101911.00002f59@unknown
>     Signed-off-by: Bjorn Helgaas <bhelgaas@xxxxxxxxxx>
> 
> diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
> index 05b78b1..5e8af12 100644
> --- a/drivers/pci/pci-sysfs.c
> +++ b/drivers/pci/pci-sysfs.c
> @@ -422,77 +422,60 @@ static ssize_t sriov_numvfs_show(struct device
> *dev, }
>  
>  /*
> - * num_vfs > 0; number of vfs to enable
> - * num_vfs = 0; disable all vfs
> + * num_vfs > 0; number of VFs to enable
> + * num_vfs = 0; disable all VFs
>   *
>   * Note: SRIOV spec doesn't allow partial VF
> - *       disable, so its all or none.
> + *       disable, so it's all or none.
>   */
>  static ssize_t sriov_numvfs_store(struct device *dev,
>  				  struct device_attribute *attr,
>  				  const char *buf, size_t count)
>  {
>  	struct pci_dev *pdev = to_pci_dev(dev);
> -	int num_vfs_enabled = 0;
> -	int num_vfs;
> -	int ret = 0;
> -	u16 total;
> +	int ret;
> +	u16 num_vfs;
>  
> -	if (kstrtoint(buf, 0, &num_vfs) < 0)
> -		return -EINVAL;
> +	ret = kstrtou16(buf, 0, &num_vfs);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (num_vfs > pci_sriov_get_totalvfs(pdev))
> +		return -ERANGE;
> +
> +	if (num_vfs == pdev->sriov->num_VFs)
> +		return count;		/* no change */
>  
>  	/* is PF driver loaded w/callback */
>  	if (!pdev->driver || !pdev->driver->sriov_configure) {
> -		dev_info(&pdev->dev,
> -			 "Driver doesn't support SRIOV configuration
> via sysfs\n");
> +		dev_info(&pdev->dev, "Driver doesn't support SRIOV
> configuration via sysfs\n"); return -ENOSYS;
>  	}
>  
> -	/* if enabling vf's ... */
> -	total = pci_sriov_get_totalvfs(pdev);
> -	/* Requested VFs to enable < totalvfs and none enabled
> already */
> -	if ((num_vfs > 0) && (num_vfs <= total)) {
> -		if (pdev->sriov->num_VFs == 0) {
> -			num_vfs_enabled =
> -				pdev->driver->sriov_configure(pdev,
> num_vfs);
> -			if ((num_vfs_enabled >= 0) &&
> -			    (num_vfs_enabled != num_vfs)) {
> -				dev_warn(&pdev->dev,
> -					 "Only %d VFs enabled\n",
> -					 num_vfs_enabled);
> -				return count;
> -			} else if (num_vfs_enabled < 0)
> -				/* error code from driver callback */
> -				return num_vfs_enabled;
> -		} else if (num_vfs == pdev->sriov->num_VFs) {
> -			dev_warn(&pdev->dev,
> -				 "%d VFs already enabled; no enable
> action taken\n",
> -				 num_vfs);
> -			return count;
> -		} else {
> -			dev_warn(&pdev->dev,
> -				 "%d VFs already enabled. Disable
> before enabling %d VFs\n",
> -				 pdev->sriov->num_VFs, num_vfs);
> -			return -EINVAL;
> -		}
> +	if (num_vfs == 0) {
> +		/* disable VFs */
> +		ret = pdev->driver->sriov_configure(pdev, 0);
> +		if (ret < 0)
> +			return ret;
> +		return count;
>  	}
>  
> -	/* disable vfs */
> -	if (num_vfs == 0) {
> -		if (pdev->sriov->num_VFs != 0) {
> -			ret = pdev->driver->sriov_configure(pdev, 0);
> -			return ret ? ret : count;
> -		} else {
> -			dev_warn(&pdev->dev,
> -				 "All VFs disabled; no disable
> action taken\n");
> -			return count;
> -		}
> +	/* enable VFs */
> +	if (pdev->sriov->num_VFs) {
> +		dev_warn(&pdev->dev, "%d VFs already enabled.
> Disable before enabling %d VFs\n",
> +			 pdev->sriov->num_VFs, num_vfs);
> +		return -EINVAL;
>  	}

Maybe return -EPERM instead?

>  
> -	dev_err(&pdev->dev,
> -		"Invalid value for number of VFs to enable: %d\n",
> num_vfs);
> +	ret = pdev->driver->sriov_configure(pdev, num_vfs);
> +	if (ret < 0)
> +		return ret;
>  
> -	return -EINVAL;
> +	if (ret != num_vfs)
> +		dev_warn(&pdev->dev, "%d VFs requested; only %d
> enabled\n",
> +			 num_vfs, ret);
> +
> +	return count;
>  }
>  
>  static struct device_attribute sriov_totalvfs_attr =
> __ATTR_RO(sriov_totalvfs);

Looks good to me.

Thanks,

- Greg


--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux