Blame view
drivers/pci/search.c
11.1 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 |
/* * PCI searching functions. * * Copyright (C) 1993 -- 1997 Drew Eckhardt, Frederic Potter, * David Mosberger-Tang * Copyright (C) 1997 -- 2000 Martin Mares <mj@ucw.cz> * Copyright (C) 2003 -- 2004 Greg Kroah-Hartman <greg@kroah.com> */ #include <linux/init.h> #include <linux/pci.h> |
5a0e3ad6a include cleanup: ... |
12 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
13 14 15 |
#include <linux/module.h> #include <linux/interrupt.h> #include "pci.h" |
d71374daf [PATCH] PCI: fix ... |
16 |
DECLARE_RWSEM(pci_bus_sem); |
994a65e25 Intel IOMMU: PCI ... |
17 |
/* |
45e829ea4 PCI: change PCI n... |
18 |
* find the upstream PCIe-to-PCI bridge of a PCI device |
994a65e25 Intel IOMMU: PCI ... |
19 |
* if the device is PCIE, return NULL |
45e829ea4 PCI: change PCI n... |
20 |
* if the device isn't connected to a PCIe bridge (that is its parent is a |
994a65e25 Intel IOMMU: PCI ... |
21 22 23 24 25 26 27 |
* legacy PCI bridge and the bridge is directly connected to bus 0), return its * parent */ struct pci_dev * pci_find_upstream_pcie_bridge(struct pci_dev *pdev) { struct pci_dev *tmp = NULL; |
5f4d91a12 PCI: use pci_is_p... |
28 |
if (pci_is_pcie(pdev)) |
994a65e25 Intel IOMMU: PCI ... |
29 30 |
return NULL; while (1) { |
6e3f36df0 PCI: use pci_is_r... |
31 |
if (pci_is_root_bus(pdev->bus)) |
994a65e25 Intel IOMMU: PCI ... |
32 33 34 |
break; pdev = pdev->bus->self; /* a p2p bridge */ |
5f4d91a12 PCI: use pci_is_p... |
35 |
if (!pci_is_pcie(pdev)) { |
994a65e25 Intel IOMMU: PCI ... |
36 37 38 |
tmp = pdev; continue; } |
45e829ea4 PCI: change PCI n... |
39 |
/* PCI device should connect to a PCIe bridge */ |
994a65e25 Intel IOMMU: PCI ... |
40 41 42 43 44 45 46 47 48 49 |
if (pdev->pcie_type != PCI_EXP_TYPE_PCI_BRIDGE) { /* Busted hardware? */ WARN_ON_ONCE(1); return NULL; } return pdev; } return tmp; } |
1da177e4c Linux-2.6.12-rc2 |
50 |
|
96bde06a2 pci: do not mark ... |
51 |
static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr) |
1da177e4c Linux-2.6.12-rc2 |
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
{ struct pci_bus* child; struct list_head *tmp; if(bus->number == busnr) return bus; list_for_each(tmp, &bus->children) { child = pci_do_find_bus(pci_bus_b(tmp), busnr); if(child) return child; } return NULL; } /** * pci_find_bus - locate PCI bus from a given domain and bus number * @domain: number of PCI domain to search * @busnr: number of desired PCI bus * * Given a PCI bus number and domain number, the desired PCI bus is located * in the global list of PCI buses. If the bus is found, a pointer to its * data structure is returned. If no bus is found, %NULL is returned. */ |
c8439cfcc PCI: pci/search: ... |
76 |
struct pci_bus * pci_find_bus(int domain, int busnr) |
1da177e4c Linux-2.6.12-rc2 |
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
{ struct pci_bus *bus = NULL; struct pci_bus *tmp_bus; while ((bus = pci_find_next_bus(bus)) != NULL) { if (pci_domain_nr(bus) != domain) continue; tmp_bus = pci_do_find_bus(bus, busnr); if (tmp_bus) return tmp_bus; } return NULL; } /** * pci_find_next_bus - begin or continue searching for a PCI bus * @from: Previous PCI bus found, or %NULL for new search. * * Iterates through the list of known PCI busses. A new search is |
d75763d24 [PATCH] pci/searc... |
96 |
* initiated by passing %NULL as the @from argument. Otherwise if |
1da177e4c Linux-2.6.12-rc2 |
97 98 99 100 101 102 103 104 105 106 |
* @from is not %NULL, searches continue from next device on the * global list. */ struct pci_bus * pci_find_next_bus(const struct pci_bus *from) { struct list_head *n; struct pci_bus *b = NULL; WARN_ON(in_interrupt()); |
d71374daf [PATCH] PCI: fix ... |
107 |
down_read(&pci_bus_sem); |
1da177e4c Linux-2.6.12-rc2 |
108 109 110 |
n = from ? from->node.next : pci_root_buses.next; if (n != &pci_root_buses) b = pci_bus_b(n); |
d71374daf [PATCH] PCI: fix ... |
111 |
up_read(&pci_bus_sem); |
1da177e4c Linux-2.6.12-rc2 |
112 113 |
return b; } |
1da177e4c Linux-2.6.12-rc2 |
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
/** * pci_get_slot - locate PCI device for a given PCI slot * @bus: PCI bus on which desired PCI device resides * @devfn: encodes number of PCI slot in which the desired PCI * device resides and the logical device number within that slot * in case of multi-function devices. * * Given a PCI bus and slot/function number, the desired PCI device * is located in the list of PCI devices. * If the device is found, its reference count is increased and this * function returns a pointer to its data structure. The caller must * decrement the reference count by calling pci_dev_put(). * If no device is found, %NULL is returned. */ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) { struct list_head *tmp; struct pci_dev *dev; WARN_ON(in_interrupt()); |
d71374daf [PATCH] PCI: fix ... |
134 |
down_read(&pci_bus_sem); |
1da177e4c Linux-2.6.12-rc2 |
135 136 137 138 139 140 141 142 143 144 |
list_for_each(tmp, &bus->devices) { dev = pci_dev_b(tmp); if (dev->devfn == devfn) goto out; } dev = NULL; out: pci_dev_get(dev); |
d71374daf [PATCH] PCI: fix ... |
145 |
up_read(&pci_bus_sem); |
1da177e4c Linux-2.6.12-rc2 |
146 147 148 149 |
return dev; } /** |
3c299dc22 PCI: add pci_get_... |
150 151 152 153 154 155 |
* pci_get_domain_bus_and_slot - locate PCI device for a given PCI domain (segment), bus, and slot * @domain: PCI domain/segment on which the PCI device resides. * @bus: PCI bus on which desired PCI device resides * @devfn: encodes number of PCI slot in which the desired PCI device * resides and the logical device number within that slot in case of * multi-function devices. |
5463d9f0f PCI: limit pci_ge... |
156 |
* |
3c299dc22 PCI: add pci_get_... |
157 158 159 160 161 162 |
* Given a PCI domain, bus, and slot/function number, the desired PCI * device is located in the list of PCI devices. If the device is * found, its reference count is increased and this function returns a * pointer to its data structure. The caller must decrement the * reference count by calling pci_dev_put(). If no device is found, * %NULL is returned. |
29f3eb646 pci: Additional s... |
163 |
*/ |
3c299dc22 PCI: add pci_get_... |
164 165 |
struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus, unsigned int devfn) |
29f3eb646 pci: Additional s... |
166 167 |
{ struct pci_dev *dev = NULL; |
4e344b1cc PCI: use for_each... |
168 |
for_each_pci_dev(dev) { |
3c299dc22 PCI: add pci_get_... |
169 170 |
if (pci_domain_nr(dev->bus) == domain && (dev->bus->number == bus && dev->devfn == devfn)) |
29f3eb646 pci: Additional s... |
171 172 173 174 |
return dev; } return NULL; } |
3c299dc22 PCI: add pci_get_... |
175 |
EXPORT_SYMBOL(pci_get_domain_bus_and_slot); |
29f3eb646 pci: Additional s... |
176 |
|
95247b57e PCI: clean up sea... |
177 |
static int match_pci_dev_by_id(struct device *dev, void *data) |
1da177e4c Linux-2.6.12-rc2 |
178 |
{ |
95247b57e PCI: clean up sea... |
179 180 |
struct pci_dev *pdev = to_pci_dev(dev); struct pci_device_id *id = data; |
1da177e4c Linux-2.6.12-rc2 |
181 |
|
95247b57e PCI: clean up sea... |
182 183 184 |
if (pci_match_one_device(id, pdev)) return 1; return 0; |
1da177e4c Linux-2.6.12-rc2 |
185 |
} |
95247b57e PCI: clean up sea... |
186 187 188 |
/* * pci_get_dev_by_id - begin or continue searching for a PCI device by id * @id: pointer to struct pci_device_id to match for the device |
1da177e4c Linux-2.6.12-rc2 |
189 190 |
* @from: Previous PCI device found in search, or %NULL for new search. * |
d75763d24 [PATCH] pci/searc... |
191 |
* Iterates through the list of known PCI devices. If a PCI device is found |
95247b57e PCI: clean up sea... |
192 193 194 195 196 197 198 199 200 |
* with a matching id a pointer to its device structure is returned, and the * reference count to the device is incremented. Otherwise, %NULL is returned. * A new search is initiated by passing %NULL as the @from argument. Otherwise * if @from is not %NULL, searches continue from next device on the global * list. The reference count for @from is always decremented if it is not * %NULL. * * This is an internal function for use by the other search functions in * this file. |
1da177e4c Linux-2.6.12-rc2 |
201 |
*/ |
95247b57e PCI: clean up sea... |
202 |
static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id, |
b08508c40 PCI: fix compiler... |
203 |
struct pci_dev *from) |
1da177e4c Linux-2.6.12-rc2 |
204 |
{ |
95247b57e PCI: clean up sea... |
205 206 207 208 209 |
struct device *dev; struct device *dev_start = NULL; struct pci_dev *pdev = NULL; WARN_ON(in_interrupt()); |
c4ed02fae PCI: Fix referenc... |
210 211 |
if (from) dev_start = &from->dev; |
95247b57e PCI: clean up sea... |
212 213 214 215 |
dev = bus_find_device(&pci_bus_type, dev_start, (void *)id, match_pci_dev_by_id); if (dev) pdev = to_pci_dev(dev); |
ebca4f1bc PCI: fix referenc... |
216 217 |
if (from) pci_dev_put(from); |
95247b57e PCI: clean up sea... |
218 |
return pdev; |
1da177e4c Linux-2.6.12-rc2 |
219 220 221 222 223 224 225 226 227 228 |
} /** * pci_get_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids * @ss_vendor: PCI subsystem vendor id to match, or %PCI_ANY_ID to match all vendor ids * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids * @from: Previous PCI device found in search, or %NULL for new search. * |
d75763d24 [PATCH] pci/searc... |
229 230 |
* Iterates through the list of known PCI devices. If a PCI device is found * with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its |
1da177e4c Linux-2.6.12-rc2 |
231 232 |
* device structure is returned, and the reference count to the device is * incremented. Otherwise, %NULL is returned. A new search is initiated by |
d75763d24 [PATCH] pci/searc... |
233 |
* passing %NULL as the @from argument. Otherwise if @from is not %NULL, |
1da177e4c Linux-2.6.12-rc2 |
234 235 236 |
* searches continue from next device on the global list. * The reference count for @from is always decremented if it is not %NULL. */ |
95247b57e PCI: clean up sea... |
237 238 |
struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, |
b08508c40 PCI: fix compiler... |
239 |
struct pci_dev *from) |
1da177e4c Linux-2.6.12-rc2 |
240 |
{ |
95247b57e PCI: clean up sea... |
241 242 |
struct pci_dev *pdev; struct pci_device_id *id; |
6ae4adf50 [PATCH] PCI: prev... |
243 244 |
/* |
95247b57e PCI: clean up sea... |
245 246 247 248 |
* pci_find_subsys() can be called on the ide_setup() path, * super-early in boot. But the down_read() will enable local * interrupts, which can cause some machines to crash. So here we * detect and flag that situation and bail out early. |
6ae4adf50 [PATCH] PCI: prev... |
249 |
*/ |
35ef63f63 use no_pci_device... |
250 |
if (unlikely(no_pci_devices())) |
6ae4adf50 [PATCH] PCI: prev... |
251 |
return NULL; |
95247b57e PCI: clean up sea... |
252 253 254 255 256 257 258 259 260 261 262 263 264 |
id = kzalloc(sizeof(*id), GFP_KERNEL); if (!id) return NULL; id->vendor = vendor; id->device = device; id->subvendor = ss_vendor; id->subdevice = ss_device; pdev = pci_get_dev_by_id(id, from); kfree(id); return pdev; |
1da177e4c Linux-2.6.12-rc2 |
265 266 267 268 269 270 271 272 273 274 275 276 |
} /** * pci_get_device - begin or continue searching for a PCI device by vendor/device id * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids * @from: Previous PCI device found in search, or %NULL for new search. * * Iterates through the list of known PCI devices. If a PCI device is * found with a matching @vendor and @device, the reference count to the * device is incremented and a pointer to its device structure is returned. * Otherwise, %NULL is returned. A new search is initiated by passing %NULL |
d75763d24 [PATCH] pci/searc... |
277 |
* as the @from argument. Otherwise if @from is not %NULL, searches continue |
1da177e4c Linux-2.6.12-rc2 |
278 279 280 281 282 283 284 285 |
* from next device on the global list. The reference count for @from is * always decremented if it is not %NULL. */ struct pci_dev * pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from) { return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); } |
29f3eb646 pci: Additional s... |
286 |
/** |
1da177e4c Linux-2.6.12-rc2 |
287 288 289 290 291 292 293 294 |
* pci_get_class - begin or continue searching for a PCI device by class * @class: search for a PCI device with this class designation * @from: Previous PCI device found in search, or %NULL for new search. * * Iterates through the list of known PCI devices. If a PCI device is * found with a matching @class, the reference count to the device is * incremented and a pointer to its device structure is returned. * Otherwise, %NULL is returned. |
d75763d24 [PATCH] pci/searc... |
295 |
* A new search is initiated by passing %NULL as the @from argument. |
1da177e4c Linux-2.6.12-rc2 |
296 297 298 299 300 301 |
* Otherwise if @from is not %NULL, searches continue from next device * on the global list. The reference count for @from is always decremented * if it is not %NULL. */ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) { |
1da177e4c Linux-2.6.12-rc2 |
302 |
struct pci_dev *dev; |
95247b57e PCI: clean up sea... |
303 |
struct pci_device_id *id; |
1da177e4c Linux-2.6.12-rc2 |
304 |
|
95247b57e PCI: clean up sea... |
305 306 307 308 309 310 |
id = kzalloc(sizeof(*id), GFP_KERNEL); if (!id) return NULL; id->vendor = id->device = id->subvendor = id->subdevice = PCI_ANY_ID; id->class_mask = PCI_ANY_ID; id->class = class; |
1da177e4c Linux-2.6.12-rc2 |
311 |
|
95247b57e PCI: clean up sea... |
312 313 |
dev = pci_get_dev_by_id(id, from); kfree(id); |
1da177e4c Linux-2.6.12-rc2 |
314 315 |
return dev; } |
448432c4b PCI: remove pci_f... |
316 317 318 319 320 321 322 323 324 325 326 327 |
/** * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not. * @ids: A pointer to a null terminated list of struct pci_device_id structures * that describe the type of PCI device the caller is trying to find. * * Obvious fact: You do not have a reference to any device that might be found * by this function, so if that device is removed from the system right after * this function is finished, the value will be stale. Use this function to * find devices that are usually built into a system, or for a general hint as * to if another device happens to be present at this specific moment in time. */ int pci_dev_present(const struct pci_device_id *ids) |
d86f90f99 pci: Introduce pc... |
328 |
{ |
95247b57e PCI: clean up sea... |
329 |
struct pci_dev *found = NULL; |
d86f90f99 pci: Introduce pc... |
330 331 |
WARN_ON(in_interrupt()); |
d86f90f99 pci: Introduce pc... |
332 |
while (ids->vendor || ids->subvendor || ids->class_mask) { |
95247b57e PCI: clean up sea... |
333 334 335 |
found = pci_get_dev_by_id(ids, NULL); if (found) goto exit; |
d86f90f99 pci: Introduce pc... |
336 337 |
ids++; } |
3c92c57af PCI: Fix pci_find... |
338 |
exit: |
448432c4b PCI: remove pci_f... |
339 340 341 |
if (found) return 1; return 0; |
1da177e4c Linux-2.6.12-rc2 |
342 343 |
} EXPORT_SYMBOL(pci_dev_present); |
29f3eb646 pci: Additional s... |
344 345 346 347 |
/* For boot time work */ EXPORT_SYMBOL(pci_find_bus); EXPORT_SYMBOL(pci_find_next_bus); /* For everyone */ |
1da177e4c Linux-2.6.12-rc2 |
348 349 350 351 |
EXPORT_SYMBOL(pci_get_device); EXPORT_SYMBOL(pci_get_subsys); EXPORT_SYMBOL(pci_get_slot); EXPORT_SYMBOL(pci_get_class); |