summaryrefslogtreecommitdiffstats
path: root/patches/boot_time_opt_guest/0110-pci-probe-identify-known-devices.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/boot_time_opt_guest/0110-pci-probe-identify-known-devices.patch')
-rw-r--r--patches/boot_time_opt_guest/0110-pci-probe-identify-known-devices.patch190
1 files changed, 190 insertions, 0 deletions
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 @@
1From c662d99134b67c58e63ecc17c2531588a3a51596 Mon Sep 17 00:00:00 2001
2From: Arjan van de Ven <arjan@linux.intel.com>
3Date: Sat, 14 Feb 2015 09:49:41 -0600
4Subject: [PATCH 110/114] pci: probe: identify known devices
5
6Author: Arjan van de Ven <arjan@linux.intel.com>
7Modify-by: Miguel Bernal Marin <miguel.bernal.marin@linux.intel.com>
8
9Signed-off-by: Miguel Bernal Marin <miguel.bernal.marin@linux.intel.com>
10---
11 drivers/pci/probe.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++
12 1 file changed, 156 insertions(+)
13
14diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
15index 7399a06698da..4fb2d7fed4c5 100644
16--- a/drivers/pci/probe.c
17+++ b/drivers/pci/probe.c
18@@ -163,6 +163,159 @@ static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar)
19
20 #define PCI_COMMAND_DECODE_ENABLE (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)
21
22+/* shortcut version of __pci_read_base where we know the sizes already */
23+int __pci_read_base_shortcut(struct pci_dev *dev, enum pci_bar_type type,
24+ struct resource *res, unsigned int pos, u32 sz_in, u32 sz2_in)
25+{
26+ u32 l, sz;
27+ u64 l64, sz64, mask64;
28+ struct pci_bus_region region, inverted_region;
29+
30+ res->name = pci_name(dev);
31+
32+ pci_read_config_dword(dev, pos, &l);
33+
34+ sz = sz_in;
35+
36+ /*
37+ * All bits set in sz means the device isn't working properly.
38+ * If the BAR isn't implemented, all bits must be 0. If it's a
39+ * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit
40+ * 1 must be clear.
41+ * Here we set the size and is not 0xffffffff
42+ */
43+
44+ /*
45+ * I don't know how l can have all bits set. Copied from old code.
46+ * Maybe it fixes a bug on some ancient platform.
47+ */
48+ if (l == 0xffffffff)
49+ l = 0;
50+
51+ if (type == pci_bar_unknown) {
52+ res->flags = decode_bar(dev, l);
53+ res->flags |= IORESOURCE_SIZEALIGN;
54+ if (res->flags & IORESOURCE_IO) {
55+ l64 = l & PCI_BASE_ADDRESS_IO_MASK;
56+ sz64 = sz & PCI_BASE_ADDRESS_IO_MASK;
57+ mask64 = PCI_BASE_ADDRESS_IO_MASK & (u32)IO_SPACE_LIMIT;
58+ } else {
59+ l64 = l & PCI_BASE_ADDRESS_MEM_MASK;
60+ sz64 = sz & PCI_BASE_ADDRESS_MEM_MASK;
61+ mask64 = (u32)PCI_BASE_ADDRESS_MEM_MASK;
62+ }
63+ } else {
64+ res->flags |= (l & IORESOURCE_ROM_ENABLE);
65+ l64 = l & PCI_ROM_ADDRESS_MASK;
66+ sz64 = sz & PCI_ROM_ADDRESS_MASK;
67+ mask64 = (u32)PCI_ROM_ADDRESS_MASK;
68+ }
69+
70+ if (res->flags & IORESOURCE_MEM_64) {
71+ pci_read_config_dword(dev, pos + 4, &l);
72+ sz = sz2_in;
73+
74+ l64 |= ((u64)l << 32);
75+ sz64 |= ((u64)sz << 32);
76+ mask64 |= ((u64)~0 << 32);
77+ }
78+
79+ if (!sz64)
80+ goto fail;
81+
82+ sz64 = pci_size(l64, sz64, mask64);
83+ if (!sz64) {
84+ dev_info(&dev->dev, FW_BUG "reg 0x%x: invalid BAR (can't size)\n",
85+ pos);
86+ goto fail;
87+ }
88+
89+ if (res->flags & IORESOURCE_MEM_64) {
90+ if ((sizeof(dma_addr_t) < 8 || sizeof(resource_size_t) < 8) &&
91+ sz64 > 0x100000000ULL) {
92+ res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
93+ res->start = 0;
94+ res->end = 0;
95+ dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n",
96+ pos, (unsigned long long)sz64);
97+ goto out;
98+ }
99+
100+ if ((sizeof(dma_addr_t) < 8) && l) {
101+ /* Above 32-bit boundary; try to reallocate */
102+ res->flags |= IORESOURCE_UNSET;
103+ res->start = 0;
104+ res->end = sz64;
105+ dev_info(&dev->dev, "reg 0x%x: can't handle BAR above 4GB (bus address %#010llx)\n",
106+ pos, (unsigned long long)l64);
107+ goto out;
108+ }
109+ }
110+
111+ region.start = l64;
112+ region.end = l64 + sz64;
113+
114+ pcibios_bus_to_resource(dev->bus, res, &region);
115+ pcibios_resource_to_bus(dev->bus, &inverted_region, res);
116+
117+ /*
118+ * If "A" is a BAR value (a bus address), "bus_to_resource(A)" is
119+ * the corresponding resource address (the physical address used by
120+ * the CPU. Converting that resource address back to a bus address
121+ * should yield the original BAR value:
122+ *
123+ * resource_to_bus(bus_to_resource(A)) == A
124+ *
125+ * If it doesn't, CPU accesses to "bus_to_resource(A)" will not
126+ * be claimed by the device.
127+ */
128+ if (inverted_region.start != region.start) {
129+ res->flags |= IORESOURCE_UNSET;
130+ res->start = 0;
131+ res->end = region.end - region.start;
132+ dev_info(&dev->dev, "reg 0x%x: initial BAR value %#010llx invalid\n",
133+ pos, (unsigned long long)region.start);
134+ }
135+
136+ goto out;
137+
138+
139+fail:
140+ res->flags = 0;
141+out:
142+ if (res->flags)
143+ dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res);
144+
145+ return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
146+}
147+
148+static int is_known_device(struct pci_dev *dev, int pos, int *sz)
149+{
150+ /* Red Hat, Inc : Virtio network device */
151+ if (dev->vendor == 0x1af4 && dev->device == 0x1000) {
152+ if (pos == 0x10) {
153+ *sz = 0xffffffe1;
154+ return 1;
155+ }
156+ if (pos == 0x14) {
157+ *sz = 0xfffff000;
158+ return 1;
159+ }
160+ }
161+ /* Red Hat, Inc : Virtio block device */
162+ if (dev->vendor == 0x1af4 && dev->device == 0x1001) {
163+ if (pos == 0x10) {
164+ *sz = 0xffffffc1;
165+ return 1;
166+ }
167+ if (pos == 0x14) {
168+ *sz = 0xfffff000;
169+ return 1;
170+ }
171+ }
172+ return 0;
173+}
174+
175 /**
176 * pci_read_base - read a PCI BAR
177 * @dev: the PCI device
178@@ -182,6 +335,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
179
180 mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
181
182+ if (is_known_device(dev, pos, &sz))
183+ return __pci_read_base_shortcut(dev, type, res, pos, sz, 0);
184+
185 res->name = pci_name(dev);
186
187 printk("clr: Starting probe for %s\n", res->name);
188--
1892.11.1
190