ia64/linux-2.6.18-xen.hg

annotate drivers/pci/search.c @ 912:dd42cdb0ab89

[IA64] Build blktap2 driver by default in x86 builds.

add CONFIG_XEN_BLKDEV_TAP2=y to buildconfigs/linux-defconfig_xen_ia64.

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