Skip to contentSkip to conversation

Enable support of IOAPIC hotplug on x86 platforms

PATCH Superseded Jiang Liu 10 participants 70 messages Oct 27, 2014 – Dec 19, 2014

Subsystems (4)

v7 of 8 Superseded Latest is v8 →

lore
Share & tools
lore

Jiang Liu

author
#0 lore raw

v7 cover Enable support of IOAPIC hotplug on x86 platforms

This patch set enhances IOAPIC core and ACPI drivers to support IOAPIC hotplug on x86 platforms. It's based on v3.18-rc2 at
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

You may pull it from
https://github.com/jiangliu/linux.git ioapic/hotplug_v7

We have pick up several patches from Yinghai's original IOAPIC hotplug patch set and reimplemented IOAPIC driver as an ACPI driver instead of a PCI driver.

It has been tested on a 4-socket Intel SDV with socket hot-addition capability. Any suggestions are welcomed!

Patch 1-3 are bugfixes against v3.17 and should target v3.18. Patch 1 has been merged into tip/x86/urgent.
Patch 4-7 are bugfixes and enhancements to ACPI subsystem Patch 8 killes PCI IOAPIC driver
Patch 9-17 enhances IOAPIC core to support IOAPIC hotplug Patch 18 reimplements ACPI IOAPIC driver and enables IOAPIC hotplug

V6->V7:
1) Rebase to v3.18-rc2
2) Three bugfixes for v3.18
V5->V6:
1) Rebase to the latest v3.17-16
2) Minor fixes for comments
V4->V5:
1) Fix a building error
2) Don't rename processor_core.c as apic_id.c
3) Improve comments
4) Reorder patches to get rid of some temporary code V3->V4:
1) Fix a bug in manage IOAPIC reference count
2) Rebase to v3.17-rc2
3) Refine commit messages
V2->V3:
1) Refine ACPI resource walk functions for PCI root bus and IOAPIC
2) Improve commit messages
3) Reorder patch order for better maintenence

Jiang Liu (15):
ACPI, irq: fix regression casued by 6b9fb7082409 x86, intel-mid: Create IRQs for APB timers and RTC timers ACPI, irq, x86: Return IRQ instead of GSI in mp_register_gsi() x86, PCI, ACPI: Kill private function resource_to_addr() in

    arch/x86/pci/acpi.c

ACPI: Correct return value of acpi_dev_resource_address_space()
ACPI: Fix minor syntax issues in processor_core.c
PCI: Remove PCI ioapic driver
x86, irq: Remove __init marker for functions will be used by IOAPIC
hotplug
x86, irq: Keep balance of IOAPIC pin reference count x86, irq: Refine mp_register_ioapic() to prepare for IOAPIC hotplug x86, irq, ACPI: Introduce a rwsem to protect IOAPIC operations from
hotplug
x86, irq, ACPI: Implement interface to support ACPI based IOAPIC
hot-addition
x86, irq, ACPI: Implement interfaces to support ACPI based IOAPIC
hot-removal
x86, irq: Introduce helper to check whether an IOAPIC has been
registered
x86, irq, ACPI: Implement ACPI driver to support IOAPIC hotplug

Yinghai Lu (3):
ACPI: Add interfaces to parse IOAPIC ID for IOAPIC hotplug x86, irq: Split out alloc_ioapic_save_registers() x86, irq: Prefer assigned ID in APIC ID register for x86_64

 arch/x86/include/asm/io_apic.h    |    6 +-
 arch/x86/kernel/acpi/boot.c       |  102 ++++++++++++++--
 arch/x86/kernel/apb_timer.c       |    2 -
 arch/x86/kernel/apic/io_apic.c    |  234 +++++++++++++++++++++++++++++-------
 arch/x86/pci/acpi.c               |  144 +++++++++--------------
 arch/x86/pci/intel_mid_pci.c      |   10 +-
 arch/x86/pci/irq.c                |    7 +-
 arch/x86/platform/intel-mid/sfi.c |    2 +
 drivers/acpi/Kconfig              |    6 +
 drivers/acpi/Makefile             |    1 +
 drivers/acpi/internal.h           |    7 ++
 drivers/acpi/ioapic.c             |  235 +++++++++++++++++++++++++++++++++++++
 drivers/acpi/pci_irq.c            |   11 +-
 drivers/acpi/pci_root.c           |    3 +
 drivers/acpi/processor_core.c     |  131 ++++++++++++++++++---
 drivers/acpi/resource.c           |    2 +-
 drivers/pci/Kconfig               |    7 --
 drivers/pci/Makefile              |    2 -
 drivers/pci/ioapic.c              |  121 -------------------
 include/linux/acpi.h              |    5 +
 include/linux/pci.h               |    1 +
 21 files changed, 739 insertions(+), 300 deletions(-)
 create mode 100644 drivers/acpi/ioapic.c
 delete mode 100644 drivers/pci/ioapic.c
Signature · 1 line
1.7.10.4
author
#1 lore raw

PATCH v7 1/18 ACPI, irq: fix regression casued by 6b9fb7082409

When IOAPIC is disabled, acpi_gsi_to_irq() should return gsi directly instead of calling mp_map_gsi_to_irq() to translate gsi to IRQ by IOAPIC. It fixes https://bugzilla.kernel.org/show_bug.cgi?id=84381.

---
 arch/x86/kernel/acpi/boot.c |   13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
arch/x86/kernel/acpi/boot.c +9 -4
index b436fc735aa4..eceba9d9e116 100644
@@ -604,14 +604,19 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
 
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
 {
-	int irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
+	int irq;
 
-	if (irq >= 0) {
+	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
+		*irqp = gsi;
+	} else {
+		irq = mp_map_gsi_to_irq(gsi,
+					IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
+		if (irq < 0)
+			return -1;
 		*irqp = irq;
-		return 0;
 	}
 
-	return -1;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
 
Signature · 1 line
1.7.10.4
Acked-by on v7 1/18
#2 lore raw

Re: [Patch v7 01/18] ACPI, irq: fix regression casued by 6b9fb7082409

Hi!

Quoted 17 lines

When IOAPIC is disabled, acpi_gsi_to_irq() should return gsi directly instead of calling mp_map_gsi_to_irq() to translate gsi to IRQ by IOAPIC. It fixes https://bugzilla.kernel.org/show_bug.cgi?id=84381.

---
 arch/x86/kernel/acpi/boot.c |   13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
arch/x86/kernel/acpi/boot.c +0 -0
index b436fc735aa4..eceba9d9e116 100644

arch/x86/kernel/acpi/boot.c void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger) · line 610

Quoted 9 lines
arch/x86/kernel/acpi/boot.c +3 -2
@@ -604,14 +604,19 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
 
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
 {
-	int irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
+	int irq;
 
-	if (irq >= 0) {
+	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
+		*irqp = gsi;

As you have multiple return points, anyway, I'd do return 0; here

arch/x86/kernel/acpi/boot.c void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger) · line 617

Quoted 8 lines
arch/x86/kernel/acpi/boot.c +5 -1
+	} else {
+		irq = mp_map_gsi_to_irq(gsi,
+					IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
+		if (irq < 0)
+			return -1;
 		*irqp = irq;
-		return 0;
 	}

...so that one level of nesting is avoided, and there are no problems with fiting to 80 colums.

With that,

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
maintainer
#3 lore raw

Re: [Patch v7 01/18] ACPI, irq: fix regression casued by 6b9fb7082409

In reply to Jiang Liu

The subject should describe the change you're making. "Fix regression caused by xxx" doesn't say anything about what the patch does.

Quoted 2 lines · Jiang Liu

When IOAPIC is disabled, acpi_gsi_to_irq() should return gsi directly instead of calling mp_map_gsi_to_irq() to translate gsi to IRQ by IOAPIC.

I don't know what the convention is or if there even is one, but "GSI" is even more of an acronym than "IRQ", so I'd capitalize it.

Quoted 1 line

It fixes https://bugzilla.kernel.org/show_bug.cgi?id=84381.

A line like the following may be useful to those who have to backport this.

Fixes 6b9fb7082409 ("x86, ACPI, irq: Consolidate algorithm of mapping

(ioapic, pin) to IRQ number")

Quoted 39 lines
---
 arch/x86/kernel/acpi/boot.c |   13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
arch/x86/kernel/acpi/boot.c +9 -5
index b436fc735aa4..eceba9d9e116 100644
@@ -604,14 +604,19 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
 
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
 {
-       int irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
+       int irq;
 
-       if (irq >= 0) {
+       if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
+               *irqp = gsi;
+       } else {
+               irq = mp_map_gsi_to_irq(gsi,
+                                       IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
+               if (irq < 0)
+                       return -1;
                *irqp = irq;
-               return 0;
        }
 
-       return -1;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
 
--

1.7.10.4

#4 lore raw

Re: [Patch v7 01/18] ACPI, irq: fix regression casued by 6b9fb7082409

Quoted 10 lines · Bjorn Helgaas

The subject should describe the change you're making. "Fix regression caused by xxx" doesn't say anything about what the patch does.

Quoted 2 lines · Jiang Liu

When IOAPIC is disabled, acpi_gsi_to_irq() should return gsi directly instead of calling mp_map_gsi_to_irq() to translate gsi to IRQ by IOAPIC.

I don't know what the convention is or if there even is one, but "GSI" is even more of an acronym than "IRQ", so I'd capitalize it.

Quoted 6 lines
Quoted 1 line

It fixes https://bugzilla.kernel.org/show_bug.cgi?id=84381.

A line like the following may be useful to those who have to backport this.

Fixes 6b9fb7082409 ("x86, ACPI, irq: Consolidate algorithm of mapping

(ioapic, pin) to IRQ number")

The patch is already queued in tip x86/urgent with a proper changelog.

http://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/commit/?id=961b6a7003acec4f9d70dabc1a253b783cb74272

Thanks,

tglx

author
#5 lore raw

PATCH v7 2/18 x86, intel-mid: Create IRQs for APB timers and RTC timers

In reply to Jiang Liu

Intel MID platforms has no legacy interrupts, so no IRQ descriptors preallocated. We need to call mp_map_gsi_to_irq() to create IRQ descriptors for APB timers and RTC timers, otherwise it may cause invalid memory access as:

[    0.116839] BUG: unable to handle kernel NULL pointer dereference at
0000003a
[    0.123803] IP: [<c1071c0e>] setup_irq+0xf/0x4d
---
 arch/x86/kernel/apb_timer.c       |    2 --
 arch/x86/platform/intel-mid/sfi.c |    2 ++
 2 files changed, 2 insertions(+), 2 deletions(-)
arch/x86/kernel/apb_timer.c +0 -2
index 5972b108f15a..b708738d016e 100644
@@ -185,8 +185,6 @@ static void apbt_setup_irq(struct apbt_dev *adev)
 
 	irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT);
 	irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
-	/* APB timer irqs are set up as mp_irqs, timer is edge type */
-	__irq_set_handler(adev->irq, handle_edge_irq, 0, "edge");
 }
 
 /* Should be called with per cpu */
arch/x86/platform/intel-mid/sfi.c +2 -0
index 3c53a90fdb18..c14ad34776c4 100644
@@ -106,6 +106,7 @@ int __init sfi_parse_mtmr(struct sfi_table_header *table)
 			mp_irq.dstapic = MP_APIC_ALL;
 			mp_irq.dstirq = pentry->irq;
 			mp_save_irq(&mp_irq);
+			mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC);
 	}
 
 	return 0;
@@ -176,6 +177,7 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table)
 		mp_irq.dstapic = MP_APIC_ALL;
 		mp_irq.dstirq = pentry->irq;
 		mp_save_irq(&mp_irq);
+		mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC);
 	}
 	return 0;
 }
Signature · 1 line
1.7.10.4
#6 lore raw

[tip:x86/urgent] x86, intel-mid: Create IRQs for APB timers and RTC timers

x86, intel-mid: Create IRQs for APB timers and RTC timers
Commit-ID:  287d0625f072e78bb438e6a5f0cf106f9aa03d60
Gitweb:     http://git.kernel.org/tip/287d0625f072e78bb438e6a5f0cf106f9aa03d60
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:32 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 28 Oct 2014 19:50:50 +0100

x86, intel-mid: Create IRQs for APB timers and RTC timers

Intel MID platforms has no legacy interrupts, so no IRQ descriptors preallocated. We need to call mp_map_gsi_to_irq() to create IRQ descriptors for APB timers and RTC timers, otherwise it may cause invalid memory access as:

[    0.116839] BUG: unable to handle kernel NULL pointer dereference at
0000003a
[    0.123803] IP: [<c1071c0e>] setup_irq+0xf/0x4d
Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Cohen <[email protected]>
Cc <[email protected]> # 3.17
---
 arch/x86/kernel/apb_timer.c       | 2 --
 arch/x86/platform/intel-mid/sfi.c | 2 ++
 2 files changed, 2 insertions(+), 2 deletions(-)
arch/x86/kernel/apb_timer.c +0 -2
index 5972b10..b708738 100644
@@ -185,8 +185,6 @@ static void apbt_setup_irq(struct apbt_dev *adev)
 
 	irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT);
 	irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
-	/* APB timer irqs are set up as mp_irqs, timer is edge type */
-	__irq_set_handler(adev->irq, handle_edge_irq, 0, "edge");
 }
 
 /* Should be called with per cpu */
arch/x86/platform/intel-mid/sfi.c +2 -0
index 3c53a90..c14ad34 100644
@@ -106,6 +106,7 @@ int __init sfi_parse_mtmr(struct sfi_table_header *table)
 			mp_irq.dstapic = MP_APIC_ALL;
 			mp_irq.dstirq = pentry->irq;
 			mp_save_irq(&mp_irq);
+			mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC);
 	}
 
 	return 0;
@@ -176,6 +177,7 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table)
 		mp_irq.dstapic = MP_APIC_ALL;
 		mp_irq.dstirq = pentry->irq;
 		mp_save_irq(&mp_irq);
+		mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC);
 	}
 	return 0;
 }
#7 lore raw

[tip:x86/urgent] x86, intel-mid: Create IRQs for APB timers and RTC timers

In reply to Jiang Liu
x86, intel-mid: Create IRQs for APB timers and RTC timers
Commit-ID:  f18298595aefa2c836a128ec6e0f75f39965dd81
Gitweb:     http://git.kernel.org/tip/f18298595aefa2c836a128ec6e0f75f39965dd81
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:32 +0800
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 29 Oct 2014 08:52:23 +0100

x86, intel-mid: Create IRQs for APB timers and RTC timers

Intel MID platforms has no legacy interrupts, so no IRQ descriptors preallocated. We need to call mp_map_gsi_to_irq() to create IRQ descriptors for APB timers and RTC timers, otherwise it may cause invalid memory access as:

[    0.116839] BUG: unable to handle kernel NULL pointer dereference at
0000003a
[    0.123803] IP: [<c1071c0e>] setup_irq+0xf/0x4d
Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Cohen <[email protected]>
Cc <[email protected]> # 3.17
---
 arch/x86/kernel/apb_timer.c       | 2 --
 arch/x86/platform/intel-mid/sfi.c | 2 ++
 2 files changed, 2 insertions(+), 2 deletions(-)
arch/x86/kernel/apb_timer.c +0 -2
index 5972b10..b708738 100644
@@ -185,8 +185,6 @@ static void apbt_setup_irq(struct apbt_dev *adev)
 
 	irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT);
 	irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
-	/* APB timer irqs are set up as mp_irqs, timer is edge type */
-	__irq_set_handler(adev->irq, handle_edge_irq, 0, "edge");
 }
 
 /* Should be called with per cpu */
arch/x86/platform/intel-mid/sfi.c +2 -0
index 3c53a90..c14ad34 100644
@@ -106,6 +106,7 @@ int __init sfi_parse_mtmr(struct sfi_table_header *table)
 			mp_irq.dstapic = MP_APIC_ALL;
 			mp_irq.dstirq = pentry->irq;
 			mp_save_irq(&mp_irq);
+			mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC);
 	}
 
 	return 0;
@@ -176,6 +177,7 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table)
 		mp_irq.dstapic = MP_APIC_ALL;
 		mp_irq.dstirq = pentry->irq;
 		mp_save_irq(&mp_irq);
+		mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC);
 	}
 	return 0;
 }
author
#8 lore raw

PATCH v7 3/18 ACPI, irq, x86: Return IRQ instead of GSI in mp_register_gsi()

In reply to Jiang Liu

The GSI for ACPI SCI may be shared with other devices. For example,

Function mp_register_gsi() should return IRQ number, so fix a regression by returning mp_map_gsi_to_irq(gsi, 0) instead of gsi.

The regression was caused by commit 84245af7297ced9e8fe "x86, irq, ACPI:
Change __acpi_register_gsi to return IRQ number instead of GSI" and exposed on a SuperMicro system, which shares one GSI between ACPI SCI and PCI device, with following failure:

http://sourceforge.net/p/linux1394/mailman/linux1394-user/?viewmonth=201410

[    0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low
level)
[    2.699224] firewire_ohci 0000:06:00.0: failed to allocate interrupt

20

---
 arch/x86/kernel/acpi/boot.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kernel/acpi/boot.c +1 -1
index eceba9d9e116..e077c080a519 100644
@@ -397,7 +397,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
 
 	/* Don't set up the ACPI SCI because it's already set up */
 	if (acpi_gbl_FADT.sci_interrupt == gsi)
-		return gsi;
+		return mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
 
 	trigger = trigger == ACPI_EDGE_SENSITIVE ? 0 : 1;
 	polarity = polarity == ACPI_ACTIVE_HIGH ? 0 : 1;
Signature · 1 line
1.7.10.4
#9 lore raw

[tip:x86/urgent] ACPI, irq, x86: Return IRQ instead of GSI in mp_register_gsi()

ACPI, irq, x86: Return IRQ instead of GSI in mp_register_gsi()
Commit-ID:  91d0639923526b8f312a4d865451934ab67e7730
Gitweb:     http://git.kernel.org/tip/91d0639923526b8f312a4d865451934ab67e7730
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:33 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 28 Oct 2014 19:50:50 +0100

ACPI, irq, x86: Return IRQ instead of GSI in mp_register_gsi()

Function mp_register_gsi() returns blindly the GSI number for the ACPI SCI interrupt. That causes a regression when the GSI for ACPI SCI is shared with other devices.

The regression was caused by commit 84245af7297ced9e8fe "x86, irq, ACPI:
Change __acpi_register_gsi to return IRQ number instead of GSI" and exposed on a SuperMicro system, which shares one GSI between ACPI SCI and PCI device, with following failure:

http://sourceforge.net/p/linux1394/mailman/linux1394-user/?viewmonth=201410

[    0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low
level)
[    2.699224] firewire_ohci 0000:06:00.0: failed to allocate interrupt

20

Return mp_map_gsi_to_irq(gsi, 0) instead of the GSI number.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
Cc Pavel Machek <[email protected]>
Cc <[email protected]> # 3.17
---
 arch/x86/kernel/acpi/boot.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kernel/acpi/boot.c +1 -1
index d5c8872..a142e77 100644
@@ -397,7 +397,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
 
 	/* Don't set up the ACPI SCI because it's already set up */
 	if (acpi_gbl_FADT.sci_interrupt == gsi)
-		return gsi;
+		return mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
 
 	trigger = trigger == ACPI_EDGE_SENSITIVE ? 0 : 1;
 	polarity = polarity == ACPI_ACTIVE_HIGH ? 0 : 1;
#10 lore raw

[tip:x86/urgent] ACPI, irq, x86: Return IRQ instead of GSI in mp_register_gsi()

In reply to Jiang Liu
ACPI, irq, x86: Return IRQ instead of GSI in mp_register_gsi()
Commit-ID:  b77e8f435337baa1cd15852fb9db3f6d26cd8eb7
Gitweb:     http://git.kernel.org/tip/b77e8f435337baa1cd15852fb9db3f6d26cd8eb7
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:33 +0800
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 29 Oct 2014 08:52:30 +0100

ACPI, irq, x86: Return IRQ instead of GSI in mp_register_gsi()

Function mp_register_gsi() returns blindly the GSI number for the ACPI SCI interrupt. That causes a regression when the GSI for ACPI SCI is shared with other devices.

The regression was caused by commit 84245af7297ced9e8fe "x86, irq, ACPI:
Change __acpi_register_gsi to return IRQ number instead of GSI" and exposed on a SuperMicro system, which shares one GSI between ACPI SCI and PCI device, with following failure:

http://sourceforge.net/p/linux1394/mailman/linux1394-user/?viewmonth=201410

[    0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low
level)
[    2.699224] firewire_ohci 0000:06:00.0: failed to allocate interrupt

20

Return mp_map_gsi_to_irq(gsi, 0) instead of the GSI number.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
Cc Pavel Machek <[email protected]>
Cc <[email protected]> # 3.17
---
 arch/x86/kernel/acpi/boot.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kernel/acpi/boot.c +1 -1
index d5c8872..a142e77 100644
@@ -397,7 +397,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
 
 	/* Don't set up the ACPI SCI because it's already set up */
 	if (acpi_gbl_FADT.sci_interrupt == gsi)
-		return gsi;
+		return mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
 
 	trigger = trigger == ACPI_EDGE_SENSITIVE ? 0 : 1;
 	polarity = polarity == ACPI_ACTIVE_HIGH ? 0 : 1;
author
#11 lore raw

PATCH v7 4/18 x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

In reply to Jiang Liu

Private function resource_to_addr() is used to parse ACPI resources for PCI host bridge. There are public interfaces available for that purpose, so replace resource_to_addr() with public interfaces.

---
 arch/x86/pci/acpi.c |  144 +++++++++++++++++++--------------------------------
 1 file changed, 53 insertions(+), 91 deletions(-)
arch/x86/pci/acpi.c +53 -91
index cfd1b132b8e3..3f72d934dc16 100644
@@ -218,114 +218,76 @@ static void teardown_mcfg_map(struct pci_root_info *info)
 }
 #endif
 
-static acpi_status resource_to_addr(struct acpi_resource *resource,
-				    struct acpi_resource_address64 *addr)
-{
-	acpi_status status;
-	struct acpi_resource_memory24 *memory24;
-	struct acpi_resource_memory32 *memory32;
-	struct acpi_resource_fixed_memory32 *fixed_memory32;
-
-	memset(addr, 0, sizeof(*addr));
-	switch (resource->type) {
-	case ACPI_RESOURCE_TYPE_MEMORY24:
-		memory24 = &resource->data.memory24;
-		addr->resource_type = ACPI_MEMORY_RANGE;
-		addr->minimum = memory24->minimum;
-		addr->address_length = memory24->address_length;
-		addr->maximum = addr->minimum + addr->address_length - 1;
-		return AE_OK;
-	case ACPI_RESOURCE_TYPE_MEMORY32:
-		memory32 = &resource->data.memory32;
-		addr->resource_type = ACPI_MEMORY_RANGE;
-		addr->minimum = memory32->minimum;
-		addr->address_length = memory32->address_length;
-		addr->maximum = addr->minimum + addr->address_length - 1;
-		return AE_OK;
-	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
-		fixed_memory32 = &resource->data.fixed_memory32;
-		addr->resource_type = ACPI_MEMORY_RANGE;
-		addr->minimum = fixed_memory32->address;
-		addr->address_length = fixed_memory32->address_length;
-		addr->maximum = addr->minimum + addr->address_length - 1;
-		return AE_OK;
-	case ACPI_RESOURCE_TYPE_ADDRESS16:
-	case ACPI_RESOURCE_TYPE_ADDRESS32:
-	case ACPI_RESOURCE_TYPE_ADDRESS64:
-		status = acpi_resource_to_address64(resource, addr);
-		if (ACPI_SUCCESS(status) &&
-		    (addr->resource_type == ACPI_MEMORY_RANGE ||
-		    addr->resource_type == ACPI_IO_RANGE) &&
-		    addr->address_length > 0) {
-			return AE_OK;
-		}
-		break;
-	}
-	return AE_ERROR;
-}
-
 static acpi_status count_resource(struct acpi_resource *acpi_res, void *data)
 {
 	struct pci_root_info *info = data;
-	struct acpi_resource_address64 addr;
-	acpi_status status;
+	struct resource r = {
+		.flags = 0
+	};
 
-	status = resource_to_addr(acpi_res, &addr);
-	if (ACPI_SUCCESS(status))
+	if (!acpi_dev_resource_memory(acpi_res, &r) &&
+	    !acpi_dev_resource_address_space(acpi_res, &r))
+		return AE_OK;
+
+	if ((r.flags & (IORESOURCE_IO | IORESOURCE_MEM)) && resource_size(&r))
 		info->res_num++;
+
 	return AE_OK;
 }
 
 static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
 {
 	struct pci_root_info *info = data;
-	struct resource *res;
-	struct acpi_resource_address64 addr;
-	acpi_status status;
-	unsigned long flags;
-	u64 start, orig_end, end;
+	u64 translation_offset = 0;
+	struct resource r = {
+		.flags = 0
+	};
+
+	if (acpi_dev_resource_memory(acpi_res, &r)) {
+		r.flags &= IORESOURCE_MEM | IORESOURCE_IO;
+	} else if (acpi_dev_resource_address_space(acpi_res, &r)) {
+		u64 orig_end;
+		struct acpi_resource_address64 addr;
+
+		r.flags &= IORESOURCE_MEM | IORESOURCE_IO;
+		if (r.flags == 0)
+			return AE_OK;
 
-	status = resource_to_addr(acpi_res, &addr);
-	if (!ACPI_SUCCESS(status))
-		return AE_OK;
+		if (ACPI_FAILURE(acpi_resource_to_address64(acpi_res, &addr)))
+			return AE_OK;
 
-	if (addr.resource_type == ACPI_MEMORY_RANGE) {
-		flags = IORESOURCE_MEM;
-		if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
-			flags |= IORESOURCE_PREFETCH;
-	} else if (addr.resource_type == ACPI_IO_RANGE) {
-		flags = IORESOURCE_IO;
-	} else
-		return AE_OK;
+		if (addr.resource_type == ACPI_MEMORY_RANGE &&
+		    addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
+			r.flags |= IORESOURCE_PREFETCH;
 
-	start = addr.minimum + addr.translation_offset;
-	orig_end = end = addr.maximum + addr.translation_offset;
+		translation_offset = addr.translation_offset;
+		orig_end = r.end;
+		r.start += translation_offset;
+		r.end += translation_offset;
 
-	/* Exclude non-addressable range or non-addressable portion of range */
-	end = min(end, (u64)iomem_resource.end);
-	if (end <= start) {
-		dev_info(&info->bridge->dev,
-			"host bridge window [%#llx-%#llx] "
-			"(ignored, not CPU addressable)\n", start, orig_end);
-		return AE_OK;
-	} else if (orig_end != end) {
-		dev_info(&info->bridge->dev,
-			"host bridge window [%#llx-%#llx] "
-			"([%#llx-%#llx] ignored, not CPU addressable)\n", 
-			start, orig_end, end + 1, orig_end);
+		/* Exclude non-addressable range or non-addressable portion of range */
+		r.end = min(r.end, iomem_resource.end);
+		if (r.end <= r.start) {
+			dev_info(&info->bridge->dev,
+				"host bridge window [%#llx-%#llx] (ignored, not CPU addressable)\n",
+				 r.start, orig_end);
+			return AE_OK;
+		} else if (orig_end != r.end) {
+			dev_info(&info->bridge->dev,
+				"host bridge window [%#llx-%#llx] ([%#llx-%#llx] ignored, not CPU addressable)\n",
+				r.start, orig_end, r.end + 1, orig_end);
+		}
 	}
 
-	res = &info->res[info->res_num];
-	res->name = info->name;
-	res->flags = flags;
-	res->start = start;
-	res->end = end;
-	info->res_offset[info->res_num] = addr.translation_offset;
-	info->res_num++;
-
-	if (!pci_use_crs)
-		dev_printk(KERN_DEBUG, &info->bridge->dev,
-			   "host bridge window %pR (ignored)\n", res);
+	if (r.flags && resource_size(&r)) {
+		r.name = info->name;
+		info->res[info->res_num] = r;
+		info->res_offset[info->res_num] = translation_offset;
+		info->res_num++;
+		if (!pci_use_crs)
+			dev_printk(KERN_DEBUG, &info->bridge->dev,
+				   "host bridge window %pR (ignored)\n", &r);
+	}
 
 	return AE_OK;
 }
Signature · 1 line
1.7.10.4
#12 lore raw

[tip:x86/apic] x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c
Commit-ID:  e22ce93870deae0e9a54e1539f0088538f187780
Gitweb:     http://git.kernel.org/tip/e22ce93870deae0e9a54e1539f0088538f187780
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:34 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Mon, 3 Nov 2014 11:56:07 +0100

x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

Private function resource_to_addr() is used to parse ACPI resources for PCI host bridge. There are public interfaces available for that purpose, so replace resource_to_addr() with public interfaces.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 arch/x86/pci/acpi.c | 144 +++++++++++++++++++---------------------------------
 1 file changed, 53 insertions(+), 91 deletions(-)
arch/x86/pci/acpi.c +53 -91
index cfd1b13..3f72d93 100644
@@ -218,114 +218,76 @@ static void teardown_mcfg_map(struct pci_root_info *info)
 }
 #endif
 
-static acpi_status resource_to_addr(struct acpi_resource *resource,
-				    struct acpi_resource_address64 *addr)
-{
-	acpi_status status;
-	struct acpi_resource_memory24 *memory24;
-	struct acpi_resource_memory32 *memory32;
-	struct acpi_resource_fixed_memory32 *fixed_memory32;
-
-	memset(addr, 0, sizeof(*addr));
-	switch (resource->type) {
-	case ACPI_RESOURCE_TYPE_MEMORY24:
-		memory24 = &resource->data.memory24;
-		addr->resource_type = ACPI_MEMORY_RANGE;
-		addr->minimum = memory24->minimum;
-		addr->address_length = memory24->address_length;
-		addr->maximum = addr->minimum + addr->address_length - 1;
-		return AE_OK;
-	case ACPI_RESOURCE_TYPE_MEMORY32:
-		memory32 = &resource->data.memory32;
-		addr->resource_type = ACPI_MEMORY_RANGE;
-		addr->minimum = memory32->minimum;
-		addr->address_length = memory32->address_length;
-		addr->maximum = addr->minimum + addr->address_length - 1;
-		return AE_OK;
-	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
-		fixed_memory32 = &resource->data.fixed_memory32;
-		addr->resource_type = ACPI_MEMORY_RANGE;
-		addr->minimum = fixed_memory32->address;
-		addr->address_length = fixed_memory32->address_length;
-		addr->maximum = addr->minimum + addr->address_length - 1;
-		return AE_OK;
-	case ACPI_RESOURCE_TYPE_ADDRESS16:
-	case ACPI_RESOURCE_TYPE_ADDRESS32:
-	case ACPI_RESOURCE_TYPE_ADDRESS64:
-		status = acpi_resource_to_address64(resource, addr);
-		if (ACPI_SUCCESS(status) &&
-		    (addr->resource_type == ACPI_MEMORY_RANGE ||
-		    addr->resource_type == ACPI_IO_RANGE) &&
-		    addr->address_length > 0) {
-			return AE_OK;
-		}
-		break;
-	}
-	return AE_ERROR;
-}
-
 static acpi_status count_resource(struct acpi_resource *acpi_res, void *data)
 {
 	struct pci_root_info *info = data;
-	struct acpi_resource_address64 addr;
-	acpi_status status;
+	struct resource r = {
+		.flags = 0
+	};
 
-	status = resource_to_addr(acpi_res, &addr);
-	if (ACPI_SUCCESS(status))
+	if (!acpi_dev_resource_memory(acpi_res, &r) &&
+	    !acpi_dev_resource_address_space(acpi_res, &r))
+		return AE_OK;
+
+	if ((r.flags & (IORESOURCE_IO | IORESOURCE_MEM)) && resource_size(&r))
 		info->res_num++;
+
 	return AE_OK;
 }
 
 static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
 {
 	struct pci_root_info *info = data;
-	struct resource *res;
-	struct acpi_resource_address64 addr;
-	acpi_status status;
-	unsigned long flags;
-	u64 start, orig_end, end;
+	u64 translation_offset = 0;
+	struct resource r = {
+		.flags = 0
+	};
+
+	if (acpi_dev_resource_memory(acpi_res, &r)) {
+		r.flags &= IORESOURCE_MEM | IORESOURCE_IO;
+	} else if (acpi_dev_resource_address_space(acpi_res, &r)) {
+		u64 orig_end;
+		struct acpi_resource_address64 addr;
+
+		r.flags &= IORESOURCE_MEM | IORESOURCE_IO;
+		if (r.flags == 0)
+			return AE_OK;
 
-	status = resource_to_addr(acpi_res, &addr);
-	if (!ACPI_SUCCESS(status))
-		return AE_OK;
+		if (ACPI_FAILURE(acpi_resource_to_address64(acpi_res, &addr)))
+			return AE_OK;
 
-	if (addr.resource_type == ACPI_MEMORY_RANGE) {
-		flags = IORESOURCE_MEM;
-		if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
-			flags |= IORESOURCE_PREFETCH;
-	} else if (addr.resource_type == ACPI_IO_RANGE) {
-		flags = IORESOURCE_IO;
-	} else
-		return AE_OK;
+		if (addr.resource_type == ACPI_MEMORY_RANGE &&
+		    addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
+			r.flags |= IORESOURCE_PREFETCH;
 
-	start = addr.minimum + addr.translation_offset;
-	orig_end = end = addr.maximum + addr.translation_offset;
+		translation_offset = addr.translation_offset;
+		orig_end = r.end;
+		r.start += translation_offset;
+		r.end += translation_offset;
 
-	/* Exclude non-addressable range or non-addressable portion of range */
-	end = min(end, (u64)iomem_resource.end);
-	if (end <= start) {
-		dev_info(&info->bridge->dev,
-			"host bridge window [%#llx-%#llx] "
-			"(ignored, not CPU addressable)\n", start, orig_end);
-		return AE_OK;
-	} else if (orig_end != end) {
-		dev_info(&info->bridge->dev,
-			"host bridge window [%#llx-%#llx] "
-			"([%#llx-%#llx] ignored, not CPU addressable)\n", 
-			start, orig_end, end + 1, orig_end);
+		/* Exclude non-addressable range or non-addressable portion of range */
+		r.end = min(r.end, iomem_resource.end);
+		if (r.end <= r.start) {
+			dev_info(&info->bridge->dev,
+				"host bridge window [%#llx-%#llx] (ignored, not CPU addressable)\n",
+				 r.start, orig_end);
+			return AE_OK;
+		} else if (orig_end != r.end) {
+			dev_info(&info->bridge->dev,
+				"host bridge window [%#llx-%#llx] ([%#llx-%#llx] ignored, not CPU addressable)\n",
+				r.start, orig_end, r.end + 1, orig_end);
+		}
 	}
 
-	res = &info->res[info->res_num];
-	res->name = info->name;
-	res->flags = flags;
-	res->start = start;
-	res->end = end;
-	info->res_offset[info->res_num] = addr.translation_offset;
-	info->res_num++;
-
-	if (!pci_use_crs)
-		dev_printk(KERN_DEBUG, &info->bridge->dev,
-			   "host bridge window %pR (ignored)\n", res);
+	if (r.flags && resource_size(&r)) {
+		r.name = info->name;
+		info->res[info->res_num] = r;
+		info->res_offset[info->res_num] = translation_offset;
+		info->res_num++;
+		if (!pci_use_crs)
+			dev_printk(KERN_DEBUG, &info->bridge->dev,
+				   "host bridge window %pR (ignored)\n", &r);
+	}
 
 	return AE_OK;
 }
maintainer
#13 lore raw

Re: [tip:x86/apic] x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

Quoted 27 lines · tip-bot for Jiang Liu
Commit-ID:  e22ce93870deae0e9a54e1539f0088538f187780
Gitweb:     http://git.kernel.org/tip/e22ce93870deae0e9a54e1539f0088538f187780
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:34 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Mon, 3 Nov 2014 11:56:07 +0100

x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

Private function resource_to_addr() is used to parse ACPI resources for PCI host bridge. There are public interfaces available for that purpose, so replace resource_to_addr() with public interfaces.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>

---

...

Quoted 62 lines

static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data) {

arch/x86/pci/acpi.c +25 -30
 	struct pci_root_info *info = data;
-	struct resource *res;
-	struct acpi_resource_address64 addr;
-	acpi_status status;
-	unsigned long flags;
-	u64 start, orig_end, end;
+	u64 translation_offset = 0;
+	struct resource r = {
+		.flags = 0
+	};
+
+	if (acpi_dev_resource_memory(acpi_res, &r)) {
+		r.flags &= IORESOURCE_MEM | IORESOURCE_IO;
+	} else if (acpi_dev_resource_address_space(acpi_res, &r)) {
+		u64 orig_end;
+		struct acpi_resource_address64 addr;
+
+		r.flags &= IORESOURCE_MEM | IORESOURCE_IO;
+		if (r.flags == 0)
+			return AE_OK;
 
-	status = resource_to_addr(acpi_res, &addr);
-	if (!ACPI_SUCCESS(status))
-		return AE_OK;
+		if (ACPI_FAILURE(acpi_resource_to_address64(acpi_res, &addr)))
+			return AE_OK;
 
-	if (addr.resource_type == ACPI_MEMORY_RANGE) {
-		flags = IORESOURCE_MEM;
-		if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
-			flags |= IORESOURCE_PREFETCH;
-	} else if (addr.resource_type == ACPI_IO_RANGE) {
-		flags = IORESOURCE_IO;
-	} else
-		return AE_OK;
+		if (addr.resource_type == ACPI_MEMORY_RANGE &&
+		    addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
+			r.flags |= IORESOURCE_PREFETCH;
 
-	start = addr.minimum + addr.translation_offset;
-	orig_end = end = addr.maximum + addr.translation_offset;
+		translation_offset = addr.translation_offset;
+		orig_end = r.end;
+		r.start += translation_offset;
+		r.end += translation_offset;
 
-	/* Exclude non-addressable range or non-addressable portion of range */
-	end = min(end, (u64)iomem_resource.end);
-	if (end <= start) {
-		dev_info(&info->bridge->dev,
-			"host bridge window [%#llx-%#llx] "
-			"(ignored, not CPU addressable)\n", start, orig_end);
-		return AE_OK;
-	} else if (orig_end != end) {
-		dev_info(&info->bridge->dev,
-			"host bridge window [%#llx-%#llx] "
-			"([%#llx-%#llx] ignored, not CPU addressable)\n", 
-			start, orig_end, end + 1, orig_end);
+		/* Exclude non-addressable range or non-addressable portion of range */
+		r.end = min(r.end, iomem_resource.end);

arch/x86/pci/acpi.c static void teardown_mcfg_map(struct pci_root_info *info) · line 279

Quoted 10 lines
arch/x86/pci/acpi.c +10 -0
+		if (r.end <= r.start) {
+			dev_info(&info->bridge->dev,
+				"host bridge window [%#llx-%#llx] (ignored, not CPU addressable)\n",
+				 r.start, orig_end);
+			return AE_OK;
+		} else if (orig_end != r.end) {
+			dev_info(&info->bridge->dev,
+				"host bridge window [%#llx-%#llx] ([%#llx-%#llx] ignored, not CPU addressable)\n",
+				r.start, orig_end, r.end + 1, orig_end);
+		}

I see the warnings below on 32-bit, those resource_size_t things on 32-bit are u32 through the phys_addr_t typedef:

#ifdef CONFIG_PHYS_ADDR_T_64BIT
typedef u64 phys_addr_t;
#else
typedef u32 phys_addr_t;
#endif

typedef phys_addr_t resource_size_t;
---

arch/x86/pci/acpi.c: In function ‘setup_resource’:
arch/x86/pci/acpi.c:271:4: warning: format ‘%llx’ expects argument of type ‘long long unsigned int’, but argument 3 has type ‘resource_size_t’ [-Wformat=]

    dev_info(&info->bridge->dev,
    ^
arch/x86/pci/acpi.c:276:4: warning: format ‘%llx’ expects argument of type ‘long long unsigned int’, but argument 3 has type ‘resource_size_t’ [-Wformat=]
    dev_info(&info->bridge->dev,
    ^

arch/x86/pci/acpi.c:276:4: warning: format ‘%llx’ expects argument of type ‘long long unsigned int’, but argument 5 has type ‘resource_size_t’ [-Wformat=]

Signature · 5 lines
Regards/Gruss,
    Boris.

Sent from a fat crate under my desk. Formatting is fine.
--
#14 lore raw

Re: [tip:x86/apic] x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

In reply to tip-bot for Jiang Liu
Quoted 192 lines · tip-bot for Jiang Liu
Commit-ID:  e22ce93870deae0e9a54e1539f0088538f187780
Gitweb:     http://git.kernel.org/tip/e22ce93870deae0e9a54e1539f0088538f187780
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:34 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Mon, 3 Nov 2014 11:56:07 +0100

x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

Private function resource_to_addr() is used to parse ACPI resources for PCI host bridge. There are public interfaces available for that purpose, so replace resource_to_addr() with public interfaces.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 arch/x86/pci/acpi.c | 144 +++++++++++++++++++---------------------------------
 1 file changed, 53 insertions(+), 91 deletions(-)
arch/x86/pci/acpi.c +46 -91
index cfd1b13..3f72d93 100644
@@ -218,114 +218,76 @@ static void teardown_mcfg_map(struct pci_root_info *info)
 }
 #endif
 
-static acpi_status resource_to_addr(struct acpi_resource *resource,
-                                   struct acpi_resource_address64 *addr)
-{
-       acpi_status status;
-       struct acpi_resource_memory24 *memory24;
-       struct acpi_resource_memory32 *memory32;
-       struct acpi_resource_fixed_memory32 *fixed_memory32;
-
-       memset(addr, 0, sizeof(*addr));
-       switch (resource->type) {
-       case ACPI_RESOURCE_TYPE_MEMORY24:
-               memory24 = &resource->data.memory24;
-               addr->resource_type = ACPI_MEMORY_RANGE;
-               addr->minimum = memory24->minimum;
-               addr->address_length = memory24->address_length;
-               addr->maximum = addr->minimum + addr->address_length - 1;
-               return AE_OK;
-       case ACPI_RESOURCE_TYPE_MEMORY32:
-               memory32 = &resource->data.memory32;
-               addr->resource_type = ACPI_MEMORY_RANGE;
-               addr->minimum = memory32->minimum;
-               addr->address_length = memory32->address_length;
-               addr->maximum = addr->minimum + addr->address_length - 1;
-               return AE_OK;
-       case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
-               fixed_memory32 = &resource->data.fixed_memory32;
-               addr->resource_type = ACPI_MEMORY_RANGE;
-               addr->minimum = fixed_memory32->address;
-               addr->address_length = fixed_memory32->address_length;
-               addr->maximum = addr->minimum + addr->address_length - 1;
-               return AE_OK;
-       case ACPI_RESOURCE_TYPE_ADDRESS16:
-       case ACPI_RESOURCE_TYPE_ADDRESS32:
-       case ACPI_RESOURCE_TYPE_ADDRESS64:
-               status = acpi_resource_to_address64(resource, addr);
-               if (ACPI_SUCCESS(status) &&
-                   (addr->resource_type == ACPI_MEMORY_RANGE ||
-                   addr->resource_type == ACPI_IO_RANGE) &&
-                   addr->address_length > 0) {
-                       return AE_OK;
-               }
-               break;
-       }
-       return AE_ERROR;
-}
-
 static acpi_status count_resource(struct acpi_resource *acpi_res, void *data)
 {
        struct pci_root_info *info = data;
-       struct acpi_resource_address64 addr;
-       acpi_status status;
+       struct resource r = {
+               .flags = 0
+       };
 
-       status = resource_to_addr(acpi_res, &addr);
-       if (ACPI_SUCCESS(status))
+       if (!acpi_dev_resource_memory(acpi_res, &r) &&
+           !acpi_dev_resource_address_space(acpi_res, &r))
+               return AE_OK;
+
+       if ((r.flags & (IORESOURCE_IO | IORESOURCE_MEM)) && resource_size(&r))
                info->res_num++;
+
        return AE_OK;
 }
 
 static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
 {
        struct pci_root_info *info = data;
-       struct resource *res;
-       struct acpi_resource_address64 addr;
-       acpi_status status;
-       unsigned long flags;
-       u64 start, orig_end, end;
+       u64 translation_offset = 0;
+       struct resource r = {
+               .flags = 0
+       };
+
+       if (acpi_dev_resource_memory(acpi_res, &r)) {
+               r.flags &= IORESOURCE_MEM | IORESOURCE_IO;
+       } else if (acpi_dev_resource_address_space(acpi_res, &r)) {
+               u64 orig_end;
+               struct acpi_resource_address64 addr;
+
+               r.flags &= IORESOURCE_MEM | IORESOURCE_IO;
+               if (r.flags == 0)
+                       return AE_OK;
 
-       status = resource_to_addr(acpi_res, &addr);
-       if (!ACPI_SUCCESS(status))
-               return AE_OK;
+               if (ACPI_FAILURE(acpi_resource_to_address64(acpi_res, &addr)))
+                       return AE_OK;
 
-       if (addr.resource_type == ACPI_MEMORY_RANGE) {
-               flags = IORESOURCE_MEM;
-               if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
-                       flags |= IORESOURCE_PREFETCH;
-       } else if (addr.resource_type == ACPI_IO_RANGE) {
-               flags = IORESOURCE_IO;
-       } else
-               return AE_OK;
+               if (addr.resource_type == ACPI_MEMORY_RANGE &&
+                   addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
+                       r.flags |= IORESOURCE_PREFETCH;
 
-       start = addr.minimum + addr.translation_offset;
-       orig_end = end = addr.maximum + addr.translation_offset;
+               translation_offset = addr.translation_offset;
+               orig_end = r.end;
+               r.start += translation_offset;
+               r.end += translation_offset;
 
-       /* Exclude non-addressable range or non-addressable portion of range */
-       end = min(end, (u64)iomem_resource.end);
-       if (end <= start) {
-               dev_info(&info->bridge->dev,
-                       "host bridge window [%#llx-%#llx] "
-                       "(ignored, not CPU addressable)\n", start, orig_end);
-               return AE_OK;
-       } else if (orig_end != end) {
-               dev_info(&info->bridge->dev,
-                       "host bridge window [%#llx-%#llx] "
-                       "([%#llx-%#llx] ignored, not CPU addressable)\n",
-                       start, orig_end, end + 1, orig_end);
+               /* Exclude non-addressable range or non-addressable portion of range */
+               r.end = min(r.end, iomem_resource.end);
+               if (r.end <= r.start) {
+                       dev_info(&info->bridge->dev,
+                               "host bridge window [%#llx-%#llx] (ignored, not CPU addressable)\n",
+                                r.start, orig_end);
+                       return AE_OK;
+               } else if (orig_end != r.end) {
+                       dev_info(&info->bridge->dev,
+                               "host bridge window [%#llx-%#llx] ([%#llx-%#llx] ignored, not CPU addressable)\n",
+                               r.start, orig_end, r.end + 1, orig_end);
+               }
        }
 
-       res = &info->res[info->res_num];
-       res->name = info->name;
-       res->flags = flags;
-       res->start = start;
-       res->end = end;
-       info->res_offset[info->res_num] = addr.translation_offset;
-       info->res_num++;
-
-       if (!pci_use_crs)
-               dev_printk(KERN_DEBUG, &info->bridge->dev,
-                          "host bridge window %pR (ignored)\n", res);
+       if (r.flags && resource_size(&r)) {
+               r.name = info->name;

arch/x86/pci/acpi.c static void teardown_mcfg_map(struct pci_root_info *info) · line 293

Quoted 10 lines
arch/x86/pci/acpi.c +7 -0
+               info->res[info->res_num] = r;
+               info->res_offset[info->res_num] = translation_offset;
+               info->res_num++;
+               if (!pci_use_crs)
+                       dev_printk(KERN_DEBUG, &info->bridge->dev,
+                                  "host bridge window %pR (ignored)\n", &r);
+       }
 
        return AE_OK;
 }

This one cause one system with Nehalem and one with Westmere failing.

[   32.353347] acpi PNP0A08:00: host bridge window expanded to [mem
0x00000000-0xffffffff]; [mem 0x000a0000-0x000bffff] ignored
[   32.362897] acpi PNP0A08:00: host bridge window expanded to [mem
0x00000000-0xffffffff]; [mem 0x000d0000-0x000dffff] ignored
[   32.382862] acpi PNP0A08:00: host bridge window expanded to [mem
0x00000000-0xffffffff]; [mem 0x00000000-0xffffffff] ignored
[   32.402889] acpi PNP0A08:00: host bridge window expanded to [mem
0x00000000-0xffffffff]; [??? 0x00000000-0xffffffff flags 0x0] ignored
[   32.423000] acpi PNP0A08:00: host bridge window expanded to [mem
0x00000000-0xffffffff]; [mem 0x00000000-0xffffffff] ignored
[   32.602921] PCI host bridge to bus 0000:00
[   32.603158] pci_bus 0000:00: root bus resource [bus 00-3f]
[   32.622782] pci_bus 0000:00: root bus resource [io  0x0000-0x5fff]
[   32.642569] pci_bus 0000:00: root bus resource [mem 0x00000000-0xffffffff]
[   32.642893] pci_bus 0000:00: root bus resource [mem

0xfc000000000-0xfc07fffffff pref]

Looks like the commit have several problems.

Attached patch should address them.

Please fix it before it get into linus tree.

Thanks

Yinghai

Subject: [PATCH] x86, pci, acpi: fix root res probing

old setup with nehalem got:

[   32.353347] acpi PNP0A08:00: host bridge window expanded to [mem 0x00000000-0xffffffff]; [mem 0x000a0000-0x000bffff] ignored
[   32.362897] acpi PNP0A08:00: host bridge window expanded to [mem 0x00000000-0xffffffff]; [mem 0x000d0000-0x000dffff] ignored
[   32.382862] acpi PNP0A08:00: host bridge window expanded to [mem 0x00000000-0xffffffff]; [mem 0x00000000-0xffffffff] ignored
[   32.402889] acpi PNP0A08:00: host bridge window expanded to [mem 0x00000000-0xffffffff]; [??? 0x00000000-0xffffffff flags 0x0] ignored
[   32.423000] acpi PNP0A08:00: host bridge window expanded to [mem 0x00000000-0xffffffff]; [mem 0x00000000-0xffffffff] ignored
[   32.602921] PCI host bridge to bus 0000:00
[   32.603158] pci_bus 0000:00: root bus resource [bus 00-3f]
[   32.622782] pci_bus 0000:00: root bus resource [io  0x0000-0x5fff]
[   32.642569] pci_bus 0000:00: root bus resource [mem 0x00000000-0xffffffff]
[   32.642893] pci_bus 0000:00: root bus resource [mem 0xfc000000000-0xfc07fffffff pref]

The problem is caused commit e22ce93870de ("x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c").

as the system has

[   32.395504] acpi PNP0A08:00: addr host bridge window [bus 00-3f]
[   32.412395] acpi PNP0A08:00: addr host bridge window [io  0x0000-0x5fff window]
[   32.412745] acpi PNP0A08:00: addr host bridge window [mem 0x000a0000-0x000bffff window]
[   32.432559] acpi PNP0A08:00: addr host bridge window [mem 0x000d0000-0x000dffff window]
[   32.452432] acpi PNP0A08:00: addr host bridge window [mem 0x00000000-0xffffffff window]
[   32.472303] acpi PNP0A08:00: addr host bridge window [mem 0x90000000-0xafffffff window]
[   32.472653] acpi PNP0A08:00: addr host bridge window [mem 0xfed40000-0xfed44fff window]
[   32.492539] acpi PNP0A08:00: addr host bridge window [mem 0xfc000000000-0xfc07fffffff window]

but the one [mem 0x00000000-0xffffffff window] with address_length == 0 that was rejected by old resource_to_addr().

Add that check into acpi_dev_resource_address_space() to fix the problem.

Also fixes other problems:
1. need to initialize local r and addr to 0.
2. fix orig_end assigning, as it should be after offset adding.
3. need to do clipping and checking for acpi_dev_resource_memory path.
4. also acpi_dev_resource_memory should & with IORESOURCE_MEM.

Fixes commit e22ce93870de ("x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c").
---
 arch/x86/pci/acpi.c     |   60 +++++++++++++++++++++++-------------------------
 drivers/acpi/resource.c |    2 -
 2 files changed, 30 insertions(+), 32 deletions(-)
arch/x86/pci/acpi.c +29 -31
Index: linux-2.6/arch/x86/pci/acpi.c
===================================================================
@@ -221,10 +221,9 @@ static void teardown_mcfg_map(struct pci
 static acpi_status count_resource(struct acpi_resource *acpi_res, void *data)
 {
 	struct pci_root_info *info = data;
-	struct resource r = {
-		.flags = 0
-	};
+	struct resource r;
 
+	memset(&r, 0, sizeof(r));
 	if (!acpi_dev_resource_memory(acpi_res, &r) &&
 	    !acpi_dev_resource_address_space(acpi_res, &r))
 		return AE_OK;
@@ -239,20 +238,20 @@ static acpi_status setup_resource(struct
 {
 	struct pci_root_info *info = data;
 	u64 translation_offset = 0;
-	struct resource r = {
-		.flags = 0
-	};
+	struct resource r;
+	u64 orig_end;
 
+	memset(&r, 0, sizeof(r));
 	if (acpi_dev_resource_memory(acpi_res, &r)) {
-		r.flags &= IORESOURCE_MEM | IORESOURCE_IO;
+		r.flags &= IORESOURCE_MEM;
 	} else if (acpi_dev_resource_address_space(acpi_res, &r)) {
-		u64 orig_end;
 		struct acpi_resource_address64 addr;
 
 		r.flags &= IORESOURCE_MEM | IORESOURCE_IO;
 		if (r.flags == 0)
 			return AE_OK;
 
+		memset(&addr, 0, sizeof(addr));
 		if (ACPI_FAILURE(acpi_resource_to_address64(acpi_res, &addr)))
 			return AE_OK;
 
@@ -261,34 +260,33 @@ static acpi_status setup_resource(struct
 			r.flags |= IORESOURCE_PREFETCH;
 
 		translation_offset = addr.translation_offset;
-		orig_end = r.end;
 		r.start += translation_offset;
 		r.end += translation_offset;
+	} else
+		return AE_OK;
 
-		/* Exclude non-addressable range or non-addressable portion of range */
-		r.end = min(r.end, iomem_resource.end);
-		if (r.end <= r.start) {
-			dev_info(&info->bridge->dev,
-				"host bridge window [%#llx-%#llx] (ignored, not CPU addressable)\n",
-				 (unsigned long long)r.start, orig_end);
-			return AE_OK;
-		} else if (orig_end != r.end) {
-			dev_info(&info->bridge->dev,
-				"host bridge window [%#llx-%#llx] ([%#llx-%#llx] ignored, not CPU addressable)\n",
-				 (unsigned long long)r.start, orig_end,
-				 (unsigned long long)r.end + 1, orig_end);
-		}
+	/* Exclude non-addressable range or non-addressable portion of range */
+	orig_end = r.end;
+	r.end = min(r.end, iomem_resource.end);
+	if (r.end <= r.start) {
+		dev_info(&info->bridge->dev,
+			"host bridge window [%#llx-%#llx] (ignored, not CPU addressable)\n",
+			 (unsigned long long)r.start, orig_end);
+		return AE_OK;
+	} else if (orig_end != r.end) {
+		dev_info(&info->bridge->dev,
+			"host bridge window [%#llx-%#llx] ([%#llx-%#llx] ignored, not CPU addressable)\n",
+			 (unsigned long long)r.start, orig_end,
+			 (unsigned long long)r.end + 1, orig_end);
 	}
 
-	if (r.flags && resource_size(&r)) {
-		r.name = info->name;
-		info->res[info->res_num] = r;
-		info->res_offset[info->res_num] = translation_offset;
-		info->res_num++;
-		if (!pci_use_crs)
-			dev_printk(KERN_DEBUG, &info->bridge->dev,
-				   "host bridge window %pR (ignored)\n", &r);
-	}
+	r.name = info->name;
+	info->res[info->res_num] = r;
+	info->res_offset[info->res_num] = translation_offset;
+	info->res_num++;
+	if (!pci_use_crs)
+		dev_printk(KERN_DEBUG, &info->bridge->dev,
+			"host bridge window %pR (ignored)\n", &r);
 
 	return AE_OK;
 }
drivers/acpi/resource.c +1 -1
Index: linux-2.6/drivers/acpi/resource.c
===================================================================
@@ -199,7 +199,7 @@ bool acpi_dev_resource_address_space(str
 	}
 
 	status = acpi_resource_to_address64(ares, &addr);
-	if (ACPI_FAILURE(status))
+	if (ACPI_FAILURE(status) || !addr.address_length)
 		return false;
 
 	res->start = addr.minimum;
author Reviewed-by
#15 lore raw

Re: [tip:x86/apic] x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

Hi Yinghai,
I have one comment about the attached patch related to
following piece of code. I'm not sure whether we should check "addr.maximum - addr.minimum + 1 != addr.address_length" instead of "!addr.address_length". Otherwise:

Regards!
Gerry

drivers/acpi/resource.c +1 -1
Index: linux-2.6/drivers/acpi/resource.c
===================================================================
@@ -199,7 +199,7 @@ bool acpi_dev_resource_address_space(str
 	}
 
 	status = acpi_resource_to_address64(ares, &addr);
-	if (ACPI_FAILURE(status))
+	if (ACPI_FAILURE(status) || !addr.address_length)
 		return false;
 
 	res->start = addr.minimum;	
Quoted 233 lines · Yinghai Lu
Quoted 192 lines · tip-bot for Jiang Liu
Commit-ID:  e22ce93870deae0e9a54e1539f0088538f187780
Gitweb:     http://git.kernel.org/tip/e22ce93870deae0e9a54e1539f0088538f187780
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:34 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Mon, 3 Nov 2014 11:56:07 +0100

x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

Private function resource_to_addr() is used to parse ACPI resources for PCI host bridge. There are public interfaces available for that purpose, so replace resource_to_addr() with public interfaces.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 arch/x86/pci/acpi.c | 144 +++++++++++++++++++---------------------------------
 1 file changed, 53 insertions(+), 91 deletions(-)
arch/x86/pci/acpi.c +46 -91
index cfd1b13..3f72d93 100644
@@ -218,114 +218,76 @@ static void teardown_mcfg_map(struct pci_root_info *info)
 }
 #endif
 
-static acpi_status resource_to_addr(struct acpi_resource *resource,
-                                   struct acpi_resource_address64 *addr)
-{
-       acpi_status status;
-       struct acpi_resource_memory24 *memory24;
-       struct acpi_resource_memory32 *memory32;
-       struct acpi_resource_fixed_memory32 *fixed_memory32;
-
-       memset(addr, 0, sizeof(*addr));
-       switch (resource->type) {
-       case ACPI_RESOURCE_TYPE_MEMORY24:
-               memory24 = &resource->data.memory24;
-               addr->resource_type = ACPI_MEMORY_RANGE;
-               addr->minimum = memory24->minimum;
-               addr->address_length = memory24->address_length;
-               addr->maximum = addr->minimum + addr->address_length - 1;
-               return AE_OK;
-       case ACPI_RESOURCE_TYPE_MEMORY32:
-               memory32 = &resource->data.memory32;
-               addr->resource_type = ACPI_MEMORY_RANGE;
-               addr->minimum = memory32->minimum;
-               addr->address_length = memory32->address_length;
-               addr->maximum = addr->minimum + addr->address_length - 1;
-               return AE_OK;
-       case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
-               fixed_memory32 = &resource->data.fixed_memory32;
-               addr->resource_type = ACPI_MEMORY_RANGE;
-               addr->minimum = fixed_memory32->address;
-               addr->address_length = fixed_memory32->address_length;
-               addr->maximum = addr->minimum + addr->address_length - 1;
-               return AE_OK;
-       case ACPI_RESOURCE_TYPE_ADDRESS16:
-       case ACPI_RESOURCE_TYPE_ADDRESS32:
-       case ACPI_RESOURCE_TYPE_ADDRESS64:
-               status = acpi_resource_to_address64(resource, addr);
-               if (ACPI_SUCCESS(status) &&
-                   (addr->resource_type == ACPI_MEMORY_RANGE ||
-                   addr->resource_type == ACPI_IO_RANGE) &&
-                   addr->address_length > 0) {
-                       return AE_OK;
-               }
-               break;
-       }
-       return AE_ERROR;
-}
-
 static acpi_status count_resource(struct acpi_resource *acpi_res, void *data)
 {
        struct pci_root_info *info = data;
-       struct acpi_resource_address64 addr;
-       acpi_status status;
+       struct resource r = {
+               .flags = 0
+       };
 
-       status = resource_to_addr(acpi_res, &addr);
-       if (ACPI_SUCCESS(status))
+       if (!acpi_dev_resource_memory(acpi_res, &r) &&
+           !acpi_dev_resource_address_space(acpi_res, &r))
+               return AE_OK;
+
+       if ((r.flags & (IORESOURCE_IO | IORESOURCE_MEM)) && resource_size(&r))
                info->res_num++;
+
        return AE_OK;
 }
 
 static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
 {
        struct pci_root_info *info = data;
-       struct resource *res;
-       struct acpi_resource_address64 addr;
-       acpi_status status;
-       unsigned long flags;
-       u64 start, orig_end, end;
+       u64 translation_offset = 0;
+       struct resource r = {
+               .flags = 0
+       };
+
+       if (acpi_dev_resource_memory(acpi_res, &r)) {
+               r.flags &= IORESOURCE_MEM | IORESOURCE_IO;
+       } else if (acpi_dev_resource_address_space(acpi_res, &r)) {
+               u64 orig_end;
+               struct acpi_resource_address64 addr;
+
+               r.flags &= IORESOURCE_MEM | IORESOURCE_IO;
+               if (r.flags == 0)
+                       return AE_OK;
 
-       status = resource_to_addr(acpi_res, &addr);
-       if (!ACPI_SUCCESS(status))
-               return AE_OK;
+               if (ACPI_FAILURE(acpi_resource_to_address64(acpi_res, &addr)))
+                       return AE_OK;
 
-       if (addr.resource_type == ACPI_MEMORY_RANGE) {
-               flags = IORESOURCE_MEM;
-               if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
-                       flags |= IORESOURCE_PREFETCH;
-       } else if (addr.resource_type == ACPI_IO_RANGE) {
-               flags = IORESOURCE_IO;
-       } else
-               return AE_OK;
+               if (addr.resource_type == ACPI_MEMORY_RANGE &&
+                   addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
+                       r.flags |= IORESOURCE_PREFETCH;
 
-       start = addr.minimum + addr.translation_offset;
-       orig_end = end = addr.maximum + addr.translation_offset;
+               translation_offset = addr.translation_offset;
+               orig_end = r.end;
+               r.start += translation_offset;
+               r.end += translation_offset;
 
-       /* Exclude non-addressable range or non-addressable portion of range */
-       end = min(end, (u64)iomem_resource.end);
-       if (end <= start) {
-               dev_info(&info->bridge->dev,
-                       "host bridge window [%#llx-%#llx] "
-                       "(ignored, not CPU addressable)\n", start, orig_end);
-               return AE_OK;
-       } else if (orig_end != end) {
-               dev_info(&info->bridge->dev,
-                       "host bridge window [%#llx-%#llx] "
-                       "([%#llx-%#llx] ignored, not CPU addressable)\n",
-                       start, orig_end, end + 1, orig_end);
+               /* Exclude non-addressable range or non-addressable portion of range */
+               r.end = min(r.end, iomem_resource.end);
+               if (r.end <= r.start) {
+                       dev_info(&info->bridge->dev,
+                               "host bridge window [%#llx-%#llx] (ignored, not CPU addressable)\n",
+                                r.start, orig_end);
+                       return AE_OK;
+               } else if (orig_end != r.end) {
+                       dev_info(&info->bridge->dev,
+                               "host bridge window [%#llx-%#llx] ([%#llx-%#llx] ignored, not CPU addressable)\n",
+                               r.start, orig_end, r.end + 1, orig_end);
+               }
        }
 
-       res = &info->res[info->res_num];
-       res->name = info->name;
-       res->flags = flags;
-       res->start = start;
-       res->end = end;
-       info->res_offset[info->res_num] = addr.translation_offset;
-       info->res_num++;
-
-       if (!pci_use_crs)
-               dev_printk(KERN_DEBUG, &info->bridge->dev,
-                          "host bridge window %pR (ignored)\n", res);
+       if (r.flags && resource_size(&r)) {
+               r.name = info->name;

arch/x86/pci/acpi.c static void teardown_mcfg_map(struct pci_root_info *info) · line 293

Quoted 10 lines
arch/x86/pci/acpi.c +7 -0
+               info->res[info->res_num] = r;
+               info->res_offset[info->res_num] = translation_offset;
+               info->res_num++;
+               if (!pci_use_crs)
+                       dev_printk(KERN_DEBUG, &info->bridge->dev,
+                                  "host bridge window %pR (ignored)\n", &r);
+       }
 
        return AE_OK;
 }

This one cause one system with Nehalem and one with Westmere failing.

[   32.353347] acpi PNP0A08:00: host bridge window expanded to [mem
0x00000000-0xffffffff]; [mem 0x000a0000-0x000bffff] ignored
[   32.362897] acpi PNP0A08:00: host bridge window expanded to [mem
0x00000000-0xffffffff]; [mem 0x000d0000-0x000dffff] ignored
[   32.382862] acpi PNP0A08:00: host bridge window expanded to [mem
0x00000000-0xffffffff]; [mem 0x00000000-0xffffffff] ignored
[   32.402889] acpi PNP0A08:00: host bridge window expanded to [mem
0x00000000-0xffffffff]; [??? 0x00000000-0xffffffff flags 0x0] ignored
[   32.423000] acpi PNP0A08:00: host bridge window expanded to [mem
0x00000000-0xffffffff]; [mem 0x00000000-0xffffffff] ignored
[   32.602921] PCI host bridge to bus 0000:00
[   32.603158] pci_bus 0000:00: root bus resource [bus 00-3f]
[   32.622782] pci_bus 0000:00: root bus resource [io  0x0000-0x5fff]
[   32.642569] pci_bus 0000:00: root bus resource [mem 0x00000000-0xffffffff]
[   32.642893] pci_bus 0000:00: root bus resource [mem

0xfc000000000-0xfc07fffffff pref]

Looks like the commit have several problems.

Attached patch should address them.

Please fix it before it get into linus tree.

Thanks

Yinghai

#16 lore raw

Re: [tip:x86/apic] x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

In reply to Yinghai Lu

On Tue, 9 Dec 2014, Yinghai Lu wrote:

Can you please

1) Cut out the completely irrelevant information from your replies? It's just annoying to scroll through hundreds of quoted lines to find the guts of the mail.

2) Send patches inline. It's a pain to review and reply and I can't use my normal tooling.

Quoted 23 lines

This one cause one system with Nehalem and one with Westmere failing.

[   32.353347] acpi PNP0A08:00: host bridge window expanded to [mem
0x00000000-0xffffffff]; [mem 0x000a0000-0x000bffff] ignored
[   32.362897] acpi PNP0A08:00: host bridge window expanded to [mem
0x00000000-0xffffffff]; [mem 0x000d0000-0x000dffff] ignored
[   32.382862] acpi PNP0A08:00: host bridge window expanded to [mem
0x00000000-0xffffffff]; [mem 0x00000000-0xffffffff] ignored
[   32.402889] acpi PNP0A08:00: host bridge window expanded to [mem
0x00000000-0xffffffff]; [??? 0x00000000-0xffffffff flags 0x0] ignored
[   32.423000] acpi PNP0A08:00: host bridge window expanded to [mem
0x00000000-0xffffffff]; [mem 0x00000000-0xffffffff] ignored
[   32.602921] PCI host bridge to bus 0000:00
[   32.603158] pci_bus 0000:00: root bus resource [bus 00-3f]
[   32.622782] pci_bus 0000:00: root bus resource [io  0x0000-0x5fff]
[   32.642569] pci_bus 0000:00: root bus resource [mem 0x00000000-0xffffffff]
[   32.642893] pci_bus 0000:00: root bus resource [mem

0xfc000000000-0xfc07fffffff pref]

Looks like the commit have several problems.

Attached patch should address them.

arch/x86/pci/acpi.c static void teardown_mcfg_map(struct pci · line 226

Quoted 6 lines
arch/x86/pci/acpi.c +2 -3
-       struct resource r = {
-               .flags = 0
-       };
+       struct resource r;
 
+       memset(&r, 0, sizeof(r));

What's the point of this change? Both initialize r to 0. memset() generates better code, but that's irrelevant for the problem at hand.

And the "fix" is also missing that the address range check happens for IORESOURCE_IO as well. Which is silly because acpi_dev_resource_address_space() has that already for the IO case. But sure, that does not help, because it does not return false, it sets the IORESOURCE_DISABLED flag and returns true.

Now the code in setup_resource() clears that flag along with all other flags which does not make any sense, at least not without a comment.

But clearing and therefor ignoring IORESOURCE_DISABLED does not make any sense at all and is outright wrong.

So there is another interesting flag: IORESOURCE_WINDOW. That's cleared as well and of course the rest of that setup code does not handle it either. If IORESOURCE_WINDOW is not set, then this is address space which is consumed by the bridge itself. So its just wrong to treat it as window and try coalescing it with the real window spaces.

Also why is this x86 bridge specific?

     if (addr.resource_type == ACPI_MEMORY_RANGE &&
     	 addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
	    r.flags |= IORESOURCE_PREFETCH;

and not happening in the acpi code? Just because struct resource does not have a field for it? Sigh.

This needs more than a hacked together fixup, really. It was wrong before Jiangs change already.

Quoted 1 line

Please fix it before it get into linus tree.

You can be sure that I'm going to fix the whole mess there proper and not by applying a cobbled together bandaid.

Thanks,

tglx

#17 lore raw

Re: [tip:x86/apic] x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

Quoted 7 lines · Thomas Gleixner

On Tue, 9 Dec 2014, Yinghai Lu wrote:

Can you please

1) Cut out the completely irrelevant information from your replies? It's just annoying to scroll through hundreds of quoted lines to find the guts of the mail.

ok.

Quoted 3 lines

2) Send patches inline. It's a pain to review and reply and I can't use my normal tooling.

I can not, as gmail does not allow that.

Quoted 8 lines
Quoted 8 lines

Attached patch should address them.

arch/x86/pci/acpi.c +1 -3
-       struct resource r = {
-               .flags = 0
-       };
+       struct resource r;
Quoted 4 lines
Quoted 1 line

+ memset(&r, 0, sizeof(r));

What's the point of this change? Both initialize r to 0. memset() generates better code, but that's irrelevant for the problem at hand.

late there is

info->res[info->res_num] = r;

don't want the random pointer in r get copied.

Quoted 5 lines
Quoted 2 lines

Please fix it before it get into linus tree.

You can be sure that I'm going to fix the whole mess there proper and not by applying a cobbled together bandaid.

Good.

Yinghai

maintainer
#18 lore raw

Re: [tip:x86/apic] x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

Quoted 4 lines · Yinghai Lu
Quoted 2 lines

2) Send patches inline. It's a pain to review and reply and I can't use my normal tooling.

I can not, as gmail does not allow that.

Lemme guess, this is some kind of a joke you're making, right?

Signature · 5 lines
Regards/Gruss,
    Boris.

Sent from a fat crate under my desk. Formatting is fine.
--
#19 lore raw

Re: [tip:x86/apic] x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

Quoted 7 lines · Borislav Petkov
Quoted 4 lines · Yinghai Lu
Quoted 2 lines

2) Send patches inline. It's a pain to review and reply and I can't use my normal tooling.

I can not, as gmail does not allow that.

Lemme guess, this is some kind of a joke you're making, right?

I am using [email protected] to send as [email protected].

Tried with mutt or thunderbird etc, all kept on downloading ....

so have to stuck with the gmail web gui. and it does not allow insert plain text in the mail.

Thanks

Yinghai

#20 lore raw

Re: [tip:x86/apic] x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

Quoted 5 lines · Yinghai Lu
Quoted 4 lines · Borislav Petkov
Quoted 3 lines · Yinghai Lu
Quoted 2 lines

2) Send patches inline. It's a pain to review and reply and I can't use my normal tooling.

Quoted 7 lines
Quoted 3 lines
Quoted 1 line

I can not, as gmail does not allow that.

Lemme guess, this is some kind of a joke you're making, right?

I am using [email protected] to send as [email protected].

Tried with mutt or thunderbird etc, all kept on downloading ....

All mail clients are sh*t :)

Evolution has it's annoyances too, but this ain't one of them. I've set up both imap and pop evolution accounts for gmail. I generally only enable the pop account, but can enable both simultaneously.

-Mike

#21 lore raw

Re: [tip:x86/apic] x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

In reply to Yinghai Lu
Quoted 1 line · Yinghai Lu

Tried with mutt or thunderbird etc, all kept on downloading ....

Mutt with gmail via imap works just fine for me.

set folder="imaps://imap.gmail.com:993"
set imap_user="[email protected]"
set imap_pass="SuperSecret"

You don't have to set imap_pass if you prefer an interactive prompt.

Thanks,
Richard

#22 lore raw

Re: [tip:x86/apic] x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

In reply to Yinghai Lu
Quoted 8 lines · Yinghai Lu
Quoted 7 lines · Thomas Gleixner
Quoted 6 lines
arch/x86/pci/acpi.c +2 -3
-       struct resource r = {
-               .flags = 0
-       };
+       struct resource r;
 
+       memset(&r, 0, sizeof(r));
Quoted 8 lines
Quoted 2 lines

What's the point of this change? Both initialize r to 0. memset() generates better code, but that's irrelevant for the problem at hand.

late there is

info->res[info->res_num] = r;

don't want the random pointer in r get copied.

Did you actually read what I wrote?

    	struct resource r = {
	       .flags = 0
	};

initializes r completely to 0. So how do you get a random pointer in r?

Thanks,

tglx

#23 lore raw

Re: [tip:x86/apic] x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

Quoted 12 lines · Thomas Gleixner
Quoted 10 lines · Yinghai Lu
Quoted 9 lines · Thomas Gleixner

arch/x86/pci/acpi.c static void teardown_mcfg_map(struct pci · line 226

Quoted 6 lines
arch/x86/pci/acpi.c +2 -3
-       struct resource r = {
-               .flags = 0
-       };
+       struct resource r;
 
+       memset(&r, 0, sizeof(r));

What's the point of this change? Both initialize r to 0. memset() generates better code, but that's irrelevant for the problem at hand.

Quoted 7 lines

Did you actually read what I wrote?

        struct resource r = {
               .flags = 0
        };

initializes r completely to 0. So how do you get a random pointer in r?

ok, I get it now.

I was thinking that compiler will generate code like

    struct resource r;
    r.flags = 0;

Thanks

Yinghai

maintainer
#24 lore raw

Re: [tip:x86/apic] x86, PCI, ACPI: Kill private function resource_to_addr() in arch/x86/pci/acpi.c

In reply to Yinghai Lu
Quoted 7 lines · Yinghai Lu
Quoted 6 lines · Thomas Gleixner

On Tue, 9 Dec 2014, Yinghai Lu wrote:

Can you please
...
2) Send patches inline. It's a pain to review and reply and I can't use my normal tooling.

I agree, it is noticeably more hassle for me to deal with patches sent as attachments. I can do it, but I tend to avoid it because it's a nuisance.

Quoted 1 line

I can not, as gmail does not allow that.

I agree, gmail is a pain in the neck in this regard. I personally use mutt with imap to my gmail account to send patches and to review and apply patches. It isn't perfect, and it is a bit of a hassle, but it can be done.

Bjorn

author
#25 lore raw

PATCH v7 5/18 ACPI: Correct return value of acpi_dev_resource_address_space()

In reply to Jiang Liu

Change acpi_dev_resource_address_space() to return failure if the acpi_resource structure can't be converted to an ACPI address64 structure, so caller could correctly detect failure.

---
 drivers/acpi/resource.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/resource.c +1 -1
index 2ba8f02ced36..782a0d15c25f 100644
@@ -200,7 +200,7 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
 
 	status = acpi_resource_to_address64(ares, &addr);
 	if (ACPI_FAILURE(status))
-		return true;
+		return false;
 
 	res->start = addr.minimum;
 	res->end = addr.maximum;
Signature · 1 line
1.7.10.4
#26 lore raw

Re: [Patch v7 05/18] ACPI: Correct return value of acpi_dev_resource_address_space()

Quoted 5 lines · Jiang Liu

Change acpi_dev_resource_address_space() to return failure if the acpi_resource structure can't be converted to an ACPI address64 structure, so caller could correctly detect failure.

ACK

Quoted 18 lines
---
 drivers/acpi/resource.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/resource.c +1 -1
index 2ba8f02ced36..782a0d15c25f 100644
@@ -200,7 +200,7 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
 
 	status = acpi_resource_to_address64(ares, &addr);
 	if (ACPI_FAILURE(status))
-		return true;
+		return false;
 
 	res->start = addr.minimum;
 	res->end = addr.maximum;
Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
maintainer
#27 lore raw

Re: [Patch v7 05/18] ACPI: Correct return value of acpi_dev_resource_address_space()

In reply to Jiang Liu
Quoted 3 lines · Jiang Liu

Change acpi_dev_resource_address_space() to return failure if the acpi_resource structure can't be converted to an ACPI address64 structure, so caller could correctly detect failure.

Fixes 046d9ce6820e ("ACPI: Move device resources interpretation code

from PNP to ACPI core")

Possible stable candidate? 046d9ce6820e appeared in v3.8.

Quoted 21 lines
---
 drivers/acpi/resource.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/resource.c +1 -2
index 2ba8f02ced36..782a0d15c25f 100644
@@ -200,7 +200,7 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
 
        status = acpi_resource_to_address64(ares, &addr);
        if (ACPI_FAILURE(status))
-               return true;
+               return false;
 
        res->start = addr.minimum;
        res->end = addr.maximum;
--

1.7.10.4

#28 lore raw

Re: [Patch v7 05/18] ACPI: Correct return value of acpi_dev_resource_address_space()

Quoted 9 lines · Bjorn Helgaas
Quoted 3 lines · Jiang Liu

Change acpi_dev_resource_address_space() to return failure if the acpi_resource structure can't be converted to an ACPI address64 structure, so caller could correctly detect failure.

Fixes 046d9ce6820e ("ACPI: Move device resources interpretation code

from PNP to ACPI core")

Possible stable candidate? 046d9ce6820e appeared in v3.8.

Well, are we seeing problems with it?

Quoted 25 lines
Quoted 19 lines
---
 drivers/acpi/resource.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/resource.c +1 -2
index 2ba8f02ced36..782a0d15c25f 100644
@@ -200,7 +200,7 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
 
        status = acpi_resource_to_address64(ares, &addr);
        if (ACPI_FAILURE(status))
-               return true;
+               return false;
 
        res->start = addr.minimum;
        res->end = addr.maximum;
--
Quoted 2 lines

1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
maintainer
#29 lore raw

Re: [Patch v7 05/18] ACPI: Correct return value of acpi_dev_resource_address_space()

Quoted 6 lines · Rafael J. Wysocki
Quoted 5 lines · Bjorn Helgaas
Quoted 3 lines · Jiang Liu

Change acpi_dev_resource_address_space() to return failure if the acpi_resource structure can't be converted to an ACPI address64 structure, so caller could correctly detect failure.

Quoted 6 lines
Quoted 4 lines
Fixes 046d9ce6820e ("ACPI: Move device resources interpretation code

from PNP to ACPI core")

Possible stable candidate? 046d9ce6820e appeared in v3.8.

Well, are we seeing problems with it?

Not to my knowledge. I only raised the possibility because it seems like we are seeing more and more things backported to stable. But if we we're not seeing a problem, I agree we probably shouldn't push it.

Quoted 29 lines
Quoted 16 lines
Quoted 16 lines
---
 drivers/acpi/resource.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/resource.c +1 -1
index 2ba8f02ced36..782a0d15c25f 100644
@@ -200,7 +200,7 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
 
        status = acpi_resource_to_address64(ares, &addr);
        if (ACPI_FAILURE(status))
-               return true;
+               return false;
 
Quoted 9 lines
Quoted 5 lines
drivers/acpi/resource.c +0 -1
        res->start = addr.minimum;
        res->end = addr.maximum;
--

1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

#30 lore raw

[tip:x86/apic] ACPI: Correct return value of acpi_dev_resource_address_space()

In reply to Jiang Liu
ACPI: Correct return value of acpi_dev_resource_address_space()
Commit-ID:  36ef5fb509c1b19be0dec02caf4e5081c33328df
Gitweb:     http://git.kernel.org/tip/36ef5fb509c1b19be0dec02caf4e5081c33328df
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:35 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Mon, 3 Nov 2014 11:56:07 +0100

ACPI: Correct return value of acpi_dev_resource_address_space()

Change acpi_dev_resource_address_space() to return failure if the acpi_resource structure can't be converted to an ACPI address64 structure, so caller could correctly detect failure.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
---
 drivers/acpi/resource.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/resource.c +1 -1
index 2ba8f02..782a0d1 100644
@@ -200,7 +200,7 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
 
 	status = acpi_resource_to_address64(ares, &addr);
 	if (ACPI_FAILURE(status))
-		return true;
+		return false;
 
 	res->start = addr.minimum;
 	res->end = addr.maximum;
#31 lore raw

[tip:x86/apic] ACPI: Correct return value of acpi_dev_resource_address_space()

In reply to Jiang Liu
ACPI: Correct return value of acpi_dev_resource_address_space()
Commit-ID:  6658c739431cfa1bdf15737774ed1cac432b5c35
Gitweb:     http://git.kernel.org/tip/6658c739431cfa1bdf15737774ed1cac432b5c35
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:35 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 16 Dec 2014 14:08:14 +0100

ACPI: Correct return value of acpi_dev_resource_address_space()

Change acpi_dev_resource_address_space() to return failure if the acpi_resource structure can't be converted to an ACPI address64 structure, so caller could correctly detect failure.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
---
 drivers/acpi/resource.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/resource.c +1 -1
index 2ba8f02..782a0d1 100644
@@ -200,7 +200,7 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
 
 	status = acpi_resource_to_address64(ares, &addr);
 	if (ACPI_FAILURE(status))
-		return true;
+		return false;
 
 	res->start = addr.minimum;
 	res->end = addr.maximum;
author
#32 lore raw

PATCH v7 6/18 ACPI: Fix minor syntax issues in processor_core.c

In reply to Jiang Liu

Fix minor syntax issues in processor_core.c to follow coding styles.

---
 drivers/acpi/processor_core.c |    9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/acpi/processor_core.c +4 -5
index ef58f46c8442..342942f90a10 100644
@@ -125,13 +125,12 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
 	}
 
 	header = (struct acpi_subtable_header *)obj->buffer.pointer;
-	if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
+	if (header->type == ACPI_MADT_TYPE_LOCAL_APIC)
 		map_lapic_id(header, acpi_id, &apic_id);
-	} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
+	else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC)
 		map_lsapic_id(header, type, acpi_id, &apic_id);
-	} else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
+	else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC)
 		map_x2apic_id(header, type, acpi_id, &apic_id);
-	}
 
 exit:
 	kfree(buffer.pointer);
@@ -164,7 +163,7 @@ int acpi_map_cpuid(int apic_id, u32 acpi_id)
 		 * For example,
 		 *
 		 * Scope (_PR)
-                 * {
+		 * {
 		 *     Processor (CPU0, 0x00, 0x00000410, 0x06) {}
 		 *     Processor (CPU1, 0x01, 0x00000410, 0x06) {}
 		 *     Processor (CPU2, 0x02, 0x00000410, 0x06) {}
Signature · 1 line
1.7.10.4
#33 lore raw

[tip:x86/apic] ACPI: Fix minor syntax issues in processor_core.c

ACPI: Fix minor syntax issues in processor_core.c
Commit-ID:  5922b6f497ed2daf5c06654c3dbda7ca911bcfef
Gitweb:     http://git.kernel.org/tip/5922b6f497ed2daf5c06654c3dbda7ca911bcfef
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:36 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Mon, 3 Nov 2014 11:56:07 +0100

ACPI: Fix minor syntax issues in processor_core.c

Fix minor syntax issues in processor_core.c to follow coding styles.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
---
 drivers/acpi/processor_core.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/acpi/processor_core.c +4 -5
index ef58f46..342942f 100644
@@ -125,13 +125,12 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
 	}
 
 	header = (struct acpi_subtable_header *)obj->buffer.pointer;
-	if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
+	if (header->type == ACPI_MADT_TYPE_LOCAL_APIC)
 		map_lapic_id(header, acpi_id, &apic_id);
-	} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
+	else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC)
 		map_lsapic_id(header, type, acpi_id, &apic_id);
-	} else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
+	else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC)
 		map_x2apic_id(header, type, acpi_id, &apic_id);
-	}
 
 exit:
 	kfree(buffer.pointer);
@@ -164,7 +163,7 @@ int acpi_map_cpuid(int apic_id, u32 acpi_id)
 		 * For example,
 		 *
 		 * Scope (_PR)
-                 * {
+		 * {
 		 *     Processor (CPU0, 0x00, 0x00000410, 0x06) {}
 		 *     Processor (CPU1, 0x01, 0x00000410, 0x06) {}
 		 *     Processor (CPU2, 0x02, 0x00000410, 0x06) {}
#34 lore raw

[tip:x86/apic] ACPI: Fix minor syntax issues in processor_core.c

In reply to Jiang Liu
ACPI: Fix minor syntax issues in processor_core.c
Commit-ID:  13ca62b243f69b5c0f82386e1cfbb880ee6fce10
Gitweb:     http://git.kernel.org/tip/13ca62b243f69b5c0f82386e1cfbb880ee6fce10
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:36 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 16 Dec 2014 14:08:14 +0100

ACPI: Fix minor syntax issues in processor_core.c

Fix minor syntax issues in processor_core.c to follow coding styles.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
---
 drivers/acpi/processor_core.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/acpi/processor_core.c +4 -5
index ef58f46..342942f 100644
@@ -125,13 +125,12 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
 	}
 
 	header = (struct acpi_subtable_header *)obj->buffer.pointer;
-	if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
+	if (header->type == ACPI_MADT_TYPE_LOCAL_APIC)
 		map_lapic_id(header, acpi_id, &apic_id);
-	} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
+	else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC)
 		map_lsapic_id(header, type, acpi_id, &apic_id);
-	} else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
+	else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC)
 		map_x2apic_id(header, type, acpi_id, &apic_id);
-	}
 
 exit:
 	kfree(buffer.pointer);
@@ -164,7 +163,7 @@ int acpi_map_cpuid(int apic_id, u32 acpi_id)
 		 * For example,
 		 *
 		 * Scope (_PR)
-                 * {
+		 * {
 		 *     Processor (CPU0, 0x00, 0x00000410, 0x06) {}
 		 *     Processor (CPU1, 0x01, 0x00000410, 0x06) {}
 		 *     Processor (CPU2, 0x02, 0x00000410, 0x06) {}
author
#35 lore raw

PATCH v7 7/18 ACPI: Add interfaces to parse IOAPIC ID for IOAPIC hotplug

In reply to Jiang Liu

From: Yinghai Lu <[email protected]>

We need to parse APIC ID for IOAPIC registration for IOAPIC hotplug. ACPI _MAT method and MADT table are used to figure out IOAPIC ID, just like parsing CPU APIC ID for CPU hotplug.

---
 drivers/acpi/processor_core.c |  122 ++++++++++++++++++++++++++++++++++++++---
 include/linux/acpi.h          |    4 ++
 2 files changed, 117 insertions(+), 9 deletions(-)
drivers/acpi/processor_core.c +113 -9
index 342942f90a10..9ff12905aed9 100644
@@ -4,6 +4,10 @@
  *
  *	Alex Chiang <[email protected]>
  *	- Unified x86/ia64 implementations
+ *
+ * I/O APIC hotplug support
+ *	Yinghai Lu <[email protected]>
+ *	Jiang Liu <[email protected]>
  */
 #include <linux/export.h>
 #include <linux/acpi.h>
@@ -12,6 +16,21 @@
 #define _COMPONENT		ACPI_PROCESSOR_COMPONENT
 ACPI_MODULE_NAME("processor_core");
 
+static struct acpi_table_madt *get_madt_table(void)
+{
+	static struct acpi_table_madt *madt;
+	static int read_madt;
+
+	if (!read_madt) {
+		if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
+					(struct acpi_table_header **)&madt)))
+			madt = NULL;
+		read_madt++;
+	}
+
+	return madt;
+}
+
 static int map_lapic_id(struct acpi_subtable_header *entry,
 		 u32 acpi_id, int *apic_id)
 {
@@ -67,17 +86,10 @@ static int map_lsapic_id(struct acpi_subtable_header *entry,
 static int map_madt_entry(int type, u32 acpi_id)
 {
 	unsigned long madt_end, entry;
-	static struct acpi_table_madt *madt;
-	static int read_madt;
 	int apic_id = -1;
+	struct acpi_table_madt *madt;
 
-	if (!read_madt) {
-		if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
-					(struct acpi_table_header **)&madt)))
-			madt = NULL;
-		read_madt++;
-	}
-
+	madt = get_madt_table();
 	if (!madt)
 		return apic_id;
 
@@ -203,3 +215,95 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
 	return acpi_map_cpuid(apic_id, acpi_id);
 }
 EXPORT_SYMBOL_GPL(acpi_get_cpuid);
+
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+static int get_ioapic_id(struct acpi_subtable_header *entry, u32 gsi_base,
+			 u64 *phys_addr, int *ioapic_id)
+{
+	struct acpi_madt_io_apic *ioapic = (struct acpi_madt_io_apic *)entry;
+
+	if (ioapic->global_irq_base != gsi_base)
+		return 0;
+
+	*phys_addr = ioapic->address;
+	*ioapic_id = ioapic->id;
+	return 1;
+}
+
+static int parse_madt_ioapic_entry(u32 gsi_base, u64 *phys_addr)
+{
+	struct acpi_subtable_header *hdr;
+	unsigned long madt_end, entry;
+	int apic_id = -1;
+	struct acpi_table_madt *madt;
+
+	madt = get_madt_table();
+	if (!madt)
+		return apic_id;
+
+	entry = (unsigned long)madt;
+	madt_end = entry + madt->header.length;
+
+	/* Parse all entries looking for a match. */
+	entry += sizeof(struct acpi_table_madt);
+	while (entry + sizeof(struct acpi_subtable_header) < madt_end) {
+		hdr = (struct acpi_subtable_header *)entry;
+		if (hdr->type == ACPI_MADT_TYPE_IO_APIC &&
+		    get_ioapic_id(hdr, gsi_base, phys_addr, &apic_id))
+			break;
+		else
+			entry += hdr->length;
+	}
+
+	return apic_id;
+}
+
+static int parse_mat_ioapic_entry(acpi_handle handle, u32 gsi_base,
+				  u64 *phys_addr)
+{
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *obj;
+	struct acpi_subtable_header *header;
+	int apic_id = -1;
+
+	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
+		goto exit;
+
+	if (!buffer.length || !buffer.pointer)
+		goto exit;
+
+	obj = buffer.pointer;
+	if (obj->type != ACPI_TYPE_BUFFER ||
+	    obj->buffer.length < sizeof(struct acpi_subtable_header))
+		goto exit;
+
+	header = (struct acpi_subtable_header *)obj->buffer.pointer;
+	if (header->type == ACPI_MADT_TYPE_IO_APIC)
+		get_ioapic_id(header, gsi_base, phys_addr, &apic_id);
+
+exit:
+	kfree(buffer.pointer);
+	return apic_id;
+}
+
+/**
+ * acpi_get_ioapic_id - Get IOAPIC ID and physical address matching @gsi_base
+ * @handle:	ACPI object for IOAPIC device
+ * @gsi_base:	GSI base to match with
+ * @phys_add:	hold physical address of matching IOAPIC record
+ *
+ * Walk resources returned by ACPI_MAT method, then ACPI MADT table, to search
+ * for an ACPI IOAPIC record matching @gsi_base.
+ * Return IOAPIC id and physical address if found a match, otherwise return <0.
+ */
+int acpi_get_ioapic_id(acpi_handle handle, u32 gsi_base, u64 *phys_addr)
+{
+	int apic_id;
+
+	apic_id = parse_mat_ioapic_entry(handle, gsi_base, phys_addr);
+	if (apic_id == -1)
+		apic_id = parse_madt_ioapic_entry(gsi_base, phys_addr);
+
+	return apic_id;
+}
+#endif /* CONFIG_ACPI_HOTPLUG_IOAPIC */
include/linux/acpi.h +4 -0
index 407a12f663eb..77cecd0350e7 100644
@@ -146,6 +146,10 @@ int acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu);
 int acpi_unmap_lsapic(int cpu);
 #endif /* CONFIG_ACPI_HOTPLUG_CPU */
 
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+int acpi_get_ioapic_id(acpi_handle handle, u32 gsi_base, u64 *phys_addr);
+#endif
+
 int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base);
 int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base);
 void acpi_irq_stats_init(void);
Signature · 1 line
1.7.10.4
#36 lore raw

[tip:x86/apic] ACPI: Add interfaces to parse IOAPIC ID for IOAPIC hotplug

ACPI: Add interfaces to parse IOAPIC ID for IOAPIC hotplug
Commit-ID:  717ed6192d16cecf06b7412bf07c207ed92a9f52
Gitweb:     http://git.kernel.org/tip/717ed6192d16cecf06b7412bf07c207ed92a9f52
Author:     Yinghai Lu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:37 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Mon, 3 Nov 2014 11:56:07 +0100

ACPI: Add interfaces to parse IOAPIC ID for IOAPIC hotplug

We need to parse APIC ID for IOAPIC registration for IOAPIC hotplug. ACPI _MAT method and MADT table are used to figure out IOAPIC ID, just like parsing CPU APIC ID for CPU hotplug.

[ tglx: Fixed docbook comment ]

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
---
 drivers/acpi/processor_core.c | 123 ++++++++++++++++++++++++++++++++++++++----
 include/linux/acpi.h          |   4 ++
 2 files changed, 118 insertions(+), 9 deletions(-)
drivers/acpi/processor_core.c +114 -9
index 342942f..f124cbb 100644
@@ -4,6 +4,10 @@
  *
  *	Alex Chiang <[email protected]>
  *	- Unified x86/ia64 implementations
+ *
+ * I/O APIC hotplug support
+ *	Yinghai Lu <[email protected]>
+ *	Jiang Liu <[email protected]>
  */
 #include <linux/export.h>
 #include <linux/acpi.h>
@@ -12,6 +16,21 @@
 #define _COMPONENT		ACPI_PROCESSOR_COMPONENT
 ACPI_MODULE_NAME("processor_core");
 
+static struct acpi_table_madt *get_madt_table(void)
+{
+	static struct acpi_table_madt *madt;
+	static int read_madt;
+
+	if (!read_madt) {
+		if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
+					(struct acpi_table_header **)&madt)))
+			madt = NULL;
+		read_madt++;
+	}
+
+	return madt;
+}
+
 static int map_lapic_id(struct acpi_subtable_header *entry,
 		 u32 acpi_id, int *apic_id)
 {
@@ -67,17 +86,10 @@ static int map_lsapic_id(struct acpi_subtable_header *entry,
 static int map_madt_entry(int type, u32 acpi_id)
 {
 	unsigned long madt_end, entry;
-	static struct acpi_table_madt *madt;
-	static int read_madt;
 	int apic_id = -1;
+	struct acpi_table_madt *madt;
 
-	if (!read_madt) {
-		if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
-					(struct acpi_table_header **)&madt)))
-			madt = NULL;
-		read_madt++;
-	}
-
+	madt = get_madt_table();
 	if (!madt)
 		return apic_id;
 
@@ -203,3 +215,96 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
 	return acpi_map_cpuid(apic_id, acpi_id);
 }
 EXPORT_SYMBOL_GPL(acpi_get_cpuid);
+
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+static int get_ioapic_id(struct acpi_subtable_header *entry, u32 gsi_base,
+			 u64 *phys_addr, int *ioapic_id)
+{
+	struct acpi_madt_io_apic *ioapic = (struct acpi_madt_io_apic *)entry;
+
+	if (ioapic->global_irq_base != gsi_base)
+		return 0;
+
+	*phys_addr = ioapic->address;
+	*ioapic_id = ioapic->id;
+	return 1;
+}
+
+static int parse_madt_ioapic_entry(u32 gsi_base, u64 *phys_addr)
+{
+	struct acpi_subtable_header *hdr;
+	unsigned long madt_end, entry;
+	struct acpi_table_madt *madt;
+	int apic_id = -1;
+
+	madt = get_madt_table();
+	if (!madt)
+		return apic_id;
+
+	entry = (unsigned long)madt;
+	madt_end = entry + madt->header.length;
+
+	/* Parse all entries looking for a match. */
+	entry += sizeof(struct acpi_table_madt);
+	while (entry + sizeof(struct acpi_subtable_header) < madt_end) {
+		hdr = (struct acpi_subtable_header *)entry;
+		if (hdr->type == ACPI_MADT_TYPE_IO_APIC &&
+		    get_ioapic_id(hdr, gsi_base, phys_addr, &apic_id))
+			break;
+		else
+			entry += hdr->length;
+	}
+
+	return apic_id;
+}
+
+static int parse_mat_ioapic_entry(acpi_handle handle, u32 gsi_base,
+				  u64 *phys_addr)
+{
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	struct acpi_subtable_header *header;
+	union acpi_object *obj;
+	int apic_id = -1;
+
+	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
+		goto exit;
+
+	if (!buffer.length || !buffer.pointer)
+		goto exit;
+
+	obj = buffer.pointer;
+	if (obj->type != ACPI_TYPE_BUFFER ||
+	    obj->buffer.length < sizeof(struct acpi_subtable_header))
+		goto exit;
+
+	header = (struct acpi_subtable_header *)obj->buffer.pointer;
+	if (header->type == ACPI_MADT_TYPE_IO_APIC)
+		get_ioapic_id(header, gsi_base, phys_addr, &apic_id);
+
+exit:
+	kfree(buffer.pointer);
+	return apic_id;
+}
+
+/**
+ * acpi_get_ioapic_id - Get IOAPIC ID and physical address matching @gsi_base
+ * @handle:	ACPI object for IOAPIC device
+ * @gsi_base:	GSI base to match with
+ * @phys_addr:	Pointer to store physical address of matching IOAPIC record
+ *
+ * Walk resources returned by ACPI_MAT method, then ACPI MADT table, to search
+ * for an ACPI IOAPIC record matching @gsi_base.
+ * Return IOAPIC id and store physical address in @phys_addr if found a match,
+ * otherwise return <0.
+ */
+int acpi_get_ioapic_id(acpi_handle handle, u32 gsi_base, u64 *phys_addr)
+{
+	int apic_id;
+
+	apic_id = parse_mat_ioapic_entry(handle, gsi_base, phys_addr);
+	if (apic_id == -1)
+		apic_id = parse_madt_ioapic_entry(gsi_base, phys_addr);
+
+	return apic_id;
+}
+#endif /* CONFIG_ACPI_HOTPLUG_IOAPIC */
include/linux/acpi.h +4 -0
index 407a12f..77cecd0 100644
@@ -146,6 +146,10 @@ int acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu);
 int acpi_unmap_lsapic(int cpu);
 #endif /* CONFIG_ACPI_HOTPLUG_CPU */
 
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+int acpi_get_ioapic_id(acpi_handle handle, u32 gsi_base, u64 *phys_addr);
+#endif
+
 int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base);
 int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base);
 void acpi_irq_stats_init(void);
author
#37 lore raw

PATCH v7 8/18 PCI: Remove PCI ioapic driver

In reply to Jiang Liu

To support IOAPIC hotplug on x86 and IA64 platforms, OS needs to figure out global interrupt source number(GSI) and IOAPIC enumeration ID through ACPI interfaces. So BIOS must implement an ACPI IOAPIC device with _GSB/_UID or _MAT method to support IOAPIC hotplug. OS also needs to figure out base physical address to access IOAPIC registers. OS may get the base physical address through PCI BARs if IOAPIC device is visible in PCI domain, otherwise OS may get the address by ACPI _CRS method if IOAPIC device is hidden from PCI domain by BIOS.

When adding a PCI subtree, we need to add IOAPIC devices before enabling all other PCI devices because other PCI devices may use the IOAPIC to allocate PCI interrupts.

So we plan to reimplement IOAPIC driver as an ACPI instead of PCI driver due to:
1) hot-pluggable IOAPIC devices are always visible in ACPI domain, but may or may not be visible in PCI domain.
2) we could explicitly control the order between IOAPIC and other PCI devices.

We also have another choice to use a PCI driver to manage IOAPIC device if it's visible in PCI domain and use an ACPI driver if it's only visible in ACPI domain. But this solution is a little complex.

It shouldn't cause serious backward compatibility issues because:
1) IOAPIC hotplug is never supported on x86 yet because it hasn't implemented the required acpi_register_ioapic() and acpi_unregister_ioapic().
2) Currently only ACPI based IOAPIC hotplug is possible on x86 and IA64, we don't know other specifications and interfaces to support IOAPIC hotplug yet.
3) We will reimplement an ACPI IOAPICtdriver support IOAPIC hotplug.

This change also helps to get rid of the false alarm on all current Linux distributions:

[    6.952497] ioapic: probe of 0000:00:05.4 failed with error -22
[    6.959542] ioapic: probe of 0000:80:05.4 failed with error -22
---
 drivers/pci/Kconfig  |    7 ---
 drivers/pci/Makefile |    2 -
 drivers/pci/ioapic.c |  121 --------------------------------------------------
 3 files changed, 130 deletions(-)
 delete mode 100644 drivers/pci/ioapic.c
drivers/pci/Kconfig +0 -7
index 893503fa1782..39866d18004e 100644
@@ -104,13 +104,6 @@ config PCI_PASID
 
 	  If unsure, say N.
 
-config PCI_IOAPIC
-	bool "PCI IO-APIC hotplug support" if X86
-	depends on PCI
-	depends on ACPI
-	depends on X86_IO_APIC
-	default !X86
-
 config PCI_LABEL
 	def_bool y if (DMI || ACPI)
 	select NLS
drivers/pci/Makefile +0 -2
index e04fe2d9df3b..73e4af400a5a 100644
@@ -13,8 +13,6 @@ obj-$(CONFIG_PCI_QUIRKS) += quirks.o
 # Build PCI Express stuff if needed
 obj-$(CONFIG_PCIEPORTBUS) += pcie/
 
-obj-$(CONFIG_PCI_IOAPIC) += ioapic.o
-
 # Build the PCI Hotplug drivers if we were asked to
 obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
 ifdef CONFIG_HOTPLUG_PCI
drivers/pci/ioapic.c deleted +0 -121

121 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#38 lore raw

[tip:x86/apic] PCI: Remove PCI ioapic driver

PCI: Remove PCI ioapic driver
Commit-ID:  e07cfbfaeec96c2e2f7ab81e8125891089e3065c
Gitweb:     http://git.kernel.org/tip/e07cfbfaeec96c2e2f7ab81e8125891089e3065c
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:38 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Mon, 3 Nov 2014 11:56:07 +0100

PCI: Remove PCI ioapic driver

To support IOAPIC hotplug on x86 and IA64 platforms, OS needs to figure out global interrupt source number(GSI) and IOAPIC enumeration ID through ACPI interfaces. So BIOS must implement an ACPI IOAPIC device with _GSB/_UID or _MAT method to support IOAPIC hotplug. OS also needs to figure out base physical address to access IOAPIC registers. OS may get the base physical address through PCI BARs if IOAPIC device is visible in PCI domain, otherwise OS may get the address by ACPI _CRS method if IOAPIC device is hidden from PCI domain by BIOS.

When adding a PCI subtree, we need to add IOAPIC devices before enabling all other PCI devices because other PCI devices may use the IOAPIC to allocate PCI interrupts.

So we plan to reimplement IOAPIC driver as an ACPI instead of PCI driver due to:
1) hot-pluggable IOAPIC devices are always visible in ACPI domain, but may or may not be visible in PCI domain.
2) we could explicitly control the order between IOAPIC and other PCI devices.

We also have another choice to use a PCI driver to manage IOAPIC device if it's visible in PCI domain and use an ACPI driver if it's only visible in ACPI domain. But this solution is a little complex.

It shouldn't cause serious backward compatibility issues because:
1) IOAPIC hotplug is never supported on x86 yet because it hasn't implemented the required acpi_register_ioapic() and acpi_unregister_ioapic().
2) Currently only ACPI based IOAPIC hotplug is possible on x86 and IA64, we don't know other specifications and interfaces to support IOAPIC hotplug yet.
3) We will reimplement an ACPI IOAPIC driver to support IOAPIC hotplug.

This change also helps to get rid of the false alarm on all current Linux distributions:

[    6.952497] ioapic: probe of 0000:00:05.4 failed with error -22
[    6.959542] ioapic: probe of 0000:80:05.4 failed with error -22
Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 drivers/pci/Kconfig  |   7 ---
 drivers/pci/Makefile |   2 -
 drivers/pci/ioapic.c | 121 ---------------------------------------------------
 3 files changed, 130 deletions(-)
drivers/pci/Kconfig +0 -7
index 893503f..39866d1 100644
@@ -104,13 +104,6 @@ config PCI_PASID
 
 	  If unsure, say N.
 
-config PCI_IOAPIC
-	bool "PCI IO-APIC hotplug support" if X86
-	depends on PCI
-	depends on ACPI
-	depends on X86_IO_APIC
-	default !X86
-
 config PCI_LABEL
 	def_bool y if (DMI || ACPI)
 	select NLS
drivers/pci/Makefile +0 -2
index e04fe2d..73e4af4 100644
@@ -13,8 +13,6 @@ obj-$(CONFIG_PCI_QUIRKS) += quirks.o
 # Build PCI Express stuff if needed
 obj-$(CONFIG_PCIEPORTBUS) += pcie/
 
-obj-$(CONFIG_PCI_IOAPIC) += ioapic.o
-
 # Build the PCI Hotplug drivers if we were asked to
 obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
 ifdef CONFIG_HOTPLUG_PCI
drivers/pci/ioapic.c deleted +0 -121

121 lines not on this page · raw message

#39 lore raw

[tip:x86/apic] PCI: Remove PCI ioapic driver

In reply to Jiang Liu
PCI: Remove PCI ioapic driver
Commit-ID:  5db66334a7e83cda70fb6193dcaa2590da3a1b7d
Gitweb:     http://git.kernel.org/tip/5db66334a7e83cda70fb6193dcaa2590da3a1b7d
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:38 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 16 Dec 2014 14:08:14 +0100

PCI: Remove PCI ioapic driver

To support IOAPIC hotplug on x86 and IA64 platforms, OS needs to figure out global interrupt source number(GSI) and IOAPIC enumeration ID through ACPI interfaces. So BIOS must implement an ACPI IOAPIC device with _GSB/_UID or _MAT method to support IOAPIC hotplug. OS also needs to figure out base physical address to access IOAPIC registers. OS may get the base physical address through PCI BARs if IOAPIC device is visible in PCI domain, otherwise OS may get the address by ACPI _CRS method if IOAPIC device is hidden from PCI domain by BIOS.

When adding a PCI subtree, we need to add IOAPIC devices before enabling all other PCI devices because other PCI devices may use the IOAPIC to allocate PCI interrupts.

So we plan to reimplement IOAPIC driver as an ACPI instead of PCI driver due to:
1) hot-pluggable IOAPIC devices are always visible in ACPI domain, but may or may not be visible in PCI domain.
2) we could explicitly control the order between IOAPIC and other PCI devices.

We also have another choice to use a PCI driver to manage IOAPIC device if it's visible in PCI domain and use an ACPI driver if it's only visible in ACPI domain. But this solution is a little complex.

It shouldn't cause serious backward compatibility issues because:
1) IOAPIC hotplug is never supported on x86 yet because it hasn't implemented the required acpi_register_ioapic() and acpi_unregister_ioapic().
2) Currently only ACPI based IOAPIC hotplug is possible on x86 and IA64, we don't know other specifications and interfaces to support IOAPIC hotplug yet.
3) We will reimplement an ACPI IOAPIC driver to support IOAPIC hotplug.

This change also helps to get rid of the false alarm on all current Linux distributions:

[    6.952497] ioapic: probe of 0000:00:05.4 failed with error -22
[    6.959542] ioapic: probe of 0000:80:05.4 failed with error -22
Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 drivers/pci/Kconfig  |   7 ---
 drivers/pci/Makefile |   2 -
 drivers/pci/ioapic.c | 121 ---------------------------------------------------
 3 files changed, 130 deletions(-)
drivers/pci/Kconfig +0 -7
index cced842..91a64d3 100644
@@ -110,13 +110,6 @@ config PCI_PASID
 
 	  If unsure, say N.
 
-config PCI_IOAPIC
-	bool "PCI IO-APIC hotplug support" if X86
-	depends on PCI
-	depends on ACPI
-	depends on X86_IO_APIC
-	default !X86
-
 config PCI_LABEL
 	def_bool y if (DMI || ACPI)
 	select NLS
drivers/pci/Makefile +0 -2
index e04fe2d..73e4af4 100644
@@ -13,8 +13,6 @@ obj-$(CONFIG_PCI_QUIRKS) += quirks.o
 # Build PCI Express stuff if needed
 obj-$(CONFIG_PCIEPORTBUS) += pcie/
 
-obj-$(CONFIG_PCI_IOAPIC) += ioapic.o
-
 # Build the PCI Hotplug drivers if we were asked to
 obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
 ifdef CONFIG_HOTPLUG_PCI
drivers/pci/ioapic.c deleted +0 -121

121 lines not on this page · raw message

author
#40 lore raw

PATCH v7 9/18 x86, irq: Split out alloc_ioapic_save_registers()

In reply to Jiang Liu

From: Yinghai Lu <[email protected]>

Split out alloc_ioapic_save_registers() from early_irq_init(), so it could be used for ioapic hotplug later.

Cc Joerg Roedel <[email protected]>
Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Sebastian Andrzej Siewior <[email protected]>
---
 arch/x86/kernel/apic/io_apic.c |   22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)
arch/x86/kernel/apic/io_apic.c +15 -7
index 1183d545da1e..acaee90fc9cc 100644
@@ -237,6 +237,19 @@ static struct irq_pin_list *alloc_irq_pin_list(int node)
 	return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node);
 }
 
+static void alloc_ioapic_saved_registers(int idx)
+{
+	size_t size;
+
+	if (ioapics[idx].saved_registers)
+		return;
+
+	size = sizeof(struct IO_APIC_route_entry) * ioapics[idx].nr_registers;
+	ioapics[idx].saved_registers = kzalloc(size, GFP_KERNEL);
+	if (!ioapics[idx].saved_registers)
+		pr_err("IOAPIC %d: suspend/resume impossible!\n", idx);
+}
+
 int __init arch_early_irq_init(void)
 {
 	struct irq_cfg *cfg;
@@ -245,13 +258,8 @@ int __init arch_early_irq_init(void)
 	if (!nr_legacy_irqs())
 		io_apic_irqs = ~0UL;
 
-	for_each_ioapic(i) {
-		ioapics[i].saved_registers =
-			kzalloc(sizeof(struct IO_APIC_route_entry) *
-				ioapics[i].nr_registers, GFP_KERNEL);
-		if (!ioapics[i].saved_registers)
-			pr_err("IOAPIC %d: suspend/resume impossible!\n", i);
-	}
+	for_each_ioapic(i)
+		alloc_ioapic_saved_registers(i);
 
 	/*
 	 * For legacy IRQ's, start with assigning irq0 to irq15 to
Signature · 1 line
1.7.10.4
#41 lore raw

[tip:x86/apic] x86, irq: Split out alloc_ioapic_save_registers()

x86, irq: Split out alloc_ioapic_save_registers()
Commit-ID:  8cda974ab278dd8d4a9024085535f71175ddf38d
Gitweb:     http://git.kernel.org/tip/8cda974ab278dd8d4a9024085535f71175ddf38d
Author:     Yinghai Lu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:39 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Mon, 3 Nov 2014 11:56:07 +0100

x86, irq: Split out alloc_ioapic_save_registers()

Split out alloc_ioapic_save_registers() from early_irq_init(), so it could be used for ioapic hotplug later.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Sebastian Andrzej Siewior <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Grant Likely <[email protected]>
Cc Prarit Bhargava <[email protected]>
---
 arch/x86/kernel/apic/io_apic.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)
arch/x86/kernel/apic/io_apic.c +15 -7
index 1183d54..acaee90 100644
@@ -237,6 +237,19 @@ static struct irq_pin_list *alloc_irq_pin_list(int node)
 	return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node);
 }
 
+static void alloc_ioapic_saved_registers(int idx)
+{
+	size_t size;
+
+	if (ioapics[idx].saved_registers)
+		return;
+
+	size = sizeof(struct IO_APIC_route_entry) * ioapics[idx].nr_registers;
+	ioapics[idx].saved_registers = kzalloc(size, GFP_KERNEL);
+	if (!ioapics[idx].saved_registers)
+		pr_err("IOAPIC %d: suspend/resume impossible!\n", idx);
+}
+
 int __init arch_early_irq_init(void)
 {
 	struct irq_cfg *cfg;
@@ -245,13 +258,8 @@ int __init arch_early_irq_init(void)
 	if (!nr_legacy_irqs())
 		io_apic_irqs = ~0UL;
 
-	for_each_ioapic(i) {
-		ioapics[i].saved_registers =
-			kzalloc(sizeof(struct IO_APIC_route_entry) *
-				ioapics[i].nr_registers, GFP_KERNEL);
-		if (!ioapics[i].saved_registers)
-			pr_err("IOAPIC %d: suspend/resume impossible!\n", i);
-	}
+	for_each_ioapic(i)
+		alloc_ioapic_saved_registers(i);
 
 	/*
 	 * For legacy IRQ's, start with assigning irq0 to irq15 to
#42 lore raw

[tip:x86/apic] x86, irq: Split out alloc_ioapic_save_registers()

In reply to Jiang Liu
x86, irq: Split out alloc_ioapic_save_registers()
Commit-ID:  7e8994196a5196fbe6f344ff9f0616e08d440506
Gitweb:     http://git.kernel.org/tip/7e8994196a5196fbe6f344ff9f0616e08d440506
Author:     Yinghai Lu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:39 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 16 Dec 2014 14:08:15 +0100

x86, irq: Split out alloc_ioapic_save_registers()

Split out alloc_ioapic_save_registers() from early_irq_init(), so it could be used for ioapic hotplug later.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Sebastian Andrzej Siewior <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Grant Likely <[email protected]>
Cc Prarit Bhargava <[email protected]>
---
 arch/x86/kernel/apic/io_apic.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)
arch/x86/kernel/apic/io_apic.c +15 -7
index a157b66..654b69b 100644
@@ -237,6 +237,19 @@ static struct irq_pin_list *alloc_irq_pin_list(int node)
 	return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node);
 }
 
+static void alloc_ioapic_saved_registers(int idx)
+{
+	size_t size;
+
+	if (ioapics[idx].saved_registers)
+		return;
+
+	size = sizeof(struct IO_APIC_route_entry) * ioapics[idx].nr_registers;
+	ioapics[idx].saved_registers = kzalloc(size, GFP_KERNEL);
+	if (!ioapics[idx].saved_registers)
+		pr_err("IOAPIC %d: suspend/resume impossible!\n", idx);
+}
+
 int __init arch_early_irq_init(void)
 {
 	struct irq_cfg *cfg;
@@ -245,13 +258,8 @@ int __init arch_early_irq_init(void)
 	if (!nr_legacy_irqs())
 		io_apic_irqs = ~0UL;
 
-	for_each_ioapic(i) {
-		ioapics[i].saved_registers =
-			kzalloc(sizeof(struct IO_APIC_route_entry) *
-				ioapics[i].nr_registers, GFP_KERNEL);
-		if (!ioapics[i].saved_registers)
-			pr_err("IOAPIC %d: suspend/resume impossible!\n", i);
-	}
+	for_each_ioapic(i)
+		alloc_ioapic_saved_registers(i);
 
 	/*
 	 * For legacy IRQ's, start with assigning irq0 to irq15 to
author
#43 lore raw

PATCH v7 10/18 x86, irq: Prefer assigned ID in APIC ID register for x86_64

In reply to Jiang Liu

From: Yinghai Lu <[email protected]>

Perfer the assigned ID in APIC ID register for x86_64 if it's still available.

Cc Joerg Roedel <[email protected]>
Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Sebastian Andrzej Siewior <[email protected]>
---
 arch/x86/kernel/apic/io_apic.c |   35 ++++++++++++++++++++++++++++++-----
 1 file changed, 30 insertions(+), 5 deletions(-)
arch/x86/kernel/apic/io_apic.c +30 -5
index acaee90fc9cc..eaa7ea385600 100644
@@ -3580,26 +3580,51 @@ static int __init io_apic_get_unique_id(int ioapic, int apic_id)
 	return apic_id;
 }
 
-static u8 __init io_apic_unique_id(u8 id)
+static u8 __init io_apic_unique_id(int idx, u8 id)
 {
 	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
 	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
-		return io_apic_get_unique_id(nr_ioapics, id);
+		return io_apic_get_unique_id(idx, id);
 	else
 		return id;
 }
 #else
-static u8 __init io_apic_unique_id(u8 id)
+static u8 __init io_apic_unique_id(int idx, u8 id)
 {
 	int i;
+	u8 new_id;
+	unsigned long flags;
 	DECLARE_BITMAP(used, 256);
+	union IO_APIC_reg_00 reg_00;
 
 	bitmap_zero(used, 256);
 	for_each_ioapic(i)
 		__set_bit(mpc_ioapic_id(i), used);
 	if (!test_bit(id, used))
 		return id;
-	return find_first_zero_bit(used, 256);
+
+	/* check register at first */
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
+	reg_00.raw = io_apic_read(idx, 0);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+	new_id = reg_00.bits.ID;
+	if (!test_bit(new_id, used)) {
+		apic_printk(APIC_VERBOSE, KERN_INFO
+			"IOAPIC[%d]: Using reg apic_id %d instead of %d\n",
+			 idx, new_id, id);
+		return new_id;
+	}
+
+	new_id = find_first_zero_bit(used, 256);
+	reg_00.bits.ID = new_id;
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
+	io_apic_write(idx, 0, reg_00.raw);
+	reg_00.raw = io_apic_read(idx, 0);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+	/* Sanity check */
+	BUG_ON(reg_00.bits.ID != new_id);
+
+	return new_id;
 }
 #endif
 
@@ -3865,7 +3890,7 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
 		return;
 	}
 
-	ioapics[idx].mp_config.apicid = io_apic_unique_id(id);
+	ioapics[idx].mp_config.apicid = io_apic_unique_id(idx, id);
 	ioapics[idx].mp_config.apicver = io_apic_get_version(idx);
 
 	/*
Signature · 1 line
1.7.10.4
#44 lore raw

[tip:x86/apic] x86, irq: Prefer assigned ID in APIC ID register for x86_64

x86, irq: Prefer assigned ID in APIC ID register for x86_64
Commit-ID:  b141cb5363583a887ab2d6f742bc849f615634ff
Gitweb:     http://git.kernel.org/tip/b141cb5363583a887ab2d6f742bc849f615634ff
Author:     Yinghai Lu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:40 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Mon, 3 Nov 2014 11:56:07 +0100

x86, irq: Prefer assigned ID in APIC ID register for x86_64

Perfer the assigned ID in APIC ID register for x86_64 if it's still available.

[ tglx: Added comments ]

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Sebastian Andrzej Siewior <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Grant Likely <[email protected]>
Cc Prarit Bhargava <[email protected]>
---
 arch/x86/kernel/apic/io_apic.c | 45 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 39 insertions(+), 6 deletions(-)
arch/x86/kernel/apic/io_apic.c +39 -6
index acaee90..02212fb 100644
@@ -3580,26 +3580,59 @@ static int __init io_apic_get_unique_id(int ioapic, int apic_id)
 	return apic_id;
 }
 
-static u8 __init io_apic_unique_id(u8 id)
+static u8 __init io_apic_unique_id(int idx, u8 id)
 {
 	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
 	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
-		return io_apic_get_unique_id(nr_ioapics, id);
+		return io_apic_get_unique_id(idx, id);
 	else
 		return id;
 }
 #else
-static u8 __init io_apic_unique_id(u8 id)
+static u8 __init io_apic_unique_id(int idx, u8 id)
 {
-	int i;
+	union IO_APIC_reg_00 reg_00;
 	DECLARE_BITMAP(used, 256);
+	unsigned long flags;
+	u8 new_id;
+	int i;
 
 	bitmap_zero(used, 256);
 	for_each_ioapic(i)
 		__set_bit(mpc_ioapic_id(i), used);
+
+	/* Hand out the requested id if available */
 	if (!test_bit(id, used))
 		return id;
-	return find_first_zero_bit(used, 256);
+
+	/*
+	 * Read the current id from the ioapic and keep it if
+	 * available.
+	 */
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
+	reg_00.raw = io_apic_read(idx, 0);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+	new_id = reg_00.bits.ID;
+	if (!test_bit(new_id, used)) {
+		apic_printk(APIC_VERBOSE, KERN_INFO
+			"IOAPIC[%d]: Using reg apic_id %d instead of %d\n",
+			 idx, new_id, id);
+		return new_id;
+	}
+
+	/*
+	 * Get the next free id and write it to the ioapic.
+	 */
+	new_id = find_first_zero_bit(used, 256);
+	reg_00.bits.ID = new_id;
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
+	io_apic_write(idx, 0, reg_00.raw);
+	reg_00.raw = io_apic_read(idx, 0);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+	/* Sanity check */
+	BUG_ON(reg_00.bits.ID != new_id);
+
+	return new_id;
 }
 #endif
 
@@ -3865,7 +3898,7 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
 		return;
 	}
 
-	ioapics[idx].mp_config.apicid = io_apic_unique_id(id);
+	ioapics[idx].mp_config.apicid = io_apic_unique_id(idx, id);
 	ioapics[idx].mp_config.apicver = io_apic_get_version(idx);
 
 	/*
#45 lore raw

[tip:x86/apic] x86, irq: Prefer assigned ID in APIC ID register for x86_64

In reply to Jiang Liu
x86, irq: Prefer assigned ID in APIC ID register for x86_64
Commit-ID:  5411dc4ccb25de133701774dd2a3cf3f7e246f17
Gitweb:     http://git.kernel.org/tip/5411dc4ccb25de133701774dd2a3cf3f7e246f17
Author:     Yinghai Lu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:40 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 16 Dec 2014 14:08:15 +0100

x86, irq: Prefer assigned ID in APIC ID register for x86_64

Perfer the assigned ID in APIC ID register for x86_64 if it's still available.

[ tglx: Added comments ]

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Sebastian Andrzej Siewior <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Grant Likely <[email protected]>
Cc Prarit Bhargava <[email protected]>
---
 arch/x86/kernel/apic/io_apic.c | 45 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 39 insertions(+), 6 deletions(-)
arch/x86/kernel/apic/io_apic.c +39 -6
index 654b69b..86fd286 100644
@@ -3580,26 +3580,59 @@ static int __init io_apic_get_unique_id(int ioapic, int apic_id)
 	return apic_id;
 }
 
-static u8 __init io_apic_unique_id(u8 id)
+static u8 __init io_apic_unique_id(int idx, u8 id)
 {
 	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
 	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
-		return io_apic_get_unique_id(nr_ioapics, id);
+		return io_apic_get_unique_id(idx, id);
 	else
 		return id;
 }
 #else
-static u8 __init io_apic_unique_id(u8 id)
+static u8 __init io_apic_unique_id(int idx, u8 id)
 {
-	int i;
+	union IO_APIC_reg_00 reg_00;
 	DECLARE_BITMAP(used, 256);
+	unsigned long flags;
+	u8 new_id;
+	int i;
 
 	bitmap_zero(used, 256);
 	for_each_ioapic(i)
 		__set_bit(mpc_ioapic_id(i), used);
+
+	/* Hand out the requested id if available */
 	if (!test_bit(id, used))
 		return id;
-	return find_first_zero_bit(used, 256);
+
+	/*
+	 * Read the current id from the ioapic and keep it if
+	 * available.
+	 */
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
+	reg_00.raw = io_apic_read(idx, 0);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+	new_id = reg_00.bits.ID;
+	if (!test_bit(new_id, used)) {
+		apic_printk(APIC_VERBOSE, KERN_INFO
+			"IOAPIC[%d]: Using reg apic_id %d instead of %d\n",
+			 idx, new_id, id);
+		return new_id;
+	}
+
+	/*
+	 * Get the next free id and write it to the ioapic.
+	 */
+	new_id = find_first_zero_bit(used, 256);
+	reg_00.bits.ID = new_id;
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
+	io_apic_write(idx, 0, reg_00.raw);
+	reg_00.raw = io_apic_read(idx, 0);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+	/* Sanity check */
+	BUG_ON(reg_00.bits.ID != new_id);
+
+	return new_id;
 }
 #endif
 
@@ -3865,7 +3898,7 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
 		return;
 	}
 
-	ioapics[idx].mp_config.apicid = io_apic_unique_id(id);
+	ioapics[idx].mp_config.apicid = io_apic_unique_id(idx, id);
 	ioapics[idx].mp_config.apicver = io_apic_get_version(idx);
 
 	/*
author
#46 lore raw

PATCH v7 11/18 x86, irq: Remove __init marker for functions will be used by IOAPIC hotplug

In reply to Jiang Liu

Remove __init marker for functions which will be used by IOAPIC hotplug at runtime.

---
 arch/x86/include/asm/io_apic.h |    4 ++--
 arch/x86/kernel/apic/io_apic.c |   18 +++++++++---------
 2 files changed, 11 insertions(+), 11 deletions(-)
arch/x86/include/asm/io_apic.h +2 -2
index 1733ab49ac5e..a666dcdeea67 100644
@@ -188,8 +188,8 @@ extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
 extern u32 mp_pin_to_gsi(int ioapic, int pin);
 extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
 extern void mp_unmap_irq(int irq);
-extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
-				      struct ioapic_domain_cfg *cfg);
+extern void mp_register_ioapic(int id, u32 address, u32 gsi_base,
+			       struct ioapic_domain_cfg *cfg);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
arch/x86/kernel/apic/io_apic.c +9 -9
index eaa7ea385600..581e51728871 100644
@@ -3459,7 +3459,7 @@ io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
 	return ret;
 }
 
-static int __init io_apic_get_redir_entries(int ioapic)
+static int io_apic_get_redir_entries(int ioapic)
 {
 	union IO_APIC_reg_01	reg_01;
 	unsigned long flags;
@@ -3505,7 +3505,7 @@ int __init arch_probe_nr_irqs(void)
 }
 
 #ifdef CONFIG_X86_32
-static int __init io_apic_get_unique_id(int ioapic, int apic_id)
+static int io_apic_get_unique_id(int ioapic, int apic_id)
 {
 	union IO_APIC_reg_00 reg_00;
 	static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
@@ -3580,7 +3580,7 @@ static int __init io_apic_get_unique_id(int ioapic, int apic_id)
 	return apic_id;
 }
 
-static u8 __init io_apic_unique_id(int idx, u8 id)
+static u8 io_apic_unique_id(int idx, u8 id)
 {
 	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
 	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
@@ -3589,7 +3589,7 @@ static u8 __init io_apic_unique_id(int idx, u8 id)
 		return id;
 }
 #else
-static u8 __init io_apic_unique_id(int idx, u8 id)
+static u8 io_apic_unique_id(int idx, u8 id)
 {
 	int i;
 	u8 new_id;
@@ -3628,7 +3628,7 @@ static u8 __init io_apic_unique_id(int idx, u8 id)
 }
 #endif
 
-static int __init io_apic_get_version(int ioapic)
+static int io_apic_get_version(int ioapic)
 {
 	union IO_APIC_reg_01	reg_01;
 	unsigned long flags;
@@ -3832,7 +3832,7 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi)
 	return gsi - gsi_cfg->gsi_base;
 }
 
-static __init int bad_ioapic(unsigned long address)
+static int bad_ioapic(unsigned long address)
 {
 	if (nr_ioapics >= MAX_IO_APICS) {
 		pr_warn("WARNING: Max # of I/O APICs (%d) exceeded (found %d), skipping\n",
@@ -3846,7 +3846,7 @@ static __init int bad_ioapic(unsigned long address)
 	return 0;
 }
 
-static __init int bad_ioapic_register(int idx)
+static int bad_ioapic_register(int idx)
 {
 	union IO_APIC_reg_00 reg_00;
 	union IO_APIC_reg_01 reg_01;
@@ -3865,8 +3865,8 @@ static __init int bad_ioapic_register(int idx)
 	return 0;
 }
 
-void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
-			       struct ioapic_domain_cfg *cfg)
+void mp_register_ioapic(int id, u32 address, u32 gsi_base,
+			struct ioapic_domain_cfg *cfg)
 {
 	int idx = 0;
 	int entries;
Signature · 1 line
1.7.10.4
#47 lore raw

[tip:x86/apic] x86, irq: Remove __init marker for functions will be used by IOAPIC hotplug

x86, irq: Remove __init marker for functions will be used by IOAPIC hotplug
Commit-ID:  9999a6756f064a1b11b5e2dfdbc2dc06b790bcb6
Gitweb:     http://git.kernel.org/tip/9999a6756f064a1b11b5e2dfdbc2dc06b790bcb6
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:41 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Mon, 3 Nov 2014 11:56:08 +0100

x86, irq: Remove __init marker for functions will be used by IOAPIC hotplug

Remove __init marker for functions which will be used by IOAPIC hotplug at runtime.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Grant Likely <[email protected]>
Cc Prarit Bhargava <[email protected]>
---
 arch/x86/include/asm/io_apic.h |  4 ++--
 arch/x86/kernel/apic/io_apic.c | 18 +++++++++---------
 2 files changed, 11 insertions(+), 11 deletions(-)
arch/x86/include/asm/io_apic.h +2 -2
index 1733ab4..a666dcd 100644
@@ -188,8 +188,8 @@ extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
 extern u32 mp_pin_to_gsi(int ioapic, int pin);
 extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
 extern void mp_unmap_irq(int irq);
-extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
-				      struct ioapic_domain_cfg *cfg);
+extern void mp_register_ioapic(int id, u32 address, u32 gsi_base,
+			       struct ioapic_domain_cfg *cfg);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
arch/x86/kernel/apic/io_apic.c +9 -9
index 02212fb..19501ab 100644
@@ -3459,7 +3459,7 @@ io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
 	return ret;
 }
 
-static int __init io_apic_get_redir_entries(int ioapic)
+static int io_apic_get_redir_entries(int ioapic)
 {
 	union IO_APIC_reg_01	reg_01;
 	unsigned long flags;
@@ -3505,7 +3505,7 @@ int __init arch_probe_nr_irqs(void)
 }
 
 #ifdef CONFIG_X86_32
-static int __init io_apic_get_unique_id(int ioapic, int apic_id)
+static int io_apic_get_unique_id(int ioapic, int apic_id)
 {
 	union IO_APIC_reg_00 reg_00;
 	static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
@@ -3580,7 +3580,7 @@ static int __init io_apic_get_unique_id(int ioapic, int apic_id)
 	return apic_id;
 }
 
-static u8 __init io_apic_unique_id(int idx, u8 id)
+static u8 io_apic_unique_id(int idx, u8 id)
 {
 	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
 	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
@@ -3589,7 +3589,7 @@ static u8 __init io_apic_unique_id(int idx, u8 id)
 		return id;
 }
 #else
-static u8 __init io_apic_unique_id(int idx, u8 id)
+static u8 io_apic_unique_id(int idx, u8 id)
 {
 	union IO_APIC_reg_00 reg_00;
 	DECLARE_BITMAP(used, 256);
@@ -3636,7 +3636,7 @@ static u8 __init io_apic_unique_id(int idx, u8 id)
 }
 #endif
 
-static int __init io_apic_get_version(int ioapic)
+static int io_apic_get_version(int ioapic)
 {
 	union IO_APIC_reg_01	reg_01;
 	unsigned long flags;
@@ -3840,7 +3840,7 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi)
 	return gsi - gsi_cfg->gsi_base;
 }
 
-static __init int bad_ioapic(unsigned long address)
+static int bad_ioapic(unsigned long address)
 {
 	if (nr_ioapics >= MAX_IO_APICS) {
 		pr_warn("WARNING: Max # of I/O APICs (%d) exceeded (found %d), skipping\n",
@@ -3854,7 +3854,7 @@ static __init int bad_ioapic(unsigned long address)
 	return 0;
 }
 
-static __init int bad_ioapic_register(int idx)
+static int bad_ioapic_register(int idx)
 {
 	union IO_APIC_reg_00 reg_00;
 	union IO_APIC_reg_01 reg_01;
@@ -3873,8 +3873,8 @@ static __init int bad_ioapic_register(int idx)
 	return 0;
 }
 
-void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
-			       struct ioapic_domain_cfg *cfg)
+void mp_register_ioapic(int id, u32 address, u32 gsi_base,
+			struct ioapic_domain_cfg *cfg)
 {
 	int idx = 0;
 	int entries;
#48 lore raw

[tip:x86/apic] x86, irq: Remove __init marker for functions will be used by IOAPIC hotplug

In reply to Jiang Liu
x86, irq: Remove __init marker for functions will be used by IOAPIC hotplug
Commit-ID:  67dc5e701fda884d49ed5c1904986bd5333610f4
Gitweb:     http://git.kernel.org/tip/67dc5e701fda884d49ed5c1904986bd5333610f4
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:41 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 16 Dec 2014 14:08:15 +0100

x86, irq: Remove __init marker for functions will be used by IOAPIC hotplug

Remove __init marker for functions which will be used by IOAPIC hotplug at runtime.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Grant Likely <[email protected]>
Cc Prarit Bhargava <[email protected]>
---
 arch/x86/include/asm/io_apic.h |  4 ++--
 arch/x86/kernel/apic/io_apic.c | 18 +++++++++---------
 2 files changed, 11 insertions(+), 11 deletions(-)
arch/x86/include/asm/io_apic.h +2 -2
index 0aeed5c..0b31aeb 100644
@@ -188,8 +188,8 @@ extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
 extern u32 mp_pin_to_gsi(int ioapic, int pin);
 extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
 extern void mp_unmap_irq(int irq);
-extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
-				      struct ioapic_domain_cfg *cfg);
+extern void mp_register_ioapic(int id, u32 address, u32 gsi_base,
+			       struct ioapic_domain_cfg *cfg);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
arch/x86/kernel/apic/io_apic.c +9 -9
index 86fd286..60f25e88 100644
@@ -3459,7 +3459,7 @@ io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
 	return ret;
 }
 
-static int __init io_apic_get_redir_entries(int ioapic)
+static int io_apic_get_redir_entries(int ioapic)
 {
 	union IO_APIC_reg_01	reg_01;
 	unsigned long flags;
@@ -3505,7 +3505,7 @@ int __init arch_probe_nr_irqs(void)
 }
 
 #ifdef CONFIG_X86_32
-static int __init io_apic_get_unique_id(int ioapic, int apic_id)
+static int io_apic_get_unique_id(int ioapic, int apic_id)
 {
 	union IO_APIC_reg_00 reg_00;
 	static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
@@ -3580,7 +3580,7 @@ static int __init io_apic_get_unique_id(int ioapic, int apic_id)
 	return apic_id;
 }
 
-static u8 __init io_apic_unique_id(int idx, u8 id)
+static u8 io_apic_unique_id(int idx, u8 id)
 {
 	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
 	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
@@ -3589,7 +3589,7 @@ static u8 __init io_apic_unique_id(int idx, u8 id)
 		return id;
 }
 #else
-static u8 __init io_apic_unique_id(int idx, u8 id)
+static u8 io_apic_unique_id(int idx, u8 id)
 {
 	union IO_APIC_reg_00 reg_00;
 	DECLARE_BITMAP(used, 256);
@@ -3636,7 +3636,7 @@ static u8 __init io_apic_unique_id(int idx, u8 id)
 }
 #endif
 
-static int __init io_apic_get_version(int ioapic)
+static int io_apic_get_version(int ioapic)
 {
 	union IO_APIC_reg_01	reg_01;
 	unsigned long flags;
@@ -3840,7 +3840,7 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi)
 	return gsi - gsi_cfg->gsi_base;
 }
 
-static __init int bad_ioapic(unsigned long address)
+static int bad_ioapic(unsigned long address)
 {
 	if (nr_ioapics >= MAX_IO_APICS) {
 		pr_warn("WARNING: Max # of I/O APICs (%d) exceeded (found %d), skipping\n",
@@ -3854,7 +3854,7 @@ static __init int bad_ioapic(unsigned long address)
 	return 0;
 }
 
-static __init int bad_ioapic_register(int idx)
+static int bad_ioapic_register(int idx)
 {
 	union IO_APIC_reg_00 reg_00;
 	union IO_APIC_reg_01 reg_01;
@@ -3873,8 +3873,8 @@ static __init int bad_ioapic_register(int idx)
 	return 0;
 }
 
-void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
-			       struct ioapic_domain_cfg *cfg)
+void mp_register_ioapic(int id, u32 address, u32 gsi_base,
+			struct ioapic_domain_cfg *cfg)
 {
 	int idx = 0;
 	int entries;
author
#49 lore raw

PATCH v7 12/18 x86, irq: Keep balance of IOAPIC pin reference count

In reply to Jiang Liu

To keep balance of IOAPIC pin reference count, we need to protect pirq_enable_irq(), acpi_pci_irq_enable() and intel_mid_pci_irq_enable() from reentrance. There are two cases which will cause reentrance.

The first case is caused by suspend/hibernation. If pcibios_disable_irq is called during suspending/hibernating, we don't release the assigned IRQ number, otherwise it may break the suspend/hibernation. So late when pcibios_enable_irq is called during resume, we shouldn't allocate IRQ number again.

The second case is that function acpi_pci_irq_enable() may be called twice for PCI devices present at boot time as below:
1) pci_acpi_init()

	--> acpi_pci_irq_enable() if pci_routeirq is true
2) pci_enable_device()
	--> pcibios_enable_device()
		--> acpi_pci_irq_enable()

We can't kill kernel parameter pci_routeirq yet because it's still needed for debugging purpose.

So flag irq_managed is introduced to track whether IRQ number is assigned by OS and to protect pirq_enable_irq(), acpi_pci_irq_enable() and intel_mid_pci_irq_enable() from reentrance.

---
 arch/x86/pci/intel_mid_pci.c |   10 +++++++++-
 arch/x86/pci/irq.c           |    7 ++++++-
 drivers/acpi/pci_irq.c       |   11 +++++++++--
 include/linux/pci.h          |    1 +
 4 files changed, 25 insertions(+), 4 deletions(-)
arch/x86/pci/intel_mid_pci.c +9 -1
index b9958c364075..44b9271580b5 100644
@@ -210,6 +210,9 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 {
 	int polarity;
 
+	if (dev->irq_managed && dev->irq > 0)
+		return 0;
+
 	if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
 		polarity = 0; /* active high */
 	else
@@ -224,13 +227,18 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 	if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC) < 0)
 		return -EBUSY;
 
+	dev->irq_managed = 1;
+
 	return 0;
 }
 
 static void intel_mid_pci_irq_disable(struct pci_dev *dev)
 {
-	if (!mp_should_keep_irq(&dev->dev) && dev->irq > 0)
+	if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed &&
+	    dev->irq > 0) {
 		mp_unmap_irq(dev->irq);
+		dev->irq_managed = 0;
+	}
 }
 
 struct pci_ops intel_mid_pci_ops = {
arch/x86/pci/irq.c +6 -1
index eb500c2592ad..a47e2dea0972 100644
@@ -1202,6 +1202,9 @@ static int pirq_enable_irq(struct pci_dev *dev)
 			int irq;
 			struct io_apic_irq_attr irq_attr;
 
+			if (dev->irq_managed && dev->irq > 0)
+				return 0;
+
 			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
 						PCI_SLOT(dev->devfn),
 						pin - 1, &irq_attr);
@@ -1228,6 +1231,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
 			}
 			dev = temp_dev;
 			if (irq >= 0) {
+				dev->irq_managed = 1;
 				dev->irq = irq;
 				dev_info(&dev->dev, "PCI->APIC IRQ transform: "
 					 "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
@@ -1257,8 +1261,9 @@ static int pirq_enable_irq(struct pci_dev *dev)
 static void pirq_disable_irq(struct pci_dev *dev)
 {
 	if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
-	    dev->irq) {
+	    dev->irq_managed && dev->irq) {
 		mp_unmap_irq(dev->irq);
 		dev->irq = 0;
+		dev->irq_managed = 0;
 	}
 }
drivers/acpi/pci_irq.c +9 -2
index 6e6b80eb0bba..5f1fdca65e5f 100644
@@ -413,6 +413,9 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 		return 0;
 	}
 
+	if (dev->irq_managed && dev->irq > 0)
+		return 0;
+
 	entry = acpi_pci_irq_lookup(dev, pin);
 	if (!entry) {
 		/*
@@ -456,6 +459,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 		return rc;
 	}
 	dev->irq = rc;
+	dev->irq_managed = 1;
 
 	if (link)
 		snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link);
@@ -478,7 +482,7 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
 	u8 pin;
 
 	pin = dev->pin;
-	if (!pin)
+	if (!pin || !dev->irq_managed || dev->irq <= 0)
 		return;
 
 	/* Keep IOAPIC pin configuration when suspending */
@@ -506,6 +510,9 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
 	 */
 
 	dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
-	if (gsi >= 0 && dev->irq > 0)
+	if (gsi >= 0) {
 		acpi_unregister_gsi(gsi);
+		dev->irq = 0;
+		dev->irq_managed = 0;
+	}
 }
include/linux/pci.h +1 -0
index 5be8db45e368..2a8c4055ae9d 100644
@@ -348,6 +348,7 @@ struct pci_dev {
 	unsigned int	__aer_firmware_first:1;
 	unsigned int	broken_intx_masking:1;
 	unsigned int	io_window_1k:1;	/* Intel P2P bridge 1K I/O windows */
+	unsigned int	irq_managed:1;
 	pci_dev_flags_t dev_flags;
 	atomic_t	enable_cnt;	/* pci_enable_device has been called */
 
Signature · 1 line
1.7.10.4
#50 lore raw

[tip:x86/apic] x86, irq: Keep balance of IOAPIC pin reference count

x86, irq: Keep balance of IOAPIC pin reference count
Commit-ID:  5dfaa804e3e25317b4e55cd67117ac5b33e01004
Gitweb:     http://git.kernel.org/tip/5dfaa804e3e25317b4e55cd67117ac5b33e01004
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:42 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Mon, 3 Nov 2014 11:56:08 +0100

x86, irq: Keep balance of IOAPIC pin reference count

To keep balance of IOAPIC pin reference count, we need to protect pirq_enable_irq(), acpi_pci_irq_enable() and intel_mid_pci_irq_enable() from reentrance. There are two cases which will cause reentrance.

The first case is caused by suspend/hibernation. If pcibios_disable_irq is called during suspending/hibernating, we don't release the assigned IRQ number, otherwise it may break the suspend/hibernation. So late when pcibios_enable_irq is called during resume, we shouldn't allocate IRQ number again.

The second case is that function acpi_pci_irq_enable() may be called twice for PCI devices present at boot time as below:
1) pci_acpi_init()

	--> acpi_pci_irq_enable() if pci_routeirq is true
2) pci_enable_device()
	--> pcibios_enable_device()
		--> acpi_pci_irq_enable()

We can't kill kernel parameter pci_routeirq yet because it's still needed for debugging purpose.

So flag irq_managed is introduced to track whether IRQ number is assigned by OS and to protect pirq_enable_irq(), acpi_pci_irq_enable() and intel_mid_pci_irq_enable() from reentrance.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
---
 arch/x86/pci/intel_mid_pci.c | 10 +++++++++-
 arch/x86/pci/irq.c           |  7 ++++++-
 drivers/acpi/pci_irq.c       | 11 +++++++++--
 include/linux/pci.h          |  1 +
 4 files changed, 25 insertions(+), 4 deletions(-)
arch/x86/pci/intel_mid_pci.c +9 -1
index b9958c3..44b9271 100644
@@ -210,6 +210,9 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 {
 	int polarity;
 
+	if (dev->irq_managed && dev->irq > 0)
+		return 0;
+
 	if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
 		polarity = 0; /* active high */
 	else
@@ -224,13 +227,18 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 	if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC) < 0)
 		return -EBUSY;
 
+	dev->irq_managed = 1;
+
 	return 0;
 }
 
 static void intel_mid_pci_irq_disable(struct pci_dev *dev)
 {
-	if (!mp_should_keep_irq(&dev->dev) && dev->irq > 0)
+	if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed &&
+	    dev->irq > 0) {
 		mp_unmap_irq(dev->irq);
+		dev->irq_managed = 0;
+	}
 }
 
 struct pci_ops intel_mid_pci_ops = {
arch/x86/pci/irq.c +6 -1
index eb500c2..a47e2de 100644
@@ -1202,6 +1202,9 @@ static int pirq_enable_irq(struct pci_dev *dev)
 			int irq;
 			struct io_apic_irq_attr irq_attr;
 
+			if (dev->irq_managed && dev->irq > 0)
+				return 0;
+
 			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
 						PCI_SLOT(dev->devfn),
 						pin - 1, &irq_attr);
@@ -1228,6 +1231,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
 			}
 			dev = temp_dev;
 			if (irq >= 0) {
+				dev->irq_managed = 1;
 				dev->irq = irq;
 				dev_info(&dev->dev, "PCI->APIC IRQ transform: "
 					 "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
@@ -1257,8 +1261,9 @@ static int pirq_enable_irq(struct pci_dev *dev)
 static void pirq_disable_irq(struct pci_dev *dev)
 {
 	if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
-	    dev->irq) {
+	    dev->irq_managed && dev->irq) {
 		mp_unmap_irq(dev->irq);
 		dev->irq = 0;
+		dev->irq_managed = 0;
 	}
 }
drivers/acpi/pci_irq.c +9 -2
index 6e6b80e..5f1fdca 100644
@@ -413,6 +413,9 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 		return 0;
 	}
 
+	if (dev->irq_managed && dev->irq > 0)
+		return 0;
+
 	entry = acpi_pci_irq_lookup(dev, pin);
 	if (!entry) {
 		/*
@@ -456,6 +459,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 		return rc;
 	}
 	dev->irq = rc;
+	dev->irq_managed = 1;
 
 	if (link)
 		snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link);
@@ -478,7 +482,7 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
 	u8 pin;
 
 	pin = dev->pin;
-	if (!pin)
+	if (!pin || !dev->irq_managed || dev->irq <= 0)
 		return;
 
 	/* Keep IOAPIC pin configuration when suspending */
@@ -506,6 +510,9 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
 	 */
 
 	dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
-	if (gsi >= 0 && dev->irq > 0)
+	if (gsi >= 0) {
 		acpi_unregister_gsi(gsi);
+		dev->irq = 0;
+		dev->irq_managed = 0;
+	}
 }
include/linux/pci.h +1 -0
index 5be8db4..2a8c405 100644
@@ -348,6 +348,7 @@ struct pci_dev {
 	unsigned int	__aer_firmware_first:1;
 	unsigned int	broken_intx_masking:1;
 	unsigned int	io_window_1k:1;	/* Intel P2P bridge 1K I/O windows */
+	unsigned int	irq_managed:1;
 	pci_dev_flags_t dev_flags;
 	atomic_t	enable_cnt;	/* pci_enable_device has been called */
 
#51 lore raw

[tip:x86/apic] x86, irq: Keep balance of IOAPIC pin reference count

In reply to Jiang Liu
x86, irq: Keep balance of IOAPIC pin reference count
Commit-ID:  cffe0a2b5a34c95a4dadc9ec7132690a5b0f6687
Gitweb:     http://git.kernel.org/tip/cffe0a2b5a34c95a4dadc9ec7132690a5b0f6687
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:42 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 16 Dec 2014 14:08:15 +0100

x86, irq: Keep balance of IOAPIC pin reference count

To keep balance of IOAPIC pin reference count, we need to protect pirq_enable_irq(), acpi_pci_irq_enable() and intel_mid_pci_irq_enable() from reentrance. There are two cases which will cause reentrance.

The first case is caused by suspend/hibernation. If pcibios_disable_irq is called during suspending/hibernating, we don't release the assigned IRQ number, otherwise it may break the suspend/hibernation. So late when pcibios_enable_irq is called during resume, we shouldn't allocate IRQ number again.

The second case is that function acpi_pci_irq_enable() may be called twice for PCI devices present at boot time as below:
1) pci_acpi_init()

	--> acpi_pci_irq_enable() if pci_routeirq is true
2) pci_enable_device()
	--> pcibios_enable_device()
		--> acpi_pci_irq_enable()

We can't kill kernel parameter pci_routeirq yet because it's still needed for debugging purpose.

So flag irq_managed is introduced to track whether IRQ number is assigned by OS and to protect pirq_enable_irq(), acpi_pci_irq_enable() and intel_mid_pci_irq_enable() from reentrance.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
---
 arch/x86/pci/intel_mid_pci.c | 10 +++++++++-
 arch/x86/pci/irq.c           |  7 ++++++-
 drivers/acpi/pci_irq.c       | 11 +++++++++--
 include/linux/pci.h          |  1 +
 4 files changed, 25 insertions(+), 4 deletions(-)
arch/x86/pci/intel_mid_pci.c +9 -1
index b9958c3..44b9271 100644
@@ -210,6 +210,9 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 {
 	int polarity;
 
+	if (dev->irq_managed && dev->irq > 0)
+		return 0;
+
 	if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
 		polarity = 0; /* active high */
 	else
@@ -224,13 +227,18 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 	if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC) < 0)
 		return -EBUSY;
 
+	dev->irq_managed = 1;
+
 	return 0;
 }
 
 static void intel_mid_pci_irq_disable(struct pci_dev *dev)
 {
-	if (!mp_should_keep_irq(&dev->dev) && dev->irq > 0)
+	if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed &&
+	    dev->irq > 0) {
 		mp_unmap_irq(dev->irq);
+		dev->irq_managed = 0;
+	}
 }
 
 struct pci_ops intel_mid_pci_ops = {
arch/x86/pci/irq.c +6 -1
index cb50e28..9988458 100644
@@ -1202,6 +1202,9 @@ static int pirq_enable_irq(struct pci_dev *dev)
 			int irq;
 			struct io_apic_irq_attr irq_attr;
 
+			if (dev->irq_managed && dev->irq > 0)
+				return 0;
+
 			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
 						PCI_SLOT(dev->devfn),
 						pin - 1, &irq_attr);
@@ -1228,6 +1231,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
 			}
 			dev = temp_dev;
 			if (irq >= 0) {
+				dev->irq_managed = 1;
 				dev->irq = irq;
 				dev_info(&dev->dev, "PCI->APIC IRQ transform: "
 					 "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
@@ -1269,8 +1273,9 @@ bool mp_should_keep_irq(struct device *dev)
 static void pirq_disable_irq(struct pci_dev *dev)
 {
 	if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
-	    dev->irq) {
+	    dev->irq_managed && dev->irq) {
 		mp_unmap_irq(dev->irq);
 		dev->irq = 0;
+		dev->irq_managed = 0;
 	}
 }
drivers/acpi/pci_irq.c +9 -2
index 6e6b80e..5f1fdca 100644
@@ -413,6 +413,9 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 		return 0;
 	}
 
+	if (dev->irq_managed && dev->irq > 0)
+		return 0;
+
 	entry = acpi_pci_irq_lookup(dev, pin);
 	if (!entry) {
 		/*
@@ -456,6 +459,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 		return rc;
 	}
 	dev->irq = rc;
+	dev->irq_managed = 1;
 
 	if (link)
 		snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link);
@@ -478,7 +482,7 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
 	u8 pin;
 
 	pin = dev->pin;
-	if (!pin)
+	if (!pin || !dev->irq_managed || dev->irq <= 0)
 		return;
 
 	/* Keep IOAPIC pin configuration when suspending */
@@ -506,6 +510,9 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
 	 */
 
 	dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
-	if (gsi >= 0 && dev->irq > 0)
+	if (gsi >= 0) {
 		acpi_unregister_gsi(gsi);
+		dev->irq = 0;
+		dev->irq_managed = 0;
+	}
 }
include/linux/pci.h +1 -0
index a523cee..c888c5e 100644
@@ -349,6 +349,7 @@ struct pci_dev {
 	unsigned int	__aer_firmware_first:1;
 	unsigned int	broken_intx_masking:1;
 	unsigned int	io_window_1k:1;	/* Intel P2P bridge 1K I/O windows */
+	unsigned int	irq_managed:1;
 	pci_dev_flags_t dev_flags;
 	atomic_t	enable_cnt;	/* pci_enable_device has been called */
 
author
#52 lore raw

PATCH v7 13/18 x86, irq: Refine mp_register_ioapic() to prepare for IOAPIC hotplug

In reply to Jiang Liu

Refine mp_register_ioapic() to prepare for IOAPIC hotplug by:
1) change return value from void to int.
2) check for gsi range conflicts
3) check for IOAPIC physical address conflicts
4) enhance the way to allocate IOAPIC index

---
 arch/x86/include/asm/io_apic.h |    4 +-
 arch/x86/kernel/apic/io_apic.c |   87 ++++++++++++++++++++++++++--------------
 2 files changed, 58 insertions(+), 33 deletions(-)
arch/x86/include/asm/io_apic.h +2 -2
index a666dcdeea67..8741c1ea33c3 100644
@@ -188,8 +188,8 @@ extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
 extern u32 mp_pin_to_gsi(int ioapic, int pin);
 extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
 extern void mp_unmap_irq(int irq);
-extern void mp_register_ioapic(int id, u32 address, u32 gsi_base,
-			       struct ioapic_domain_cfg *cfg);
+extern int mp_register_ioapic(int id, u32 address, u32 gsi_base,
+			      struct ioapic_domain_cfg *cfg);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
arch/x86/kernel/apic/io_apic.c +56 -31

129 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#53 lore raw

[tip:x86/apic] x86, irq: Refine mp_register_ioapic() to prepare for IOAPIC hotplug

x86, irq: Refine mp_register_ioapic() to prepare for IOAPIC hotplug
Commit-ID:  36f3a2a6cec30b332035ccad32d749b2216a2168
Gitweb:     http://git.kernel.org/tip/36f3a2a6cec30b332035ccad32d749b2216a2168
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:43 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Mon, 3 Nov 2014 11:56:08 +0100

x86, irq: Refine mp_register_ioapic() to prepare for IOAPIC hotplug

Refine mp_register_ioapic() to prepare for IOAPIC hotplug by:
1) change return value from void to int.
2) check for gsi range conflicts
3) check for IOAPIC physical address conflicts
4) enhance the way to allocate IOAPIC index

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Grant Likely <[email protected]>
Cc Prarit Bhargava <[email protected]>
---
 arch/x86/include/asm/io_apic.h |  4 +-
 arch/x86/kernel/apic/io_apic.c | 87 +++++++++++++++++++++++++++---------------
 2 files changed, 58 insertions(+), 33 deletions(-)
arch/x86/include/asm/io_apic.h +2 -2
index a666dcd..8741c1e 100644
@@ -188,8 +188,8 @@ extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
 extern u32 mp_pin_to_gsi(int ioapic, int pin);
 extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
 extern void mp_unmap_irq(int irq);
-extern void mp_register_ioapic(int id, u32 address, u32 gsi_base,
-			       struct ioapic_domain_cfg *cfg);
+extern int mp_register_ioapic(int id, u32 address, u32 gsi_base,
+			      struct ioapic_domain_cfg *cfg);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
arch/x86/kernel/apic/io_apic.c +56 -31

129 lines not on this page · raw message

#54 lore raw

[tip:x86/apic] x86, irq: Refine mp_register_ioapic() to prepare for IOAPIC hotplug

In reply to Jiang Liu
x86, irq: Refine mp_register_ioapic() to prepare for IOAPIC hotplug
Commit-ID:  35ef9c941c93f72bb49fe01396fc963ab80105bd
Gitweb:     http://git.kernel.org/tip/35ef9c941c93f72bb49fe01396fc963ab80105bd
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:43 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 16 Dec 2014 14:08:15 +0100

x86, irq: Refine mp_register_ioapic() to prepare for IOAPIC hotplug

Refine mp_register_ioapic() to prepare for IOAPIC hotplug by:
1) change return value from void to int.
2) check for gsi range conflicts
3) check for IOAPIC physical address conflicts
4) enhance the way to allocate IOAPIC index

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Grant Likely <[email protected]>
Cc Prarit Bhargava <[email protected]>
---
 arch/x86/include/asm/io_apic.h |  4 +-
 arch/x86/kernel/apic/io_apic.c | 87 +++++++++++++++++++++++++++---------------
 2 files changed, 58 insertions(+), 33 deletions(-)
arch/x86/include/asm/io_apic.h +2 -2
index 0b31aeb..94d05bd 100644
@@ -188,8 +188,8 @@ extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
 extern u32 mp_pin_to_gsi(int ioapic, int pin);
 extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
 extern void mp_unmap_irq(int irq);
-extern void mp_register_ioapic(int id, u32 address, u32 gsi_base,
-			       struct ioapic_domain_cfg *cfg);
+extern int mp_register_ioapic(int id, u32 address, u32 gsi_base,
+			      struct ioapic_domain_cfg *cfg);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
arch/x86/kernel/apic/io_apic.c +56 -31

129 lines not on this page · raw message

author
#55 lore raw

PATCH v7 14/18 x86, irq, ACPI: Introduce a rwsem to protect IOAPIC operations from hotplug

In reply to Jiang Liu

We are going to support ACPI based IOAPIC hotplug, so introduce a rwsem to protect IOAPIC data structures from IOAPIC hotplug. We choose to serialize in ACPI instead of in the IOAPIC core because:
1) currently we are only plan to support ACPI based IOAPIC hotplug
2) it's much more cleaner and easier
3) It does't affect IOAPIC discovered by devicetree, SFI and mpparse.

---
 arch/x86/kernel/acpi/boot.c |   21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
arch/x86/kernel/acpi/boot.c +21 -0
index e077c080a519..3f6b665f5aa6 100644
@@ -76,6 +76,19 @@ int acpi_fix_pin2_polarity __initdata;
 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
 #endif
 
+/*
+ * Locks related to IOAPIC hotplug
+ * Hotplug side:
+ * 	->lock_device_hotplug()	//device_hotplug_lock
+ *		->acpi_ioapic_rwsem
+ *			->ioapic_lock
+ * Interrupt mapping side:
+ *	->acpi_ioapic_rwsem
+ *		->ioapic_mutex
+ *			->ioapic_lock
+ */
+static DECLARE_RWSEM(acpi_ioapic_rwsem);
+
 /* --------------------------------------------------------------------------
                               Boot-time Configuration
    -------------------------------------------------------------------------- */
@@ -609,8 +622,10 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
 	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
 		*irqp = gsi;
 	} else {
+		down_read(&acpi_ioapic_rwsem);
 		irq = mp_map_gsi_to_irq(gsi,
 					IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
+		up_read(&acpi_ioapic_rwsem);
 		if (irq < 0)
 			return -1;
 		*irqp = irq;
@@ -651,7 +666,9 @@ static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
 	int irq = gsi;
 
 #ifdef CONFIG_X86_IO_APIC
+	down_read(&acpi_ioapic_rwsem);
 	irq = mp_register_gsi(dev, gsi, trigger, polarity);
+	up_read(&acpi_ioapic_rwsem);
 #endif
 
 	return irq;
@@ -660,7 +677,9 @@ static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
 static void acpi_unregister_gsi_ioapic(u32 gsi)
 {
 #ifdef CONFIG_X86_IO_APIC
+	down_read(&acpi_ioapic_rwsem);
 	mp_unregister_gsi(gsi);
+	up_read(&acpi_ioapic_rwsem);
 #endif
 }
 
@@ -1186,7 +1205,9 @@ static void __init acpi_process_madt(void)
 			/*
 			 * Parse MADT IO-APIC entries
 			 */
+			down_write(&acpi_ioapic_rwsem);
 			error = acpi_parse_madt_ioapic_entries();
+			up_write(&acpi_ioapic_rwsem);
 			if (!error) {
 				acpi_set_irq_model_ioapic();
 
Signature · 1 line
1.7.10.4
#56 lore raw

Re: [Patch v7 14/18] x86, irq, ACPI: Introduce a rwsem to protect IOAPIC operations from hotplug

Quoted 6 lines · Jiang Liu

We are going to support ACPI based IOAPIC hotplug, so introduce a rwsem to protect IOAPIC data structures from IOAPIC hotplug. We choose to serialize in ACPI instead of in the IOAPIC core because:
1) currently we are only plan to support ACPI based IOAPIC hotplug
2) it's much more cleaner and easier
3) It does't affect IOAPIC discovered by devicetree, SFI and mpparse.

I had a last intensive look at this series as I was about to merge it. So I looked at the locking rules here again

Quoted 11 lines

+/*
+ * Locks related to IOAPIC hotplug
+ * Hotplug side:
+ * ->lock_device_hotplug() //device_hotplug_lock
+ * ->acpi_ioapic_rwsem
+ * ->ioapic_lock
+ * Interrupt mapping side:
+ * ->acpi_ioapic_rwsem
+ * ->ioapic_mutex
+ * ->ioapic_lock
+ */

This looks sane, but I cannot figure out at all why this needs to be a rwsem.

Quoted 1 line

+static DECLARE_RWSEM(acpi_ioapic_rwsem);

I think it should be a simple mutex because the rwsem does not protect against concurrent execution what taken for read.

And the site which takes it for write is in the early boot process where nothing runs in parallel AFAICT.

Thanks,

tglx

author
#57 lore raw

Re: [Patch v7 14/18] x86, irq, ACPI: Introduce a rwsem to protect IOAPIC operations from hotplug

Quoted 26 lines · Thomas Gleixner
Quoted 6 lines · Jiang Liu

We are going to support ACPI based IOAPIC hotplug, so introduce a rwsem to protect IOAPIC data structures from IOAPIC hotplug. We choose to serialize in ACPI instead of in the IOAPIC core because:
1) currently we are only plan to support ACPI based IOAPIC hotplug
2) it's much more cleaner and easier
3) It does't affect IOAPIC discovered by devicetree, SFI and mpparse.

I had a last intensive look at this series as I was about to merge it. So I looked at the locking rules here again

Quoted 11 lines

+/*
+ * Locks related to IOAPIC hotplug
+ * Hotplug side:
+ * ->lock_device_hotplug() //device_hotplug_lock
+ * ->acpi_ioapic_rwsem
+ * ->ioapic_lock
+ * Interrupt mapping side:
+ * ->acpi_ioapic_rwsem
+ * ->ioapic_mutex
+ * ->ioapic_lock
+ */

This looks sane, but I cannot figure out at all why this needs to be a rwsem.

Quoted 7 lines
Quoted 1 line

+static DECLARE_RWSEM(acpi_ioapic_rwsem);

I think it should be a simple mutex because the rwsem does not protect against concurrent execution what taken for read.

And the site which takes it for write is in the early boot process where nothing runs in parallel AFAICT.

Hi Thomas,
You are right. It's not on hot path, so a mutex is better than
a rwsem here. I will send out an updated version soon. Regards!
Gerry

Quoted 5 lines

Thanks,

tglx

author
#58 lore raw

PATCH v7 15/18 x86, irq, ACPI: Implement interface to support ACPI based IOAPIC hot-addition

In reply to Jiang Liu

Implement acpi_register_ioapic() and enhance mp_register_ioapic() to support ACPI based IOAPIC hot-addition.

---
 arch/x86/kernel/acpi/boot.c    |   31 +++++++++++++++++++++++++++++--
 arch/x86/kernel/apic/io_apic.c |   22 +++++++++++++++++++++-
 2 files changed, 50 insertions(+), 3 deletions(-)
arch/x86/kernel/acpi/boot.c +29 -2
index 3f6b665f5aa6..8205f6381d77 100644
@@ -779,8 +779,35 @@ EXPORT_SYMBOL(acpi_unmap_lsapic);
 
 int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
 {
-	/* TBD */
-	return -EINVAL;
+	int ret = -ENOSYS;
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+	int ioapic_id;
+	u64 addr;
+	struct ioapic_domain_cfg cfg = {
+		.type = IOAPIC_DOMAIN_DYNAMIC,
+		.ops = &acpi_irqdomain_ops,
+	};
+
+	ioapic_id = acpi_get_ioapic_id(handle, gsi_base, &addr);
+	if (ioapic_id < 0) {
+		unsigned long long uid;
+		acpi_status status;
+
+		status = acpi_evaluate_integer(handle, METHOD_NAME__UID,
+					       NULL, &uid);
+		if (ACPI_FAILURE(status)) {
+			acpi_handle_warn(handle, "failed to get IOAPIC ID.\n");
+			return -EINVAL;
+		}
+		ioapic_id = (int)uid;
+	}
+
+	down_write(&acpi_ioapic_rwsem);
+	ret  = mp_register_ioapic(ioapic_id, phys_addr, gsi_base, &cfg);
+	up_write(&acpi_ioapic_rwsem);
+#endif
+
+	return ret;
 }
 
 EXPORT_SYMBOL(acpi_register_ioapic);
arch/x86/kernel/apic/io_apic.c +21 -1
index 59267659e5b1..4d9d87cc3259 100644
@@ -3853,7 +3853,13 @@ static int bad_ioapic_register(int idx)
 
 static int find_free_ioapic_entry(void)
 {
-	return nr_ioapics;
+	int idx;
+
+	for (idx = 0; idx < MAX_IO_APICS; idx++)
+		if (ioapics[idx].nr_registers == 0)
+			return idx;
+
+	return MAX_IO_APICS;
 }
 
 /**
@@ -3869,6 +3875,7 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 	u32 gsi_end;
 	int idx, ioapic, entries;
 	struct mp_ioapic_gsi *gsi_cfg;
+	bool hotplug = !!ioapic_initialized;
 
 	if (!address) {
 		pr_warn("Bogus (zero) I/O APIC address found, skipping!\n");
@@ -3927,6 +3934,19 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 	ioapics[idx].irqdomain = NULL;
 	ioapics[idx].irqdomain_cfg = *cfg;
 
+	/*
+	 * If mp_register_ioapic() is called during early boot stage when
+	 * walking ACPI/SFI/DT tables, it's too early to create irqdomain,
+	 * we are still using bootmem allocator. So delay it to setup_IO_APIC().
+	 */
+	if (hotplug) {
+		if (mp_irqdomain_create(idx)) {
+			clear_fixmap(FIX_IO_APIC_BASE_0 + idx);
+			return -ENOMEM;
+		}
+		alloc_ioapic_saved_registers(idx);
+	}
+
 	if (gsi_cfg->gsi_end >= gsi_top)
 		gsi_top = gsi_cfg->gsi_end + 1;
 	if (nr_ioapics <= idx)
Signature · 1 line
1.7.10.4
#59 lore raw

[tip:x86/apic] x86, irq, ACPI: Implement interface to support ACPI based IOAPIC hot-addition

x86, irq, ACPI: Implement interface to support ACPI based IOAPIC hot-addition
Commit-ID:  ff6213974cd90e1ebf9a153c74e6b0da647092b2
Gitweb:     http://git.kernel.org/tip/ff6213974cd90e1ebf9a153c74e6b0da647092b2
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:45 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Mon, 3 Nov 2014 11:56:08 +0100

x86, irq, ACPI: Implement interface to support ACPI based IOAPIC hot-addition

Implement acpi_register_ioapic() and enhance mp_register_ioapic() to support ACPI based IOAPIC hot-addition.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
Cc Pavel Machek <[email protected]>
Cc Grant Likely <[email protected]>
Cc Prarit Bhargava <[email protected]>
---
 arch/x86/kernel/acpi/boot.c    | 31 +++++++++++++++++++++++++++++--
 arch/x86/kernel/apic/io_apic.c | 22 +++++++++++++++++++++-
 2 files changed, 50 insertions(+), 3 deletions(-)
arch/x86/kernel/acpi/boot.c +29 -2
index 1a2d9d4..ee7b311 100644
@@ -778,8 +778,35 @@ EXPORT_SYMBOL(acpi_unmap_lsapic);
 
 int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
 {
-	/* TBD */
-	return -EINVAL;
+	int ret = -ENOSYS;
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+	int ioapic_id;
+	u64 addr;
+	struct ioapic_domain_cfg cfg = {
+		.type = IOAPIC_DOMAIN_DYNAMIC,
+		.ops = &acpi_irqdomain_ops,
+	};
+
+	ioapic_id = acpi_get_ioapic_id(handle, gsi_base, &addr);
+	if (ioapic_id < 0) {
+		unsigned long long uid;
+		acpi_status status;
+
+		status = acpi_evaluate_integer(handle, METHOD_NAME__UID,
+					       NULL, &uid);
+		if (ACPI_FAILURE(status)) {
+			acpi_handle_warn(handle, "failed to get IOAPIC ID.\n");
+			return -EINVAL;
+		}
+		ioapic_id = (int)uid;
+	}
+
+	mutex_lock(&acpi_ioapic_lock);
+	ret  = mp_register_ioapic(ioapic_id, phys_addr, gsi_base, &cfg);
+	mutex_unlock(&acpi_ioapic_lock);
+#endif
+
+	return ret;
 }
 
 EXPORT_SYMBOL(acpi_register_ioapic);
arch/x86/kernel/apic/io_apic.c +21 -1
index 090d3fe..830244d 100644
@@ -3861,7 +3861,13 @@ static int bad_ioapic_register(int idx)
 
 static int find_free_ioapic_entry(void)
 {
-	return nr_ioapics;
+	int idx;
+
+	for (idx = 0; idx < MAX_IO_APICS; idx++)
+		if (ioapics[idx].nr_registers == 0)
+			return idx;
+
+	return MAX_IO_APICS;
 }
 
 /**
@@ -3874,6 +3880,7 @@ static int find_free_ioapic_entry(void)
 int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 		       struct ioapic_domain_cfg *cfg)
 {
+	bool hotplug = !!ioapic_initialized;
 	struct mp_ioapic_gsi *gsi_cfg;
 	int idx, ioapic, entries;
 	u32 gsi_end;
@@ -3935,6 +3942,19 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 	ioapics[idx].irqdomain = NULL;
 	ioapics[idx].irqdomain_cfg = *cfg;
 
+	/*
+	 * If mp_register_ioapic() is called during early boot stage when
+	 * walking ACPI/SFI/DT tables, it's too early to create irqdomain,
+	 * we are still using bootmem allocator. So delay it to setup_IO_APIC().
+	 */
+	if (hotplug) {
+		if (mp_irqdomain_create(idx)) {
+			clear_fixmap(FIX_IO_APIC_BASE_0 + idx);
+			return -ENOMEM;
+		}
+		alloc_ioapic_saved_registers(idx);
+	}
+
 	if (gsi_cfg->gsi_end >= gsi_top)
 		gsi_top = gsi_cfg->gsi_end + 1;
 	if (nr_ioapics <= idx)
#60 lore raw

[tip:x86/apic] x86, irq, ACPI: Implement interface to support ACPI based IOAPIC hot-addition

In reply to Jiang Liu
x86, irq, ACPI: Implement interface to support ACPI based IOAPIC hot-addition
Commit-ID:  7db298cb70125e322dfdb3f41e8129681a6f6b20
Gitweb:     http://git.kernel.org/tip/7db298cb70125e322dfdb3f41e8129681a6f6b20
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:45 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 16 Dec 2014 14:08:15 +0100

x86, irq, ACPI: Implement interface to support ACPI based IOAPIC hot-addition

Implement acpi_register_ioapic() and enhance mp_register_ioapic() to support ACPI based IOAPIC hot-addition.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
Cc Pavel Machek <[email protected]>
Cc Grant Likely <[email protected]>
Cc Prarit Bhargava <[email protected]>
---
 arch/x86/kernel/acpi/boot.c    | 31 +++++++++++++++++++++++++++++--
 arch/x86/kernel/apic/io_apic.c | 22 +++++++++++++++++++++-
 2 files changed, 50 insertions(+), 3 deletions(-)
arch/x86/kernel/acpi/boot.c +29 -2
index 2d76f02..0b99351 100644
@@ -780,8 +780,35 @@ EXPORT_SYMBOL(acpi_unmap_lsapic);
 
 int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
 {
-	/* TBD */
-	return -EINVAL;
+	int ret = -ENOSYS;
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+	int ioapic_id;
+	u64 addr;
+	struct ioapic_domain_cfg cfg = {
+		.type = IOAPIC_DOMAIN_DYNAMIC,
+		.ops = &acpi_irqdomain_ops,
+	};
+
+	ioapic_id = acpi_get_ioapic_id(handle, gsi_base, &addr);
+	if (ioapic_id < 0) {
+		unsigned long long uid;
+		acpi_status status;
+
+		status = acpi_evaluate_integer(handle, METHOD_NAME__UID,
+					       NULL, &uid);
+		if (ACPI_FAILURE(status)) {
+			acpi_handle_warn(handle, "failed to get IOAPIC ID.\n");
+			return -EINVAL;
+		}
+		ioapic_id = (int)uid;
+	}
+
+	mutex_lock(&acpi_ioapic_lock);
+	ret  = mp_register_ioapic(ioapic_id, phys_addr, gsi_base, &cfg);
+	mutex_unlock(&acpi_ioapic_lock);
+#endif
+
+	return ret;
 }
 
 EXPORT_SYMBOL(acpi_register_ioapic);
arch/x86/kernel/apic/io_apic.c +21 -1
index 4333a75..826f44f 100644
@@ -3861,7 +3861,13 @@ static int bad_ioapic_register(int idx)
 
 static int find_free_ioapic_entry(void)
 {
-	return nr_ioapics;
+	int idx;
+
+	for (idx = 0; idx < MAX_IO_APICS; idx++)
+		if (ioapics[idx].nr_registers == 0)
+			return idx;
+
+	return MAX_IO_APICS;
 }
 
 /**
@@ -3874,6 +3880,7 @@ static int find_free_ioapic_entry(void)
 int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 		       struct ioapic_domain_cfg *cfg)
 {
+	bool hotplug = !!ioapic_initialized;
 	struct mp_ioapic_gsi *gsi_cfg;
 	int idx, ioapic, entries;
 	u32 gsi_end;
@@ -3935,6 +3942,19 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 	ioapics[idx].irqdomain = NULL;
 	ioapics[idx].irqdomain_cfg = *cfg;
 
+	/*
+	 * If mp_register_ioapic() is called during early boot stage when
+	 * walking ACPI/SFI/DT tables, it's too early to create irqdomain,
+	 * we are still using bootmem allocator. So delay it to setup_IO_APIC().
+	 */
+	if (hotplug) {
+		if (mp_irqdomain_create(idx)) {
+			clear_fixmap(FIX_IO_APIC_BASE_0 + idx);
+			return -ENOMEM;
+		}
+		alloc_ioapic_saved_registers(idx);
+	}
+
 	if (gsi_cfg->gsi_end >= gsi_top)
 		gsi_top = gsi_cfg->gsi_end + 1;
 	if (nr_ioapics <= idx)
author
#61 lore raw

PATCH v7 16/18 x86, irq, ACPI: Implement interfaces to support ACPI based IOAPIC hot-removal

In reply to Jiang Liu

Implement acpi_unregister_ioapic() to support ACPI based IOAPIC hot-removal. An IOAPIC could only be removed when all its pins are unused.

---
 arch/x86/include/asm/io_apic.h |    1 +
 arch/x86/kernel/acpi/boot.c    |   13 +++++++---
 arch/x86/kernel/apic/io_apic.c |   55 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+), 4 deletions(-)
arch/x86/include/asm/io_apic.h +1 -0
index 8741c1ea33c3..7c04b8ec22a4 100644
@@ -190,6 +190,7 @@ extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
 extern void mp_unmap_irq(int irq);
 extern int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 			      struct ioapic_domain_cfg *cfg);
+extern int mp_unregister_ioapic(u32 gsi_base);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
arch/x86/kernel/acpi/boot.c +9 -4
index 8205f6381d77..bc61a5c0e7b6 100644
@@ -809,15 +809,20 @@ int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
 
 	return ret;
 }
-
 EXPORT_SYMBOL(acpi_register_ioapic);
 
 int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
 {
-	/* TBD */
-	return -EINVAL;
-}
+	int ret = -ENOSYS;
+
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+	down_write(&acpi_ioapic_rwsem);
+	ret  = mp_unregister_ioapic(gsi_base);
+	up_write(&acpi_ioapic_rwsem);
+#endif
 
+	return ret;
+}
 EXPORT_SYMBOL(acpi_unregister_ioapic);
 
 static int __init acpi_parse_sbf(struct acpi_table_header *table)
arch/x86/kernel/apic/io_apic.c +55 -0

85 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#62 lore raw

[tip:x86/apic] x86, irq, ACPI: Implement interfaces to support ACPI based IOAPIC hot-removal

x86, irq, ACPI: Implement interfaces to support ACPI based IOAPIC hot-removal
Commit-ID:  5fcb864ef90df093d964171539c87ffa0ab49f0f
Gitweb:     http://git.kernel.org/tip/5fcb864ef90df093d964171539c87ffa0ab49f0f
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:46 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Mon, 3 Nov 2014 11:56:08 +0100

x86, irq, ACPI: Implement interfaces to support ACPI based IOAPIC hot-removal

Implement acpi_unregister_ioapic() to support ACPI based IOAPIC hot-removal. An IOAPIC could only be removed when all its pins are unused.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
Cc Pavel Machek <[email protected]>
Cc Grant Likely <[email protected]>
Cc Prarit Bhargava <[email protected]>
---
 arch/x86/include/asm/io_apic.h |  1 +
 arch/x86/kernel/acpi/boot.c    | 13 +++++++---
 arch/x86/kernel/apic/io_apic.c | 55 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+), 4 deletions(-)
arch/x86/include/asm/io_apic.h +1 -0
index 8741c1e..7c04b8e 100644
@@ -190,6 +190,7 @@ extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
 extern void mp_unmap_irq(int irq);
 extern int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 			      struct ioapic_domain_cfg *cfg);
+extern int mp_unregister_ioapic(u32 gsi_base);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
arch/x86/kernel/acpi/boot.c +9 -4
index ee7b311..77107a9 100644
@@ -808,15 +808,20 @@ int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
 
 	return ret;
 }
-
 EXPORT_SYMBOL(acpi_register_ioapic);
 
 int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
 {
-	/* TBD */
-	return -EINVAL;
-}
+	int ret = -ENOSYS;
+
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+	mutex_lock(&acpi_ioapic_lock);
+	ret  = mp_unregister_ioapic(gsi_base);
+	mutex_unlock(&acpi_ioapic_lock);
+#endif
 
+	return ret;
+}
 EXPORT_SYMBOL(acpi_unregister_ioapic);
 
 static int __init acpi_parse_sbf(struct acpi_table_header *table)
arch/x86/kernel/apic/io_apic.c +55 -0

85 lines not on this page · raw message

#63 lore raw

[tip:x86/apic] x86, irq, ACPI: Implement interfaces to support ACPI based IOAPIC hot-removal

In reply to Jiang Liu
x86, irq, ACPI: Implement interfaces to support ACPI based IOAPIC hot-removal
Commit-ID:  15516a3b8633a32f03a82a2db23b87cf9600514c
Gitweb:     http://git.kernel.org/tip/15516a3b8633a32f03a82a2db23b87cf9600514c
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:46 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 16 Dec 2014 14:08:15 +0100

x86, irq, ACPI: Implement interfaces to support ACPI based IOAPIC hot-removal

Implement acpi_unregister_ioapic() to support ACPI based IOAPIC hot-removal. An IOAPIC could only be removed when all its pins are unused.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
Cc Pavel Machek <[email protected]>
Cc Grant Likely <[email protected]>
Cc Prarit Bhargava <[email protected]>
---
 arch/x86/include/asm/io_apic.h |  1 +
 arch/x86/kernel/acpi/boot.c    | 13 +++++++---
 arch/x86/kernel/apic/io_apic.c | 55 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+), 4 deletions(-)
arch/x86/include/asm/io_apic.h +1 -0
index 94d05bd..ce63cf3 100644
@@ -190,6 +190,7 @@ extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
 extern void mp_unmap_irq(int irq);
 extern int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 			      struct ioapic_domain_cfg *cfg);
+extern int mp_unregister_ioapic(u32 gsi_base);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
arch/x86/kernel/acpi/boot.c +9 -4
index 0b99351..5427d9b 100644
@@ -810,15 +810,20 @@ int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
 
 	return ret;
 }
-
 EXPORT_SYMBOL(acpi_register_ioapic);
 
 int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
 {
-	/* TBD */
-	return -EINVAL;
-}
+	int ret = -ENOSYS;
+
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+	mutex_lock(&acpi_ioapic_lock);
+	ret  = mp_unregister_ioapic(gsi_base);
+	mutex_unlock(&acpi_ioapic_lock);
+#endif
 
+	return ret;
+}
 EXPORT_SYMBOL(acpi_unregister_ioapic);
 
 static int __init acpi_parse_sbf(struct acpi_table_header *table)
arch/x86/kernel/apic/io_apic.c +55 -0

85 lines not on this page · raw message

author
#64 lore raw

PATCH v7 17/18 x86, irq: Introduce helper to check whether an IOAPIC has been registered

In reply to Jiang Liu

Introduce acpi_ioapic_registered() to check whether an IOAPIC has already been registered, it will be used when enabling IOAPIC hotplug.

---
 arch/x86/include/asm/io_apic.h |    1 +
 arch/x86/kernel/acpi/boot.c    |   22 ++++++++++++++++++++++
 arch/x86/kernel/apic/io_apic.c |   11 +++++++++++
 include/linux/acpi.h           |    1 +
 4 files changed, 35 insertions(+)
arch/x86/include/asm/io_apic.h +1 -0
index 7c04b8ec22a4..ca742d5249db 100644
@@ -191,6 +191,7 @@ extern void mp_unmap_irq(int irq);
 extern int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 			      struct ioapic_domain_cfg *cfg);
 extern int mp_unregister_ioapic(u32 gsi_base);
+extern int mp_ioapic_registered(u32 gsi_base);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
arch/x86/kernel/acpi/boot.c +22 -0
index bc61a5c0e7b6..f27b33194e06 100644
@@ -825,6 +825,28 @@ int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
 }
 EXPORT_SYMBOL(acpi_unregister_ioapic);
 
+/**
+ * acpi_ioapic_registered - Check whether IOAPIC assoicatied with @gsi_base
+ *			    has been registered
+ * @handle:	ACPI handle of the IOAPIC deivce
+ * @gsi_base:	GSI base associated with the IOAPIC
+ *
+ * Assume caller holds some type of lock to serialize acpi_ioapic_registered()
+ * with acpi_register_ioapic()/acpi_unregister_ioapic().
+ */
+int acpi_ioapic_registered(acpi_handle handle, u32 gsi_base)
+{
+	int ret = 0;
+
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+	down_read(&acpi_ioapic_rwsem);
+	ret  = mp_ioapic_registered(gsi_base);
+	up_read(&acpi_ioapic_rwsem);
+#endif
+
+	return ret;
+}
+
 static int __init acpi_parse_sbf(struct acpi_table_header *table)
 {
 	struct acpi_table_boot *sb;
arch/x86/kernel/apic/io_apic.c +11 -0
index 9e5432ee2070..df3858de3031 100644
@@ -4018,6 +4018,17 @@ int mp_unregister_ioapic(u32 gsi_base)
 	return 0;
 }
 
+int mp_ioapic_registered(u32 gsi_base)
+{
+	int ioapic;
+
+	for_each_ioapic(ioapic)
+		if (ioapics[ioapic].gsi_config.gsi_base == gsi_base)
+			return 1;
+
+	return 0;
+}
+
 int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 		     irq_hw_number_t hwirq)
 {
include/linux/acpi.h +1 -0
index 77cecd0350e7..be6be0f91337 100644
@@ -152,6 +152,7 @@ int acpi_get_ioapic_id(acpi_handle handle, u32 gsi_base, u64 *phys_addr);
 
 int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base);
 int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base);
+int acpi_ioapic_registered(acpi_handle handle, u32 gsi_base);
 void acpi_irq_stats_init(void);
 extern u32 acpi_irq_handled;
 extern u32 acpi_irq_not_handled;
Signature · 1 line
1.7.10.4
Acked-by on v7 17/18
#65 lore raw

Re: [Patch v7 17/18] x86, irq: Introduce helper to check whether an IOAPIC has been registered

Quoted 4 lines · Jiang Liu

Introduce acpi_ioapic_registered() to check whether an IOAPIC has already been registered, it will be used when enabling IOAPIC hotplug.

Nothing obviously wrong.

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
#66 lore raw

[tip:x86/apic] x86, irq: Introduce helper to check whether an IOAPIC has been registered

In reply to Jiang Liu
x86, irq: Introduce helper to check whether an IOAPIC has been registered
Commit-ID:  cf45268eceac09ff4af677f6e876b4d0397e1d3f
Gitweb:     http://git.kernel.org/tip/cf45268eceac09ff4af677f6e876b4d0397e1d3f
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:47 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Mon, 3 Nov 2014 11:56:08 +0100

x86, irq: Introduce helper to check whether an IOAPIC has been registered

Introduce acpi_ioapic_registered() to check whether an IOAPIC has already been registered, it will be used when enabling IOAPIC hotplug.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
Cc Grant Likely <[email protected]>
Cc Prarit Bhargava <[email protected]>
---
 arch/x86/include/asm/io_apic.h |  1 +
 arch/x86/kernel/acpi/boot.c    | 22 ++++++++++++++++++++++
 arch/x86/kernel/apic/io_apic.c | 11 +++++++++++
 include/linux/acpi.h           |  1 +
 4 files changed, 35 insertions(+)
arch/x86/include/asm/io_apic.h +1 -0
index 7c04b8e..ca742d5 100644
@@ -191,6 +191,7 @@ extern void mp_unmap_irq(int irq);
 extern int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 			      struct ioapic_domain_cfg *cfg);
 extern int mp_unregister_ioapic(u32 gsi_base);
+extern int mp_ioapic_registered(u32 gsi_base);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
arch/x86/kernel/acpi/boot.c +22 -0
index 77107a9..1ae52e0 100644
@@ -824,6 +824,28 @@ int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
 }
 EXPORT_SYMBOL(acpi_unregister_ioapic);
 
+/**
+ * acpi_ioapic_registered - Check whether IOAPIC assoicatied with @gsi_base
+ *			    has been registered
+ * @handle:	ACPI handle of the IOAPIC deivce
+ * @gsi_base:	GSI base associated with the IOAPIC
+ *
+ * Assume caller holds some type of lock to serialize acpi_ioapic_registered()
+ * with acpi_register_ioapic()/acpi_unregister_ioapic().
+ */
+int acpi_ioapic_registered(acpi_handle handle, u32 gsi_base)
+{
+	int ret = 0;
+
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+	mutex_lock(&acpi_ioapic_lock);
+	ret  = mp_ioapic_registered(gsi_base);
+	mutex_unlock(&acpi_ioapic_lock);
+#endif
+
+	return ret;
+}
+
 static int __init acpi_parse_sbf(struct acpi_table_header *table)
 {
 	struct acpi_table_boot *sb;
arch/x86/kernel/apic/io_apic.c +11 -0
index 011ebca..ff2709e 100644
@@ -4026,6 +4026,17 @@ int mp_unregister_ioapic(u32 gsi_base)
 	return 0;
 }
 
+int mp_ioapic_registered(u32 gsi_base)
+{
+	int ioapic;
+
+	for_each_ioapic(ioapic)
+		if (ioapics[ioapic].gsi_config.gsi_base == gsi_base)
+			return 1;
+
+	return 0;
+}
+
 int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 		     irq_hw_number_t hwirq)
 {
include/linux/acpi.h +1 -0
index 77cecd0..be6be0f 100644
@@ -152,6 +152,7 @@ int acpi_get_ioapic_id(acpi_handle handle, u32 gsi_base, u64 *phys_addr);
 
 int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base);
 int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base);
+int acpi_ioapic_registered(acpi_handle handle, u32 gsi_base);
 void acpi_irq_stats_init(void);
 extern u32 acpi_irq_handled;
 extern u32 acpi_irq_not_handled;
#67 lore raw

[tip:x86/apic] x86, irq: Introduce helper to check whether an IOAPIC has been registered

In reply to Jiang Liu
x86, irq: Introduce helper to check whether an IOAPIC has been registered
Commit-ID:  e89900c9ad75a1b80e1f1f46ce9c9bb0e7ea1d96
Gitweb:     http://git.kernel.org/tip/e89900c9ad75a1b80e1f1f46ce9c9bb0e7ea1d96
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:47 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 16 Dec 2014 14:08:15 +0100

x86, irq: Introduce helper to check whether an IOAPIC has been registered

Introduce acpi_ioapic_registered() to check whether an IOAPIC has already been registered, it will be used when enabling IOAPIC hotplug.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
Cc Grant Likely <[email protected]>
Cc Prarit Bhargava <[email protected]>
---
 arch/x86/include/asm/io_apic.h |  1 +
 arch/x86/kernel/acpi/boot.c    | 22 ++++++++++++++++++++++
 arch/x86/kernel/apic/io_apic.c | 11 +++++++++++
 include/linux/acpi.h           |  1 +
 4 files changed, 35 insertions(+)
arch/x86/include/asm/io_apic.h +1 -0
index ce63cf3..0db2b70 100644
@@ -191,6 +191,7 @@ extern void mp_unmap_irq(int irq);
 extern int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 			      struct ioapic_domain_cfg *cfg);
 extern int mp_unregister_ioapic(u32 gsi_base);
+extern int mp_ioapic_registered(u32 gsi_base);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
arch/x86/kernel/acpi/boot.c +22 -0
index 5427d9b..ddddaed 100644
@@ -826,6 +826,28 @@ int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
 }
 EXPORT_SYMBOL(acpi_unregister_ioapic);
 
+/**
+ * acpi_ioapic_registered - Check whether IOAPIC assoicatied with @gsi_base
+ *			    has been registered
+ * @handle:	ACPI handle of the IOAPIC deivce
+ * @gsi_base:	GSI base associated with the IOAPIC
+ *
+ * Assume caller holds some type of lock to serialize acpi_ioapic_registered()
+ * with acpi_register_ioapic()/acpi_unregister_ioapic().
+ */
+int acpi_ioapic_registered(acpi_handle handle, u32 gsi_base)
+{
+	int ret = 0;
+
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+	mutex_lock(&acpi_ioapic_lock);
+	ret  = mp_ioapic_registered(gsi_base);
+	mutex_unlock(&acpi_ioapic_lock);
+#endif
+
+	return ret;
+}
+
 static int __init acpi_parse_sbf(struct acpi_table_header *table)
 {
 	struct acpi_table_boot *sb;
arch/x86/kernel/apic/io_apic.c +11 -0
index 06a0a6c..1cedf41 100644
@@ -4026,6 +4026,17 @@ int mp_unregister_ioapic(u32 gsi_base)
 	return 0;
 }
 
+int mp_ioapic_registered(u32 gsi_base)
+{
+	int ioapic;
+
+	for_each_ioapic(ioapic)
+		if (ioapics[ioapic].gsi_config.gsi_base == gsi_base)
+			return 1;
+
+	return 0;
+}
+
 int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 		     irq_hw_number_t hwirq)
 {
include/linux/acpi.h +1 -0
index 407a12f..a81dd43 100644
@@ -148,6 +148,7 @@ int acpi_unmap_lsapic(int cpu);
 
 int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base);
 int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base);
+int acpi_ioapic_registered(acpi_handle handle, u32 gsi_base);
 void acpi_irq_stats_init(void);
 extern u32 acpi_irq_handled;
 extern u32 acpi_irq_not_handled;
author
#68 lore raw

PATCH v7 18/18 x86, irq, ACPI: Implement ACPI driver to support IOAPIC hotplug

In reply to Jiang Liu

Enable support of IOAPIC hotplug by:
1) reintroducing ACPI based IOAPIC driver
2) enhance pci_root driver to hook hotplug events

The ACPI IOAPIC driver is always enabled if all of ACPI, PCI and IOAPIC are enabled.

---
 drivers/acpi/Kconfig    |    6 ++
 drivers/acpi/Makefile   |    1 +
 drivers/acpi/internal.h |    7 ++
 drivers/acpi/ioapic.c   |  235 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/acpi/pci_root.c |    3 +
 5 files changed, 252 insertions(+)
 create mode 100644 drivers/acpi/ioapic.c
drivers/acpi/Kconfig +6 -0
index b23fe37f67c0..127bc2fc43be 100644
@@ -315,6 +315,12 @@ config ACPI_HOTPLUG_MEMORY
 	  To compile this driver as a module, choose M here:
 	  the module will be called acpi_memhotplug.
 
+config ACPI_HOTPLUG_IOAPIC
+	bool
+	depends on PCI
+	depends on X86_IO_APIC
+	default y
+
 config ACPI_SBS
 	tristate "Smart Battery System"
 	depends on X86
drivers/acpi/Makefile +1 -0
index c3b2fcb729f3..3b283a232f7a 100644
@@ -69,6 +69,7 @@ obj-$(CONFIG_ACPI_PROCESSOR)	+= processor.o
 obj-y				+= container.o
 obj-$(CONFIG_ACPI_THERMAL)	+= thermal.o
 obj-y				+= acpi_memhotplug.o
+obj-$(CONFIG_ACPI_HOTPLUG_IOAPIC) += ioapic.o
 obj-$(CONFIG_ACPI_BATTERY)	+= battery.o
 obj-$(CONFIG_ACPI_SBS)		+= sbshc.o
 obj-$(CONFIG_ACPI_SBS)		+= sbs.o
drivers/acpi/internal.h +7 -0
index 447f6d679b29..73efdcb8d8ad 100644
@@ -35,6 +35,13 @@ void acpi_int340x_thermal_init(void);
 int acpi_sysfs_init(void);
 void acpi_container_init(void);
 void acpi_memory_hotplug_init(void);
+#ifdef	CONFIG_ACPI_HOTPLUG_IOAPIC
+int acpi_ioapic_add(struct acpi_pci_root *root);
+int acpi_ioapic_remove(struct acpi_pci_root *root);
+#else
+static inline int acpi_ioapic_add(struct acpi_pci_root *root) { return 0; }
+static inline int acpi_ioapic_remove(struct acpi_pci_root *root) { return 0; }
+#endif
 #ifdef CONFIG_ACPI_DOCK
 void register_dock_dependent_device(struct acpi_device *adev,
 				    acpi_handle dshandle);
drivers/acpi/ioapic.c new file +235 -0

235 lines not on this page · raw message

drivers/acpi/pci_root.c +3 -0
index cd4de7e038ea..f3f77689bafc 100644
@@ -614,6 +614,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
 	if (system_state != SYSTEM_BOOTING) {
 		pcibios_resource_survey_bus(root->bus);
 		pci_assign_unassigned_root_bus_resources(root->bus);
+		acpi_ioapic_add(root);
 	}
 
 	pci_lock_rescan_remove();
@@ -634,6 +635,8 @@ static void acpi_pci_root_remove(struct acpi_device *device)
 
 	pci_stop_root_bus(root->bus);
 
+	WARN_ON(acpi_ioapic_remove(root));
+
 	device_set_run_wake(root->bus->bridge, false);
 	pci_acpi_remove_bus_pm_notifier(device);
 
Signature · 1 line
1.7.10.4
#69 lore raw

[tip:x86/apic] x86, irq, ACPI: Implement ACPI driver to support IOAPIC hotplug

x86, irq, ACPI: Implement ACPI driver to support IOAPIC hotplug
Commit-ID:  3a2f18905b31bb2c1cdb1e108c95bfd8b62b0908
Gitweb:     http://git.kernel.org/tip/3a2f18905b31bb2c1cdb1e108c95bfd8b62b0908
Author:     Jiang Liu <[email protected]>
AuthorDate: Mon, 27 Oct 2014 13:21:48 +0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Mon, 3 Nov 2014 11:56:08 +0100

x86, irq, ACPI: Implement ACPI driver to support IOAPIC hotplug

Enable support of IOAPIC hotplug by:
1) reintroducing ACPI based IOAPIC driver
2) enhance pci_root driver to hook hotplug events

The ACPI IOAPIC driver is always enabled if all of ACPI, PCI and IOAPIC are enabled.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Tony Luck <[email protected]>
Cc Joerg Roedel <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Yinghai Lu <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Len Brown <[email protected]>
---
 drivers/acpi/Kconfig    |   6 ++
 drivers/acpi/Makefile   |   1 +
 drivers/acpi/internal.h |   7 ++
 drivers/acpi/ioapic.c   | 235 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/acpi/pci_root.c |   3 +
 5 files changed, 252 insertions(+)
drivers/acpi/Kconfig +6 -0
index b23fe37..127bc2f 100644
@@ -315,6 +315,12 @@ config ACPI_HOTPLUG_MEMORY
 	  To compile this driver as a module, choose M here:
 	  the module will be called acpi_memhotplug.
 
+config ACPI_HOTPLUG_IOAPIC
+	bool
+	depends on PCI
+	depends on X86_IO_APIC
+	default y
+
 config ACPI_SBS
 	tristate "Smart Battery System"
 	depends on X86
drivers/acpi/Makefile +1 -0
index c3b2fcb..3b283a2 100644
@@ -69,6 +69,7 @@ obj-$(CONFIG_ACPI_PROCESSOR)	+= processor.o
 obj-y				+= container.o
 obj-$(CONFIG_ACPI_THERMAL)	+= thermal.o
 obj-y				+= acpi_memhotplug.o
+obj-$(CONFIG_ACPI_HOTPLUG_IOAPIC) += ioapic.o
 obj-$(CONFIG_ACPI_BATTERY)	+= battery.o
 obj-$(CONFIG_ACPI_SBS)		+= sbshc.o
 obj-$(CONFIG_ACPI_SBS)		+= sbs.o
drivers/acpi/internal.h +7 -0
index 447f6d6..73efdcb 100644
@@ -35,6 +35,13 @@ void acpi_int340x_thermal_init(void);
 int acpi_sysfs_init(void);
 void acpi_container_init(void);
 void acpi_memory_hotplug_init(void);
+#ifdef	CONFIG_ACPI_HOTPLUG_IOAPIC
+int acpi_ioapic_add(struct acpi_pci_root *root);
+int acpi_ioapic_remove(struct acpi_pci_root *root);
+#else
+static inline int acpi_ioapic_add(struct acpi_pci_root *root) { return 0; }
+static inline int acpi_ioapic_remove(struct acpi_pci_root *root) { return 0; }
+#endif
 #ifdef CONFIG_ACPI_DOCK
 void register_dock_dependent_device(struct acpi_device *adev,
 				    acpi_handle dshandle);
drivers/acpi/ioapic.c new file +235 -0

235 lines not on this page · raw message

drivers/acpi/pci_root.c +3 -0
index cd4de7e..f3f7768 100644
@@ -614,6 +614,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
 	if (system_state != SYSTEM_BOOTING) {
 		pcibios_resource_survey_bus(root->bus);
 		pci_assign_unassigned_root_bus_resources(root->bus);
+		acpi_ioapic_add(root);
 	}
 
 	pci_lock_rescan_remove();
@@ -634,6 +635,8 @@ static void acpi_pci_root_remove(struct acpi_device *device)
 
 	pci_stop_root_bus(root->bus);
 
+	WARN_ON(acpi_ioapic_remove(root));
+
 	device_set_run_wake(root->bus->bridge, false);
 	pci_acpi_remove_bus_pm_notifier(device);