diff options
Diffstat (limited to 'drivers/pnp')
-rw-r--r-- | drivers/pnp/resource.c | 68 |
1 files changed, 57 insertions, 11 deletions
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index d6388970a1a4..4cfe3a1efdfb 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c | |||
@@ -286,6 +286,61 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id) | |||
286 | return IRQ_HANDLED; | 286 | return IRQ_HANDLED; |
287 | } | 287 | } |
288 | 288 | ||
289 | #ifdef CONFIG_PCI | ||
290 | static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci, | ||
291 | unsigned int irq) | ||
292 | { | ||
293 | u32 class; | ||
294 | u8 progif; | ||
295 | |||
296 | if (pci->irq == irq) { | ||
297 | dev_dbg(&pnp->dev, "device %s using irq %d\n", | ||
298 | pci_name(pci), irq); | ||
299 | return 1; | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * See pci_setup_device() and ata_pci_sff_activate_host() for | ||
304 | * similar IDE legacy detection. | ||
305 | */ | ||
306 | pci_read_config_dword(pci, PCI_CLASS_REVISION, &class); | ||
307 | class >>= 8; /* discard revision ID */ | ||
308 | progif = class & 0xff; | ||
309 | class >>= 8; | ||
310 | |||
311 | if (class == PCI_CLASS_STORAGE_IDE) { | ||
312 | /* | ||
313 | * Unless both channels are native-PCI mode only, | ||
314 | * treat the compatibility IRQs as busy. | ||
315 | */ | ||
316 | if ((progif & 0x5) != 0x5) | ||
317 | if (pci_get_legacy_ide_irq(pci, 0) == irq || | ||
318 | pci_get_legacy_ide_irq(pci, 1) == irq) { | ||
319 | dev_dbg(&pnp->dev, "legacy IDE device %s " | ||
320 | "using irq %d\n", pci_name(pci), irq); | ||
321 | return 1; | ||
322 | } | ||
323 | } | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | #endif | ||
328 | |||
329 | static int pci_uses_irq(struct pnp_dev *pnp, unsigned int irq) | ||
330 | { | ||
331 | #ifdef CONFIG_PCI | ||
332 | struct pci_dev *pci = NULL; | ||
333 | |||
334 | for_each_pci_dev(pci) { | ||
335 | if (pci_dev_uses_irq(pnp, pci, irq)) { | ||
336 | pci_dev_put(pci); | ||
337 | return 1; | ||
338 | } | ||
339 | } | ||
340 | #endif | ||
341 | return 0; | ||
342 | } | ||
343 | |||
289 | int pnp_check_irq(struct pnp_dev *dev, struct resource *res) | 344 | int pnp_check_irq(struct pnp_dev *dev, struct resource *res) |
290 | { | 345 | { |
291 | int i; | 346 | int i; |
@@ -317,18 +372,9 @@ int pnp_check_irq(struct pnp_dev *dev, struct resource *res) | |||
317 | } | 372 | } |
318 | } | 373 | } |
319 | 374 | ||
320 | #ifdef CONFIG_PCI | ||
321 | /* check if the resource is being used by a pci device */ | 375 | /* check if the resource is being used by a pci device */ |
322 | { | 376 | if (pci_uses_irq(dev, *irq)) |
323 | struct pci_dev *pci = NULL; | 377 | return 0; |
324 | for_each_pci_dev(pci) { | ||
325 | if (pci->irq == *irq) { | ||
326 | pci_dev_put(pci); | ||
327 | return 0; | ||
328 | } | ||
329 | } | ||
330 | } | ||
331 | #endif | ||
332 | 378 | ||
333 | /* check if the resource is already in use, skip if the | 379 | /* check if the resource is already in use, skip if the |
334 | * device is active because it itself may be in use */ | 380 | * device is active because it itself may be in use */ |