[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [linux-2.6.18-xen] Guest SR-IOV: Replace previous changeset with a more complete implementation from Intel
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1267437309 0 # Node ID 4b0c1a686393ed4283e4942c6997354b7c37d370 # Parent 693c40564c8de65e32f48168bd8733918f661d7e Guest SR-IOV: Replace previous changeset with a more complete implementation from Intel """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.""" Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- drivers/xen/pciback/conf_space_header.c | 112 +++++++++++++++++++++++--------- 1 files changed, 81 insertions(+), 31 deletions(-) diff -r 693c40564c8d -r 4b0c1a686393 drivers/xen/pciback/conf_space_header.c --- a/drivers/xen/pciback/conf_space_header.c Fri Feb 26 17:15:45 2010 +0000 +++ b/drivers/xen/pciback/conf_space_header.c Mon Mar 01 09:55:09 2010 +0000 @@ -17,6 +17,25 @@ struct pci_bar_info { #define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO)) #define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER) + +static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data) +{ + int i; + int ret; + + ret = pciback_read_config_word(dev, offset, value, data); + /*if (!atomic_read(&dev->enable_cnt)) + return ret;*/ + + for (i = 0; i < PCI_ROM_RESOURCE; i++) { + if (dev->resource[i].flags & IORESOURCE_IO) + *value |= PCI_COMMAND_IO; + if (dev->resource[i].flags & IORESOURCE_MEM) + *value |= PCI_COMMAND_MEMORY; + } + + return ret; +} static int command_write(struct pci_dev *dev, int offset, u16 value, void *data) { @@ -73,7 +92,17 @@ static int rom_write(struct pci_dev *dev /* A write to obtain the length must happen as a 32-bit write. * This does not (yet) support writing individual bytes */ - bar->which = (value == ~PCI_ROM_ADDRESS_ENABLE); + if (value == ~PCI_ROM_ADDRESS_ENABLE) + bar->which = 1; + else { + u32 tmpval; + pci_read_config_dword(dev, offset, &tmpval); + if (tmpval != bar->val && value == bar->val) { + /* Allow restoration of bar value. */ + pci_write_config_dword(dev, offset, bar->val); + } + bar->which = 0; + } /* Do we need to support enabling/disabling the rom address here? */ @@ -97,7 +126,17 @@ static int bar_write(struct pci_dev *dev /* A write to obtain the length must happen as a 32-bit write. * This does not (yet) support writing individual bytes */ - bar->which = (value == ~0); + if (value == ~0) + bar->which = 1; + else { + u32 tmpval; + pci_read_config_dword(dev, offset, &tmpval); + if (tmpval != bar->val && value == bar->val) { + /* Allow restoration of bar value. */ + pci_write_config_dword(dev, offset, bar->val); + } + bar->which = 0; + } return 0; } @@ -105,10 +144,6 @@ static int bar_read(struct pci_dev *dev, static int bar_read(struct pci_dev *dev, int offset, u32 * value, void *data) { struct pci_bar_info *bar = data; - int idx = (offset - 0x10) >> 2; - - if (idx > PCI_STD_RESOURCE_END ) - idx = PCI_ROM_RESOURCE; if (unlikely(!bar)) { printk(KERN_WARNING "pciback: driver data not found for %s\n", @@ -116,8 +151,7 @@ static int bar_read(struct pci_dev *dev, return XEN_PCI_ERR_op_failed; } - *value = bar->which ? ~(pci_resource_len(dev, idx)-1) : pci_resource_start(dev, idx); - *value |= pci_resource_flags(dev, idx) & 0xf; + *value = bar->which ? bar->len_val : bar->val; return 0; } @@ -126,10 +160,26 @@ static inline void read_dev_bar(struct p struct pci_bar_info *bar_info, int offset, u32 len_mask) { - pci_read_config_dword(dev, offset, &bar_info->val); - pci_write_config_dword(dev, offset, len_mask); - pci_read_config_dword(dev, offset, &bar_info->len_val); - pci_write_config_dword(dev, offset, bar_info->val); + int pos; + struct resource *res = dev->resource; + + if (offset == PCI_ROM_ADDRESS || offset == PCI_ROM_ADDRESS1) + pos = PCI_ROM_RESOURCE; + else { + pos = (offset - PCI_BASE_ADDRESS_0) / 4; + if (pos && ((res[pos - 1].flags & (PCI_BASE_ADDRESS_SPACE | + PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == + (PCI_BASE_ADDRESS_SPACE_MEMORY | + PCI_BASE_ADDRESS_MEM_TYPE_64))) { + bar_info->val = res[pos - 1].start >> 32; + bar_info->len_val = res[pos - 1].end >> 32; + return; + } + } + + bar_info->val = res[pos].start | + (res[pos].flags & PCI_REGION_FLAG_MASK); + bar_info->len_val = res[pos].end - res[pos].start + 1; } static void *bar_init(struct pci_dev *dev, int offset) @@ -170,26 +220,26 @@ static void bar_release(struct pci_dev * kfree(data); } +static int pciback_read_vendor(struct pci_dev *dev, int offset, + u16 *value, void *data) +{ + *value = dev->vendor; + + return 0; +} + +static int pciback_read_device(struct pci_dev *dev, int offset, + u16 *value, void *data) +{ + *value = dev->device; + + return 0; +} + static int interrupt_read(struct pci_dev *dev, int offset, u8 * value, void *data) { *value = (u8) dev->irq; - - return 0; -} - -static int vendor_read(struct pci_dev *dev, int offset, u16 * value, - void *data) -{ - *value = dev->vendor; - - return 0; -} - -static int device_read(struct pci_dev *dev, int offset, u16 * value, - void *data) -{ - *value = dev->device; return 0; } @@ -215,17 +265,17 @@ static const struct config_field header_ { .offset = PCI_VENDOR_ID, .size = 2, - .u.w.read = vendor_read + .u.w.read = pciback_read_vendor, }, { .offset = PCI_DEVICE_ID, .size = 2, - .u.w.read = device_read + .u.w.read = pciback_read_device, }, { .offset = PCI_COMMAND, .size = 2, - .u.w.read = pciback_read_config_word, + .u.w.read = command_read, .u.w.write = command_write, }, { _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog |
Lists.xenproject.org is hosted with RackSpace, monitoring our |