aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/xen-pciback
diff options
context:
space:
mode:
authorZhao, Yu <yu.zhao@intel.com>2010-03-03 13:27:55 -0500
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-07-19 20:58:30 -0400
commitfd5b221b348adf63d413de9adad030e4f13664b7 (patch)
treed641063dc2dc94cd6e04482049a23c8d87998d04 /drivers/xen/xen-pciback
parent6221a9b2a11acfb54e7b41da425e961b31e88553 (diff)
xen/pciback: guest SR-IOV support for PV guest
These changes are for PV guest to use Virtual Function. Because the VF's vendor, device registers in cfg space are 0xffff, which are invalid and ignored by PCI device scan. Values in 'struct pci_dev' are fixed up by SR-IOV code, and using these values will present correct VID and DID to PV guest kernel. And command registers in the cfg space are read only 0, which means we have to emulate MMIO enable bit (VF only uses MMIO resource) so PV kernel can work properly. Acked-by: Jan Beulich <jbeulich@novell.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/xen/xen-pciback')
-rw-r--r--drivers/xen/xen-pciback/conf_space_header.c71
1 files changed, 66 insertions, 5 deletions
diff --git a/drivers/xen/xen-pciback/conf_space_header.c b/drivers/xen/xen-pciback/conf_space_header.c
index 40166e04a2b9..dcd6dd964e3b 100644
--- a/drivers/xen/xen-pciback/conf_space_header.c
+++ b/drivers/xen/xen-pciback/conf_space_header.c
@@ -18,6 +18,25 @@ struct pci_bar_info {
18#define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO)) 18#define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO))
19#define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER) 19#define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER)
20 20
21static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data)
22{
23 int i;
24 int ret;
25
26 ret = pciback_read_config_word(dev, offset, value, data);
27 if (!atomic_read(&dev->enable_cnt))
28 return ret;
29
30 for (i = 0; i < PCI_ROM_RESOURCE; i++) {
31 if (dev->resource[i].flags & IORESOURCE_IO)
32 *value |= PCI_COMMAND_IO;
33 if (dev->resource[i].flags & IORESOURCE_MEM)
34 *value |= PCI_COMMAND_MEMORY;
35 }
36
37 return ret;
38}
39
21static int command_write(struct pci_dev *dev, int offset, u16 value, void *data) 40static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
22{ 41{
23 int err; 42 int err;
@@ -142,10 +161,26 @@ static inline void read_dev_bar(struct pci_dev *dev,
142 struct pci_bar_info *bar_info, int offset, 161 struct pci_bar_info *bar_info, int offset,
143 u32 len_mask) 162 u32 len_mask)
144{ 163{
145 pci_read_config_dword(dev, offset, &bar_info->val); 164 int pos;
146 pci_write_config_dword(dev, offset, len_mask); 165 struct resource *res = dev->resource;
147 pci_read_config_dword(dev, offset, &bar_info->len_val); 166
148 pci_write_config_dword(dev, offset, bar_info->val); 167 if (offset == PCI_ROM_ADDRESS || offset == PCI_ROM_ADDRESS1)
168 pos = PCI_ROM_RESOURCE;
169 else {
170 pos = (offset - PCI_BASE_ADDRESS_0) / 4;
171 if (pos && ((res[pos - 1].flags & (PCI_BASE_ADDRESS_SPACE |
172 PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
173 (PCI_BASE_ADDRESS_SPACE_MEMORY |
174 PCI_BASE_ADDRESS_MEM_TYPE_64))) {
175 bar_info->val = res[pos - 1].start >> 32;
176 bar_info->len_val = res[pos - 1].end >> 32;
177 return;
178 }
179 }
180
181 bar_info->val = res[pos].start |
182 (res[pos].flags & PCI_REGION_FLAG_MASK);
183 bar_info->len_val = res[pos].end - res[pos].start + 1;
149} 184}
150 185
151static void *bar_init(struct pci_dev *dev, int offset) 186static void *bar_init(struct pci_dev *dev, int offset)
@@ -186,6 +221,22 @@ static void bar_release(struct pci_dev *dev, int offset, void *data)
186 kfree(data); 221 kfree(data);
187} 222}
188 223
224static int pciback_read_vendor(struct pci_dev *dev, int offset,
225 u16 *value, void *data)
226{
227 *value = dev->vendor;
228
229 return 0;
230}
231
232static int pciback_read_device(struct pci_dev *dev, int offset,
233 u16 *value, void *data)
234{
235 *value = dev->device;
236
237 return 0;
238}
239
189static int interrupt_read(struct pci_dev *dev, int offset, u8 * value, 240static int interrupt_read(struct pci_dev *dev, int offset, u8 * value,
190 void *data) 241 void *data)
191{ 242{
@@ -213,9 +264,19 @@ out:
213 264
214static const struct config_field header_common[] = { 265static const struct config_field header_common[] = {
215 { 266 {
267 .offset = PCI_VENDOR_ID,
268 .size = 2,
269 .u.w.read = pciback_read_vendor,
270 },
271 {
272 .offset = PCI_DEVICE_ID,
273 .size = 2,
274 .u.w.read = pciback_read_device,
275 },
276 {
216 .offset = PCI_COMMAND, 277 .offset = PCI_COMMAND,
217 .size = 2, 278 .size = 2,
218 .u.w.read = pciback_read_config_word, 279 .u.w.read = command_read,
219 .u.w.write = command_write, 280 .u.w.write = command_write,
220 }, 281 },
221 { 282 {