ia64/linux-2.6.18-xen.hg

view drivers/pci/search.c @ 882:8dec4aa9b8b9

PCI pass through: PCIe IO space multiplexing

This is required for more than 16 HVM domain to boot from
PCIe pass through device.

Linux as dom0 exclusively assigns IO space to downstream PCI bridges
and the assignment unit of PCI bridge IO space is 4K. So the only up
to 16 PCIe device can be accessed via IO space within 64K IO ports.
PCI expansion ROM BIOS often uses IO port access to boot from the
device, so on virtualized environment, it means only up to 16 guest
domain can boot from pass-through device.

This patch allows PCIe IO space sharing of pass-through device.
- reassign IO space of PCIe devices specified by
"guestiomuldev=[<segment>:]<bus>:<dev>[,[<segment:><bus>:dev]][,...]"
to be shared.
This is implemented as Linux PCI quirk fixup.

The sharing unit is PCIe switch. Ie IO space of the end point
devices under the same switch will be shared. If there are more than
one switches, two areas of IO space will be used.

- And the driver which arbitrates the accesses to the multiplexed PCIe
IO space. Later qemu-dm will use this.

Limitation:
IO port of IO shared devices can't be accessed from dom0 Linux device
driver. But this wouldn't be a big issue because PCIe specification
discourages the use of IO space and recommends that IO space should be
used only for bootable device with ROM code. OS device driver should
work without IO space access.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Keir Fraser <keir.fraser@citrix.com>
date Thu May 28 09:57:49 2009 +0100 (2009-05-28)
parents 5888ffa4b252
children
line source
1 /*
2 * PCI searching functions.
3 *
4 * Copyright (C) 1993 -- 1997 Drew Eckhardt, Frederic Potter,
5 * David Mosberger-Tang
6 * Copyright (C) 1997 -- 2000 Martin Mares <mj@ucw.cz>
7 * Copyright (C) 2003 -- 2004 Greg Kroah-Hartman <greg@kroah.com>
8 */
10 #include <linux/init.h>
11 #include <linux/pci.h>
12 #include <linux/module.h>
13 #include <linux/interrupt.h>
14 #include "pci.h"
16 DECLARE_RWSEM(pci_bus_sem);
18 static struct pci_bus * __devinit
19 pci_do_find_bus(struct pci_bus* bus, unsigned char busnr)
20 {
21 struct pci_bus* child;
22 struct list_head *tmp;
24 if(bus->number == busnr)
25 return bus;
27 list_for_each(tmp, &bus->children) {
28 child = pci_do_find_bus(pci_bus_b(tmp), busnr);
29 if(child)
30 return child;
31 }
32 return NULL;
33 }
35 /**
36 * pci_find_bus - locate PCI bus from a given domain and bus number
37 * @domain: number of PCI domain to search
38 * @busnr: number of desired PCI bus
39 *
40 * Given a PCI bus number and domain number, the desired PCI bus is located
41 * in the global list of PCI buses. If the bus is found, a pointer to its
42 * data structure is returned. If no bus is found, %NULL is returned.
43 */
44 struct pci_bus * pci_find_bus(int domain, int busnr)
45 {
46 struct pci_bus *bus = NULL;
47 struct pci_bus *tmp_bus;
49 while ((bus = pci_find_next_bus(bus)) != NULL) {
50 if (pci_domain_nr(bus) != domain)
51 continue;
52 tmp_bus = pci_do_find_bus(bus, busnr);
53 if (tmp_bus)
54 return tmp_bus;
55 }
56 return NULL;
57 }
59 /**
60 * pci_find_next_bus - begin or continue searching for a PCI bus
61 * @from: Previous PCI bus found, or %NULL for new search.
62 *
63 * Iterates through the list of known PCI busses. A new search is
64 * initiated by passing %NULL as the @from argument. Otherwise if
65 * @from is not %NULL, searches continue from next device on the
66 * global list.
67 */
68 struct pci_bus *
69 pci_find_next_bus(const struct pci_bus *from)
70 {
71 struct list_head *n;
72 struct pci_bus *b = NULL;
74 WARN_ON(in_interrupt());
75 down_read(&pci_bus_sem);
76 n = from ? from->node.next : pci_root_buses.next;
77 if (n != &pci_root_buses)
78 b = pci_bus_b(n);
79 up_read(&pci_bus_sem);
80 return b;
81 }
83 /**
84 * pci_find_slot - locate PCI device from a given PCI slot
85 * @bus: number of PCI bus on which desired PCI device resides
86 * @devfn: encodes number of PCI slot in which the desired PCI
87 * device resides and the logical device number within that slot
88 * in case of multi-function devices.
89 *
90 * Given a PCI bus and slot/function number, the desired PCI device
91 * is located in system global list of PCI devices. If the device
92 * is found, a pointer to its data structure is returned. If no
93 * device is found, %NULL is returned.
94 */
95 struct pci_dev *
96 pci_find_slot(unsigned int bus, unsigned int devfn)
97 {
98 struct pci_dev *dev = NULL;
100 while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
101 if (dev->bus->number == bus && dev->devfn == devfn)
102 return dev;
103 }
104 return NULL;
105 }
107 /**
108 * pci_get_slot - locate PCI device for a given PCI slot
109 * @bus: PCI bus on which desired PCI device resides
110 * @devfn: encodes number of PCI slot in which the desired PCI
111 * device resides and the logical device number within that slot
112 * in case of multi-function devices.
113 *
114 * Given a PCI bus and slot/function number, the desired PCI device
115 * is located in the list of PCI devices.
116 * If the device is found, its reference count is increased and this
117 * function returns a pointer to its data structure. The caller must
118 * decrement the reference count by calling pci_dev_put().
119 * If no device is found, %NULL is returned.
120 */
121 struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn)
122 {
123 struct list_head *tmp;
124 struct pci_dev *dev;
126 WARN_ON(in_interrupt());
127 down_read(&pci_bus_sem);
129 list_for_each(tmp, &bus->devices) {
130 dev = pci_dev_b(tmp);
131 if (dev->devfn == devfn)
132 goto out;
133 }
135 dev = NULL;
136 out:
137 pci_dev_get(dev);
138 up_read(&pci_bus_sem);
139 return dev;
140 }
142 /**
143 * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
144 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
145 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
146 * @ss_vendor: PCI subsystem vendor id to match, or %PCI_ANY_ID to match all vendor ids
147 * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids
148 * @from: Previous PCI device found in search, or %NULL for new search.
149 *
150 * Iterates through the list of known PCI devices. If a PCI device is
151 * found with a matching @vendor, @device, @ss_vendor and @ss_device, a
152 * pointer to its device structure is returned. Otherwise, %NULL is returned.
153 * A new search is initiated by passing %NULL as the @from argument.
154 * Otherwise if @from is not %NULL, searches continue from next device
155 * on the global list.
156 *
157 * NOTE: Do not use this function any more; use pci_get_subsys() instead, as
158 * the PCI device returned by this function can disappear at any moment in
159 * time.
160 */
161 static struct pci_dev * pci_find_subsys(unsigned int vendor,
162 unsigned int device,
163 unsigned int ss_vendor,
164 unsigned int ss_device,
165 const struct pci_dev *from)
166 {
167 struct list_head *n;
168 struct pci_dev *dev;
170 WARN_ON(in_interrupt());
171 down_read(&pci_bus_sem);
172 n = from ? from->global_list.next : pci_devices.next;
174 while (n && (n != &pci_devices)) {
175 dev = pci_dev_g(n);
176 if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
177 (device == PCI_ANY_ID || dev->device == device) &&
178 (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
179 (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
180 goto exit;
181 n = n->next;
182 }
183 dev = NULL;
184 exit:
185 up_read(&pci_bus_sem);
186 return dev;
187 }
189 /**
190 * pci_find_device - begin or continue searching for a PCI device by vendor/device id
191 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
192 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
193 * @from: Previous PCI device found in search, or %NULL for new search.
194 *
195 * Iterates through the list of known PCI devices. If a PCI device is found
196 * with a matching @vendor and @device, a pointer to its device structure is
197 * returned. Otherwise, %NULL is returned.
198 * A new search is initiated by passing %NULL as the @from argument.
199 * Otherwise if @from is not %NULL, searches continue from next device
200 * on the global list.
201 *
202 * NOTE: Do not use this function any more; use pci_get_device() instead, as
203 * the PCI device returned by this function can disappear at any moment in
204 * time.
205 */
206 struct pci_dev *
207 pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *from)
208 {
209 return pci_find_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
210 }
212 /**
213 * pci_get_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
214 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
215 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
216 * @ss_vendor: PCI subsystem vendor id to match, or %PCI_ANY_ID to match all vendor ids
217 * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids
218 * @from: Previous PCI device found in search, or %NULL for new search.
219 *
220 * Iterates through the list of known PCI devices. If a PCI device is found
221 * with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its
222 * device structure is returned, and the reference count to the device is
223 * incremented. Otherwise, %NULL is returned. A new search is initiated by
224 * passing %NULL as the @from argument. Otherwise if @from is not %NULL,
225 * searches continue from next device on the global list.
226 * The reference count for @from is always decremented if it is not %NULL.
227 */
228 struct pci_dev *
229 pci_get_subsys(unsigned int vendor, unsigned int device,
230 unsigned int ss_vendor, unsigned int ss_device,
231 struct pci_dev *from)
232 {
233 struct list_head *n;
234 struct pci_dev *dev;
236 WARN_ON(in_interrupt());
237 down_read(&pci_bus_sem);
238 n = from ? from->global_list.next : pci_devices.next;
240 while (n && (n != &pci_devices)) {
241 dev = pci_dev_g(n);
242 if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
243 (device == PCI_ANY_ID || dev->device == device) &&
244 (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
245 (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
246 goto exit;
247 n = n->next;
248 }
249 dev = NULL;
250 exit:
251 dev = pci_dev_get(dev);
252 up_read(&pci_bus_sem);
253 pci_dev_put(from);
254 return dev;
255 }
257 /**
258 * pci_get_device - begin or continue searching for a PCI device by vendor/device id
259 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
260 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
261 * @from: Previous PCI device found in search, or %NULL for new search.
262 *
263 * Iterates through the list of known PCI devices. If a PCI device is
264 * found with a matching @vendor and @device, the reference count to the
265 * device is incremented and a pointer to its device structure is returned.
266 * Otherwise, %NULL is returned. A new search is initiated by passing %NULL
267 * as the @from argument. Otherwise if @from is not %NULL, searches continue
268 * from next device on the global list. The reference count for @from is
269 * always decremented if it is not %NULL.
270 */
271 struct pci_dev *
272 pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from)
273 {
274 return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
275 }
278 /**
279 * pci_find_device_reverse - begin or continue searching for a PCI device by vendor/device id
280 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
281 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
282 * @from: Previous PCI device found in search, or %NULL for new search.
283 *
284 * Iterates through the list of known PCI devices in the reverse order of
285 * pci_find_device().
286 * If a PCI device is found with a matching @vendor and @device, a pointer to
287 * its device structure is returned. Otherwise, %NULL is returned.
288 * A new search is initiated by passing %NULL as the @from argument.
289 * Otherwise if @from is not %NULL, searches continue from previous device
290 * on the global list.
291 */
292 struct pci_dev *
293 pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct pci_dev *from)
294 {
295 struct list_head *n;
296 struct pci_dev *dev;
298 WARN_ON(in_interrupt());
299 down_read(&pci_bus_sem);
300 n = from ? from->global_list.prev : pci_devices.prev;
302 while (n && (n != &pci_devices)) {
303 dev = pci_dev_g(n);
304 if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
305 (device == PCI_ANY_ID || dev->device == device))
306 goto exit;
307 n = n->prev;
308 }
309 dev = NULL;
310 exit:
311 up_read(&pci_bus_sem);
312 return dev;
313 }
315 /**
316 * pci_get_class - begin or continue searching for a PCI device by class
317 * @class: search for a PCI device with this class designation
318 * @from: Previous PCI device found in search, or %NULL for new search.
319 *
320 * Iterates through the list of known PCI devices. If a PCI device is
321 * found with a matching @class, the reference count to the device is
322 * incremented and a pointer to its device structure is returned.
323 * Otherwise, %NULL is returned.
324 * A new search is initiated by passing %NULL as the @from argument.
325 * Otherwise if @from is not %NULL, searches continue from next device
326 * on the global list. The reference count for @from is always decremented
327 * if it is not %NULL.
328 */
329 struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
330 {
331 struct list_head *n;
332 struct pci_dev *dev;
334 WARN_ON(in_interrupt());
335 down_read(&pci_bus_sem);
336 n = from ? from->global_list.next : pci_devices.next;
338 while (n && (n != &pci_devices)) {
339 dev = pci_dev_g(n);
340 if (dev->class == class)
341 goto exit;
342 n = n->next;
343 }
344 dev = NULL;
345 exit:
346 dev = pci_dev_get(dev);
347 up_read(&pci_bus_sem);
348 pci_dev_put(from);
349 return dev;
350 }
352 /**
353 * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not.
354 * @ids: A pointer to a null terminated list of struct pci_device_id structures
355 * that describe the type of PCI device the caller is trying to find.
356 *
357 * Obvious fact: You do not have a reference to any device that might be found
358 * by this function, so if that device is removed from the system right after
359 * this function is finished, the value will be stale. Use this function to
360 * find devices that are usually built into a system, or for a general hint as
361 * to if another device happens to be present at this specific moment in time.
362 */
363 int pci_dev_present(const struct pci_device_id *ids)
364 {
365 struct pci_dev *dev;
366 int found = 0;
368 WARN_ON(in_interrupt());
369 down_read(&pci_bus_sem);
370 while (ids->vendor || ids->subvendor || ids->class_mask) {
371 list_for_each_entry(dev, &pci_devices, global_list) {
372 if (pci_match_one_device(ids, dev)) {
373 found = 1;
374 goto exit;
375 }
376 }
377 ids++;
378 }
379 exit:
380 up_read(&pci_bus_sem);
381 return found;
382 }
384 /**
385 * pci_get_bus_and_slot - locate PCI device from a given PCI bus & slot
386 * @bus: number of PCI bus on which desired PCI device resides
387 * @devfn: encodes number of PCI slot in which the desired PCI
388 * device resides and the logical device number within that slot
389 * in case of multi-function devices.
390 *
391 * Note: the bus/slot search is limited to PCI domain (segment) 0.
392 *
393 * Given a PCI bus and slot/function number, the desired PCI device
394 * is located in system global list of PCI devices. If the device
395 * is found, a pointer to its data structure is returned. If no
396 * device is found, %NULL is returned. The returned device has its
397 * reference count bumped by one.
398 */
400 struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
401 {
402 struct pci_dev *dev = NULL;
404 while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
405 if (pci_domain_nr(dev->bus) == 0 &&
406 (dev->bus->number == bus && dev->devfn == devfn))
407 return dev;
408 }
409 return NULL;
410 }
413 EXPORT_SYMBOL(pci_dev_present);
415 EXPORT_SYMBOL(pci_find_bus);
416 EXPORT_SYMBOL(pci_find_next_bus);
417 EXPORT_SYMBOL(pci_find_device);
418 EXPORT_SYMBOL(pci_find_device_reverse);
419 EXPORT_SYMBOL(pci_find_slot);
420 EXPORT_SYMBOL(pci_get_device);
421 EXPORT_SYMBOL(pci_get_subsys);
422 EXPORT_SYMBOL(pci_get_slot);
423 EXPORT_SYMBOL(pci_get_bus_and_slot);
424 EXPORT_SYMBOL(pci_get_class);