diff options
-rw-r--r-- | arch/x86/pci/intel_mid_pci.c | 10 | ||||
-rw-r--r-- | arch/x86/pci/irq.c | 7 | ||||
-rw-r--r-- | drivers/acpi/pci_irq.c | 11 | ||||
-rw-r--r-- | include/linux/pci.h | 1 |
4 files changed, 25 insertions, 4 deletions
diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c index b9958c364075..44b9271580b5 100644 --- a/arch/x86/pci/intel_mid_pci.c +++ b/arch/x86/pci/intel_mid_pci.c | |||
@@ -210,6 +210,9 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev) | |||
210 | { | 210 | { |
211 | int polarity; | 211 | int polarity; |
212 | 212 | ||
213 | if (dev->irq_managed && dev->irq > 0) | ||
214 | return 0; | ||
215 | |||
213 | if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER) | 216 | if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER) |
214 | polarity = 0; /* active high */ | 217 | polarity = 0; /* active high */ |
215 | else | 218 | else |
@@ -224,13 +227,18 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev) | |||
224 | if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC) < 0) | 227 | if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC) < 0) |
225 | return -EBUSY; | 228 | return -EBUSY; |
226 | 229 | ||
230 | dev->irq_managed = 1; | ||
231 | |||
227 | return 0; | 232 | return 0; |
228 | } | 233 | } |
229 | 234 | ||
230 | static void intel_mid_pci_irq_disable(struct pci_dev *dev) | 235 | static void intel_mid_pci_irq_disable(struct pci_dev *dev) |
231 | { | 236 | { |
232 | if (!mp_should_keep_irq(&dev->dev) && dev->irq > 0) | 237 | if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed && |
238 | dev->irq > 0) { | ||
233 | mp_unmap_irq(dev->irq); | 239 | mp_unmap_irq(dev->irq); |
240 | dev->irq_managed = 0; | ||
241 | } | ||
234 | } | 242 | } |
235 | 243 | ||
236 | struct pci_ops intel_mid_pci_ops = { | 244 | struct pci_ops intel_mid_pci_ops = { |
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index cb50e281d838..99884588a47a 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c | |||
@@ -1202,6 +1202,9 @@ static int pirq_enable_irq(struct pci_dev *dev) | |||
1202 | int irq; | 1202 | int irq; |
1203 | struct io_apic_irq_attr irq_attr; | 1203 | struct io_apic_irq_attr irq_attr; |
1204 | 1204 | ||
1205 | if (dev->irq_managed && dev->irq > 0) | ||
1206 | return 0; | ||
1207 | |||
1205 | irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, | 1208 | irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, |
1206 | PCI_SLOT(dev->devfn), | 1209 | PCI_SLOT(dev->devfn), |
1207 | pin - 1, &irq_attr); | 1210 | pin - 1, &irq_attr); |
@@ -1228,6 +1231,7 @@ static int pirq_enable_irq(struct pci_dev *dev) | |||
1228 | } | 1231 | } |
1229 | dev = temp_dev; | 1232 | dev = temp_dev; |
1230 | if (irq >= 0) { | 1233 | if (irq >= 0) { |
1234 | dev->irq_managed = 1; | ||
1231 | dev->irq = irq; | 1235 | dev->irq = irq; |
1232 | dev_info(&dev->dev, "PCI->APIC IRQ transform: " | 1236 | dev_info(&dev->dev, "PCI->APIC IRQ transform: " |
1233 | "INT %c -> IRQ %d\n", 'A' + pin - 1, irq); | 1237 | "INT %c -> IRQ %d\n", 'A' + pin - 1, irq); |
@@ -1269,8 +1273,9 @@ bool mp_should_keep_irq(struct device *dev) | |||
1269 | static void pirq_disable_irq(struct pci_dev *dev) | 1273 | static void pirq_disable_irq(struct pci_dev *dev) |
1270 | { | 1274 | { |
1271 | if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) && | 1275 | if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) && |
1272 | dev->irq) { | 1276 | dev->irq_managed && dev->irq) { |
1273 | mp_unmap_irq(dev->irq); | 1277 | mp_unmap_irq(dev->irq); |
1274 | dev->irq = 0; | 1278 | dev->irq = 0; |
1279 | dev->irq_managed = 0; | ||
1275 | } | 1280 | } |
1276 | } | 1281 | } |
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 6e6b80eb0bba..5f1fdca65e5f 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c | |||
@@ -413,6 +413,9 @@ int acpi_pci_irq_enable(struct pci_dev *dev) | |||
413 | return 0; | 413 | return 0; |
414 | } | 414 | } |
415 | 415 | ||
416 | if (dev->irq_managed && dev->irq > 0) | ||
417 | return 0; | ||
418 | |||
416 | entry = acpi_pci_irq_lookup(dev, pin); | 419 | entry = acpi_pci_irq_lookup(dev, pin); |
417 | if (!entry) { | 420 | if (!entry) { |
418 | /* | 421 | /* |
@@ -456,6 +459,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) | |||
456 | return rc; | 459 | return rc; |
457 | } | 460 | } |
458 | dev->irq = rc; | 461 | dev->irq = rc; |
462 | dev->irq_managed = 1; | ||
459 | 463 | ||
460 | if (link) | 464 | if (link) |
461 | snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link); | 465 | snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link); |
@@ -478,7 +482,7 @@ void acpi_pci_irq_disable(struct pci_dev *dev) | |||
478 | u8 pin; | 482 | u8 pin; |
479 | 483 | ||
480 | pin = dev->pin; | 484 | pin = dev->pin; |
481 | if (!pin) | 485 | if (!pin || !dev->irq_managed || dev->irq <= 0) |
482 | return; | 486 | return; |
483 | 487 | ||
484 | /* Keep IOAPIC pin configuration when suspending */ | 488 | /* Keep IOAPIC pin configuration when suspending */ |
@@ -506,6 +510,9 @@ void acpi_pci_irq_disable(struct pci_dev *dev) | |||
506 | */ | 510 | */ |
507 | 511 | ||
508 | dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin)); | 512 | dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin)); |
509 | if (gsi >= 0 && dev->irq > 0) | 513 | if (gsi >= 0) { |
510 | acpi_unregister_gsi(gsi); | 514 | acpi_unregister_gsi(gsi); |
515 | dev->irq = 0; | ||
516 | dev->irq_managed = 0; | ||
517 | } | ||
511 | } | 518 | } |
diff --git a/include/linux/pci.h b/include/linux/pci.h index a523cee3abb5..c888c5e4e225 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -349,6 +349,7 @@ struct pci_dev { | |||
349 | unsigned int __aer_firmware_first:1; | 349 | unsigned int __aer_firmware_first:1; |
350 | unsigned int broken_intx_masking:1; | 350 | unsigned int broken_intx_masking:1; |
351 | unsigned int io_window_1k:1; /* Intel P2P bridge 1K I/O windows */ | 351 | unsigned int io_window_1k:1; /* Intel P2P bridge 1K I/O windows */ |
352 | unsigned int irq_managed:1; | ||
352 | pci_dev_flags_t dev_flags; | 353 | pci_dev_flags_t dev_flags; |
353 | atomic_t enable_cnt; /* pci_enable_device has been called */ | 354 | atomic_t enable_cnt; /* pci_enable_device has been called */ |
354 | 355 | ||