Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 343258
b: refs/heads/master
c: 1789382
h: refs/heads/master
v: v3
  • Loading branch information
Donald Dutile authored and Bjorn Helgaas committed Nov 10, 2012
1 parent ea7d4fc commit 10be9ac
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 625e1d59a89f50bace376f429d8cf50347af75f7
refs/heads/master: 1789382a72a537447d65ea4131d8bcc1ad85ce7b
127 changes: 127 additions & 0 deletions trunk/drivers/pci/pci-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,106 @@ static ssize_t d3cold_allowed_show(struct device *dev,
}
#endif

#ifdef CONFIG_PCI_IOV
static ssize_t sriov_totalvfs_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct pci_dev *pdev = to_pci_dev(dev);

return sprintf(buf, "%u\n", pdev->sriov->total);
}


static ssize_t sriov_numvfs_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct pci_dev *pdev = to_pci_dev(dev);

return sprintf(buf, "%u\n", pdev->sriov->nr_virtfn);
}

/*
* 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.
*/
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;

if (kstrtoint(buf, 0, &num_vfs) < 0)
return -EINVAL;

/* 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");
return -ENOSYS;
}

/* if enabling vf's ... */
total = pdev->sriov->total;
/* Requested VFs to enable < totalvfs and none enabled already */
if ((num_vfs > 0) && (num_vfs <= total)) {
if (pdev->sriov->nr_virtfn == 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->nr_virtfn) {
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->nr_virtfn, num_vfs);
return -EINVAL;
}
}

/* disable vfs */
if (num_vfs == 0) {
if (pdev->sriov->nr_virtfn != 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;
}
}

dev_err(&pdev->dev,
"Invalid value for number of VFs to enable: %d\n", num_vfs);

return -EINVAL;
}

static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs);
static struct device_attribute sriov_numvfs_attr =
__ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP),
sriov_numvfs_show, sriov_numvfs_store);
#endif /* CONFIG_PCI_IOV */

struct device_attribute pci_dev_attrs[] = {
__ATTR_RO(resource),
__ATTR_RO(vendor),
Expand Down Expand Up @@ -1421,13 +1521,40 @@ static umode_t pci_dev_attrs_are_visible(struct kobject *kobj,
return a->mode;
}

#ifdef CONFIG_PCI_IOV
static struct attribute *sriov_dev_attrs[] = {
&sriov_totalvfs_attr.attr,
&sriov_numvfs_attr.attr,
NULL,
};

static umode_t sriov_attrs_are_visible(struct kobject *kobj,
struct attribute *a, int n)
{
struct device *dev = container_of(kobj, struct device, kobj);

if (!dev_is_pf(dev))
return 0;

return a->mode;
}

static struct attribute_group sriov_dev_attr_group = {
.attrs = sriov_dev_attrs,
.is_visible = sriov_attrs_are_visible,
};
#endif /* CONFIG_PCI_IOV */

static struct attribute_group pci_dev_attr_group = {
.attrs = pci_dev_dev_attrs,
.is_visible = pci_dev_attrs_are_visible,
};

static const struct attribute_group *pci_dev_attr_groups[] = {
&pci_dev_attr_group,
#ifdef CONFIG_PCI_IOV
&sriov_dev_attr_group,
#endif
NULL,
};

Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@ struct pci_driver {
int (*resume_early) (struct pci_dev *dev);
int (*resume) (struct pci_dev *dev); /* Device woken up */
void (*shutdown) (struct pci_dev *dev);
int (*sriov_configure) (struct pci_dev *dev, int num_vfs); /* PF pdev */
const struct pci_error_handlers *err_handler;
struct device_driver driver;
struct pci_dynids dynids;
Expand Down

0 comments on commit 10be9ac

Please sign in to comment.