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>
This commit is contained in:
Родитель
1f32ca31e7
Коммит
84684c7469
|
@ -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 */
|
||||
|
|
Загрузка…
Ссылка в новой задаче