-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
yaml --- r: 139364 b: refs/heads/master c: d1b054d h: refs/heads/master v: v3
- Loading branch information
Yu Zhao
authored and
Jesse Barnes
committed
Mar 20, 2009
1 parent
b3ff8b1
commit a66cfec
Showing
9 changed files
with
287 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
--- | ||
refs/heads/master: 8293b0f629095efbe7c7e3f9b437f8c040c19eb5 | ||
refs/heads/master: d1b054da8f599905f3c18a218961dcf17f9d5f13 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
/* | ||
* drivers/pci/iov.c | ||
* | ||
* Copyright (C) 2009 Intel Corporation, Yu Zhao <yu.zhao@intel.com> | ||
* | ||
* PCI Express I/O Virtualization (IOV) support. | ||
* Single Root IOV 1.0 | ||
*/ | ||
|
||
#include <linux/pci.h> | ||
#include <linux/mutex.h> | ||
#include <linux/string.h> | ||
#include <linux/delay.h> | ||
#include "pci.h" | ||
|
||
|
||
static int sriov_init(struct pci_dev *dev, int pos) | ||
{ | ||
int i; | ||
int rc; | ||
int nres; | ||
u32 pgsz; | ||
u16 ctrl, total, offset, stride; | ||
struct pci_sriov *iov; | ||
struct resource *res; | ||
struct pci_dev *pdev; | ||
|
||
if (dev->pcie_type != PCI_EXP_TYPE_RC_END && | ||
dev->pcie_type != PCI_EXP_TYPE_ENDPOINT) | ||
return -ENODEV; | ||
|
||
pci_read_config_word(dev, pos + PCI_SRIOV_CTRL, &ctrl); | ||
if (ctrl & PCI_SRIOV_CTRL_VFE) { | ||
pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, 0); | ||
ssleep(1); | ||
} | ||
|
||
pci_read_config_word(dev, pos + PCI_SRIOV_TOTAL_VF, &total); | ||
if (!total) | ||
return 0; | ||
|
||
ctrl = 0; | ||
list_for_each_entry(pdev, &dev->bus->devices, bus_list) | ||
if (pdev->is_physfn) | ||
goto found; | ||
|
||
pdev = NULL; | ||
if (pci_ari_enabled(dev->bus)) | ||
ctrl |= PCI_SRIOV_CTRL_ARI; | ||
|
||
found: | ||
pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, ctrl); | ||
pci_write_config_word(dev, pos + PCI_SRIOV_NUM_VF, total); | ||
pci_read_config_word(dev, pos + PCI_SRIOV_VF_OFFSET, &offset); | ||
pci_read_config_word(dev, pos + PCI_SRIOV_VF_STRIDE, &stride); | ||
if (!offset || (total > 1 && !stride)) | ||
return -EIO; | ||
|
||
pci_read_config_dword(dev, pos + PCI_SRIOV_SUP_PGSIZE, &pgsz); | ||
i = PAGE_SHIFT > 12 ? PAGE_SHIFT - 12 : 0; | ||
pgsz &= ~((1 << i) - 1); | ||
if (!pgsz) | ||
return -EIO; | ||
|
||
pgsz &= ~(pgsz - 1); | ||
pci_write_config_dword(dev, pos + PCI_SRIOV_SYS_PGSIZE, pgsz); | ||
|
||
nres = 0; | ||
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { | ||
res = dev->resource + PCI_IOV_RESOURCES + i; | ||
i += __pci_read_base(dev, pci_bar_unknown, res, | ||
pos + PCI_SRIOV_BAR + i * 4); | ||
if (!res->flags) | ||
continue; | ||
if (resource_size(res) & (PAGE_SIZE - 1)) { | ||
rc = -EIO; | ||
goto failed; | ||
} | ||
res->end = res->start + resource_size(res) * total - 1; | ||
nres++; | ||
} | ||
|
||
iov = kzalloc(sizeof(*iov), GFP_KERNEL); | ||
if (!iov) { | ||
rc = -ENOMEM; | ||
goto failed; | ||
} | ||
|
||
iov->pos = pos; | ||
iov->nres = nres; | ||
iov->ctrl = ctrl; | ||
iov->total = total; | ||
iov->offset = offset; | ||
iov->stride = stride; | ||
iov->pgsz = pgsz; | ||
iov->self = dev; | ||
pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap); | ||
pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link); | ||
|
||
if (pdev) | ||
iov->dev = pci_dev_get(pdev); | ||
else { | ||
iov->dev = dev; | ||
mutex_init(&iov->lock); | ||
} | ||
|
||
dev->sriov = iov; | ||
dev->is_physfn = 1; | ||
|
||
return 0; | ||
|
||
failed: | ||
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { | ||
res = dev->resource + PCI_IOV_RESOURCES + i; | ||
res->flags = 0; | ||
} | ||
|
||
return rc; | ||
} | ||
|
||
static void sriov_release(struct pci_dev *dev) | ||
{ | ||
if (dev == dev->sriov->dev) | ||
mutex_destroy(&dev->sriov->lock); | ||
else | ||
pci_dev_put(dev->sriov->dev); | ||
|
||
kfree(dev->sriov); | ||
dev->sriov = NULL; | ||
} | ||
|
||
/** | ||
* pci_iov_init - initialize the IOV capability | ||
* @dev: the PCI device | ||
* | ||
* Returns 0 on success, or negative on failure. | ||
*/ | ||
int pci_iov_init(struct pci_dev *dev) | ||
{ | ||
int pos; | ||
|
||
if (!dev->is_pcie) | ||
return -ENODEV; | ||
|
||
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); | ||
if (pos) | ||
return sriov_init(dev, pos); | ||
|
||
return -ENODEV; | ||
} | ||
|
||
/** | ||
* pci_iov_release - release resources used by the IOV capability | ||
* @dev: the PCI device | ||
*/ | ||
void pci_iov_release(struct pci_dev *dev) | ||
{ | ||
if (dev->is_physfn) | ||
sriov_release(dev); | ||
} | ||
|
||
/** | ||
* pci_iov_resource_bar - get position of the SR-IOV BAR | ||
* @dev: the PCI device | ||
* @resno: the resource number | ||
* @type: the BAR type to be filled in | ||
* | ||
* Returns position of the BAR encapsulated in the SR-IOV capability. | ||
*/ | ||
int pci_iov_resource_bar(struct pci_dev *dev, int resno, | ||
enum pci_bar_type *type) | ||
{ | ||
if (resno < PCI_IOV_RESOURCES || resno > PCI_IOV_RESOURCE_END) | ||
return 0; | ||
|
||
BUG_ON(!dev->is_physfn); | ||
|
||
*type = pci_bar_unknown; | ||
|
||
return dev->sriov->pos + PCI_SRIOV_BAR + | ||
4 * (resno - PCI_IOV_RESOURCES); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters