Skip to content

Commit

Permalink
PNP: avoid legacy IDE IRQs
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Bjorn Helgaas authored and Andi Kleen committed Jul 16, 2008
1 parent 1f32ca3 commit 84684c7
Showing 1 changed file with 57 additions and 11 deletions.
68 changes: 57 additions & 11 deletions drivers/pnp/resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down

0 comments on commit 84684c7

Please sign in to comment.