4 * Copyright (C) 2009 Intel Corporation, Yu Zhao <yu.zhao@intel.com>
6 * PCI Express I/O Virtualization (IOV) support.
10 #include <linux/pci.h>
11 #include <linux/mutex.h>
12 #include <linux/string.h>
13 #include <linux/delay.h>
17 static int sriov_init(struct pci_dev
*dev
, int pos
)
23 u16 ctrl
, total
, offset
, stride
;
24 struct pci_sriov
*iov
;
28 if (dev
->pcie_type
!= PCI_EXP_TYPE_RC_END
&&
29 dev
->pcie_type
!= PCI_EXP_TYPE_ENDPOINT
)
32 pci_read_config_word(dev
, pos
+ PCI_SRIOV_CTRL
, &ctrl
);
33 if (ctrl
& PCI_SRIOV_CTRL_VFE
) {
34 pci_write_config_word(dev
, pos
+ PCI_SRIOV_CTRL
, 0);
38 pci_read_config_word(dev
, pos
+ PCI_SRIOV_TOTAL_VF
, &total
);
43 list_for_each_entry(pdev
, &dev
->bus
->devices
, bus_list
)
48 if (pci_ari_enabled(dev
->bus
))
49 ctrl
|= PCI_SRIOV_CTRL_ARI
;
52 pci_write_config_word(dev
, pos
+ PCI_SRIOV_CTRL
, ctrl
);
53 pci_write_config_word(dev
, pos
+ PCI_SRIOV_NUM_VF
, total
);
54 pci_read_config_word(dev
, pos
+ PCI_SRIOV_VF_OFFSET
, &offset
);
55 pci_read_config_word(dev
, pos
+ PCI_SRIOV_VF_STRIDE
, &stride
);
56 if (!offset
|| (total
> 1 && !stride
))
59 pci_read_config_dword(dev
, pos
+ PCI_SRIOV_SUP_PGSIZE
, &pgsz
);
60 i
= PAGE_SHIFT
> 12 ? PAGE_SHIFT
- 12 : 0;
61 pgsz
&= ~((1 << i
) - 1);
66 pci_write_config_dword(dev
, pos
+ PCI_SRIOV_SYS_PGSIZE
, pgsz
);
69 for (i
= 0; i
< PCI_SRIOV_NUM_BARS
; i
++) {
70 res
= dev
->resource
+ PCI_IOV_RESOURCES
+ i
;
71 i
+= __pci_read_base(dev
, pci_bar_unknown
, res
,
72 pos
+ PCI_SRIOV_BAR
+ i
* 4);
75 if (resource_size(res
) & (PAGE_SIZE
- 1)) {
79 res
->end
= res
->start
+ resource_size(res
) * total
- 1;
83 iov
= kzalloc(sizeof(*iov
), GFP_KERNEL
);
97 pci_read_config_dword(dev
, pos
+ PCI_SRIOV_CAP
, &iov
->cap
);
98 pci_read_config_byte(dev
, pos
+ PCI_SRIOV_FUNC_LINK
, &iov
->link
);
101 iov
->dev
= pci_dev_get(pdev
);
104 mutex_init(&iov
->lock
);
113 for (i
= 0; i
< PCI_SRIOV_NUM_BARS
; i
++) {
114 res
= dev
->resource
+ PCI_IOV_RESOURCES
+ i
;
121 static void sriov_release(struct pci_dev
*dev
)
123 if (dev
== dev
->sriov
->dev
)
124 mutex_destroy(&dev
->sriov
->lock
);
126 pci_dev_put(dev
->sriov
->dev
);
132 static void sriov_restore_state(struct pci_dev
*dev
)
136 struct pci_sriov
*iov
= dev
->sriov
;
138 pci_read_config_word(dev
, iov
->pos
+ PCI_SRIOV_CTRL
, &ctrl
);
139 if (ctrl
& PCI_SRIOV_CTRL_VFE
)
142 for (i
= PCI_IOV_RESOURCES
; i
<= PCI_IOV_RESOURCE_END
; i
++)
143 pci_update_resource(dev
, i
);
145 pci_write_config_dword(dev
, iov
->pos
+ PCI_SRIOV_SYS_PGSIZE
, iov
->pgsz
);
146 pci_write_config_word(dev
, iov
->pos
+ PCI_SRIOV_CTRL
, iov
->ctrl
);
147 if (iov
->ctrl
& PCI_SRIOV_CTRL_VFE
)
152 * pci_iov_init - initialize the IOV capability
153 * @dev: the PCI device
155 * Returns 0 on success, or negative on failure.
157 int pci_iov_init(struct pci_dev
*dev
)
164 pos
= pci_find_ext_capability(dev
, PCI_EXT_CAP_ID_SRIOV
);
166 return sriov_init(dev
, pos
);
172 * pci_iov_release - release resources used by the IOV capability
173 * @dev: the PCI device
175 void pci_iov_release(struct pci_dev
*dev
)
182 * pci_iov_resource_bar - get position of the SR-IOV BAR
183 * @dev: the PCI device
184 * @resno: the resource number
185 * @type: the BAR type to be filled in
187 * Returns position of the BAR encapsulated in the SR-IOV capability.
189 int pci_iov_resource_bar(struct pci_dev
*dev
, int resno
,
190 enum pci_bar_type
*type
)
192 if (resno
< PCI_IOV_RESOURCES
|| resno
> PCI_IOV_RESOURCE_END
)
195 BUG_ON(!dev
->is_physfn
);
197 *type
= pci_bar_unknown
;
199 return dev
->sriov
->pos
+ PCI_SRIOV_BAR
+
200 4 * (resno
- PCI_IOV_RESOURCES
);
204 * pci_restore_iov_state - restore the state of the IOV capability
205 * @dev: the PCI device
207 void pci_restore_iov_state(struct pci_dev
*dev
)
210 sriov_restore_state(dev
);