diff options
| -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 */ |
