1
0
Fork 0

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>
hifive-unleashed-5.1
Bjorn Helgaas 2008-06-27 16:57:18 -06:00 committed by Andi Kleen
parent 1f32ca31e7
commit 84684c7469
1 changed files with 57 additions and 11 deletions

View File

@ -286,6 +286,61 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
#ifdef CONFIG_PCI
static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
unsigned int irq)
{
u32 class;
u8 progif;
if (pci->irq == irq) {
dev_dbg(&pnp->dev, "device %s using irq %d\n",
pci_name(pci), irq);
return 1;
}
/*
* See pci_setup_device() and ata_pci_sff_activate_host() for
* similar IDE legacy detection.
*/
pci_read_config_dword(pci, PCI_CLASS_REVISION, &class);
class >>= 8; /* discard revision ID */
progif = class & 0xff;
class >>= 8;
if (class == PCI_CLASS_STORAGE_IDE) {
/*
* Unless both channels are native-PCI mode only,
* treat the compatibility IRQs as busy.
*/
if ((progif & 0x5) != 0x5)
if (pci_get_legacy_ide_irq(pci, 0) == irq ||
pci_get_legacy_ide_irq(pci, 1) == irq) {
dev_dbg(&pnp->dev, "legacy IDE device %s "
"using irq %d\n", pci_name(pci), irq);
return 1;
}
}
return 0;
}
#endif
static int pci_uses_irq(struct pnp_dev *pnp, unsigned int irq)
{
#ifdef CONFIG_PCI
struct pci_dev *pci = NULL;
for_each_pci_dev(pci) {
if (pci_dev_uses_irq(pnp, pci, irq)) {
pci_dev_put(pci);
return 1;
}
}
#endif
return 0;
}
int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
{
int i;
@ -317,18 +372,9 @@ int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
}
}
#ifdef CONFIG_PCI
/* check if the resource is being used by a pci device */
{
struct pci_dev *pci = NULL;
for_each_pci_dev(pci) {
if (pci->irq == *irq) {
pci_dev_put(pci);
return 0;
}
}
}
#endif
if (pci_uses_irq(dev, *irq))
return 0;
/* check if the resource is already in use, skip if the
* device is active because it itself may be in use */