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 */ 9 10 #include <linux/init.h> 11 #include <linux/pci.h> 12 #include <linux/slab.h> 13 #include <linux/module.h> 14 #include <linux/interrupt.h> 15 #include "pci.h" 16 17 DECLARE_RWSEM(pci_bus_sem); 18 EXPORT_SYMBOL_GPL(pci_bus_sem); 19 20 /* 21 * find the upstream PCIe-to-PCI bridge of a PCI device 22 * if the device is PCIE, return NULL 23 * if the device isn't connected to a PCIe bridge (that is its parent is a 24 * legacy PCI bridge and the bridge is directly connected to bus 0), return its 25 * parent 26 */ 27 struct pci_dev * 28 pci_find_upstream_pcie_bridge(struct pci_dev *pdev) 29 { 30 struct pci_dev *tmp = NULL; 31 32 if (pci_is_pcie(pdev)) 33 return NULL; 34 while (1) { 35 if (pci_is_root_bus(pdev->bus)) 36 break; 37 pdev = pdev->bus->self; 38 /* a p2p bridge */ 39 if (!pci_is_pcie(pdev)) { 40 tmp = pdev; 41 continue; 42 } 43 /* PCI device should connect to a PCIe bridge */ 44 if (pci_pcie_type(pdev) != PCI_EXP_TYPE_PCI_BRIDGE) { 45 /* Busted hardware? */ 46 WARN_ON_ONCE(1); 47 return NULL; 48 } 49 return pdev; 50 } 51 52 return tmp; 53 } 54 55 static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr) 56 { 57 struct pci_bus* child; 58 struct list_head *tmp; 59 60 if(bus->number == busnr) 61 return bus; 62 63 list_for_each(tmp, &bus->children) { 64 child = pci_do_find_bus(pci_bus_b(tmp), busnr); 65 if(child) 66 return child; 67 } 68 return NULL; 69 } 70 71 /** 72 * pci_find_bus - locate PCI bus from a given domain and bus number 73 * @domain: number of PCI domain to search 74 * @busnr: number of desired PCI bus 75 * 76 * Given a PCI bus number and domain number, the desired PCI bus is located 77 * in the global list of PCI buses. If the bus is found, a pointer to its 78 * data structure is returned. If no bus is found, %NULL is returned. 79 */ 80 struct pci_bus * pci_find_bus(int domain, int busnr) 81 { 82 struct pci_bus *bus = NULL; 83 struct pci_bus *tmp_bus; 84 85 while ((bus = pci_find_next_bus(bus)) != NULL) { 86 if (pci_domain_nr(bus) != domain) 87 continue; 88 tmp_bus = pci_do_find_bus(bus, busnr); 89 if (tmp_bus) 90 return tmp_bus; 91 } 92 return NULL; 93 } 94 95 /** 96 * pci_find_next_bus - begin or continue searching for a PCI bus 97 * @from: Previous PCI bus found, or %NULL for new search. 98 * 99 * Iterates through the list of known PCI buses. A new search is 100 * initiated by passing %NULL as the @from argument. Otherwise if 101 * @from is not %NULL, searches continue from next device on the 102 * global list. 103 */ 104 struct pci_bus * 105 pci_find_next_bus(const struct pci_bus *from) 106 { 107 struct list_head *n; 108 struct pci_bus *b = NULL; 109 110 WARN_ON(in_interrupt()); 111 down_read(&pci_bus_sem); 112 n = from ? from->node.next : pci_root_buses.next; 113 if (n != &pci_root_buses) 114 b = pci_bus_b(n); 115 up_read(&pci_bus_sem); 116 return b; 117 } 118 119 /** 120 * pci_get_slot - locate PCI device for a given PCI slot 121 * @bus: PCI bus on which desired PCI device resides 122 * @devfn: encodes number of PCI slot in which the desired PCI 123 * device resides and the logical device number within that slot 124 * in case of multi-function devices. 125 * 126 * Given a PCI bus and slot/function number, the desired PCI device 127 * is located in the list of PCI devices. 128 * If the device is found, its reference count is increased and this 129 * function returns a pointer to its data structure. The caller must 130 * decrement the reference count by calling pci_dev_put(). 131 * If no device is found, %NULL is returned. 132 */ 133 struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn) 134 { 135 struct pci_dev *dev; 136 137 WARN_ON(in_interrupt()); 138 down_read(&pci_bus_sem); 139 140 list_for_each_entry(dev, &bus->devices, bus_list) { 141 if (dev->devfn == devfn) 142 goto out; 143 } 144 145 dev = NULL; 146 out: 147 pci_dev_get(dev); 148 up_read(&pci_bus_sem); 149 return dev; 150 } 151 152 /** 153 * pci_get_domain_bus_and_slot - locate PCI device for a given PCI domain (segment), bus, and slot 154 * @domain: PCI domain/segment on which the PCI device resides. 155 * @bus: PCI bus on which desired PCI device resides 156 * @devfn: encodes number of PCI slot in which the desired PCI device 157 * resides and the logical device number within that slot in case of 158 * multi-function devices. 159 * 160 * Given a PCI domain, bus, and slot/function number, the desired PCI 161 * device is located in the list of PCI devices. If the device is 162 * found, its reference count is increased and this function returns a 163 * pointer to its data structure. The caller must decrement the 164 * reference count by calling pci_dev_put(). If no device is found, 165 * %NULL is returned. 166 */ 167 struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus, 168 unsigned int devfn) 169 { 170 struct pci_dev *dev = NULL; 171 172 for_each_pci_dev(dev) { 173 if (pci_domain_nr(dev->bus) == domain && 174 (dev->bus->number == bus && dev->devfn == devfn)) 175 return dev; 176 } 177 return NULL; 178 } 179 EXPORT_SYMBOL(pci_get_domain_bus_and_slot); 180 181 static int match_pci_dev_by_id(struct device *dev, void *data) 182 { 183 struct pci_dev *pdev = to_pci_dev(dev); 184 struct pci_device_id *id = data; 185 186 if (pci_match_one_device(id, pdev)) 187 return 1; 188 return 0; 189 } 190 191 /* 192 * pci_get_dev_by_id - begin or continue searching for a PCI device by id 193 * @id: pointer to struct pci_device_id to match for the device 194 * @from: Previous PCI device found in search, or %NULL for new search. 195 * 196 * Iterates through the list of known PCI devices. If a PCI device is found 197 * with a matching id a pointer to its device structure is returned, and the 198 * reference count to the device is incremented. Otherwise, %NULL is returned. 199 * A new search is initiated by passing %NULL as the @from argument. Otherwise 200 * if @from is not %NULL, searches continue from next device on the global 201 * list. The reference count for @from is always decremented if it is not 202 * %NULL. 203 * 204 * This is an internal function for use by the other search functions in 205 * this file. 206 */ 207 static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id, 208 struct pci_dev *from) 209 { 210 struct device *dev; 211 struct device *dev_start = NULL; 212 struct pci_dev *pdev = NULL; 213 214 WARN_ON(in_interrupt()); 215 if (from) 216 dev_start = &from->dev; 217 dev = bus_find_device(&pci_bus_type, dev_start, (void *)id, 218 match_pci_dev_by_id); 219 if (dev) 220 pdev = to_pci_dev(dev); 221 if (from) 222 pci_dev_put(from); 223 return pdev; 224 } 225 226 /** 227 * pci_get_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id 228 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids 229 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids 230 * @ss_vendor: PCI subsystem vendor id to match, or %PCI_ANY_ID to match all vendor ids 231 * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids 232 * @from: Previous PCI device found in search, or %NULL for new search. 233 * 234 * Iterates through the list of known PCI devices. If a PCI device is found 235 * with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its 236 * device structure is returned, and the reference count to the device is 237 * incremented. Otherwise, %NULL is returned. A new search is initiated by 238 * passing %NULL as the @from argument. Otherwise if @from is not %NULL, 239 * searches continue from next device on the global list. 240 * The reference count for @from is always decremented if it is not %NULL. 241 */ 242 struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device, 243 unsigned int ss_vendor, unsigned int ss_device, 244 struct pci_dev *from) 245 { 246 struct pci_device_id id = { 247 .vendor = vendor, 248 .device = device, 249 .subvendor = ss_vendor, 250 .subdevice = ss_device, 251 }; 252 253 return pci_get_dev_by_id(&id, from); 254 } 255 256 /** 257 * pci_get_device - begin or continue searching for a PCI device by vendor/device id 258 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids 259 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids 260 * @from: Previous PCI device found in search, or %NULL for new search. 261 * 262 * Iterates through the list of known PCI devices. If a PCI device is 263 * found with a matching @vendor and @device, the reference count to the 264 * device is incremented and a pointer to its device structure is returned. 265 * Otherwise, %NULL is returned. A new search is initiated by passing %NULL 266 * as the @from argument. Otherwise if @from is not %NULL, searches continue 267 * from next device on the global list. The reference count for @from is 268 * always decremented if it is not %NULL. 269 */ 270 struct pci_dev * 271 pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from) 272 { 273 return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); 274 } 275 276 /** 277 * pci_get_class - begin or continue searching for a PCI device by class 278 * @class: search for a PCI device with this class designation 279 * @from: Previous PCI device found in search, or %NULL for new search. 280 * 281 * Iterates through the list of known PCI devices. If a PCI device is 282 * found with a matching @class, the reference count to the device is 283 * incremented and a pointer to its device structure is returned. 284 * Otherwise, %NULL is returned. 285 * A new search is initiated by passing %NULL as the @from argument. 286 * Otherwise if @from is not %NULL, searches continue from next device 287 * on the global list. The reference count for @from is always decremented 288 * if it is not %NULL. 289 */ 290 struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) 291 { 292 struct pci_device_id id = { 293 .vendor = PCI_ANY_ID, 294 .device = PCI_ANY_ID, 295 .subvendor = PCI_ANY_ID, 296 .subdevice = PCI_ANY_ID, 297 .class_mask = PCI_ANY_ID, 298 .class = class, 299 }; 300 301 return pci_get_dev_by_id(&id, from); 302 } 303 304 /** 305 * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not. 306 * @ids: A pointer to a null terminated list of struct pci_device_id structures 307 * that describe the type of PCI device the caller is trying to find. 308 * 309 * Obvious fact: You do not have a reference to any device that might be found 310 * by this function, so if that device is removed from the system right after 311 * this function is finished, the value will be stale. Use this function to 312 * find devices that are usually built into a system, or for a general hint as 313 * to if another device happens to be present at this specific moment in time. 314 */ 315 int pci_dev_present(const struct pci_device_id *ids) 316 { 317 struct pci_dev *found = NULL; 318 319 WARN_ON(in_interrupt()); 320 while (ids->vendor || ids->subvendor || ids->class_mask) { 321 found = pci_get_dev_by_id(ids, NULL); 322 if (found) { 323 pci_dev_put(found); 324 return 1; 325 } 326 ids++; 327 } 328 329 return 0; 330 } 331 EXPORT_SYMBOL(pci_dev_present); 332 333 /* For boot time work */ 334 EXPORT_SYMBOL(pci_find_bus); 335 EXPORT_SYMBOL(pci_find_next_bus); 336 /* For everyone */ 337 EXPORT_SYMBOL(pci_get_device); 338 EXPORT_SYMBOL(pci_get_subsys); 339 EXPORT_SYMBOL(pci_get_slot); 340 EXPORT_SYMBOL(pci_get_class); 341