aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp/resource.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2008-06-27 18:57:18 -0400
committerAndi Kleen <andi@basil.nowhere.org>2008-07-16 17:27:07 -0400
commit84684c7469a2e6fcbf8c808ac5030ba2de14ff77 (patch)
tree83b2892dc924d482c004e40201006b77eb2b3c60 /drivers/pnp/resource.c
parent1f32ca31e7409d37c1b25e5f81840fb184380cdf (diff)
PNP: avoid legacy IDE IRQs
If an IDE controller is in compatibility mode, it expects to use IRQs 14 and 15, so PNP should avoid them. This patch should resolve this problem report: parallel driver grabs IRQ14 preventing legacy SFF ATA controller from working https://bugzilla.novell.com/show_bug.cgi?id=375836 Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Len Brown <len.brown@intel.com> Signed-off-by: Andi Kleen <ak@linux.intel.com>
Diffstat (limited to 'drivers/pnp/resource.c')
-rw-r--r--drivers/pnp/resource.c68
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
290static 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
329static 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
289int pnp_check_irq(struct pnp_dev *dev, struct resource *res) 344int 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 */