From ad4d4e5cbad3ad875eaa59e0a919c014dfb6a39e Mon Sep 17 00:00:00 2001 From: Adrian Calianu Date: Wed, 27 Sep 2017 10:37:36 +0200 Subject: add guest features from yocto branch Signed-off-by: Adrian Calianu --- .../0110-pci-probe-identify-known-devices.patch | 190 +++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 patches/boot_time_opt_guest/0110-pci-probe-identify-known-devices.patch (limited to 'patches/boot_time_opt_guest/0110-pci-probe-identify-known-devices.patch') diff --git a/patches/boot_time_opt_guest/0110-pci-probe-identify-known-devices.patch b/patches/boot_time_opt_guest/0110-pci-probe-identify-known-devices.patch new file mode 100644 index 0000000..742a045 --- /dev/null +++ b/patches/boot_time_opt_guest/0110-pci-probe-identify-known-devices.patch @@ -0,0 +1,190 @@ +From c662d99134b67c58e63ecc17c2531588a3a51596 Mon Sep 17 00:00:00 2001 +From: Arjan van de Ven +Date: Sat, 14 Feb 2015 09:49:41 -0600 +Subject: [PATCH 110/114] pci: probe: identify known devices + +Author: Arjan van de Ven +Modify-by: Miguel Bernal Marin + +Signed-off-by: Miguel Bernal Marin +--- + drivers/pci/probe.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 156 insertions(+) + +diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c +index 7399a06698da..4fb2d7fed4c5 100644 +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -163,6 +163,159 @@ static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar) + + #define PCI_COMMAND_DECODE_ENABLE (PCI_COMMAND_MEMORY | PCI_COMMAND_IO) + ++/* shortcut version of __pci_read_base where we know the sizes already */ ++int __pci_read_base_shortcut(struct pci_dev *dev, enum pci_bar_type type, ++ struct resource *res, unsigned int pos, u32 sz_in, u32 sz2_in) ++{ ++ u32 l, sz; ++ u64 l64, sz64, mask64; ++ struct pci_bus_region region, inverted_region; ++ ++ res->name = pci_name(dev); ++ ++ pci_read_config_dword(dev, pos, &l); ++ ++ sz = sz_in; ++ ++ /* ++ * All bits set in sz means the device isn't working properly. ++ * If the BAR isn't implemented, all bits must be 0. If it's a ++ * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit ++ * 1 must be clear. ++ * Here we set the size and is not 0xffffffff ++ */ ++ ++ /* ++ * I don't know how l can have all bits set. Copied from old code. ++ * Maybe it fixes a bug on some ancient platform. ++ */ ++ if (l == 0xffffffff) ++ l = 0; ++ ++ if (type == pci_bar_unknown) { ++ res->flags = decode_bar(dev, l); ++ res->flags |= IORESOURCE_SIZEALIGN; ++ if (res->flags & IORESOURCE_IO) { ++ l64 = l & PCI_BASE_ADDRESS_IO_MASK; ++ sz64 = sz & PCI_BASE_ADDRESS_IO_MASK; ++ mask64 = PCI_BASE_ADDRESS_IO_MASK & (u32)IO_SPACE_LIMIT; ++ } else { ++ l64 = l & PCI_BASE_ADDRESS_MEM_MASK; ++ sz64 = sz & PCI_BASE_ADDRESS_MEM_MASK; ++ mask64 = (u32)PCI_BASE_ADDRESS_MEM_MASK; ++ } ++ } else { ++ res->flags |= (l & IORESOURCE_ROM_ENABLE); ++ l64 = l & PCI_ROM_ADDRESS_MASK; ++ sz64 = sz & PCI_ROM_ADDRESS_MASK; ++ mask64 = (u32)PCI_ROM_ADDRESS_MASK; ++ } ++ ++ if (res->flags & IORESOURCE_MEM_64) { ++ pci_read_config_dword(dev, pos + 4, &l); ++ sz = sz2_in; ++ ++ l64 |= ((u64)l << 32); ++ sz64 |= ((u64)sz << 32); ++ mask64 |= ((u64)~0 << 32); ++ } ++ ++ if (!sz64) ++ goto fail; ++ ++ sz64 = pci_size(l64, sz64, mask64); ++ if (!sz64) { ++ dev_info(&dev->dev, FW_BUG "reg 0x%x: invalid BAR (can't size)\n", ++ pos); ++ goto fail; ++ } ++ ++ if (res->flags & IORESOURCE_MEM_64) { ++ if ((sizeof(dma_addr_t) < 8 || sizeof(resource_size_t) < 8) && ++ sz64 > 0x100000000ULL) { ++ res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; ++ res->start = 0; ++ res->end = 0; ++ dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n", ++ pos, (unsigned long long)sz64); ++ goto out; ++ } ++ ++ if ((sizeof(dma_addr_t) < 8) && l) { ++ /* Above 32-bit boundary; try to reallocate */ ++ res->flags |= IORESOURCE_UNSET; ++ res->start = 0; ++ res->end = sz64; ++ dev_info(&dev->dev, "reg 0x%x: can't handle BAR above 4GB (bus address %#010llx)\n", ++ pos, (unsigned long long)l64); ++ goto out; ++ } ++ } ++ ++ region.start = l64; ++ region.end = l64 + sz64; ++ ++ pcibios_bus_to_resource(dev->bus, res, ®ion); ++ pcibios_resource_to_bus(dev->bus, &inverted_region, res); ++ ++ /* ++ * If "A" is a BAR value (a bus address), "bus_to_resource(A)" is ++ * the corresponding resource address (the physical address used by ++ * the CPU. Converting that resource address back to a bus address ++ * should yield the original BAR value: ++ * ++ * resource_to_bus(bus_to_resource(A)) == A ++ * ++ * If it doesn't, CPU accesses to "bus_to_resource(A)" will not ++ * be claimed by the device. ++ */ ++ if (inverted_region.start != region.start) { ++ res->flags |= IORESOURCE_UNSET; ++ res->start = 0; ++ res->end = region.end - region.start; ++ dev_info(&dev->dev, "reg 0x%x: initial BAR value %#010llx invalid\n", ++ pos, (unsigned long long)region.start); ++ } ++ ++ goto out; ++ ++ ++fail: ++ res->flags = 0; ++out: ++ if (res->flags) ++ dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res); ++ ++ return (res->flags & IORESOURCE_MEM_64) ? 1 : 0; ++} ++ ++static int is_known_device(struct pci_dev *dev, int pos, int *sz) ++{ ++ /* Red Hat, Inc : Virtio network device */ ++ if (dev->vendor == 0x1af4 && dev->device == 0x1000) { ++ if (pos == 0x10) { ++ *sz = 0xffffffe1; ++ return 1; ++ } ++ if (pos == 0x14) { ++ *sz = 0xfffff000; ++ return 1; ++ } ++ } ++ /* Red Hat, Inc : Virtio block device */ ++ if (dev->vendor == 0x1af4 && dev->device == 0x1001) { ++ if (pos == 0x10) { ++ *sz = 0xffffffc1; ++ return 1; ++ } ++ if (pos == 0x14) { ++ *sz = 0xfffff000; ++ return 1; ++ } ++ } ++ return 0; ++} ++ + /** + * pci_read_base - read a PCI BAR + * @dev: the PCI device +@@ -182,6 +335,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, + + mask = type ? PCI_ROM_ADDRESS_MASK : ~0; + ++ if (is_known_device(dev, pos, &sz)) ++ return __pci_read_base_shortcut(dev, type, res, pos, sz, 0); ++ + res->name = pci_name(dev); + + printk("clr: Starting probe for %s\n", res->name); +-- +2.11.1 + -- cgit v1.2.3-54-g00ecf