[tip:x86/pti] selftests/x86/mpx: Fix incorrect bounds with old _sigfault
Commit-ID: 961888b1d76d84efc66a8f5604b06ac12ac2f978 Gitweb: https://git.kernel.org/tip/961888b1d76d84efc66a8f5604b06ac12ac2f978 Author: Rui Wang <rui.y.w...@intel.com> AuthorDate: Mon, 18 Dec 2017 16:34:10 +0800 Committer: Ingo Molnar <mi...@kernel.org> CommitDate: Thu, 15 Feb 2018 01:15:52 +0100 selftests/x86/mpx: Fix incorrect bounds with old _sigfault For distributions with old userspace header files, the _sigfault structure is different. mpx-mini-test fails with the following error: [root@Purley]# mpx-mini-test_64 tabletest XSAVE is supported by HW & OS XSAVE processor supported state mask: 0x2ff XSAVE OS supported state mask: 0x2ff BNDREGS: size: 64 user: 1 supervisor: 0 aligned: 0 BNDCSR: size: 64 user: 1 supervisor: 0 aligned: 0 starting mpx bounds table test ERROR: siginfo bounds do not match shadow bounds for register 0 Fix it by using the correct offset of _lower/_upper in _sigfault. RHEL needs this patch to work. Signed-off-by: Rui Wang <rui.y.w...@intel.com> Cc: Linus Torvalds <torva...@linux-foundation.org> Cc: Peter Zijlstra <pet...@infradead.org> Cc: Thomas Gleixner <t...@linutronix.de> Cc: dave.han...@linux.intel.com Fixes: e754aedc26ef ("x86/mpx, selftests: Add MPX self test") Link: http://lkml.kernel.org/r/1513586050-1641-1-git-send-email-rui.y.w...@intel.com Signed-off-by: Ingo Molnar <mi...@kernel.org> --- tools/testing/selftests/x86/mpx-mini-test.c | 32 +++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/x86/mpx-mini-test.c b/tools/testing/selftests/x86/mpx-mini-test.c index ec0f6b4..9c0325e 100644 --- a/tools/testing/selftests/x86/mpx-mini-test.c +++ b/tools/testing/selftests/x86/mpx-mini-test.c @@ -315,11 +315,39 @@ static inline void *__si_bounds_upper(siginfo_t *si) return si->si_upper; } #else + +/* + * This deals with old version of _sigfault in some distros: + * + +old _sigfault: +struct { +void *si_addr; + } _sigfault; + +new _sigfault: + struct { + void __user *_addr; + int _trapno; + short _addr_lsb; + union { + struct { + void __user *_lower; + void __user *_upper; + } _addr_bnd; + __u32 _pkey; + }; + } _sigfault; + * + */ + static inline void **__si_bounds_hack(siginfo_t *si) { void *sigfault = >_sifields._sigfault; void *end_sigfault = sigfault + sizeof(si->_sifields._sigfault); - void **__si_lower = end_sigfault; + int *trapno = (int*)end_sigfault; + /* skip _trapno and _addr_lsb */ + void **__si_lower = (void**)(trapno + 2); return __si_lower; } @@ -331,7 +359,7 @@ static inline void *__si_bounds_lower(siginfo_t *si) static inline void *__si_bounds_upper(siginfo_t *si) { - return (*__si_bounds_hack(si)) + sizeof(void *); + return *(__si_bounds_hack(si) + 1); } #endif
[tip:x86/pti] selftests/x86/mpx: Fix incorrect bounds with old _sigfault
Commit-ID: 961888b1d76d84efc66a8f5604b06ac12ac2f978 Gitweb: https://git.kernel.org/tip/961888b1d76d84efc66a8f5604b06ac12ac2f978 Author: Rui Wang AuthorDate: Mon, 18 Dec 2017 16:34:10 +0800 Committer: Ingo Molnar CommitDate: Thu, 15 Feb 2018 01:15:52 +0100 selftests/x86/mpx: Fix incorrect bounds with old _sigfault For distributions with old userspace header files, the _sigfault structure is different. mpx-mini-test fails with the following error: [root@Purley]# mpx-mini-test_64 tabletest XSAVE is supported by HW & OS XSAVE processor supported state mask: 0x2ff XSAVE OS supported state mask: 0x2ff BNDREGS: size: 64 user: 1 supervisor: 0 aligned: 0 BNDCSR: size: 64 user: 1 supervisor: 0 aligned: 0 starting mpx bounds table test ERROR: siginfo bounds do not match shadow bounds for register 0 Fix it by using the correct offset of _lower/_upper in _sigfault. RHEL needs this patch to work. Signed-off-by: Rui Wang Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: dave.han...@linux.intel.com Fixes: e754aedc26ef ("x86/mpx, selftests: Add MPX self test") Link: http://lkml.kernel.org/r/1513586050-1641-1-git-send-email-rui.y.w...@intel.com Signed-off-by: Ingo Molnar --- tools/testing/selftests/x86/mpx-mini-test.c | 32 +++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/x86/mpx-mini-test.c b/tools/testing/selftests/x86/mpx-mini-test.c index ec0f6b4..9c0325e 100644 --- a/tools/testing/selftests/x86/mpx-mini-test.c +++ b/tools/testing/selftests/x86/mpx-mini-test.c @@ -315,11 +315,39 @@ static inline void *__si_bounds_upper(siginfo_t *si) return si->si_upper; } #else + +/* + * This deals with old version of _sigfault in some distros: + * + +old _sigfault: +struct { +void *si_addr; + } _sigfault; + +new _sigfault: + struct { + void __user *_addr; + int _trapno; + short _addr_lsb; + union { + struct { + void __user *_lower; + void __user *_upper; + } _addr_bnd; + __u32 _pkey; + }; + } _sigfault; + * + */ + static inline void **__si_bounds_hack(siginfo_t *si) { void *sigfault = >_sifields._sigfault; void *end_sigfault = sigfault + sizeof(si->_sifields._sigfault); - void **__si_lower = end_sigfault; + int *trapno = (int*)end_sigfault; + /* skip _trapno and _addr_lsb */ + void **__si_lower = (void**)(trapno + 2); return __si_lower; } @@ -331,7 +359,7 @@ static inline void *__si_bounds_lower(siginfo_t *si) static inline void *__si_bounds_upper(siginfo_t *si) { - return (*__si_bounds_hack(si)) + sizeof(void *); + return *(__si_bounds_hack(si) + 1); } #endif
[tip:x86/pti] selftests/x86/mpx: Fix incorrect bounds with old _sigfault
Commit-ID: d101567aec6653cc372af3b9b957299fee06cca8 Gitweb: https://git.kernel.org/tip/d101567aec6653cc372af3b9b957299fee06cca8 Author: Rui Wang <rui.y.w...@intel.com> AuthorDate: Mon, 18 Dec 2017 16:34:10 +0800 Committer: Ingo Molnar <mi...@kernel.org> CommitDate: Tue, 13 Feb 2018 19:20:05 +0100 selftests/x86/mpx: Fix incorrect bounds with old _sigfault For distributions with old userspace header files, the _sigfault structure is different. mpx-mini-test fails with the following error: [root@Purley]# mpx-mini-test_64 tabletest XSAVE is supported by HW & OS XSAVE processor supported state mask: 0x2ff XSAVE OS supported state mask: 0x2ff BNDREGS: size: 64 user: 1 supervisor: 0 aligned: 0 BNDCSR: size: 64 user: 1 supervisor: 0 aligned: 0 starting mpx bounds table test ERROR: siginfo bounds do not match shadow bounds for register 0 Fix it by using the correct offset of _lower/_upper in _sigfault. RHEL needs this patch to work. Signed-off-by: Rui Wang <rui.y.w...@intel.com> Cc: Linus Torvalds <torva...@linux-foundation.org> Cc: Peter Zijlstra <pet...@infradead.org> Cc: Thomas Gleixner <t...@linutronix.de> Cc: dave.han...@linux.intel.com Fixes: e754aedc26ef ("x86/mpx, selftests: Add MPX self test") Link: http://lkml.kernel.org/r/1513586050-1641-1-git-send-email-rui.y.w...@intel.com Signed-off-by: Ingo Molnar <mi...@kernel.org> --- tools/testing/selftests/x86/mpx-mini-test.c | 32 +++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/x86/mpx-mini-test.c b/tools/testing/selftests/x86/mpx-mini-test.c index ec0f6b4..9c0325e 100644 --- a/tools/testing/selftests/x86/mpx-mini-test.c +++ b/tools/testing/selftests/x86/mpx-mini-test.c @@ -315,11 +315,39 @@ static inline void *__si_bounds_upper(siginfo_t *si) return si->si_upper; } #else + +/* + * This deals with old version of _sigfault in some distros: + * + +old _sigfault: +struct { +void *si_addr; + } _sigfault; + +new _sigfault: + struct { + void __user *_addr; + int _trapno; + short _addr_lsb; + union { + struct { + void __user *_lower; + void __user *_upper; + } _addr_bnd; + __u32 _pkey; + }; + } _sigfault; + * + */ + static inline void **__si_bounds_hack(siginfo_t *si) { void *sigfault = >_sifields._sigfault; void *end_sigfault = sigfault + sizeof(si->_sifields._sigfault); - void **__si_lower = end_sigfault; + int *trapno = (int*)end_sigfault; + /* skip _trapno and _addr_lsb */ + void **__si_lower = (void**)(trapno + 2); return __si_lower; } @@ -331,7 +359,7 @@ static inline void *__si_bounds_lower(siginfo_t *si) static inline void *__si_bounds_upper(siginfo_t *si) { - return (*__si_bounds_hack(si)) + sizeof(void *); + return *(__si_bounds_hack(si) + 1); } #endif
[tip:x86/pti] selftests/x86/mpx: Fix incorrect bounds with old _sigfault
Commit-ID: d101567aec6653cc372af3b9b957299fee06cca8 Gitweb: https://git.kernel.org/tip/d101567aec6653cc372af3b9b957299fee06cca8 Author: Rui Wang AuthorDate: Mon, 18 Dec 2017 16:34:10 +0800 Committer: Ingo Molnar CommitDate: Tue, 13 Feb 2018 19:20:05 +0100 selftests/x86/mpx: Fix incorrect bounds with old _sigfault For distributions with old userspace header files, the _sigfault structure is different. mpx-mini-test fails with the following error: [root@Purley]# mpx-mini-test_64 tabletest XSAVE is supported by HW & OS XSAVE processor supported state mask: 0x2ff XSAVE OS supported state mask: 0x2ff BNDREGS: size: 64 user: 1 supervisor: 0 aligned: 0 BNDCSR: size: 64 user: 1 supervisor: 0 aligned: 0 starting mpx bounds table test ERROR: siginfo bounds do not match shadow bounds for register 0 Fix it by using the correct offset of _lower/_upper in _sigfault. RHEL needs this patch to work. Signed-off-by: Rui Wang Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: dave.han...@linux.intel.com Fixes: e754aedc26ef ("x86/mpx, selftests: Add MPX self test") Link: http://lkml.kernel.org/r/1513586050-1641-1-git-send-email-rui.y.w...@intel.com Signed-off-by: Ingo Molnar --- tools/testing/selftests/x86/mpx-mini-test.c | 32 +++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/x86/mpx-mini-test.c b/tools/testing/selftests/x86/mpx-mini-test.c index ec0f6b4..9c0325e 100644 --- a/tools/testing/selftests/x86/mpx-mini-test.c +++ b/tools/testing/selftests/x86/mpx-mini-test.c @@ -315,11 +315,39 @@ static inline void *__si_bounds_upper(siginfo_t *si) return si->si_upper; } #else + +/* + * This deals with old version of _sigfault in some distros: + * + +old _sigfault: +struct { +void *si_addr; + } _sigfault; + +new _sigfault: + struct { + void __user *_addr; + int _trapno; + short _addr_lsb; + union { + struct { + void __user *_lower; + void __user *_upper; + } _addr_bnd; + __u32 _pkey; + }; + } _sigfault; + * + */ + static inline void **__si_bounds_hack(siginfo_t *si) { void *sigfault = >_sifields._sigfault; void *end_sigfault = sigfault + sizeof(si->_sifields._sigfault); - void **__si_lower = end_sigfault; + int *trapno = (int*)end_sigfault; + /* skip _trapno and _addr_lsb */ + void **__si_lower = (void**)(trapno + 2); return __si_lower; } @@ -331,7 +359,7 @@ static inline void *__si_bounds_lower(siginfo_t *si) static inline void *__si_bounds_upper(siginfo_t *si) { - return (*__si_bounds_hack(si)) + sizeof(void *); + return *(__si_bounds_hack(si) + 1); } #endif
[PATCH] x86/mpx/selftests: Fix wrong bounds with old _sigfault
I fixed this on my machine and forgot to tell anyone until a recent bug report. The patch almost get lost. Archiving it here. For distributions with old userspace header files, the _sigfault structure is different. mpx-mini-test fails with the following error: [root@Purley]# mpx-mini-test_64 tabletest XSAVE is supported by HW & OS XSAVE processor supported state mask: 0x2ff XSAVE OS supported state mask: 0x2ff BNDREGS: size: 64 user: 1 supervisor: 0 aligned: 0 BNDCSR: size: 64 user: 1 supervisor: 0 aligned: 0 starting mpx bounds table test ERROR: siginfo bounds do not match shadow bounds for register 0 Fix it by using the correct offset of _lower/_upper in _sigfault. RHEL needs this patch to work. Fixes: e754aedc26ef ("x86/mpx, selftests: Add MPX self test") Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- tools/testing/selftests/x86/mpx-mini-test.c | 27 +-- 1 files changed, 25 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/x86/mpx-mini-test.c b/tools/testing/selftests/x86/mpx-mini-test.c index ec0f6b4..45035c3 100644 --- a/tools/testing/selftests/x86/mpx-mini-test.c +++ b/tools/testing/selftests/x86/mpx-mini-test.c @@ -315,11 +315,34 @@ static uint64_t read_mpx_status_sig(ucontext_t *uctxt) return si->si_upper; } #else + +/* This deals with old version of _sigfault in some distros +old _sigfault: +struct { +void *si_addr; + } _sigfault; + +new _sigfault: + struct { + void __user *_addr; + int _trapno; + short _addr_lsb; + union { + struct { + void __user *_lower; + void __user *_upper; + } _addr_bnd; + __u32 _pkey; + }; + } _sigfault; +*/ static inline void **__si_bounds_hack(siginfo_t *si) { void *sigfault = >_sifields._sigfault; void *end_sigfault = sigfault + sizeof(si->_sifields._sigfault); - void **__si_lower = end_sigfault; + int *trapno = (int*)end_sigfault; + /* skip _trapno and _addr_lsb */ + void **__si_lower = (void**)(trapno + 2); return __si_lower; } @@ -331,7 +354,7 @@ static uint64_t read_mpx_status_sig(ucontext_t *uctxt) static inline void *__si_bounds_upper(siginfo_t *si) { - return (*__si_bounds_hack(si)) + sizeof(void *); + return *(__si_bounds_hack(si) + 1); } #endif -- 1.7.5.4
[PATCH] x86/mpx/selftests: Fix wrong bounds with old _sigfault
I fixed this on my machine and forgot to tell anyone until a recent bug report. The patch almost get lost. Archiving it here. For distributions with old userspace header files, the _sigfault structure is different. mpx-mini-test fails with the following error: [root@Purley]# mpx-mini-test_64 tabletest XSAVE is supported by HW & OS XSAVE processor supported state mask: 0x2ff XSAVE OS supported state mask: 0x2ff BNDREGS: size: 64 user: 1 supervisor: 0 aligned: 0 BNDCSR: size: 64 user: 1 supervisor: 0 aligned: 0 starting mpx bounds table test ERROR: siginfo bounds do not match shadow bounds for register 0 Fix it by using the correct offset of _lower/_upper in _sigfault. RHEL needs this patch to work. Fixes: e754aedc26ef ("x86/mpx, selftests: Add MPX self test") Signed-off-by: Rui Wang --- tools/testing/selftests/x86/mpx-mini-test.c | 27 +-- 1 files changed, 25 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/x86/mpx-mini-test.c b/tools/testing/selftests/x86/mpx-mini-test.c index ec0f6b4..45035c3 100644 --- a/tools/testing/selftests/x86/mpx-mini-test.c +++ b/tools/testing/selftests/x86/mpx-mini-test.c @@ -315,11 +315,34 @@ static uint64_t read_mpx_status_sig(ucontext_t *uctxt) return si->si_upper; } #else + +/* This deals with old version of _sigfault in some distros +old _sigfault: +struct { +void *si_addr; + } _sigfault; + +new _sigfault: + struct { + void __user *_addr; + int _trapno; + short _addr_lsb; + union { + struct { + void __user *_lower; + void __user *_upper; + } _addr_bnd; + __u32 _pkey; + }; + } _sigfault; +*/ static inline void **__si_bounds_hack(siginfo_t *si) { void *sigfault = >_sifields._sigfault; void *end_sigfault = sigfault + sizeof(si->_sifields._sigfault); - void **__si_lower = end_sigfault; + int *trapno = (int*)end_sigfault; + /* skip _trapno and _addr_lsb */ + void **__si_lower = (void**)(trapno + 2); return __si_lower; } @@ -331,7 +354,7 @@ static uint64_t read_mpx_status_sig(ucontext_t *uctxt) static inline void *__si_bounds_upper(siginfo_t *si) { - return (*__si_bounds_hack(si)) + sizeof(void *); + return *(__si_bounds_hack(si) + 1); } #endif -- 1.7.5.4
[tip:x86/urgent] x86/PCI: Implement pcibios_release_device to release IRQ from IOAPIC
Commit-ID: 153654dbe595a68845ba14d5b0bfe299fa6a7e99 Gitweb: http://git.kernel.org/tip/153654dbe595a68845ba14d5b0bfe299fa6a7e99 Author: Rui Wang <rui.y.w...@intel.com> AuthorDate: Tue, 28 Feb 2017 21:34:28 +0800 Committer: Thomas Gleixner <t...@linutronix.de> CommitDate: Wed, 1 Mar 2017 10:51:41 +0100 x86/PCI: Implement pcibios_release_device to release IRQ from IOAPIC The revert of 991de2e59090 ("PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()") causes a problem for IOAPIC hotplug. The problem is that IRQs are allocated and freed in pci_enable_device() and pci_disable_device(). But there are some drivers which don't call pci_disable_device(), and they have good reasons not calling it, so if they're using IOAPIC their IRQs won't have a chance to be released from the IOAPIC. When this happens IOAPIC hot-removal fails with a kernel stack dump and an error message like this: [149335.697989] pin16 on IOAPIC2 is still in use. It turns out that we can fix it in a different way without moving IRQ allocation into pcibios_alloc_irq(), thus avoiding the regression of 991de2e59090. We can keep the allocation and freeing of IRQs as is within pci_enable_device()/pci_disable_device(), without breaking any previous assumption of the rest of the system, keeping compatibility with both the legacy and the modern drivers. We can accomplish this by implementing the existing __weak hook of pcibios_release_device() thus when a pci device is about to be deleted we get notified in the hook and take the chance to release its IRQ, if any, from the IOAPIC. Implement pcibios_release_device() for x86 to release any IRQ not released by the driver. Signed-off-by: Rui Wang <rui.y.w...@intel.com> Cc: tony.l...@intel.com Cc: linux-...@vger.kernel.org Cc: r...@rjwysocki.net Cc: linux-a...@vger.kernel.org Cc: fengguang...@intel.com Cc: helg...@kernel.org Cc: kbuild-...@01.org Cc: bhelg...@google.com Link: http://lkml.kernel.org/r/1488288869-31290-2-git-send-email-rui.y.w...@intel.com Signed-off-by: Thomas Gleixner <t...@linutronix.de> --- arch/x86/pci/common.c | 9 + 1 file changed, 9 insertions(+) diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 0cb52ae..190e718 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -735,6 +735,15 @@ void pcibios_disable_device (struct pci_dev *dev) pcibios_disable_irq(dev); } +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +void pcibios_release_device(struct pci_dev *dev) +{ + if (atomic_dec_return(>enable_cnt) >= 0) + pcibios_disable_device(dev); + +} +#endif + int pci_ext_cfg_avail(void) { if (raw_pci_ext_ops)
[tip:x86/urgent] x86/ioapic: Split IOAPIC hot-removal into two steps
Commit-ID: f2ae5da726172fcf82f7be801489dd585f6a38eb Gitweb: http://git.kernel.org/tip/f2ae5da726172fcf82f7be801489dd585f6a38eb Author: Rui Wang <rui.y.w...@intel.com> AuthorDate: Tue, 28 Feb 2017 21:34:29 +0800 Committer: Thomas Gleixner <t...@linutronix.de> CommitDate: Wed, 1 Mar 2017 10:51:41 +0100 x86/ioapic: Split IOAPIC hot-removal into two steps The hot removal of IOAPIC is handling PCI and ACPI removal in one go. That only works when the PCI drivers released the interrupt resources, but breaks when a IOAPIC interrupt is still associated to a PCI device. The new pcibios_release_device() callback allows to solve that problem by splitting the removal into two steps: 1) PCI removal: Release all PCI resources including eventually not yet released IOAPIC interrupts via the new pcibios_release_device() callback. 2) ACPI removal: After release of all PCI resources the ACPI resources can be released without issue. [ tglx: Rewrote changelog ] Signed-off-by: Rui Wang <rui.y.w...@intel.com> Cc: tony.l...@intel.com Cc: linux-...@vger.kernel.org Cc: r...@rjwysocki.net Cc: linux-a...@vger.kernel.org Cc: fengguang...@intel.com Cc: helg...@kernel.org Cc: kbuild-...@01.org Cc: bhelg...@google.com Link: http://lkml.kernel.org/r/1488288869-31290-3-git-send-email-rui.y.w...@intel.com Signed-off-by: Thomas Gleixner <t...@linutronix.de> --- drivers/acpi/internal.h | 2 ++ drivers/acpi/ioapic.c | 22 -- drivers/acpi/pci_root.c | 4 ++-- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 219b90b..f159001 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -41,8 +41,10 @@ void acpi_gpe_apply_masked_gpes(void); void acpi_container_init(void); void acpi_memory_hotplug_init(void); #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +void pci_ioapic_remove(struct acpi_pci_root *root); int acpi_ioapic_remove(struct acpi_pci_root *root); #else +static inline void pci_ioapic_remove(struct acpi_pci_root *root) { return; } static inline int acpi_ioapic_remove(struct acpi_pci_root *root) { return 0; } #endif #ifdef CONFIG_ACPI_DOCK diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 6d7ce6e..1120dfd6 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -206,24 +206,34 @@ int acpi_ioapic_add(acpi_handle root_handle) return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } -int acpi_ioapic_remove(struct acpi_pci_root *root) +void pci_ioapic_remove(struct acpi_pci_root *root) { - int retval = 0; struct acpi_pci_ioapic *ioapic, *tmp; mutex_lock(_list_lock); list_for_each_entry_safe(ioapic, tmp, _list, list) { if (root->device->handle != ioapic->root_handle) continue; - - if (acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base)) - retval = -EBUSY; - if (ioapic->pdev) { pci_release_region(ioapic->pdev, 0); pci_disable_device(ioapic->pdev); pci_dev_put(ioapic->pdev); } + } + mutex_unlock(_list_lock); +} + +int acpi_ioapic_remove(struct acpi_pci_root *root) +{ + int retval = 0; + struct acpi_pci_ioapic *ioapic, *tmp; + + mutex_lock(_list_lock); + list_for_each_entry_safe(ioapic, tmp, _list, list) { + if (root->device->handle != ioapic->root_handle) + continue; + if (acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base)) + retval = -EBUSY; if (ioapic->res.flags && ioapic->res.parent) release_resource(>res); list_del(>list); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index bf601d4..919be0a 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -648,12 +648,12 @@ static void acpi_pci_root_remove(struct acpi_device *device) pci_stop_root_bus(root->bus); - WARN_ON(acpi_ioapic_remove(root)); - + pci_ioapic_remove(root); device_set_run_wake(root->bus->bridge, false); pci_acpi_remove_bus_pm_notifier(device); pci_remove_root_bus(root->bus); + WARN_ON(acpi_ioapic_remove(root)); dmar_device_remove(device->handle);
[tip:x86/urgent] x86/PCI: Implement pcibios_release_device to release IRQ from IOAPIC
Commit-ID: 153654dbe595a68845ba14d5b0bfe299fa6a7e99 Gitweb: http://git.kernel.org/tip/153654dbe595a68845ba14d5b0bfe299fa6a7e99 Author: Rui Wang AuthorDate: Tue, 28 Feb 2017 21:34:28 +0800 Committer: Thomas Gleixner CommitDate: Wed, 1 Mar 2017 10:51:41 +0100 x86/PCI: Implement pcibios_release_device to release IRQ from IOAPIC The revert of 991de2e59090 ("PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()") causes a problem for IOAPIC hotplug. The problem is that IRQs are allocated and freed in pci_enable_device() and pci_disable_device(). But there are some drivers which don't call pci_disable_device(), and they have good reasons not calling it, so if they're using IOAPIC their IRQs won't have a chance to be released from the IOAPIC. When this happens IOAPIC hot-removal fails with a kernel stack dump and an error message like this: [149335.697989] pin16 on IOAPIC2 is still in use. It turns out that we can fix it in a different way without moving IRQ allocation into pcibios_alloc_irq(), thus avoiding the regression of 991de2e59090. We can keep the allocation and freeing of IRQs as is within pci_enable_device()/pci_disable_device(), without breaking any previous assumption of the rest of the system, keeping compatibility with both the legacy and the modern drivers. We can accomplish this by implementing the existing __weak hook of pcibios_release_device() thus when a pci device is about to be deleted we get notified in the hook and take the chance to release its IRQ, if any, from the IOAPIC. Implement pcibios_release_device() for x86 to release any IRQ not released by the driver. Signed-off-by: Rui Wang Cc: tony.l...@intel.com Cc: linux-...@vger.kernel.org Cc: r...@rjwysocki.net Cc: linux-a...@vger.kernel.org Cc: fengguang...@intel.com Cc: helg...@kernel.org Cc: kbuild-...@01.org Cc: bhelg...@google.com Link: http://lkml.kernel.org/r/1488288869-31290-2-git-send-email-rui.y.w...@intel.com Signed-off-by: Thomas Gleixner --- arch/x86/pci/common.c | 9 + 1 file changed, 9 insertions(+) diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 0cb52ae..190e718 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -735,6 +735,15 @@ void pcibios_disable_device (struct pci_dev *dev) pcibios_disable_irq(dev); } +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +void pcibios_release_device(struct pci_dev *dev) +{ + if (atomic_dec_return(>enable_cnt) >= 0) + pcibios_disable_device(dev); + +} +#endif + int pci_ext_cfg_avail(void) { if (raw_pci_ext_ops)
[tip:x86/urgent] x86/ioapic: Split IOAPIC hot-removal into two steps
Commit-ID: f2ae5da726172fcf82f7be801489dd585f6a38eb Gitweb: http://git.kernel.org/tip/f2ae5da726172fcf82f7be801489dd585f6a38eb Author: Rui Wang AuthorDate: Tue, 28 Feb 2017 21:34:29 +0800 Committer: Thomas Gleixner CommitDate: Wed, 1 Mar 2017 10:51:41 +0100 x86/ioapic: Split IOAPIC hot-removal into two steps The hot removal of IOAPIC is handling PCI and ACPI removal in one go. That only works when the PCI drivers released the interrupt resources, but breaks when a IOAPIC interrupt is still associated to a PCI device. The new pcibios_release_device() callback allows to solve that problem by splitting the removal into two steps: 1) PCI removal: Release all PCI resources including eventually not yet released IOAPIC interrupts via the new pcibios_release_device() callback. 2) ACPI removal: After release of all PCI resources the ACPI resources can be released without issue. [ tglx: Rewrote changelog ] Signed-off-by: Rui Wang Cc: tony.l...@intel.com Cc: linux-...@vger.kernel.org Cc: r...@rjwysocki.net Cc: linux-a...@vger.kernel.org Cc: fengguang...@intel.com Cc: helg...@kernel.org Cc: kbuild-...@01.org Cc: bhelg...@google.com Link: http://lkml.kernel.org/r/1488288869-31290-3-git-send-email-rui.y.w...@intel.com Signed-off-by: Thomas Gleixner --- drivers/acpi/internal.h | 2 ++ drivers/acpi/ioapic.c | 22 -- drivers/acpi/pci_root.c | 4 ++-- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 219b90b..f159001 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -41,8 +41,10 @@ void acpi_gpe_apply_masked_gpes(void); void acpi_container_init(void); void acpi_memory_hotplug_init(void); #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +void pci_ioapic_remove(struct acpi_pci_root *root); int acpi_ioapic_remove(struct acpi_pci_root *root); #else +static inline void pci_ioapic_remove(struct acpi_pci_root *root) { return; } static inline int acpi_ioapic_remove(struct acpi_pci_root *root) { return 0; } #endif #ifdef CONFIG_ACPI_DOCK diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 6d7ce6e..1120dfd6 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -206,24 +206,34 @@ int acpi_ioapic_add(acpi_handle root_handle) return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } -int acpi_ioapic_remove(struct acpi_pci_root *root) +void pci_ioapic_remove(struct acpi_pci_root *root) { - int retval = 0; struct acpi_pci_ioapic *ioapic, *tmp; mutex_lock(_list_lock); list_for_each_entry_safe(ioapic, tmp, _list, list) { if (root->device->handle != ioapic->root_handle) continue; - - if (acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base)) - retval = -EBUSY; - if (ioapic->pdev) { pci_release_region(ioapic->pdev, 0); pci_disable_device(ioapic->pdev); pci_dev_put(ioapic->pdev); } + } + mutex_unlock(_list_lock); +} + +int acpi_ioapic_remove(struct acpi_pci_root *root) +{ + int retval = 0; + struct acpi_pci_ioapic *ioapic, *tmp; + + mutex_lock(_list_lock); + list_for_each_entry_safe(ioapic, tmp, _list, list) { + if (root->device->handle != ioapic->root_handle) + continue; + if (acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base)) + retval = -EBUSY; if (ioapic->res.flags && ioapic->res.parent) release_resource(>res); list_del(>list); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index bf601d4..919be0a 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -648,12 +648,12 @@ static void acpi_pci_root_remove(struct acpi_device *device) pci_stop_root_bus(root->bus); - WARN_ON(acpi_ioapic_remove(root)); - + pci_ioapic_remove(root); device_set_run_wake(root->bus->bridge, false); pci_acpi_remove_bus_pm_notifier(device); pci_remove_root_bus(root->bus); + WARN_ON(acpi_ioapic_remove(root)); dmar_device_remove(device->handle);
[PATCH v2 2/2] x86/ioapic: Split IOAPIC hot-removal into two steps
The hot-removal of IOAPIC is broken into two parts: the PCI part and the ACPI part. The PCI part releases PCI resources before the PCI bus is gone, and the ACPI part is moved to a stage later than the hot-removal of the PCI root bus, so that the IOAPIC driver is able to hook the pcibios_release_device() of every PCI device under the same parent root bus, before the IOAPIC is hot-removed. This makes it possible for the IOAPIC to free any IRQ resource previously unable to get freed. v2: Fixed compiling error on i386 (missing stub of pci_ioapic_remove()) Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/internal.h | 2 ++ drivers/acpi/ioapic.c | 22 -- drivers/acpi/pci_root.c | 4 ++-- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 219b90b..f159001 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -41,8 +41,10 @@ static inline void acpi_amba_init(void) {} void acpi_container_init(void); void acpi_memory_hotplug_init(void); #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +void pci_ioapic_remove(struct acpi_pci_root *root); int acpi_ioapic_remove(struct acpi_pci_root *root); #else +static inline void pci_ioapic_remove(struct acpi_pci_root *root) { return; } static inline int acpi_ioapic_remove(struct acpi_pci_root *root) { return 0; } #endif #ifdef CONFIG_ACPI_DOCK diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 6d7ce6e..1120dfd6 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -206,24 +206,34 @@ int acpi_ioapic_add(acpi_handle root_handle) return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } -int acpi_ioapic_remove(struct acpi_pci_root *root) +void pci_ioapic_remove(struct acpi_pci_root *root) { - int retval = 0; struct acpi_pci_ioapic *ioapic, *tmp; mutex_lock(_list_lock); list_for_each_entry_safe(ioapic, tmp, _list, list) { if (root->device->handle != ioapic->root_handle) continue; - - if (acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base)) - retval = -EBUSY; - if (ioapic->pdev) { pci_release_region(ioapic->pdev, 0); pci_disable_device(ioapic->pdev); pci_dev_put(ioapic->pdev); } + } + mutex_unlock(_list_lock); +} + +int acpi_ioapic_remove(struct acpi_pci_root *root) +{ + int retval = 0; + struct acpi_pci_ioapic *ioapic, *tmp; + + mutex_lock(_list_lock); + list_for_each_entry_safe(ioapic, tmp, _list, list) { + if (root->device->handle != ioapic->root_handle) + continue; + if (acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base)) + retval = -EBUSY; if (ioapic->res.flags && ioapic->res.parent) release_resource(>res); list_del(>list); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index bf601d4..919be0a 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -648,12 +648,12 @@ static void acpi_pci_root_remove(struct acpi_device *device) pci_stop_root_bus(root->bus); - WARN_ON(acpi_ioapic_remove(root)); - + pci_ioapic_remove(root); device_set_run_wake(root->bus->bridge, false); pci_acpi_remove_bus_pm_notifier(device); pci_remove_root_bus(root->bus); + WARN_ON(acpi_ioapic_remove(root)); dmar_device_remove(device->handle); -- 1.8.3.1
[PATCH v2 1/2] x86/PCI: Implement pcibios_release_device to release IRQ from IOAPIC
The revert of 991de2e59090 ("PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()") causes a problem for IOAPIC hotplug. The problem is that IRQs are allocated and freed in pci_enable_device() and pci_disable_device(). But there are some drivers which don't call pci_disable_device(), and they have good reasons not calling it, so if they're using IOAPIC their IRQs won't have a chance to be released from the IOAPIC. When this happens IOAPIC hot-removal fails with a kernel stack dump and an error message like this: [149335.697989] pin16 on IOAPIC2 is still in use. It turns out that we can fix it in a different way without moving IRQ allocation into pcibios_alloc_irq(), thus avoiding the regression of 991de2e59090. We can keep the allocation and freeing of IRQs as is within pci_enable_device()/pci_disable_device(), without breaking any previous assumption of the rest of the system, keeping compatibility with both the legacy and the modern drivers. We can accomplish this by implementing the existing __weak hook of pcibios_release_device() thus when a pci device is about to be deleted we get notified in the hook and take the chance to release its IRQ, if any, from the IOAPIC. Besides implementing pcibios_release_device(), the hot-removal of IOAPIC needs to be broken into two parts: the PCI part and the ACPI part. The PCI part releases PCI resources before the PCI bus is gone, and the ACPI part is moved to a stage later than the hot-removal of the PCI root bus, so we have the chance to hook every PCI device's pcibios_release_device(), before we remove the IOAPIC. This patch implements pcibios_release_device() on x86 to release any IRQ not released by the driver, so that the IOAPIC can then be safely hot-removed. v2: Fixed a typo (pcibios_release_device) Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- arch/x86/pci/common.c | 9 + 1 file changed, 9 insertions(+) diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 0cb52ae..190e718 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -735,6 +735,15 @@ void pcibios_disable_device (struct pci_dev *dev) pcibios_disable_irq(dev); } +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +void pcibios_release_device(struct pci_dev *dev) +{ + if (atomic_dec_return(>enable_cnt) >= 0) + pcibios_disable_device(dev); + +} +#endif + int pci_ext_cfg_avail(void) { if (raw_pci_ext_ops) -- 1.8.3.1
[PATCH v2 0/2] Improvement on ioapic hotplug
The revert of 991de2e59090 ("PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()") causes a problem for IOAPIC hotplug. If a device under the IOAPIC doesn't call pci_disable_device(), then the hot-removal of the IOAPIC causes kernel stack dump. This patchset can fix the problem. IOAPIC hot-removal works correctly after applying this patchset. v2: 0001 Fixed a missing stub function causing compiling error on i386 0002 Fixed a typo on the subject line. Rui Wang (2): x86/PCI: Implement pcibios_release_device to release IRQ from IOAPIC x86/ioapic: Split IOAPIC hot-removal into two steps arch/x86/pci/common.c | 9 + drivers/acpi/internal.h | 2 ++ drivers/acpi/ioapic.c | 22 -- drivers/acpi/pci_root.c | 4 ++-- 4 files changed, 29 insertions(+), 8 deletions(-) -- 1.8.3.1
[PATCH v2 0/2] Improvement on ioapic hotplug
The revert of 991de2e59090 ("PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()") causes a problem for IOAPIC hotplug. If a device under the IOAPIC doesn't call pci_disable_device(), then the hot-removal of the IOAPIC causes kernel stack dump. This patchset can fix the problem. IOAPIC hot-removal works correctly after applying this patchset. v2: 0001 Fixed a missing stub function causing compiling error on i386 0002 Fixed a typo on the subject line. Rui Wang (2): x86/PCI: Implement pcibios_release_device to release IRQ from IOAPIC x86/ioapic: Split IOAPIC hot-removal into two steps arch/x86/pci/common.c | 9 + drivers/acpi/internal.h | 2 ++ drivers/acpi/ioapic.c | 22 -- drivers/acpi/pci_root.c | 4 ++-- 4 files changed, 29 insertions(+), 8 deletions(-) -- 1.8.3.1
[PATCH v2 2/2] x86/ioapic: Split IOAPIC hot-removal into two steps
The hot-removal of IOAPIC is broken into two parts: the PCI part and the ACPI part. The PCI part releases PCI resources before the PCI bus is gone, and the ACPI part is moved to a stage later than the hot-removal of the PCI root bus, so that the IOAPIC driver is able to hook the pcibios_release_device() of every PCI device under the same parent root bus, before the IOAPIC is hot-removed. This makes it possible for the IOAPIC to free any IRQ resource previously unable to get freed. v2: Fixed compiling error on i386 (missing stub of pci_ioapic_remove()) Signed-off-by: Rui Wang --- drivers/acpi/internal.h | 2 ++ drivers/acpi/ioapic.c | 22 -- drivers/acpi/pci_root.c | 4 ++-- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 219b90b..f159001 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -41,8 +41,10 @@ static inline void acpi_amba_init(void) {} void acpi_container_init(void); void acpi_memory_hotplug_init(void); #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +void pci_ioapic_remove(struct acpi_pci_root *root); int acpi_ioapic_remove(struct acpi_pci_root *root); #else +static inline void pci_ioapic_remove(struct acpi_pci_root *root) { return; } static inline int acpi_ioapic_remove(struct acpi_pci_root *root) { return 0; } #endif #ifdef CONFIG_ACPI_DOCK diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 6d7ce6e..1120dfd6 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -206,24 +206,34 @@ int acpi_ioapic_add(acpi_handle root_handle) return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } -int acpi_ioapic_remove(struct acpi_pci_root *root) +void pci_ioapic_remove(struct acpi_pci_root *root) { - int retval = 0; struct acpi_pci_ioapic *ioapic, *tmp; mutex_lock(_list_lock); list_for_each_entry_safe(ioapic, tmp, _list, list) { if (root->device->handle != ioapic->root_handle) continue; - - if (acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base)) - retval = -EBUSY; - if (ioapic->pdev) { pci_release_region(ioapic->pdev, 0); pci_disable_device(ioapic->pdev); pci_dev_put(ioapic->pdev); } + } + mutex_unlock(_list_lock); +} + +int acpi_ioapic_remove(struct acpi_pci_root *root) +{ + int retval = 0; + struct acpi_pci_ioapic *ioapic, *tmp; + + mutex_lock(_list_lock); + list_for_each_entry_safe(ioapic, tmp, _list, list) { + if (root->device->handle != ioapic->root_handle) + continue; + if (acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base)) + retval = -EBUSY; if (ioapic->res.flags && ioapic->res.parent) release_resource(>res); list_del(>list); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index bf601d4..919be0a 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -648,12 +648,12 @@ static void acpi_pci_root_remove(struct acpi_device *device) pci_stop_root_bus(root->bus); - WARN_ON(acpi_ioapic_remove(root)); - + pci_ioapic_remove(root); device_set_run_wake(root->bus->bridge, false); pci_acpi_remove_bus_pm_notifier(device); pci_remove_root_bus(root->bus); + WARN_ON(acpi_ioapic_remove(root)); dmar_device_remove(device->handle); -- 1.8.3.1
[PATCH v2 1/2] x86/PCI: Implement pcibios_release_device to release IRQ from IOAPIC
The revert of 991de2e59090 ("PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()") causes a problem for IOAPIC hotplug. The problem is that IRQs are allocated and freed in pci_enable_device() and pci_disable_device(). But there are some drivers which don't call pci_disable_device(), and they have good reasons not calling it, so if they're using IOAPIC their IRQs won't have a chance to be released from the IOAPIC. When this happens IOAPIC hot-removal fails with a kernel stack dump and an error message like this: [149335.697989] pin16 on IOAPIC2 is still in use. It turns out that we can fix it in a different way without moving IRQ allocation into pcibios_alloc_irq(), thus avoiding the regression of 991de2e59090. We can keep the allocation and freeing of IRQs as is within pci_enable_device()/pci_disable_device(), without breaking any previous assumption of the rest of the system, keeping compatibility with both the legacy and the modern drivers. We can accomplish this by implementing the existing __weak hook of pcibios_release_device() thus when a pci device is about to be deleted we get notified in the hook and take the chance to release its IRQ, if any, from the IOAPIC. Besides implementing pcibios_release_device(), the hot-removal of IOAPIC needs to be broken into two parts: the PCI part and the ACPI part. The PCI part releases PCI resources before the PCI bus is gone, and the ACPI part is moved to a stage later than the hot-removal of the PCI root bus, so we have the chance to hook every PCI device's pcibios_release_device(), before we remove the IOAPIC. This patch implements pcibios_release_device() on x86 to release any IRQ not released by the driver, so that the IOAPIC can then be safely hot-removed. v2: Fixed a typo (pcibios_release_device) Signed-off-by: Rui Wang --- arch/x86/pci/common.c | 9 + 1 file changed, 9 insertions(+) diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 0cb52ae..190e718 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -735,6 +735,15 @@ void pcibios_disable_device (struct pci_dev *dev) pcibios_disable_irq(dev); } +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +void pcibios_release_device(struct pci_dev *dev) +{ + if (atomic_dec_return(>enable_cnt) >= 0) + pcibios_disable_device(dev); + +} +#endif + int pci_ext_cfg_avail(void) { if (raw_pci_ext_ops) -- 1.8.3.1
[PATCH 1/2] x86/PCI: Implement pci_release_device to release IRQ from IOAPIC
The revert of 991de2e59090 ("PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()") causes a problem for IOAPIC hotplug. The problem is that IRQs are allocated and freed in pci_enable_device() and pci_disable_device(). But there are some drivers which don't call pci_disable_device(), and they have good reasons not calling it, so if they're using IOAPIC their IRQs won't have a chance to be released from the IOAPIC. When this happens IOAPIC hot-removal fails with a kernel stack dump and an error message like this: [149335.697989] pin16 on IOAPIC2 is still in use. It turns out that we can fix it in a different way without moving IRQ allocation into pcibios_alloc_irq(), thus avoiding the regression of 991de2e59090. We can keep the allocation and freeing of IRQs as is within pci_enable_device()/pci_disable_device(), without breaking any previous assumption of the rest of the system, keeping compatibility with both the legacy and the modern drivers. We can accomplish this by implementing the existing __weak hook of pcibios_release_device() thus when a pci device is about to be deleted we get notified in the hook and take the chance to release its IRQ, if any, from the IOAPIC. Besides implementing pcibios_release_device(), the hot-removal of IOAPIC needs to be broken into two parts: the PCI part and the ACPI part. The PCI part releases PCI resources before the PCI bus is gone, and the ACPI part is moved to a stage later than the hot-removal of the PCI root bus, so we have the chance to hook every PCI device's pcibios_release_device(), before we remove the IOAPIC. This patch implements pcibios_release_device() on x86 to release any IRQ not released by the driver, so that the IOAPIC can then be safely hot-removed. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- arch/x86/pci/common.c | 9 + 1 file changed, 9 insertions(+) diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 0cb52ae..4eba071 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -735,6 +735,15 @@ void pcibios_disable_device (struct pci_dev *dev) pcibios_disable_irq(dev); } +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +void pcibios_release_device(struct pci_dev *dev) +{ + if (atomic_dec_return(>enable_cnt) >=0) + pcibios_disable_device(dev); + +} +#endif + int pci_ext_cfg_avail(void) { if (raw_pci_ext_ops) -- 1.8.3.1
[PATCH 1/2] x86/PCI: Implement pci_release_device to release IRQ from IOAPIC
The revert of 991de2e59090 ("PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()") causes a problem for IOAPIC hotplug. The problem is that IRQs are allocated and freed in pci_enable_device() and pci_disable_device(). But there are some drivers which don't call pci_disable_device(), and they have good reasons not calling it, so if they're using IOAPIC their IRQs won't have a chance to be released from the IOAPIC. When this happens IOAPIC hot-removal fails with a kernel stack dump and an error message like this: [149335.697989] pin16 on IOAPIC2 is still in use. It turns out that we can fix it in a different way without moving IRQ allocation into pcibios_alloc_irq(), thus avoiding the regression of 991de2e59090. We can keep the allocation and freeing of IRQs as is within pci_enable_device()/pci_disable_device(), without breaking any previous assumption of the rest of the system, keeping compatibility with both the legacy and the modern drivers. We can accomplish this by implementing the existing __weak hook of pcibios_release_device() thus when a pci device is about to be deleted we get notified in the hook and take the chance to release its IRQ, if any, from the IOAPIC. Besides implementing pcibios_release_device(), the hot-removal of IOAPIC needs to be broken into two parts: the PCI part and the ACPI part. The PCI part releases PCI resources before the PCI bus is gone, and the ACPI part is moved to a stage later than the hot-removal of the PCI root bus, so we have the chance to hook every PCI device's pcibios_release_device(), before we remove the IOAPIC. This patch implements pcibios_release_device() on x86 to release any IRQ not released by the driver, so that the IOAPIC can then be safely hot-removed. Signed-off-by: Rui Wang --- arch/x86/pci/common.c | 9 + 1 file changed, 9 insertions(+) diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 0cb52ae..4eba071 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -735,6 +735,15 @@ void pcibios_disable_device (struct pci_dev *dev) pcibios_disable_irq(dev); } +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +void pcibios_release_device(struct pci_dev *dev) +{ + if (atomic_dec_return(>enable_cnt) >=0) + pcibios_disable_device(dev); + +} +#endif + int pci_ext_cfg_avail(void) { if (raw_pci_ext_ops) -- 1.8.3.1
[PATCH 0/2] Improvement on ioapic hotplug
The revert of 991de2e59090 ("PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()") causes a problem for IOAPIC hotplug. If a device under the IOAPIC doesn't call pci_disable_device(), then the hot-removal of the IOAPIC causes kernel stack dump. This patchset can fix the problem. IOAPIC hot-removal works correctly after applying this patchset. Rui Wang (2): x86/PCI: Implement pci_release_device to release IRQ from IOAPIC x86/ioapic: Split IOAPIC hot-removal into two steps arch/x86/pci/common.c | 9 + drivers/acpi/internal.h | 1 + drivers/acpi/ioapic.c | 22 -- drivers/acpi/pci_root.c | 4 ++-- 4 files changed, 28 insertions(+), 8 deletions(-) -- 1.8.3.1
[PATCH 0/2] Improvement on ioapic hotplug
The revert of 991de2e59090 ("PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()") causes a problem for IOAPIC hotplug. If a device under the IOAPIC doesn't call pci_disable_device(), then the hot-removal of the IOAPIC causes kernel stack dump. This patchset can fix the problem. IOAPIC hot-removal works correctly after applying this patchset. Rui Wang (2): x86/PCI: Implement pci_release_device to release IRQ from IOAPIC x86/ioapic: Split IOAPIC hot-removal into two steps arch/x86/pci/common.c | 9 + drivers/acpi/internal.h | 1 + drivers/acpi/ioapic.c | 22 -- drivers/acpi/pci_root.c | 4 ++-- 4 files changed, 28 insertions(+), 8 deletions(-) -- 1.8.3.1
[PATCH 2/2] x86/ioapic: Split IOAPIC hot-removal into two steps
The hot-removal of IOAPIC is broken into two parts: the PCI part and the ACPI part. The PCI part releases PCI resources before the PCI bus is gone, and the ACPI part is moved to a stage later than the hot-removal of the PCI root bus, so that the IOAPIC driver is able to hook the pcibios_release_device() of every PCI device under the same parent root bus, before the IOAPIC is hot-removed. This makes it possible for the IOAPIC to free any IRQ resource previously unable to get freed. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/internal.h | 1 + drivers/acpi/ioapic.c | 22 -- drivers/acpi/pci_root.c | 4 ++-- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 219b90b..b2e3416 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -41,6 +41,7 @@ static inline void acpi_amba_init(void) {} void acpi_container_init(void); void acpi_memory_hotplug_init(void); #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +void pci_ioapic_remove(struct acpi_pci_root *root); int acpi_ioapic_remove(struct acpi_pci_root *root); #else static inline int acpi_ioapic_remove(struct acpi_pci_root *root) { return 0; } diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 6d7ce6e..1120dfd6 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -206,24 +206,34 @@ int acpi_ioapic_add(acpi_handle root_handle) return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } -int acpi_ioapic_remove(struct acpi_pci_root *root) +void pci_ioapic_remove(struct acpi_pci_root *root) { - int retval = 0; struct acpi_pci_ioapic *ioapic, *tmp; mutex_lock(_list_lock); list_for_each_entry_safe(ioapic, tmp, _list, list) { if (root->device->handle != ioapic->root_handle) continue; - - if (acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base)) - retval = -EBUSY; - if (ioapic->pdev) { pci_release_region(ioapic->pdev, 0); pci_disable_device(ioapic->pdev); pci_dev_put(ioapic->pdev); } + } + mutex_unlock(_list_lock); +} + +int acpi_ioapic_remove(struct acpi_pci_root *root) +{ + int retval = 0; + struct acpi_pci_ioapic *ioapic, *tmp; + + mutex_lock(_list_lock); + list_for_each_entry_safe(ioapic, tmp, _list, list) { + if (root->device->handle != ioapic->root_handle) + continue; + if (acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base)) + retval = -EBUSY; if (ioapic->res.flags && ioapic->res.parent) release_resource(>res); list_del(>list); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index bf601d4..919be0a 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -648,12 +648,12 @@ static void acpi_pci_root_remove(struct acpi_device *device) pci_stop_root_bus(root->bus); - WARN_ON(acpi_ioapic_remove(root)); - + pci_ioapic_remove(root); device_set_run_wake(root->bus->bridge, false); pci_acpi_remove_bus_pm_notifier(device); pci_remove_root_bus(root->bus); + WARN_ON(acpi_ioapic_remove(root)); dmar_device_remove(device->handle); -- 1.8.3.1
[PATCH 2/2] x86/ioapic: Split IOAPIC hot-removal into two steps
The hot-removal of IOAPIC is broken into two parts: the PCI part and the ACPI part. The PCI part releases PCI resources before the PCI bus is gone, and the ACPI part is moved to a stage later than the hot-removal of the PCI root bus, so that the IOAPIC driver is able to hook the pcibios_release_device() of every PCI device under the same parent root bus, before the IOAPIC is hot-removed. This makes it possible for the IOAPIC to free any IRQ resource previously unable to get freed. Signed-off-by: Rui Wang --- drivers/acpi/internal.h | 1 + drivers/acpi/ioapic.c | 22 -- drivers/acpi/pci_root.c | 4 ++-- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 219b90b..b2e3416 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -41,6 +41,7 @@ static inline void acpi_amba_init(void) {} void acpi_container_init(void); void acpi_memory_hotplug_init(void); #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +void pci_ioapic_remove(struct acpi_pci_root *root); int acpi_ioapic_remove(struct acpi_pci_root *root); #else static inline int acpi_ioapic_remove(struct acpi_pci_root *root) { return 0; } diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 6d7ce6e..1120dfd6 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -206,24 +206,34 @@ int acpi_ioapic_add(acpi_handle root_handle) return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } -int acpi_ioapic_remove(struct acpi_pci_root *root) +void pci_ioapic_remove(struct acpi_pci_root *root) { - int retval = 0; struct acpi_pci_ioapic *ioapic, *tmp; mutex_lock(_list_lock); list_for_each_entry_safe(ioapic, tmp, _list, list) { if (root->device->handle != ioapic->root_handle) continue; - - if (acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base)) - retval = -EBUSY; - if (ioapic->pdev) { pci_release_region(ioapic->pdev, 0); pci_disable_device(ioapic->pdev); pci_dev_put(ioapic->pdev); } + } + mutex_unlock(_list_lock); +} + +int acpi_ioapic_remove(struct acpi_pci_root *root) +{ + int retval = 0; + struct acpi_pci_ioapic *ioapic, *tmp; + + mutex_lock(_list_lock); + list_for_each_entry_safe(ioapic, tmp, _list, list) { + if (root->device->handle != ioapic->root_handle) + continue; + if (acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base)) + retval = -EBUSY; if (ioapic->res.flags && ioapic->res.parent) release_resource(>res); list_del(>list); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index bf601d4..919be0a 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -648,12 +648,12 @@ static void acpi_pci_root_remove(struct acpi_device *device) pci_stop_root_bus(root->bus); - WARN_ON(acpi_ioapic_remove(root)); - + pci_ioapic_remove(root); device_set_run_wake(root->bus->bridge, false); pci_acpi_remove_bus_pm_notifier(device); pci_remove_root_bus(root->bus); + WARN_ON(acpi_ioapic_remove(root)); dmar_device_remove(device->handle); -- 1.8.3.1
[tip:x86/apic] x86/ioapic: Ignore root bridges without a companion ACPI device
Commit-ID: d9c149d6ce1a94de578a4e323f6881fcb6b986ab Gitweb: http://git.kernel.org/tip/d9c149d6ce1a94de578a4e323f6881fcb6b986ab Author: Rui Wang <rui.y.w...@intel.com> AuthorDate: Sat, 10 Sep 2016 23:40:45 +0800 Committer: Ingo Molnar <mi...@kernel.org> CommitDate: Sat, 10 Sep 2016 20:30:31 +0200 x86/ioapic: Ignore root bridges without a companion ACPI device Some PCI root bridges don't have a corresponding ACPI device. This can be the case on some old platforms. Don't call acpi_ioapic_add() on these bridges because they can't support ioapic hotplug. Reported-and-tested-by: Borislav Petkov <b...@suse.de> Signed-off-by: Rui Wang <rui.y.w...@intel.com> Reviewed-by: Borislav Petkov <b...@alien8.de> Cc: Linus Torvalds <torva...@linux-foundation.org> Cc: Peter Zijlstra <pet...@infradead.org> Cc: Thomas Gleixner <t...@linutronix.de> Cc: bhelg...@google.com Cc: helg...@kernel.org Cc: linux-a...@vger.kernel.org Cc: linux-...@vger.kernel.org Cc: r...@rjwysocki.net Cc: tony.l...@intel.com Link: http://lkml.kernel.org/r/1473522046-31329-1-git-send-email-rui.y.w...@intel.com Signed-off-by: Ingo Molnar <mi...@kernel.org> --- drivers/pci/setup-bus.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index ec538d3..f30ca75 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1855,7 +1855,10 @@ void __init pci_assign_unassigned_resources(void) list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); - acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + + /* Make sure the root bridge has a companion ACPI device: */ + if (ACPI_HANDLE(root_bus->bridge)) + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); } }
[tip:x86/apic] x86/ioapic: Ignore root bridges without a companion ACPI device
Commit-ID: d9c149d6ce1a94de578a4e323f6881fcb6b986ab Gitweb: http://git.kernel.org/tip/d9c149d6ce1a94de578a4e323f6881fcb6b986ab Author: Rui Wang AuthorDate: Sat, 10 Sep 2016 23:40:45 +0800 Committer: Ingo Molnar CommitDate: Sat, 10 Sep 2016 20:30:31 +0200 x86/ioapic: Ignore root bridges without a companion ACPI device Some PCI root bridges don't have a corresponding ACPI device. This can be the case on some old platforms. Don't call acpi_ioapic_add() on these bridges because they can't support ioapic hotplug. Reported-and-tested-by: Borislav Petkov Signed-off-by: Rui Wang Reviewed-by: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bhelg...@google.com Cc: helg...@kernel.org Cc: linux-a...@vger.kernel.org Cc: linux-...@vger.kernel.org Cc: r...@rjwysocki.net Cc: tony.l...@intel.com Link: http://lkml.kernel.org/r/1473522046-31329-1-git-send-email-rui.y.w...@intel.com Signed-off-by: Ingo Molnar --- drivers/pci/setup-bus.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index ec538d3..f30ca75 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1855,7 +1855,10 @@ void __init pci_assign_unassigned_resources(void) list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); - acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + + /* Make sure the root bridge has a companion ACPI device: */ + if (ACPI_HANDLE(root_bus->bridge)) + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); } }
[PATCH] x86/ioapic: Ignore root bridges without a companion ACPI device
Some PCI root bridges don't have a corresponding ACPI device. This can be the case on some old platforms. Don't call acpi_ioapic_add() on these bridges because they can't support ioapic hotplug. v2: Per Boris's review, removed the unnecessary local var; refined comment Signed-off-by: Rui Wang <rui.y.w...@intel.com> Reviewed-by: Borislav Petkov <b...@alien8.de> --- drivers/pci/setup-bus.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index ec538d3..8b4e231 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1855,7 +1855,10 @@ void __init pci_assign_unassigned_resources(void) list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); - acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + + /* make sure the root bridge has a companion ACPI device */ + if (ACPI_HANDLE(root_bus->bridge)) + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); } } -- 1.8.3.1
[PATCH] x86/ioapic: Ignore root bridges without a companion ACPI device
Some PCI root bridges don't have a corresponding ACPI device. This can be the case on some old platforms. Don't call acpi_ioapic_add() on these bridges because they can't support ioapic hotplug. v2: Per Boris's review, removed the unnecessary local var; refined comment Signed-off-by: Rui Wang Reviewed-by: Borislav Petkov --- drivers/pci/setup-bus.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index ec538d3..8b4e231 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1855,7 +1855,10 @@ void __init pci_assign_unassigned_resources(void) list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); - acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + + /* make sure the root bridge has a companion ACPI device */ + if (ACPI_HANDLE(root_bus->bridge)) + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); } } -- 1.8.3.1
Re: 584c5c422f6c ("x86/ioapic: Support hot-removal of IOAPICs present during boot")
On Sat, Sep 10, 2016 10:31 PM, Borislav Petkov wrote: > > On Sat, Sep 10, 2016 at 09:11:30PM +0800, Rui Wang wrote: > > Thanks for the analysis. Looks like acpi_gbl_root_node == 0. It is > > Is ACPI_HANDLE(root_bus->bridge) == ACPI_ROOT_OBJECT? > > Because this is what the code does but I can't see it from the code that the > handle is of type ACPI_ROOT_OBJECT... > I seem to have the clue. It is because ACPI_HANDLE(root_bus->bridge) == NULL. Then this root bridge doesn't have a corresponding ACPI device. In this case we shouldn't call acpi_ioapic_add(). This can be true for some old platforms. If that's the case then the patch below can fix it. Thanks Rui >From b37d806c78e5eea70dbb890c1e3dbb8b7e5038e6 Mon Sep 17 00:00:00 2001 From: Rui Wang <rui.y.w...@intel.com> Date: Sat, 10 Sep 2016 10:56:34 -0400 Subject: [PATCH] x86/ioapic: Ignore root bridges without a companion ACPI device Some PCI root bridges don't have a corresponding ACPI device. Don't call acpi_ioapic_add() on these bridges because they can't support ioapic hotplug. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/pci/setup-bus.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index ec538d3..2b05ac6 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1852,10 +1852,15 @@ dump: void __init pci_assign_unassigned_resources(void) { struct pci_bus *root_bus; + acpi_handle root_handle; list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); - acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + root_handle = ACPI_HANDLE(root_bus->bridge); + + /* make sure the root bridge has a companion ACPI device */ + if (root_handle) + acpi_ioapic_add(root_handle); } } -- 1.8.3.1
Re: 584c5c422f6c ("x86/ioapic: Support hot-removal of IOAPICs present during boot")
On Sat, Sep 10, 2016 10:31 PM, Borislav Petkov wrote: > > On Sat, Sep 10, 2016 at 09:11:30PM +0800, Rui Wang wrote: > > Thanks for the analysis. Looks like acpi_gbl_root_node == 0. It is > > Is ACPI_HANDLE(root_bus->bridge) == ACPI_ROOT_OBJECT? > > Because this is what the code does but I can't see it from the code that the > handle is of type ACPI_ROOT_OBJECT... > I seem to have the clue. It is because ACPI_HANDLE(root_bus->bridge) == NULL. Then this root bridge doesn't have a corresponding ACPI device. In this case we shouldn't call acpi_ioapic_add(). This can be true for some old platforms. If that's the case then the patch below can fix it. Thanks Rui >From b37d806c78e5eea70dbb890c1e3dbb8b7e5038e6 Mon Sep 17 00:00:00 2001 From: Rui Wang Date: Sat, 10 Sep 2016 10:56:34 -0400 Subject: [PATCH] x86/ioapic: Ignore root bridges without a companion ACPI device Some PCI root bridges don't have a corresponding ACPI device. Don't call acpi_ioapic_add() on these bridges because they can't support ioapic hotplug. Signed-off-by: Rui Wang --- drivers/pci/setup-bus.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index ec538d3..2b05ac6 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1852,10 +1852,15 @@ dump: void __init pci_assign_unassigned_resources(void) { struct pci_bus *root_bus; + acpi_handle root_handle; list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); - acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + root_handle = ACPI_HANDLE(root_bus->bridge); + + /* make sure the root bridge has a companion ACPI device */ + if (root_handle) + acpi_ioapic_add(root_handle); } } -- 1.8.3.1
Re: 584c5c422f6c ("x86/ioapic: Support hot-removal of IOAPICs present during boot")
On Sat, Sep 10, 2016 7:28 PM, Borislav Petkov wrote: > > 8143ef50 : > 8143ef50: e8 6b 16 42 00 callq 818605c0 > <__fentry__> > 8143ef55: 55 push %rbp > 8143ef56: 48 89 e5mov%rsp,%rbp > 8143ef59: 41 57 push %r15 > 8143ef5b: 41 56 push %r14 > 8143ef5d: 49 89 f6mov%rsi,%r14 > 8143ef60: 41 55 push %r13 > 8143ef62: 41 54 push %r12 > 8143ef64: 41 89 ccmov%ecx,%r12d > 8143ef67: 53 push %rbx > 8143ef68: bb 01 00 00 00 mov$0x1,%ebx > 8143ef6d: 48 83 ec 28 sub$0x28,%rsp > 8143ef71: 48 83 fe ff cmp > $0x,%rsi > 8143ef75: 89 7d d0mov%edi,-0x30(%rbp) > 8143ef78: 4c 0f 44 35 58 7b 99cmove 0x1997b58(%rip),%r14 > # 82dd6ad8 > 8143ef7f: 01 > 8143ef80: 89 55 c8mov%edx,-0x38(%rbp) > 8143ef83: 45 31 ffxor%r15d,%r15d > 8143ef86: 41 83 e4 01 and$0x1,%r12d > 8143ef8a: 89 4d ccmov%ecx,-0x34(%rbp) > 8143ef8d: 4d 8b 6e 18 mov0x18(%r14),%r13 > <--- > faulting insn. > 8143ef91: 4c 89 45 c0 mov%r8,-0x40(%rbp) > 8143ef95: 4c 89 4d b8 mov%r9,-0x48(%rbp) > 8143ef99: c7 45 d4 00 00 00 00movl $0x0,-0x2c(%rbp) > 8143efa0: 4d 85 edtest %r13,%r13 Thanks for the analysis. Looks like acpi_gbl_root_node == 0. It is initialized earlier than where we call acpi_ioapic_add(). start_kernel() ->acpi_early_init() ->acpi_initialize_subsystem() ->acpi_ns_root_initialize() -> acpi_gbl_root_node = ... But acpi_gbl_root_node can be 0 if acpi_disabled == 1. Do you somehow have acpi turned off (!CONFIG_ACPI or booting with acpi=off)? Thanks Rui
Re: 584c5c422f6c ("x86/ioapic: Support hot-removal of IOAPICs present during boot")
On Sat, Sep 10, 2016 7:28 PM, Borislav Petkov wrote: > > 8143ef50 : > 8143ef50: e8 6b 16 42 00 callq 818605c0 > <__fentry__> > 8143ef55: 55 push %rbp > 8143ef56: 48 89 e5mov%rsp,%rbp > 8143ef59: 41 57 push %r15 > 8143ef5b: 41 56 push %r14 > 8143ef5d: 49 89 f6mov%rsi,%r14 > 8143ef60: 41 55 push %r13 > 8143ef62: 41 54 push %r12 > 8143ef64: 41 89 ccmov%ecx,%r12d > 8143ef67: 53 push %rbx > 8143ef68: bb 01 00 00 00 mov$0x1,%ebx > 8143ef6d: 48 83 ec 28 sub$0x28,%rsp > 8143ef71: 48 83 fe ff cmp > $0x,%rsi > 8143ef75: 89 7d d0mov%edi,-0x30(%rbp) > 8143ef78: 4c 0f 44 35 58 7b 99cmove 0x1997b58(%rip),%r14 > # 82dd6ad8 > 8143ef7f: 01 > 8143ef80: 89 55 c8mov%edx,-0x38(%rbp) > 8143ef83: 45 31 ffxor%r15d,%r15d > 8143ef86: 41 83 e4 01 and$0x1,%r12d > 8143ef8a: 89 4d ccmov%ecx,-0x34(%rbp) > 8143ef8d: 4d 8b 6e 18 mov0x18(%r14),%r13 > <--- > faulting insn. > 8143ef91: 4c 89 45 c0 mov%r8,-0x40(%rbp) > 8143ef95: 4c 89 4d b8 mov%r9,-0x48(%rbp) > 8143ef99: c7 45 d4 00 00 00 00movl $0x0,-0x2c(%rbp) > 8143efa0: 4d 85 edtest %r13,%r13 Thanks for the analysis. Looks like acpi_gbl_root_node == 0. It is initialized earlier than where we call acpi_ioapic_add(). start_kernel() ->acpi_early_init() ->acpi_initialize_subsystem() ->acpi_ns_root_initialize() -> acpi_gbl_root_node = ... But acpi_gbl_root_node can be 0 if acpi_disabled == 1. Do you somehow have acpi turned off (!CONFIG_ACPI or booting with acpi=off)? Thanks Rui
584c5c422f6c ("x86/ioapic: Support hot-removal of IOAPICs present during boot")
On Saturday, September 10, 2016 6:07 AM, Borislav Petkov wrote: > > Hi, > > commit in $Subject from tip breaks booting on my SNB test box, it freezes > somewhere very early during boot. When I revert the aforementioned > commit ontop of Linus' master + tip/master from today, it boots fine. > > Additional info is available upon request. > Hi Boris, Is it a Romley-EP ? What kind of SNB box is it? I'll try to find one to reproduce the problem. Thanks Rui
584c5c422f6c ("x86/ioapic: Support hot-removal of IOAPICs present during boot")
On Saturday, September 10, 2016 6:07 AM, Borislav Petkov wrote: > > Hi, > > commit in $Subject from tip breaks booting on my SNB test box, it freezes > somewhere very early during boot. When I revert the aforementioned > commit ontop of Linus' master + tip/master from today, it boots fine. > > Additional info is available upon request. > Hi Boris, Is it a Romley-EP ? What kind of SNB box is it? I'll try to find one to reproduce the problem. Thanks Rui
[tip:x86/apic] x86/ioapic: Support hot-removal of IOAPICs present during boot
Commit-ID: 584c5c422f6c749ced1e0bc3c6837f650f64e1e1 Gitweb: http://git.kernel.org/tip/584c5c422f6c749ced1e0bc3c6837f650f64e1e1 Author: Rui Wang <rui.y.w...@intel.com> AuthorDate: Wed, 17 Aug 2016 16:00:34 +0800 Committer: Ingo Molnar <mi...@kernel.org> CommitDate: Thu, 18 Aug 2016 11:45:18 +0200 x86/ioapic: Support hot-removal of IOAPICs present during boot IOAPICs present during system boot aren't added to ioapic_list, thus are unable to be hot-removed. Fix it by calling acpi_ioapic_add() during root bus enumeration. Signed-off-by: Rui Wang <rui.y.w...@intel.com> Acked-by: Bjorn Helgaas <bhelg...@google.com> Cc: Linus Torvalds <torva...@linux-foundation.org> Cc: Peter Zijlstra <pet...@infradead.org> Cc: Thomas Gleixner <t...@linutronix.de> Cc: helg...@kernel.org Cc: linux-a...@vger.kernel.org Cc: linux-...@vger.kernel.org Cc: r...@rjwysocki.net Cc: tony.l...@intel.com Link: http://lkml.kernel.org/r/1471420837-31003-3-git-send-email-rui.y.w...@intel.com Signed-off-by: Ingo Molnar <mi...@kernel.org> --- drivers/acpi/pci_root.c | 10 ++ drivers/pci/setup-bus.c | 5 - 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index b07eda1..bf601d4 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,6 +614,16 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); + /* +* This is only called for the hotadd case. For the boot-time +* case, we need to wait until after PCI initialization in +* order to deal with IOAPICs mapped in on a PCI BAR. +* +* This is currently x86-specific, because acpi_ioapic_add() +* is an empty function without CONFIG_ACPI_HOTPLUG_IOAPIC. +* And CONFIG_ACPI_HOTPLUG_IOAPIC depends on CONFIG_X86_IO_APIC +* (see drivers/acpi/Kconfig). +*/ acpi_ioapic_add(root->device->handle); } diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index c74059e..ec538d3 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "pci.h" unsigned int pci_flags; @@ -1852,8 +1853,10 @@ void __init pci_assign_unassigned_resources(void) { struct pci_bus *root_bus; - list_for_each_entry(root_bus, _root_buses, node) + list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + } } void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
[tip:x86/apic] x86/ioapic: Support hot-removal of IOAPICs present during boot
Commit-ID: 584c5c422f6c749ced1e0bc3c6837f650f64e1e1 Gitweb: http://git.kernel.org/tip/584c5c422f6c749ced1e0bc3c6837f650f64e1e1 Author: Rui Wang AuthorDate: Wed, 17 Aug 2016 16:00:34 +0800 Committer: Ingo Molnar CommitDate: Thu, 18 Aug 2016 11:45:18 +0200 x86/ioapic: Support hot-removal of IOAPICs present during boot IOAPICs present during system boot aren't added to ioapic_list, thus are unable to be hot-removed. Fix it by calling acpi_ioapic_add() during root bus enumeration. Signed-off-by: Rui Wang Acked-by: Bjorn Helgaas Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: helg...@kernel.org Cc: linux-a...@vger.kernel.org Cc: linux-...@vger.kernel.org Cc: r...@rjwysocki.net Cc: tony.l...@intel.com Link: http://lkml.kernel.org/r/1471420837-31003-3-git-send-email-rui.y.w...@intel.com Signed-off-by: Ingo Molnar --- drivers/acpi/pci_root.c | 10 ++ drivers/pci/setup-bus.c | 5 - 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index b07eda1..bf601d4 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,6 +614,16 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); + /* +* This is only called for the hotadd case. For the boot-time +* case, we need to wait until after PCI initialization in +* order to deal with IOAPICs mapped in on a PCI BAR. +* +* This is currently x86-specific, because acpi_ioapic_add() +* is an empty function without CONFIG_ACPI_HOTPLUG_IOAPIC. +* And CONFIG_ACPI_HOTPLUG_IOAPIC depends on CONFIG_X86_IO_APIC +* (see drivers/acpi/Kconfig). +*/ acpi_ioapic_add(root->device->handle); } diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index c74059e..ec538d3 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "pci.h" unsigned int pci_flags; @@ -1852,8 +1853,10 @@ void __init pci_assign_unassigned_resources(void) { struct pci_bus *root_bus; - list_for_each_entry(root_bus, _root_buses, node) + list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + } } void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
[tip:x86/apic] x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd
Commit-ID: 162b83bd5f1d7124e21da78bcf2685b9824d9ef0 Gitweb: http://git.kernel.org/tip/162b83bd5f1d7124e21da78bcf2685b9824d9ef0 Author: Rui Wang <rui.y.w...@intel.com> AuthorDate: Wed, 17 Aug 2016 16:00:36 +0800 Committer: Ingo Molnar <mi...@kernel.org> CommitDate: Thu, 18 Aug 2016 11:45:18 +0200 x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd IOAPIC resource at 0xfecx gets lost from /proc/iomem after hot-removing and then hot-adding the IOAPIC device. After system boot, in /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 Then hot-remove IOAPIC 2 and hot-add it again: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 The range at 0xfec4 is lost from /proc/iomem - which is a bug. This bug happens because handle_ioapic_add() requests resources from either PCI config BAR or ACPI "_CRS", not both. But Intel platforms map the IOxAPIC registers both at the PCI config BAR (called MBAR, dynamic), and at the ACPI "_CRS" (called ABAR, static). The 0xfecX_YZ00 to 0xfecX_YZFF range appears in "_CRS" of each IOAPIC device. Both ranges should be claimed from /proc/iomem for exclusive use. Signed-off-by: Rui Wang <rui.y.w...@intel.com> Cc: Linus Torvalds <torva...@linux-foundation.org> Cc: Peter Zijlstra <pet...@infradead.org> Cc: Thomas Gleixner <t...@linutronix.de> Cc: bhelg...@google.com Cc: helg...@kernel.org Cc: linux-a...@vger.kernel.org Cc: linux-...@vger.kernel.org Cc: r...@rjwysocki.net Cc: tony.l...@intel.com Link: http://lkml.kernel.org/r/1471420837-31003-5-git-send-email-rui.y.w...@intel.com Signed-off-by: Ingo Molnar <mi...@kernel.org> --- drivers/acpi/ioapic.c | 36 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 8ab6d42..ee20111 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -97,7 +97,7 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, unsigned long long gsi_base; struct acpi_pci_ioapic *ioapic; struct pci_dev *dev = NULL; - struct resource *res = NULL; + struct resource *res = NULL, *pci_res = NULL, *crs_res; char *type = NULL; if (!acpi_is_ioapic(handle, )) @@ -137,23 +137,28 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, pci_set_master(dev); if (pci_request_region(dev, 0, type)) goto exit_disable; - res = >resource[0]; + pci_res = >resource[0]; ioapic->pdev = dev; } else { pci_dev_put(dev); dev = NULL; + } - res = >res; - acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, res); - if (res->flags == 0) { - acpi_handle_warn(handle, "failed to get resource\n"); - goto exit_free; - } else if (request_resource(_resource, res)) { - acpi_handle_warn(handle, "failed to insert resource\n"); - goto exit_free; - } + crs_res = >res; + acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + if (crs_res->flags == 0) { + acpi_handle_warn(handle, "failed to get resource\n"); + goto exit_release; + } else if (request_resource(_resource, crs_res)) { + acpi_handle_warn(handle, "failed to insert resource\n"); + goto exit_release; } + /* try pci resource first, then "_CRS" resource */ + res = pci_res; + if (!res || !res->flags) + res = crs_res; + if (acpi_register_ioapic(handle, res->start, (u32)gsi_base)) { acpi_handle_warn(handle, "failed to register IOAPIC\n"); goto exit_release; @@ -174,14 +179,13 @@ done: exit_release: if (dev) pci_release_region(dev, 0); - else - release_resource(res); + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); exit_disable: if (dev) pci_disable_device(dev); exit_put: pci_dev_put(dev); -exit_free: kfree(ioapic); exit: mutex_unlock(_list_lock); @@ -217,9 +221,9 @@ int acpi_ioapic_remove(struct acpi_pci_root *root) pci_release_region(ioapic->pdev, 0); pci_disable_device(ioapic->pdev); pci_dev_put(ioapic
[tip:x86/apic] x86/ioapic: Fix setup_res() failing to get resource
Commit-ID: 6ab7eba5db93c11d61f6f7fbe21edbc875b26c1a Gitweb: http://git.kernel.org/tip/6ab7eba5db93c11d61f6f7fbe21edbc875b26c1a Author: Rui Wang <rui.y.w...@intel.com> AuthorDate: Wed, 17 Aug 2016 16:00:35 +0800 Committer: Ingo Molnar <mi...@kernel.org> CommitDate: Thu, 18 Aug 2016 11:45:18 +0200 x86/ioapic: Fix setup_res() failing to get resource acpi_dev_filter_resource_type() returns 0 on success, and 1 on failure. A return value of zero means there's a matching resource, so we should continue within setup_res() to get the resource. Signed-off-by: Rui Wang <rui.y.w...@intel.com> Cc: Linus Torvalds <torva...@linux-foundation.org> Cc: Peter Zijlstra <pet...@infradead.org> Cc: Thomas Gleixner <t...@linutronix.de> Cc: bhelg...@google.com Cc: helg...@kernel.org Cc: linux-a...@vger.kernel.org Cc: linux-...@vger.kernel.org Cc: r...@rjwysocki.net Cc: tony.l...@intel.com Link: http://lkml.kernel.org/r/1471420837-31003-4-git-send-email-rui.y.w...@intel.com Signed-off-by: Ingo Molnar <mi...@kernel.org> --- drivers/acpi/ioapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 2449377..8ab6d42 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -46,7 +46,7 @@ static acpi_status setup_res(struct acpi_resource *acpi_res, void *data) struct resource_win win; res->flags = 0; - if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM) == 0) + if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM)) return AE_OK; if (!acpi_dev_resource_memory(acpi_res, res)) {
[tip:x86/apic] x86/ioapic: Fix IOAPIC failing to request resource
Commit-ID: 624cad9d2907a0788b56e3ca664c5d7d02645ed4 Gitweb: http://git.kernel.org/tip/624cad9d2907a0788b56e3ca664c5d7d02645ed4 Author: Rui Wang <rui.y.w...@intel.com> AuthorDate: Wed, 17 Aug 2016 16:00:37 +0800 Committer: Ingo Molnar <mi...@kernel.org> CommitDate: Thu, 18 Aug 2016 11:45:19 +0200 x86/ioapic: Fix IOAPIC failing to request resource handle_ioapic_add() uses request_resource() to request ACPI "_CRS" resources. This can fail with the following error message: [ 247.325693] ACPI: \_SB_.IIO1.AID1: failed to insert resource This happens when there are multiple IOAPICs and DSDT groups their "_CRS" resources as the children of a parent resource, as seen from /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 In this case request_resource() fails because there's a conflicting resource which is the parent (fec-fecf). Fix it by using insert_resource() which can request resources by taking the conflicting resource as the parent. Signed-off-by: Rui Wang <rui.y.w...@intel.com> Cc: Linus Torvalds <torva...@linux-foundation.org> Cc: Peter Zijlstra <pet...@infradead.org> Cc: Thomas Gleixner <t...@linutronix.de> Cc: bhelg...@google.com Cc: helg...@kernel.org Cc: linux-a...@vger.kernel.org Cc: linux-...@vger.kernel.org Cc: r...@rjwysocki.net Cc: tony.l...@intel.com Link: http://lkml.kernel.org/r/1471420837-31003-6-git-send-email-rui.y.w...@intel.com Signed-off-by: Ingo Molnar <mi...@kernel.org> --- drivers/acpi/ioapic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ee20111..6d7ce6e 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -146,10 +146,12 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, crs_res = >res; acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + crs_res->name = type; + crs_res->flags |= IORESOURCE_BUSY; if (crs_res->flags == 0) { acpi_handle_warn(handle, "failed to get resource\n"); goto exit_release; - } else if (request_resource(_resource, crs_res)) { + } else if (insert_resource(_resource, crs_res)) { acpi_handle_warn(handle, "failed to insert resource\n"); goto exit_release; }
[tip:x86/apic] x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd
Commit-ID: 162b83bd5f1d7124e21da78bcf2685b9824d9ef0 Gitweb: http://git.kernel.org/tip/162b83bd5f1d7124e21da78bcf2685b9824d9ef0 Author: Rui Wang AuthorDate: Wed, 17 Aug 2016 16:00:36 +0800 Committer: Ingo Molnar CommitDate: Thu, 18 Aug 2016 11:45:18 +0200 x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd IOAPIC resource at 0xfecx gets lost from /proc/iomem after hot-removing and then hot-adding the IOAPIC device. After system boot, in /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 Then hot-remove IOAPIC 2 and hot-add it again: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 The range at 0xfec4 is lost from /proc/iomem - which is a bug. This bug happens because handle_ioapic_add() requests resources from either PCI config BAR or ACPI "_CRS", not both. But Intel platforms map the IOxAPIC registers both at the PCI config BAR (called MBAR, dynamic), and at the ACPI "_CRS" (called ABAR, static). The 0xfecX_YZ00 to 0xfecX_YZFF range appears in "_CRS" of each IOAPIC device. Both ranges should be claimed from /proc/iomem for exclusive use. Signed-off-by: Rui Wang Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bhelg...@google.com Cc: helg...@kernel.org Cc: linux-a...@vger.kernel.org Cc: linux-...@vger.kernel.org Cc: r...@rjwysocki.net Cc: tony.l...@intel.com Link: http://lkml.kernel.org/r/1471420837-31003-5-git-send-email-rui.y.w...@intel.com Signed-off-by: Ingo Molnar --- drivers/acpi/ioapic.c | 36 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 8ab6d42..ee20111 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -97,7 +97,7 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, unsigned long long gsi_base; struct acpi_pci_ioapic *ioapic; struct pci_dev *dev = NULL; - struct resource *res = NULL; + struct resource *res = NULL, *pci_res = NULL, *crs_res; char *type = NULL; if (!acpi_is_ioapic(handle, )) @@ -137,23 +137,28 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, pci_set_master(dev); if (pci_request_region(dev, 0, type)) goto exit_disable; - res = >resource[0]; + pci_res = >resource[0]; ioapic->pdev = dev; } else { pci_dev_put(dev); dev = NULL; + } - res = >res; - acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, res); - if (res->flags == 0) { - acpi_handle_warn(handle, "failed to get resource\n"); - goto exit_free; - } else if (request_resource(_resource, res)) { - acpi_handle_warn(handle, "failed to insert resource\n"); - goto exit_free; - } + crs_res = >res; + acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + if (crs_res->flags == 0) { + acpi_handle_warn(handle, "failed to get resource\n"); + goto exit_release; + } else if (request_resource(_resource, crs_res)) { + acpi_handle_warn(handle, "failed to insert resource\n"); + goto exit_release; } + /* try pci resource first, then "_CRS" resource */ + res = pci_res; + if (!res || !res->flags) + res = crs_res; + if (acpi_register_ioapic(handle, res->start, (u32)gsi_base)) { acpi_handle_warn(handle, "failed to register IOAPIC\n"); goto exit_release; @@ -174,14 +179,13 @@ done: exit_release: if (dev) pci_release_region(dev, 0); - else - release_resource(res); + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); exit_disable: if (dev) pci_disable_device(dev); exit_put: pci_dev_put(dev); -exit_free: kfree(ioapic); exit: mutex_unlock(_list_lock); @@ -217,9 +221,9 @@ int acpi_ioapic_remove(struct acpi_pci_root *root) pci_release_region(ioapic->pdev, 0); pci_disable_device(ioapic->pdev); pci_dev_put(ioapic->pdev); - } else if (ioapic->res.flags && ioapic->res.parent) { - release_resource(>res); } + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); list_del(>list); kfree(ioapic); }
[tip:x86/apic] x86/ioapic: Fix setup_res() failing to get resource
Commit-ID: 6ab7eba5db93c11d61f6f7fbe21edbc875b26c1a Gitweb: http://git.kernel.org/tip/6ab7eba5db93c11d61f6f7fbe21edbc875b26c1a Author: Rui Wang AuthorDate: Wed, 17 Aug 2016 16:00:35 +0800 Committer: Ingo Molnar CommitDate: Thu, 18 Aug 2016 11:45:18 +0200 x86/ioapic: Fix setup_res() failing to get resource acpi_dev_filter_resource_type() returns 0 on success, and 1 on failure. A return value of zero means there's a matching resource, so we should continue within setup_res() to get the resource. Signed-off-by: Rui Wang Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bhelg...@google.com Cc: helg...@kernel.org Cc: linux-a...@vger.kernel.org Cc: linux-...@vger.kernel.org Cc: r...@rjwysocki.net Cc: tony.l...@intel.com Link: http://lkml.kernel.org/r/1471420837-31003-4-git-send-email-rui.y.w...@intel.com Signed-off-by: Ingo Molnar --- drivers/acpi/ioapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 2449377..8ab6d42 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -46,7 +46,7 @@ static acpi_status setup_res(struct acpi_resource *acpi_res, void *data) struct resource_win win; res->flags = 0; - if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM) == 0) + if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM)) return AE_OK; if (!acpi_dev_resource_memory(acpi_res, res)) {
[tip:x86/apic] x86/ioapic: Fix IOAPIC failing to request resource
Commit-ID: 624cad9d2907a0788b56e3ca664c5d7d02645ed4 Gitweb: http://git.kernel.org/tip/624cad9d2907a0788b56e3ca664c5d7d02645ed4 Author: Rui Wang AuthorDate: Wed, 17 Aug 2016 16:00:37 +0800 Committer: Ingo Molnar CommitDate: Thu, 18 Aug 2016 11:45:19 +0200 x86/ioapic: Fix IOAPIC failing to request resource handle_ioapic_add() uses request_resource() to request ACPI "_CRS" resources. This can fail with the following error message: [ 247.325693] ACPI: \_SB_.IIO1.AID1: failed to insert resource This happens when there are multiple IOAPICs and DSDT groups their "_CRS" resources as the children of a parent resource, as seen from /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 In this case request_resource() fails because there's a conflicting resource which is the parent (fec-fecf). Fix it by using insert_resource() which can request resources by taking the conflicting resource as the parent. Signed-off-by: Rui Wang Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bhelg...@google.com Cc: helg...@kernel.org Cc: linux-a...@vger.kernel.org Cc: linux-...@vger.kernel.org Cc: r...@rjwysocki.net Cc: tony.l...@intel.com Link: http://lkml.kernel.org/r/1471420837-31003-6-git-send-email-rui.y.w...@intel.com Signed-off-by: Ingo Molnar --- drivers/acpi/ioapic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ee20111..6d7ce6e 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -146,10 +146,12 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, crs_res = >res; acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + crs_res->name = type; + crs_res->flags |= IORESOURCE_BUSY; if (crs_res->flags == 0) { acpi_handle_warn(handle, "failed to get resource\n"); goto exit_release; - } else if (request_resource(_resource, crs_res)) { + } else if (insert_resource(_resource, crs_res)) { acpi_handle_warn(handle, "failed to insert resource\n"); goto exit_release; }
[tip:x86/apic] x86/ioapic: Change prototype of acpi_ioapic_add()
Commit-ID: fe7bd58f5d25d5d655b1da4a084cc4ef6f085fee Gitweb: http://git.kernel.org/tip/fe7bd58f5d25d5d655b1da4a084cc4ef6f085fee Author: Rui Wang <rui.y.w...@intel.com> AuthorDate: Wed, 17 Aug 2016 16:00:33 +0800 Committer: Ingo Molnar <mi...@kernel.org> CommitDate: Thu, 18 Aug 2016 11:45:18 +0200 x86/ioapic: Change prototype of acpi_ioapic_add() Change the argument of acpi_ioapic_add() to a generic ACPI handle, and move its prototype from drivers/acpi/internal.h to include/linux/acpi.h so that it can be called from outside the pci_root driver. Signed-off-by: Rui Wang <rui.y.w...@intel.com> Cc: Linus Torvalds <torva...@linux-foundation.org> Cc: Peter Zijlstra <pet...@infradead.org> Cc: Thomas Gleixner <t...@linutronix.de> Cc: bhelg...@google.com Cc: helg...@kernel.org Cc: linux-a...@vger.kernel.org Cc: linux-...@vger.kernel.org Cc: r...@rjwysocki.net Cc: tony.l...@intel.com Link: http://lkml.kernel.org/r/1471420837-31003-2-git-send-email-rui.y.w...@intel.com Signed-off-by: Ingo Molnar <mi...@kernel.org> --- drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 6 +++--- drivers/acpi/pci_root.c | 2 +- include/linux/acpi.h| 6 ++ 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 940218f..f26fc1d 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -40,10 +40,8 @@ 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 diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ccdc8db..2449377 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -189,13 +189,13 @@ exit: return AE_OK; } -int acpi_ioapic_add(struct acpi_pci_root *root) +int acpi_ioapic_add(acpi_handle root_handle) { acpi_status status, retval = AE_OK; - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device->handle, + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root_handle, UINT_MAX, handle_ioapic_add, NULL, -root->device->handle, (void **)); +root_handle, (void **)); return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d144168..b07eda1 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,7 +614,7 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); - acpi_ioapic_add(root); + acpi_ioapic_add(root->device->handle); } pci_lock_rescan_remove(); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 4d8452c..c9a596b 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -751,6 +751,12 @@ static inline int acpi_reconfig_notifier_unregister(struct notifier_block *nb) #endif /* !CONFIG_ACPI */ +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +int acpi_ioapic_add(acpi_handle root); +#else +static inline int acpi_ioapic_add(acpi_handle root) { return 0; } +#endif + #ifdef CONFIG_ACPI void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, u32 pm1a_ctrl, u32 pm1b_ctrl));
[tip:x86/apic] x86/ioapic: Change prototype of acpi_ioapic_add()
Commit-ID: fe7bd58f5d25d5d655b1da4a084cc4ef6f085fee Gitweb: http://git.kernel.org/tip/fe7bd58f5d25d5d655b1da4a084cc4ef6f085fee Author: Rui Wang AuthorDate: Wed, 17 Aug 2016 16:00:33 +0800 Committer: Ingo Molnar CommitDate: Thu, 18 Aug 2016 11:45:18 +0200 x86/ioapic: Change prototype of acpi_ioapic_add() Change the argument of acpi_ioapic_add() to a generic ACPI handle, and move its prototype from drivers/acpi/internal.h to include/linux/acpi.h so that it can be called from outside the pci_root driver. Signed-off-by: Rui Wang Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bhelg...@google.com Cc: helg...@kernel.org Cc: linux-a...@vger.kernel.org Cc: linux-...@vger.kernel.org Cc: r...@rjwysocki.net Cc: tony.l...@intel.com Link: http://lkml.kernel.org/r/1471420837-31003-2-git-send-email-rui.y.w...@intel.com Signed-off-by: Ingo Molnar --- drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 6 +++--- drivers/acpi/pci_root.c | 2 +- include/linux/acpi.h| 6 ++ 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 940218f..f26fc1d 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -40,10 +40,8 @@ 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 diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ccdc8db..2449377 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -189,13 +189,13 @@ exit: return AE_OK; } -int acpi_ioapic_add(struct acpi_pci_root *root) +int acpi_ioapic_add(acpi_handle root_handle) { acpi_status status, retval = AE_OK; - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device->handle, + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root_handle, UINT_MAX, handle_ioapic_add, NULL, -root->device->handle, (void **)); +root_handle, (void **)); return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d144168..b07eda1 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,7 +614,7 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); - acpi_ioapic_add(root); + acpi_ioapic_add(root->device->handle); } pci_lock_rescan_remove(); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 4d8452c..c9a596b 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -751,6 +751,12 @@ static inline int acpi_reconfig_notifier_unregister(struct notifier_block *nb) #endif /* !CONFIG_ACPI */ +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +int acpi_ioapic_add(acpi_handle root); +#else +static inline int acpi_ioapic_add(acpi_handle root) { return 0; } +#endif + #ifdef CONFIG_ACPI void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, u32 pm1a_ctrl, u32 pm1b_ctrl));
[PATCH v4 4/5] x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd
IOAPIC resource at 0xfecx gets lost from /proc/iomem after hot-removing and then hot-adding the IOAPIC device. After system boot, in /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 Then hot-remove IOAPIC 2 and hot-add it again: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 The range at 0xfec4 is lost from /proc/iomem. It is because handle_ioapic_add() requests resource from either PCI config BAR or ACPI "_CRS", not both. But Intel platforms map the IOxAPIC registers both at the PCI config BAR (called MBAR, dynamic), and at the ACPI "_CRS" (called ABAR, static). The 0xfecX_YZ00 to 0xfecX_YZFF range appears in "_CRS" of each IOAPIC device. Both ranges should be claimed from /proc/iomem for exclusive use. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/ioapic.c | 36 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 8ab6d42..ee20111 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -97,7 +97,7 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, unsigned long long gsi_base; struct acpi_pci_ioapic *ioapic; struct pci_dev *dev = NULL; - struct resource *res = NULL; + struct resource *res = NULL, *pci_res = NULL, *crs_res; char *type = NULL; if (!acpi_is_ioapic(handle, )) @@ -137,23 +137,28 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, pci_set_master(dev); if (pci_request_region(dev, 0, type)) goto exit_disable; - res = >resource[0]; + pci_res = >resource[0]; ioapic->pdev = dev; } else { pci_dev_put(dev); dev = NULL; + } - res = >res; - acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, res); - if (res->flags == 0) { - acpi_handle_warn(handle, "failed to get resource\n"); - goto exit_free; - } else if (request_resource(_resource, res)) { - acpi_handle_warn(handle, "failed to insert resource\n"); - goto exit_free; - } + crs_res = >res; + acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + if (crs_res->flags == 0) { + acpi_handle_warn(handle, "failed to get resource\n"); + goto exit_release; + } else if (request_resource(_resource, crs_res)) { + acpi_handle_warn(handle, "failed to insert resource\n"); + goto exit_release; } + /* try pci resource first, then "_CRS" resource */ + res = pci_res; + if (!res || !res->flags) + res = crs_res; + if (acpi_register_ioapic(handle, res->start, (u32)gsi_base)) { acpi_handle_warn(handle, "failed to register IOAPIC\n"); goto exit_release; @@ -174,14 +179,13 @@ done: exit_release: if (dev) pci_release_region(dev, 0); - else - release_resource(res); + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); exit_disable: if (dev) pci_disable_device(dev); exit_put: pci_dev_put(dev); -exit_free: kfree(ioapic); exit: mutex_unlock(_list_lock); @@ -217,9 +221,9 @@ int acpi_ioapic_remove(struct acpi_pci_root *root) pci_release_region(ioapic->pdev, 0); pci_disable_device(ioapic->pdev); pci_dev_put(ioapic->pdev); - } else if (ioapic->res.flags && ioapic->res.parent) { - release_resource(>res); } + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); list_del(>list); kfree(ioapic); } -- 1.8.3.1
[PATCH v4 4/5] x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd
IOAPIC resource at 0xfecx gets lost from /proc/iomem after hot-removing and then hot-adding the IOAPIC device. After system boot, in /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 Then hot-remove IOAPIC 2 and hot-add it again: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 The range at 0xfec4 is lost from /proc/iomem. It is because handle_ioapic_add() requests resource from either PCI config BAR or ACPI "_CRS", not both. But Intel platforms map the IOxAPIC registers both at the PCI config BAR (called MBAR, dynamic), and at the ACPI "_CRS" (called ABAR, static). The 0xfecX_YZ00 to 0xfecX_YZFF range appears in "_CRS" of each IOAPIC device. Both ranges should be claimed from /proc/iomem for exclusive use. Signed-off-by: Rui Wang --- drivers/acpi/ioapic.c | 36 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 8ab6d42..ee20111 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -97,7 +97,7 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, unsigned long long gsi_base; struct acpi_pci_ioapic *ioapic; struct pci_dev *dev = NULL; - struct resource *res = NULL; + struct resource *res = NULL, *pci_res = NULL, *crs_res; char *type = NULL; if (!acpi_is_ioapic(handle, )) @@ -137,23 +137,28 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, pci_set_master(dev); if (pci_request_region(dev, 0, type)) goto exit_disable; - res = >resource[0]; + pci_res = >resource[0]; ioapic->pdev = dev; } else { pci_dev_put(dev); dev = NULL; + } - res = >res; - acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, res); - if (res->flags == 0) { - acpi_handle_warn(handle, "failed to get resource\n"); - goto exit_free; - } else if (request_resource(_resource, res)) { - acpi_handle_warn(handle, "failed to insert resource\n"); - goto exit_free; - } + crs_res = >res; + acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + if (crs_res->flags == 0) { + acpi_handle_warn(handle, "failed to get resource\n"); + goto exit_release; + } else if (request_resource(_resource, crs_res)) { + acpi_handle_warn(handle, "failed to insert resource\n"); + goto exit_release; } + /* try pci resource first, then "_CRS" resource */ + res = pci_res; + if (!res || !res->flags) + res = crs_res; + if (acpi_register_ioapic(handle, res->start, (u32)gsi_base)) { acpi_handle_warn(handle, "failed to register IOAPIC\n"); goto exit_release; @@ -174,14 +179,13 @@ done: exit_release: if (dev) pci_release_region(dev, 0); - else - release_resource(res); + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); exit_disable: if (dev) pci_disable_device(dev); exit_put: pci_dev_put(dev); -exit_free: kfree(ioapic); exit: mutex_unlock(_list_lock); @@ -217,9 +221,9 @@ int acpi_ioapic_remove(struct acpi_pci_root *root) pci_release_region(ioapic->pdev, 0); pci_disable_device(ioapic->pdev); pci_dev_put(ioapic->pdev); - } else if (ioapic->res.flags && ioapic->res.parent) { - release_resource(>res); } + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); list_del(>list); kfree(ioapic); } -- 1.8.3.1
[PATCH v4 1/5] x86/ioapic: Change prototype of acpi_ioapic_add()
Change the argument of acpi_ioapic_add() to a generic ACPI handle, and move its prototype from drivers/acpi/internal.h to include/linux/acpi.h so that it can be called from outside the pci_root driver. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 6 +++--- drivers/acpi/pci_root.c | 2 +- include/linux/acpi.h| 6 ++ 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 940218f..f26fc1d 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -40,10 +40,8 @@ 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 diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ccdc8db..2449377 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -189,13 +189,13 @@ exit: return AE_OK; } -int acpi_ioapic_add(struct acpi_pci_root *root) +int acpi_ioapic_add(acpi_handle root_handle) { acpi_status status, retval = AE_OK; - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device->handle, + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root_handle, UINT_MAX, handle_ioapic_add, NULL, -root->device->handle, (void **)); +root_handle, (void **)); return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d144168..b07eda1 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,7 +614,7 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); - acpi_ioapic_add(root); + acpi_ioapic_add(root->device->handle); } pci_lock_rescan_remove(); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 4d8452c..c9a596b 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -751,6 +751,12 @@ static inline int acpi_reconfig_notifier_unregister(struct notifier_block *nb) #endif /* !CONFIG_ACPI */ +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +int acpi_ioapic_add(acpi_handle root); +#else +static inline int acpi_ioapic_add(acpi_handle root) { return 0; } +#endif + #ifdef CONFIG_ACPI void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, u32 pm1a_ctrl, u32 pm1b_ctrl)); -- 1.8.3.1
[PATCH v4 2/5] x86/ioapic: Support hot-removal of IOAPICs present during boot
IOAPICs present during system boot aren't added to ioapic_list, thus are unable to be hot-removed. Fix it by calling acpi_ioapic_add() during root bus enumeration. Signed-off-by: Rui Wang <rui.y.w...@intel.com> Acked-by: Bjorn Helgaas <bhelg...@google.com> --- drivers/acpi/pci_root.c | 10 ++ drivers/pci/setup-bus.c | 5 - 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index b07eda1..bf601d4 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,6 +614,16 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); + /* +* This is only called for the hotadd case. For the boot-time +* case, we need to wait until after PCI initialization in +* order to deal with IOAPICs mapped in on a PCI BAR. +* +* This is currently x86-specific, because acpi_ioapic_add() +* is an empty function without CONFIG_ACPI_HOTPLUG_IOAPIC. +* And CONFIG_ACPI_HOTPLUG_IOAPIC depends on CONFIG_X86_IO_APIC +* (see drivers/acpi/Kconfig). +*/ acpi_ioapic_add(root->device->handle); } diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index c74059e..ec538d3 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "pci.h" unsigned int pci_flags; @@ -1852,8 +1853,10 @@ void __init pci_assign_unassigned_resources(void) { struct pci_bus *root_bus; - list_for_each_entry(root_bus, _root_buses, node) + list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + } } void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) -- 1.8.3.1
[PATCH v4 1/5] x86/ioapic: Change prototype of acpi_ioapic_add()
Change the argument of acpi_ioapic_add() to a generic ACPI handle, and move its prototype from drivers/acpi/internal.h to include/linux/acpi.h so that it can be called from outside the pci_root driver. Signed-off-by: Rui Wang --- drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 6 +++--- drivers/acpi/pci_root.c | 2 +- include/linux/acpi.h| 6 ++ 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 940218f..f26fc1d 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -40,10 +40,8 @@ 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 diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ccdc8db..2449377 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -189,13 +189,13 @@ exit: return AE_OK; } -int acpi_ioapic_add(struct acpi_pci_root *root) +int acpi_ioapic_add(acpi_handle root_handle) { acpi_status status, retval = AE_OK; - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device->handle, + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root_handle, UINT_MAX, handle_ioapic_add, NULL, -root->device->handle, (void **)); +root_handle, (void **)); return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d144168..b07eda1 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,7 +614,7 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); - acpi_ioapic_add(root); + acpi_ioapic_add(root->device->handle); } pci_lock_rescan_remove(); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 4d8452c..c9a596b 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -751,6 +751,12 @@ static inline int acpi_reconfig_notifier_unregister(struct notifier_block *nb) #endif /* !CONFIG_ACPI */ +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +int acpi_ioapic_add(acpi_handle root); +#else +static inline int acpi_ioapic_add(acpi_handle root) { return 0; } +#endif + #ifdef CONFIG_ACPI void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, u32 pm1a_ctrl, u32 pm1b_ctrl)); -- 1.8.3.1
[PATCH v4 2/5] x86/ioapic: Support hot-removal of IOAPICs present during boot
IOAPICs present during system boot aren't added to ioapic_list, thus are unable to be hot-removed. Fix it by calling acpi_ioapic_add() during root bus enumeration. Signed-off-by: Rui Wang Acked-by: Bjorn Helgaas --- drivers/acpi/pci_root.c | 10 ++ drivers/pci/setup-bus.c | 5 - 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index b07eda1..bf601d4 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,6 +614,16 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); + /* +* This is only called for the hotadd case. For the boot-time +* case, we need to wait until after PCI initialization in +* order to deal with IOAPICs mapped in on a PCI BAR. +* +* This is currently x86-specific, because acpi_ioapic_add() +* is an empty function without CONFIG_ACPI_HOTPLUG_IOAPIC. +* And CONFIG_ACPI_HOTPLUG_IOAPIC depends on CONFIG_X86_IO_APIC +* (see drivers/acpi/Kconfig). +*/ acpi_ioapic_add(root->device->handle); } diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index c74059e..ec538d3 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "pci.h" unsigned int pci_flags; @@ -1852,8 +1853,10 @@ void __init pci_assign_unassigned_resources(void) { struct pci_bus *root_bus; - list_for_each_entry(root_bus, _root_buses, node) + list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + } } void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) -- 1.8.3.1
[PATCH v4 5/5] x86/ioapic: Fix ioapic failing to request resource
handle_ioapic_add() uses request_resource() to request ACPI "_CRS" resources. This can fail with the following error message: [ 247.325693] ACPI: \_SB_.IIO1.AID1: failed to insert resource This happens when there are multiple IOAPICs and DSDT groups their "_CRS" resources as the children of a parent resource, as seen from /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 In this case request_resource() fails because there's a conflicting resource which is the parent (fec-fecf). Fix it by using insert_resource() which can request resources by taking the conflicting resource as the parent. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/ioapic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ee20111..6d7ce6e 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -146,10 +146,12 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, crs_res = >res; acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + crs_res->name = type; + crs_res->flags |= IORESOURCE_BUSY; if (crs_res->flags == 0) { acpi_handle_warn(handle, "failed to get resource\n"); goto exit_release; - } else if (request_resource(_resource, crs_res)) { + } else if (insert_resource(_resource, crs_res)) { acpi_handle_warn(handle, "failed to insert resource\n"); goto exit_release; } -- 1.8.3.1
[PATCH v4 5/5] x86/ioapic: Fix ioapic failing to request resource
handle_ioapic_add() uses request_resource() to request ACPI "_CRS" resources. This can fail with the following error message: [ 247.325693] ACPI: \_SB_.IIO1.AID1: failed to insert resource This happens when there are multiple IOAPICs and DSDT groups their "_CRS" resources as the children of a parent resource, as seen from /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 In this case request_resource() fails because there's a conflicting resource which is the parent (fec-fecf). Fix it by using insert_resource() which can request resources by taking the conflicting resource as the parent. Signed-off-by: Rui Wang --- drivers/acpi/ioapic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ee20111..6d7ce6e 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -146,10 +146,12 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, crs_res = >res; acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + crs_res->name = type; + crs_res->flags |= IORESOURCE_BUSY; if (crs_res->flags == 0) { acpi_handle_warn(handle, "failed to get resource\n"); goto exit_release; - } else if (request_resource(_resource, crs_res)) { + } else if (insert_resource(_resource, crs_res)) { acpi_handle_warn(handle, "failed to insert resource\n"); goto exit_release; } -- 1.8.3.1
[PATCH v4 0/5] Fixing a set of bugs for ioapic hotplug
A set of patches fixing bugs found while testing IOAPIC hotplug. Regards, Rui Changelog: Changes from v3 to v4: * Rebased on top of 4.8-rc2 and re-tested it. * Added the missing 'Acked-by: Bjorn Helgaas <bhelg...@google.com>' in 0002. * Sent to x...@kernel.org for review as suggested by Rafael. Changes from v2 to v3: * Rebased on top of 4.8-rc1 per Bjorn & Rafael. * Improved the commit message of 0003, w/ clearer explanation. Changes from v1 to v2: * Split the first patch into two as advised by Bjorn: "would be nicer if the interface change and header file munging were in a separate patch so they wouldn't obscure the meat of the change, i.e., the addition of calls to acpi_ioapic_add()." * Removed acpi_ioapic_add() as an exported symbol. * Fixed some typos, and s/acpi/ACPI/, s/ioapic/IOAPIC/ throughout. * Fixed a warning from 0-day testing. Rui Wang (5): x86/ioapic: Change prototype of acpi_ioapic_add() x86/ioapic: Support hot-removal of IOAPICs present during boot x86/ioapic: Fix setup_res() failing to get resource x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd x86/ioapic: Fix ioapic failing to request resource drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 46 ++ drivers/acpi/pci_root.c | 12 +++- drivers/pci/setup-bus.c | 5 - include/linux/acpi.h| 6 ++ 5 files changed, 47 insertions(+), 24 deletions(-) -- 1.8.3.1
[PATCH v4 0/5] Fixing a set of bugs for ioapic hotplug
A set of patches fixing bugs found while testing IOAPIC hotplug. Regards, Rui Changelog: Changes from v3 to v4: * Rebased on top of 4.8-rc2 and re-tested it. * Added the missing 'Acked-by: Bjorn Helgaas ' in 0002. * Sent to x...@kernel.org for review as suggested by Rafael. Changes from v2 to v3: * Rebased on top of 4.8-rc1 per Bjorn & Rafael. * Improved the commit message of 0003, w/ clearer explanation. Changes from v1 to v2: * Split the first patch into two as advised by Bjorn: "would be nicer if the interface change and header file munging were in a separate patch so they wouldn't obscure the meat of the change, i.e., the addition of calls to acpi_ioapic_add()." * Removed acpi_ioapic_add() as an exported symbol. * Fixed some typos, and s/acpi/ACPI/, s/ioapic/IOAPIC/ throughout. * Fixed a warning from 0-day testing. Rui Wang (5): x86/ioapic: Change prototype of acpi_ioapic_add() x86/ioapic: Support hot-removal of IOAPICs present during boot x86/ioapic: Fix setup_res() failing to get resource x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd x86/ioapic: Fix ioapic failing to request resource drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 46 ++ drivers/acpi/pci_root.c | 12 +++- drivers/pci/setup-bus.c | 5 - include/linux/acpi.h| 6 ++ 5 files changed, 47 insertions(+), 24 deletions(-) -- 1.8.3.1
[PATCH v4 3/5] x86/ioapic: Fix setup_res() failing to get resource
acpi_dev_filter_resource_type() returns 0 on success, and 1 on failure. A return value of zero means there's a matching resource, so we should continue within setup_res() to get the resource. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/ioapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 2449377..8ab6d42 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -46,7 +46,7 @@ static acpi_status setup_res(struct acpi_resource *acpi_res, void *data) struct resource_win win; res->flags = 0; - if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM) == 0) + if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM)) return AE_OK; if (!acpi_dev_resource_memory(acpi_res, res)) { -- 1.8.3.1
[PATCH v4 3/5] x86/ioapic: Fix setup_res() failing to get resource
acpi_dev_filter_resource_type() returns 0 on success, and 1 on failure. A return value of zero means there's a matching resource, so we should continue within setup_res() to get the resource. Signed-off-by: Rui Wang --- drivers/acpi/ioapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 2449377..8ab6d42 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -46,7 +46,7 @@ static acpi_status setup_res(struct acpi_resource *acpi_res, void *data) struct resource_win win; res->flags = 0; - if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM) == 0) + if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM)) return AE_OK; if (!acpi_dev_resource_memory(acpi_res, res)) { -- 1.8.3.1
[PATCH v3 0/5] Fixing a set of bugs for ioapic hotplug
On Wed, Aug 17, 2016 8:36 AM Rafael J. Wysocki wrote: > On Wednesday, August 10, 2016 12:01:53 PM Rui Wang wrote: > > A set of patches fixing bugs found while testing IOAPIC hotplug. > > This should have been posted to the x...@kernel.org list too for the benefit > of the maintainers. > > Can you please resend it with a CC to that one (and the Bjorn's ACK on the > second patch)? > Thanks for the advice. Will do. Regards, Rui > Thanks, > Rafael > > > > Changelog: > > > > Changes from v2 to v3: > > * Rebased on top of 4.8-rc1 per Bjorn & Rafael. > > * Improved the commit message of 0003, w/ clearer explanation. > > > > Changes from v1 to v2: > > * Split the first patch into two as advised by Bjorn: "would be nicer > > if the interface change and header file munging were in a separate > > patch so they wouldn't obscure the meat of the change, i.e., the > > addition of calls to acpi_ioapic_add()." > > * Removed acpi_ioapic_add() as an exported symbol. > > * Fixed some typos, and s/acpi/ACPI/, s/ioapic/IOAPIC/ throughout. > > * Fixed a warning from 0-day testing. > > > > Rui Wang (5): > > x86/ioapic: Change prototype of acpi_ioapic_add() > > x86/ioapic: Support hot-removal of IOAPICs present during boot > > x86/ioapic: Fix setup_res() failing to get resource > > x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd > > x86/ioapic: Fix ioapic failing to request resource > > > > drivers/acpi/internal.h | 2 -- > > drivers/acpi/ioapic.c | 46 ++- > --- > > drivers/acpi/pci_root.c | 12 +++- drivers/pci/setup-bus.c | > > 5 - > > include/linux/acpi.h| 6 ++ > > 5 files changed, 47 insertions(+), 24 deletions(-)
[PATCH v3 0/5] Fixing a set of bugs for ioapic hotplug
On Wed, Aug 17, 2016 8:36 AM Rafael J. Wysocki wrote: > On Wednesday, August 10, 2016 12:01:53 PM Rui Wang wrote: > > A set of patches fixing bugs found while testing IOAPIC hotplug. > > This should have been posted to the x...@kernel.org list too for the benefit > of the maintainers. > > Can you please resend it with a CC to that one (and the Bjorn's ACK on the > second patch)? > Thanks for the advice. Will do. Regards, Rui > Thanks, > Rafael > > > > Changelog: > > > > Changes from v2 to v3: > > * Rebased on top of 4.8-rc1 per Bjorn & Rafael. > > * Improved the commit message of 0003, w/ clearer explanation. > > > > Changes from v1 to v2: > > * Split the first patch into two as advised by Bjorn: "would be nicer > > if the interface change and header file munging were in a separate > > patch so they wouldn't obscure the meat of the change, i.e., the > > addition of calls to acpi_ioapic_add()." > > * Removed acpi_ioapic_add() as an exported symbol. > > * Fixed some typos, and s/acpi/ACPI/, s/ioapic/IOAPIC/ throughout. > > * Fixed a warning from 0-day testing. > > > > Rui Wang (5): > > x86/ioapic: Change prototype of acpi_ioapic_add() > > x86/ioapic: Support hot-removal of IOAPICs present during boot > > x86/ioapic: Fix setup_res() failing to get resource > > x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd > > x86/ioapic: Fix ioapic failing to request resource > > > > drivers/acpi/internal.h | 2 -- > > drivers/acpi/ioapic.c | 46 ++- > --- > > drivers/acpi/pci_root.c | 12 +++- drivers/pci/setup-bus.c | > > 5 - > > include/linux/acpi.h| 6 ++ > > 5 files changed, 47 insertions(+), 24 deletions(-)
[PATCH v3 4/5] x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd
IOAPIC resource at 0xfecx gets lost from /proc/iomem after hot-removing and then hot-adding the IOAPIC device. After system boot, in /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 Then hot-remove IOAPIC 2 and hot-add it again: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 The range at 0xfec4 is lost from /proc/iomem. It is because handle_ioapic_add() requests resource from either PCI config BAR or ACPI "_CRS", not both. But Intel platforms map the IOxAPIC registers both at the PCI config BAR (called MBAR, dynamic), and at the ACPI "_CRS" (called ABAR, static). The 0xfecX_YZ00 to 0xfecX_YZFF range appears in "_CRS" of each IOAPIC device. Both ranges should be claimed from /proc/iomem for exclusive use. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/ioapic.c | 36 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 8ab6d42..ee20111 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -97,7 +97,7 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, unsigned long long gsi_base; struct acpi_pci_ioapic *ioapic; struct pci_dev *dev = NULL; - struct resource *res = NULL; + struct resource *res = NULL, *pci_res = NULL, *crs_res; char *type = NULL; if (!acpi_is_ioapic(handle, )) @@ -137,23 +137,28 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, pci_set_master(dev); if (pci_request_region(dev, 0, type)) goto exit_disable; - res = >resource[0]; + pci_res = >resource[0]; ioapic->pdev = dev; } else { pci_dev_put(dev); dev = NULL; + } - res = >res; - acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, res); - if (res->flags == 0) { - acpi_handle_warn(handle, "failed to get resource\n"); - goto exit_free; - } else if (request_resource(_resource, res)) { - acpi_handle_warn(handle, "failed to insert resource\n"); - goto exit_free; - } + crs_res = >res; + acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + if (crs_res->flags == 0) { + acpi_handle_warn(handle, "failed to get resource\n"); + goto exit_release; + } else if (request_resource(_resource, crs_res)) { + acpi_handle_warn(handle, "failed to insert resource\n"); + goto exit_release; } + /* try pci resource first, then "_CRS" resource */ + res = pci_res; + if (!res || !res->flags) + res = crs_res; + if (acpi_register_ioapic(handle, res->start, (u32)gsi_base)) { acpi_handle_warn(handle, "failed to register IOAPIC\n"); goto exit_release; @@ -174,14 +179,13 @@ done: exit_release: if (dev) pci_release_region(dev, 0); - else - release_resource(res); + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); exit_disable: if (dev) pci_disable_device(dev); exit_put: pci_dev_put(dev); -exit_free: kfree(ioapic); exit: mutex_unlock(_list_lock); @@ -217,9 +221,9 @@ int acpi_ioapic_remove(struct acpi_pci_root *root) pci_release_region(ioapic->pdev, 0); pci_disable_device(ioapic->pdev); pci_dev_put(ioapic->pdev); - } else if (ioapic->res.flags && ioapic->res.parent) { - release_resource(>res); } + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); list_del(>list); kfree(ioapic); } -- 1.8.3.1
[PATCH v3 2/5] x86/ioapic: Support hot-removal of IOAPICs present during boot
IOAPICs present during system boot aren't added to ioapic_list, thus are unable to be hot-removed. Fix it by calling acpi_ioapic_add() during root bus enumeration. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/pci_root.c | 10 ++ drivers/pci/setup-bus.c | 5 - 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index b07eda1..bf601d4 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,6 +614,16 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); + /* +* This is only called for the hotadd case. For the boot-time +* case, we need to wait until after PCI initialization in +* order to deal with IOAPICs mapped in on a PCI BAR. +* +* This is currently x86-specific, because acpi_ioapic_add() +* is an empty function without CONFIG_ACPI_HOTPLUG_IOAPIC. +* And CONFIG_ACPI_HOTPLUG_IOAPIC depends on CONFIG_X86_IO_APIC +* (see drivers/acpi/Kconfig). +*/ acpi_ioapic_add(root->device->handle); } diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index c74059e..ec538d3 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "pci.h" unsigned int pci_flags; @@ -1852,8 +1853,10 @@ void __init pci_assign_unassigned_resources(void) { struct pci_bus *root_bus; - list_for_each_entry(root_bus, _root_buses, node) + list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + } } void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) -- 1.8.3.1
[PATCH v3 1/5] x86/ioapic: Change prototype of acpi_ioapic_add()
Change the argument of acpi_ioapic_add() to a generic ACPI handle, and move its prototype from drivers/acpi/internal.h to include/linux/acpi.h so that it can be called from outside the pci_root driver. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 6 +++--- drivers/acpi/pci_root.c | 2 +- include/linux/acpi.h| 6 ++ 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 940218f..f26fc1d 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -40,10 +40,8 @@ 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 diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ccdc8db..2449377 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -189,13 +189,13 @@ exit: return AE_OK; } -int acpi_ioapic_add(struct acpi_pci_root *root) +int acpi_ioapic_add(acpi_handle root_handle) { acpi_status status, retval = AE_OK; - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device->handle, + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root_handle, UINT_MAX, handle_ioapic_add, NULL, -root->device->handle, (void **)); +root_handle, (void **)); return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d144168..b07eda1 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,7 +614,7 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); - acpi_ioapic_add(root); + acpi_ioapic_add(root->device->handle); } pci_lock_rescan_remove(); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 4d8452c..c9a596b 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -751,6 +751,12 @@ static inline int acpi_reconfig_notifier_unregister(struct notifier_block *nb) #endif /* !CONFIG_ACPI */ +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +int acpi_ioapic_add(acpi_handle root); +#else +static inline int acpi_ioapic_add(acpi_handle root) { return 0; } +#endif + #ifdef CONFIG_ACPI void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, u32 pm1a_ctrl, u32 pm1b_ctrl)); -- 1.8.3.1
[PATCH v3 4/5] x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd
IOAPIC resource at 0xfecx gets lost from /proc/iomem after hot-removing and then hot-adding the IOAPIC device. After system boot, in /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 Then hot-remove IOAPIC 2 and hot-add it again: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 The range at 0xfec4 is lost from /proc/iomem. It is because handle_ioapic_add() requests resource from either PCI config BAR or ACPI "_CRS", not both. But Intel platforms map the IOxAPIC registers both at the PCI config BAR (called MBAR, dynamic), and at the ACPI "_CRS" (called ABAR, static). The 0xfecX_YZ00 to 0xfecX_YZFF range appears in "_CRS" of each IOAPIC device. Both ranges should be claimed from /proc/iomem for exclusive use. Signed-off-by: Rui Wang --- drivers/acpi/ioapic.c | 36 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 8ab6d42..ee20111 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -97,7 +97,7 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, unsigned long long gsi_base; struct acpi_pci_ioapic *ioapic; struct pci_dev *dev = NULL; - struct resource *res = NULL; + struct resource *res = NULL, *pci_res = NULL, *crs_res; char *type = NULL; if (!acpi_is_ioapic(handle, )) @@ -137,23 +137,28 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, pci_set_master(dev); if (pci_request_region(dev, 0, type)) goto exit_disable; - res = >resource[0]; + pci_res = >resource[0]; ioapic->pdev = dev; } else { pci_dev_put(dev); dev = NULL; + } - res = >res; - acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, res); - if (res->flags == 0) { - acpi_handle_warn(handle, "failed to get resource\n"); - goto exit_free; - } else if (request_resource(_resource, res)) { - acpi_handle_warn(handle, "failed to insert resource\n"); - goto exit_free; - } + crs_res = >res; + acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + if (crs_res->flags == 0) { + acpi_handle_warn(handle, "failed to get resource\n"); + goto exit_release; + } else if (request_resource(_resource, crs_res)) { + acpi_handle_warn(handle, "failed to insert resource\n"); + goto exit_release; } + /* try pci resource first, then "_CRS" resource */ + res = pci_res; + if (!res || !res->flags) + res = crs_res; + if (acpi_register_ioapic(handle, res->start, (u32)gsi_base)) { acpi_handle_warn(handle, "failed to register IOAPIC\n"); goto exit_release; @@ -174,14 +179,13 @@ done: exit_release: if (dev) pci_release_region(dev, 0); - else - release_resource(res); + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); exit_disable: if (dev) pci_disable_device(dev); exit_put: pci_dev_put(dev); -exit_free: kfree(ioapic); exit: mutex_unlock(_list_lock); @@ -217,9 +221,9 @@ int acpi_ioapic_remove(struct acpi_pci_root *root) pci_release_region(ioapic->pdev, 0); pci_disable_device(ioapic->pdev); pci_dev_put(ioapic->pdev); - } else if (ioapic->res.flags && ioapic->res.parent) { - release_resource(>res); } + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); list_del(>list); kfree(ioapic); } -- 1.8.3.1
[PATCH v3 2/5] x86/ioapic: Support hot-removal of IOAPICs present during boot
IOAPICs present during system boot aren't added to ioapic_list, thus are unable to be hot-removed. Fix it by calling acpi_ioapic_add() during root bus enumeration. Signed-off-by: Rui Wang --- drivers/acpi/pci_root.c | 10 ++ drivers/pci/setup-bus.c | 5 - 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index b07eda1..bf601d4 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,6 +614,16 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); + /* +* This is only called for the hotadd case. For the boot-time +* case, we need to wait until after PCI initialization in +* order to deal with IOAPICs mapped in on a PCI BAR. +* +* This is currently x86-specific, because acpi_ioapic_add() +* is an empty function without CONFIG_ACPI_HOTPLUG_IOAPIC. +* And CONFIG_ACPI_HOTPLUG_IOAPIC depends on CONFIG_X86_IO_APIC +* (see drivers/acpi/Kconfig). +*/ acpi_ioapic_add(root->device->handle); } diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index c74059e..ec538d3 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "pci.h" unsigned int pci_flags; @@ -1852,8 +1853,10 @@ void __init pci_assign_unassigned_resources(void) { struct pci_bus *root_bus; - list_for_each_entry(root_bus, _root_buses, node) + list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + } } void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) -- 1.8.3.1
[PATCH v3 1/5] x86/ioapic: Change prototype of acpi_ioapic_add()
Change the argument of acpi_ioapic_add() to a generic ACPI handle, and move its prototype from drivers/acpi/internal.h to include/linux/acpi.h so that it can be called from outside the pci_root driver. Signed-off-by: Rui Wang --- drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 6 +++--- drivers/acpi/pci_root.c | 2 +- include/linux/acpi.h| 6 ++ 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 940218f..f26fc1d 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -40,10 +40,8 @@ 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 diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ccdc8db..2449377 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -189,13 +189,13 @@ exit: return AE_OK; } -int acpi_ioapic_add(struct acpi_pci_root *root) +int acpi_ioapic_add(acpi_handle root_handle) { acpi_status status, retval = AE_OK; - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device->handle, + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root_handle, UINT_MAX, handle_ioapic_add, NULL, -root->device->handle, (void **)); +root_handle, (void **)); return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d144168..b07eda1 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,7 +614,7 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); - acpi_ioapic_add(root); + acpi_ioapic_add(root->device->handle); } pci_lock_rescan_remove(); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 4d8452c..c9a596b 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -751,6 +751,12 @@ static inline int acpi_reconfig_notifier_unregister(struct notifier_block *nb) #endif /* !CONFIG_ACPI */ +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +int acpi_ioapic_add(acpi_handle root); +#else +static inline int acpi_ioapic_add(acpi_handle root) { return 0; } +#endif + #ifdef CONFIG_ACPI void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, u32 pm1a_ctrl, u32 pm1b_ctrl)); -- 1.8.3.1
[PATCH v3 0/5] Fixing a set of bugs for ioapic hotplug
A set of patches fixing bugs found while testing IOAPIC hotplug. Regards, Rui Changelog: Changes from v2 to v3: * Rebased on top of 4.8-rc1 per Bjorn & Rafael. * Improved the commit message of 0003, w/ clearer explanation. Changes from v1 to v2: * Split the first patch into two as advised by Bjorn: "would be nicer if the interface change and header file munging were in a separate patch so they wouldn't obscure the meat of the change, i.e., the addition of calls to acpi_ioapic_add()." * Removed acpi_ioapic_add() as an exported symbol. * Fixed some typos, and s/acpi/ACPI/, s/ioapic/IOAPIC/ throughout. * Fixed a warning from 0-day testing. Rui Wang (5): x86/ioapic: Change prototype of acpi_ioapic_add() x86/ioapic: Support hot-removal of IOAPICs present during boot x86/ioapic: Fix setup_res() failing to get resource x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd x86/ioapic: Fix ioapic failing to request resource drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 46 ++ drivers/acpi/pci_root.c | 12 +++- drivers/pci/setup-bus.c | 5 - include/linux/acpi.h| 6 ++ 5 files changed, 47 insertions(+), 24 deletions(-) -- 1.8.3.1
[PATCH v3 0/5] Fixing a set of bugs for ioapic hotplug
A set of patches fixing bugs found while testing IOAPIC hotplug. Regards, Rui Changelog: Changes from v2 to v3: * Rebased on top of 4.8-rc1 per Bjorn & Rafael. * Improved the commit message of 0003, w/ clearer explanation. Changes from v1 to v2: * Split the first patch into two as advised by Bjorn: "would be nicer if the interface change and header file munging were in a separate patch so they wouldn't obscure the meat of the change, i.e., the addition of calls to acpi_ioapic_add()." * Removed acpi_ioapic_add() as an exported symbol. * Fixed some typos, and s/acpi/ACPI/, s/ioapic/IOAPIC/ throughout. * Fixed a warning from 0-day testing. Rui Wang (5): x86/ioapic: Change prototype of acpi_ioapic_add() x86/ioapic: Support hot-removal of IOAPICs present during boot x86/ioapic: Fix setup_res() failing to get resource x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd x86/ioapic: Fix ioapic failing to request resource drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 46 ++ drivers/acpi/pci_root.c | 12 +++- drivers/pci/setup-bus.c | 5 - include/linux/acpi.h| 6 ++ 5 files changed, 47 insertions(+), 24 deletions(-) -- 1.8.3.1
[PATCH v3 3/5] x86/ioapic: Fix setup_res() failing to get resource
acpi_dev_filter_resource_type() returns 0 on success, and 1 on failure. A return value of zero means there's a matching resource, so we should continue within setup_res() to get the resource. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/ioapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 2449377..8ab6d42 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -46,7 +46,7 @@ static acpi_status setup_res(struct acpi_resource *acpi_res, void *data) struct resource_win win; res->flags = 0; - if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM) == 0) + if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM)) return AE_OK; if (!acpi_dev_resource_memory(acpi_res, res)) { -- 1.8.3.1
[PATCH v3 5/5] x86/ioapic: Fix ioapic failing to request resource
handle_ioapic_add() uses request_resource() to request ACPI "_CRS" resources. This can fail with the following error message: [ 247.325693] ACPI: \_SB_.IIO1.AID1: failed to insert resource This happens when there are multiple IOAPICs and DSDT groups their "_CRS" resources as the children of a parent resource, as seen from /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 In this case request_resource() fails because there's a conflicting resource which is the parent (fec-fecf). Fix it by using insert_resource() which can request resources by taking the conflicting resource as the parent. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/ioapic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ee20111..6d7ce6e 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -146,10 +146,12 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, crs_res = >res; acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + crs_res->name = type; + crs_res->flags |= IORESOURCE_BUSY; if (crs_res->flags == 0) { acpi_handle_warn(handle, "failed to get resource\n"); goto exit_release; - } else if (request_resource(_resource, crs_res)) { + } else if (insert_resource(_resource, crs_res)) { acpi_handle_warn(handle, "failed to insert resource\n"); goto exit_release; } -- 1.8.3.1
[PATCH v3 3/5] x86/ioapic: Fix setup_res() failing to get resource
acpi_dev_filter_resource_type() returns 0 on success, and 1 on failure. A return value of zero means there's a matching resource, so we should continue within setup_res() to get the resource. Signed-off-by: Rui Wang --- drivers/acpi/ioapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 2449377..8ab6d42 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -46,7 +46,7 @@ static acpi_status setup_res(struct acpi_resource *acpi_res, void *data) struct resource_win win; res->flags = 0; - if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM) == 0) + if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM)) return AE_OK; if (!acpi_dev_resource_memory(acpi_res, res)) { -- 1.8.3.1
[PATCH v3 5/5] x86/ioapic: Fix ioapic failing to request resource
handle_ioapic_add() uses request_resource() to request ACPI "_CRS" resources. This can fail with the following error message: [ 247.325693] ACPI: \_SB_.IIO1.AID1: failed to insert resource This happens when there are multiple IOAPICs and DSDT groups their "_CRS" resources as the children of a parent resource, as seen from /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 In this case request_resource() fails because there's a conflicting resource which is the parent (fec-fecf). Fix it by using insert_resource() which can request resources by taking the conflicting resource as the parent. Signed-off-by: Rui Wang --- drivers/acpi/ioapic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ee20111..6d7ce6e 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -146,10 +146,12 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, crs_res = >res; acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + crs_res->name = type; + crs_res->flags |= IORESOURCE_BUSY; if (crs_res->flags == 0) { acpi_handle_warn(handle, "failed to get resource\n"); goto exit_release; - } else if (request_resource(_resource, crs_res)) { + } else if (insert_resource(_resource, crs_res)) { acpi_handle_warn(handle, "failed to insert resource\n"); goto exit_release; } -- 1.8.3.1
Re: [PATCH V5 1/3] x86/ioapic: Support hot-removal of IOAPICs present during boot
On Tuesday, Aug 9, 2016 4:23 AM, Bjorn Helgaas wrote: > On Sun, Jun 26, 2016 at 11:44:57AM +0800, Rui Wang wrote: > > v5: Remove #ifdef CONFIG_X86 from setup-bus.c, making it neutral to > archs. > > v4: Add comments explaining when to call acpi_ioapic_add(). > > v3: Previous versions break mips. This version fixes it. > > > > IOAPICs present during system boot aren't added to ioapic_list, thus > > are unable to be hot-removed. Fix it by calling > > acpi_ioapic_add() during root bus enumeration. > > > > Signed-off-by: Rui Wang <rui.y.w...@intel.com> > > Hi Rui, > > Where are we at with this? If there's anything that still needs to be merged, > can you rebase it to v4.8-rc1 and post a new, complete, series? > Hi Bjorn, Yes. These patches are needed for IOAPIC hotplug to work. So Thomas & Rafael, any advice? Thanks Rui
Re: [PATCH V5 1/3] x86/ioapic: Support hot-removal of IOAPICs present during boot
On Tuesday, Aug 9, 2016 4:23 AM, Bjorn Helgaas wrote: > On Sun, Jun 26, 2016 at 11:44:57AM +0800, Rui Wang wrote: > > v5: Remove #ifdef CONFIG_X86 from setup-bus.c, making it neutral to > archs. > > v4: Add comments explaining when to call acpi_ioapic_add(). > > v3: Previous versions break mips. This version fixes it. > > > > IOAPICs present during system boot aren't added to ioapic_list, thus > > are unable to be hot-removed. Fix it by calling > > acpi_ioapic_add() during root bus enumeration. > > > > Signed-off-by: Rui Wang > > Hi Rui, > > Where are we at with this? If there's anything that still needs to be merged, > can you rebase it to v4.8-rc1 and post a new, complete, series? > Hi Bjorn, Yes. These patches are needed for IOAPIC hotplug to work. So Thomas & Rafael, any advice? Thanks Rui
[PATCH v2 0/5] Fixing a set of bugs for ioapic hotplug
A set of patches fixing bugs found while testing IOAPIC hotplug. Regards, Rui Changelog: Changes from v1 to v2: * Split the first patch into two as advised by Bjorn: "would be nicer if the interface change and header file munging were in a separate patch so they wouldn't obscure the meat of the change, i.e., the addition of calls to acpi_ioapic_add()." * Removed acpi_ioapic_add() as an exported symbol. * Fixed some typos, and s/acpi/ACPI/, s/ioapic/IOAPIC/ throughout. * Fixed a warning from 0-day testing. Rui Wang (5): x86/ioapic: Change prototype of acpi_ioapic_add() x86/ioapic: Support hot-removal of IOAPICs present during boot x86/ioapic: Fix setup_res() failing to get resource x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd x86/ioapic: Fix ioapic failing to request resource drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 46 ++ drivers/acpi/pci_root.c | 12 +++- drivers/pci/setup-bus.c | 5 - include/linux/acpi.h| 6 ++ 5 files changed, 47 insertions(+), 24 deletions(-) -- 1.8.3.1
[PATCH v2 2/5] x86/ioapic: Support hot-removal of IOAPICs present during boot
IOAPICs present during system boot aren't added to ioapic_list, thus are unable to be hot-removed. Fix it by calling acpi_ioapic_add() during root bus enumeration. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/pci_root.c | 10 ++ drivers/pci/setup-bus.c | 5 - 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 53f5965..fa9c83a 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,6 +614,16 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); + /* +* This is only called for the hotadd case. For the boot-time +* case, we need to wait until after PCI initialization in +* order to deal with IOAPICs mapped in on a PCI BAR. +* +* This is currently x86-specific, because acpi_ioapic_add() +* is an empty function without CONFIG_ACPI_HOTPLUG_IOAPIC. +* And CONFIG_ACPI_HOTPLUG_IOAPIC depends on CONFIG_X86_IO_APIC +* (see drivers/acpi/Kconfig). +*/ acpi_ioapic_add(root->device->handle); } diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 55641a3..e32c356 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "pci.h" unsigned int pci_flags; @@ -1779,8 +1780,10 @@ void __init pci_assign_unassigned_resources(void) { struct pci_bus *root_bus; - list_for_each_entry(root_bus, _root_buses, node) + list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + } } void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) -- 1.8.3.1
[PATCH v2 1/5] x86/ioapic: Change prototype of acpi_ioapic_add()
Change the argument of acpi_ioapic_add() to a generic ACPI handle, and move its prototype from drivers/acpi/internal.h to include/linux/acpi.h so that it can be called from outside the pci_root driver. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 6 +++--- drivers/acpi/pci_root.c | 2 +- include/linux/acpi.h| 6 ++ 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 27cc7fe..6d8e67e 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -40,10 +40,8 @@ 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 diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ccdc8db..2449377 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -189,13 +189,13 @@ exit: return AE_OK; } -int acpi_ioapic_add(struct acpi_pci_root *root) +int acpi_ioapic_add(acpi_handle root_handle) { acpi_status status, retval = AE_OK; - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device->handle, + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root_handle, UINT_MAX, handle_ioapic_add, NULL, -root->device->handle, (void **)); +root_handle, (void **)); return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index ae3fe4e..53f5965 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,7 +614,7 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); - acpi_ioapic_add(root); + acpi_ioapic_add(root->device->handle); } pci_lock_rescan_remove(); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 288fac5..f5114dc 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -680,6 +680,12 @@ static inline enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev) #endif /* !CONFIG_ACPI */ +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +int acpi_ioapic_add(acpi_handle root); +#else +static inline int acpi_ioapic_add(acpi_handle root) { return 0; } +#endif + #ifdef CONFIG_ACPI void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, u32 pm1a_ctrl, u32 pm1b_ctrl)); -- 1.8.3.1
[PATCH v2 0/5] Fixing a set of bugs for ioapic hotplug
A set of patches fixing bugs found while testing IOAPIC hotplug. Regards, Rui Changelog: Changes from v1 to v2: * Split the first patch into two as advised by Bjorn: "would be nicer if the interface change and header file munging were in a separate patch so they wouldn't obscure the meat of the change, i.e., the addition of calls to acpi_ioapic_add()." * Removed acpi_ioapic_add() as an exported symbol. * Fixed some typos, and s/acpi/ACPI/, s/ioapic/IOAPIC/ throughout. * Fixed a warning from 0-day testing. Rui Wang (5): x86/ioapic: Change prototype of acpi_ioapic_add() x86/ioapic: Support hot-removal of IOAPICs present during boot x86/ioapic: Fix setup_res() failing to get resource x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd x86/ioapic: Fix ioapic failing to request resource drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 46 ++ drivers/acpi/pci_root.c | 12 +++- drivers/pci/setup-bus.c | 5 - include/linux/acpi.h| 6 ++ 5 files changed, 47 insertions(+), 24 deletions(-) -- 1.8.3.1
[PATCH v2 2/5] x86/ioapic: Support hot-removal of IOAPICs present during boot
IOAPICs present during system boot aren't added to ioapic_list, thus are unable to be hot-removed. Fix it by calling acpi_ioapic_add() during root bus enumeration. Signed-off-by: Rui Wang --- drivers/acpi/pci_root.c | 10 ++ drivers/pci/setup-bus.c | 5 - 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 53f5965..fa9c83a 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,6 +614,16 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); + /* +* This is only called for the hotadd case. For the boot-time +* case, we need to wait until after PCI initialization in +* order to deal with IOAPICs mapped in on a PCI BAR. +* +* This is currently x86-specific, because acpi_ioapic_add() +* is an empty function without CONFIG_ACPI_HOTPLUG_IOAPIC. +* And CONFIG_ACPI_HOTPLUG_IOAPIC depends on CONFIG_X86_IO_APIC +* (see drivers/acpi/Kconfig). +*/ acpi_ioapic_add(root->device->handle); } diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 55641a3..e32c356 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "pci.h" unsigned int pci_flags; @@ -1779,8 +1780,10 @@ void __init pci_assign_unassigned_resources(void) { struct pci_bus *root_bus; - list_for_each_entry(root_bus, _root_buses, node) + list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + } } void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) -- 1.8.3.1
[PATCH v2 1/5] x86/ioapic: Change prototype of acpi_ioapic_add()
Change the argument of acpi_ioapic_add() to a generic ACPI handle, and move its prototype from drivers/acpi/internal.h to include/linux/acpi.h so that it can be called from outside the pci_root driver. Signed-off-by: Rui Wang --- drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 6 +++--- drivers/acpi/pci_root.c | 2 +- include/linux/acpi.h| 6 ++ 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 27cc7fe..6d8e67e 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -40,10 +40,8 @@ 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 diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ccdc8db..2449377 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -189,13 +189,13 @@ exit: return AE_OK; } -int acpi_ioapic_add(struct acpi_pci_root *root) +int acpi_ioapic_add(acpi_handle root_handle) { acpi_status status, retval = AE_OK; - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device->handle, + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root_handle, UINT_MAX, handle_ioapic_add, NULL, -root->device->handle, (void **)); +root_handle, (void **)); return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index ae3fe4e..53f5965 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,7 +614,7 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); - acpi_ioapic_add(root); + acpi_ioapic_add(root->device->handle); } pci_lock_rescan_remove(); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 288fac5..f5114dc 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -680,6 +680,12 @@ static inline enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev) #endif /* !CONFIG_ACPI */ +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +int acpi_ioapic_add(acpi_handle root); +#else +static inline int acpi_ioapic_add(acpi_handle root) { return 0; } +#endif + #ifdef CONFIG_ACPI void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, u32 pm1a_ctrl, u32 pm1b_ctrl)); -- 1.8.3.1
[PATCH v2 4/5] x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd
IOAPIC resource at 0xfecx gets lost from /proc/iomem after hot-removing and then hot-adding the IOAPIC device. After system boot, in /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 Then hot-remove IOAPIC 2 and hot-add it again: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 The range at 0xfec4 is lost from /proc/iomem. It is because handle_ioapic_add() requests resource from either PCI config BAR or ACPI "_CRS", not both. But Intel platforms map the IOxAPIC registers both at the PCI config BAR (called MBAR, dynamic), and at the ACPI "_CRS" (called ABAR, static). The 0xfecX_YZ00 to 0xfecX_YZFF range appears in "_CRS" of each IOAPIC device. Both ranges should be claimed from /proc/iomem for exclusive use. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/ioapic.c | 36 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 8ab6d42..ee20111 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -97,7 +97,7 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, unsigned long long gsi_base; struct acpi_pci_ioapic *ioapic; struct pci_dev *dev = NULL; - struct resource *res = NULL; + struct resource *res = NULL, *pci_res = NULL, *crs_res; char *type = NULL; if (!acpi_is_ioapic(handle, )) @@ -137,23 +137,28 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, pci_set_master(dev); if (pci_request_region(dev, 0, type)) goto exit_disable; - res = >resource[0]; + pci_res = >resource[0]; ioapic->pdev = dev; } else { pci_dev_put(dev); dev = NULL; + } - res = >res; - acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, res); - if (res->flags == 0) { - acpi_handle_warn(handle, "failed to get resource\n"); - goto exit_free; - } else if (request_resource(_resource, res)) { - acpi_handle_warn(handle, "failed to insert resource\n"); - goto exit_free; - } + crs_res = >res; + acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + if (crs_res->flags == 0) { + acpi_handle_warn(handle, "failed to get resource\n"); + goto exit_release; + } else if (request_resource(_resource, crs_res)) { + acpi_handle_warn(handle, "failed to insert resource\n"); + goto exit_release; } + /* try pci resource first, then "_CRS" resource */ + res = pci_res; + if (!res || !res->flags) + res = crs_res; + if (acpi_register_ioapic(handle, res->start, (u32)gsi_base)) { acpi_handle_warn(handle, "failed to register IOAPIC\n"); goto exit_release; @@ -174,14 +179,13 @@ done: exit_release: if (dev) pci_release_region(dev, 0); - else - release_resource(res); + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); exit_disable: if (dev) pci_disable_device(dev); exit_put: pci_dev_put(dev); -exit_free: kfree(ioapic); exit: mutex_unlock(_list_lock); @@ -217,9 +221,9 @@ int acpi_ioapic_remove(struct acpi_pci_root *root) pci_release_region(ioapic->pdev, 0); pci_disable_device(ioapic->pdev); pci_dev_put(ioapic->pdev); - } else if (ioapic->res.flags && ioapic->res.parent) { - release_resource(>res); } + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); list_del(>list); kfree(ioapic); } -- 1.8.3.1
[PATCH v2 5/5] x86/ioapic: Fix ioapic failing to request resource
handle_ioapic_add() uses request_resource() to request ACPI "_CRS" resources. This can fail with the following error message: [ 247.325693] ACPI: \_SB_.IIO1.AID1: failed to insert resource This happens when there are multiple IOAPICs and DSDT groups their "_CRS" resources as the children of a parent resource, as seen from /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 In this case request_resource() fails because there's a conflicting resource which is the parent (fec-fecf). Fix it by using insert_resource() which can request resources by taking the conflicting resource as the parent. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/ioapic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ee20111..6d7ce6e 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -146,10 +146,12 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, crs_res = >res; acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + crs_res->name = type; + crs_res->flags |= IORESOURCE_BUSY; if (crs_res->flags == 0) { acpi_handle_warn(handle, "failed to get resource\n"); goto exit_release; - } else if (request_resource(_resource, crs_res)) { + } else if (insert_resource(_resource, crs_res)) { acpi_handle_warn(handle, "failed to insert resource\n"); goto exit_release; } -- 1.8.3.1
[PATCH v2 5/5] x86/ioapic: Fix ioapic failing to request resource
handle_ioapic_add() uses request_resource() to request ACPI "_CRS" resources. This can fail with the following error message: [ 247.325693] ACPI: \_SB_.IIO1.AID1: failed to insert resource This happens when there are multiple IOAPICs and DSDT groups their "_CRS" resources as the children of a parent resource, as seen from /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 In this case request_resource() fails because there's a conflicting resource which is the parent (fec-fecf). Fix it by using insert_resource() which can request resources by taking the conflicting resource as the parent. Signed-off-by: Rui Wang --- drivers/acpi/ioapic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ee20111..6d7ce6e 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -146,10 +146,12 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, crs_res = >res; acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + crs_res->name = type; + crs_res->flags |= IORESOURCE_BUSY; if (crs_res->flags == 0) { acpi_handle_warn(handle, "failed to get resource\n"); goto exit_release; - } else if (request_resource(_resource, crs_res)) { + } else if (insert_resource(_resource, crs_res)) { acpi_handle_warn(handle, "failed to insert resource\n"); goto exit_release; } -- 1.8.3.1
[PATCH v2 4/5] x86/ioapic: Fix lost IOAPIC resource after hot-removal and hotadd
IOAPIC resource at 0xfecx gets lost from /proc/iomem after hot-removing and then hot-adding the IOAPIC device. After system boot, in /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 Then hot-remove IOAPIC 2 and hot-add it again: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 The range at 0xfec4 is lost from /proc/iomem. It is because handle_ioapic_add() requests resource from either PCI config BAR or ACPI "_CRS", not both. But Intel platforms map the IOxAPIC registers both at the PCI config BAR (called MBAR, dynamic), and at the ACPI "_CRS" (called ABAR, static). The 0xfecX_YZ00 to 0xfecX_YZFF range appears in "_CRS" of each IOAPIC device. Both ranges should be claimed from /proc/iomem for exclusive use. Signed-off-by: Rui Wang --- drivers/acpi/ioapic.c | 36 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 8ab6d42..ee20111 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -97,7 +97,7 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, unsigned long long gsi_base; struct acpi_pci_ioapic *ioapic; struct pci_dev *dev = NULL; - struct resource *res = NULL; + struct resource *res = NULL, *pci_res = NULL, *crs_res; char *type = NULL; if (!acpi_is_ioapic(handle, )) @@ -137,23 +137,28 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, pci_set_master(dev); if (pci_request_region(dev, 0, type)) goto exit_disable; - res = >resource[0]; + pci_res = >resource[0]; ioapic->pdev = dev; } else { pci_dev_put(dev); dev = NULL; + } - res = >res; - acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, res); - if (res->flags == 0) { - acpi_handle_warn(handle, "failed to get resource\n"); - goto exit_free; - } else if (request_resource(_resource, res)) { - acpi_handle_warn(handle, "failed to insert resource\n"); - goto exit_free; - } + crs_res = >res; + acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + if (crs_res->flags == 0) { + acpi_handle_warn(handle, "failed to get resource\n"); + goto exit_release; + } else if (request_resource(_resource, crs_res)) { + acpi_handle_warn(handle, "failed to insert resource\n"); + goto exit_release; } + /* try pci resource first, then "_CRS" resource */ + res = pci_res; + if (!res || !res->flags) + res = crs_res; + if (acpi_register_ioapic(handle, res->start, (u32)gsi_base)) { acpi_handle_warn(handle, "failed to register IOAPIC\n"); goto exit_release; @@ -174,14 +179,13 @@ done: exit_release: if (dev) pci_release_region(dev, 0); - else - release_resource(res); + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); exit_disable: if (dev) pci_disable_device(dev); exit_put: pci_dev_put(dev); -exit_free: kfree(ioapic); exit: mutex_unlock(_list_lock); @@ -217,9 +221,9 @@ int acpi_ioapic_remove(struct acpi_pci_root *root) pci_release_region(ioapic->pdev, 0); pci_disable_device(ioapic->pdev); pci_dev_put(ioapic->pdev); - } else if (ioapic->res.flags && ioapic->res.parent) { - release_resource(>res); } + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); list_del(>list); kfree(ioapic); } -- 1.8.3.1
[PATCH v2 3/5] x86/ioapic: Fix setup_res() failing to get resource
setup_res() doesn't actually get any resource because it mistakenly checks the return value of acpi_dev_filter_resource_type(), which returns 0 on success, and 1 on failure. Fix it by taking the return value of non-zero as failing to match the specified resource type. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/ioapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 2449377..8ab6d42 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -46,7 +46,7 @@ static acpi_status setup_res(struct acpi_resource *acpi_res, void *data) struct resource_win win; res->flags = 0; - if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM) == 0) + if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM)) return AE_OK; if (!acpi_dev_resource_memory(acpi_res, res)) { -- 1.8.3.1
[PATCH v2 3/5] x86/ioapic: Fix setup_res() failing to get resource
setup_res() doesn't actually get any resource because it mistakenly checks the return value of acpi_dev_filter_resource_type(), which returns 0 on success, and 1 on failure. Fix it by taking the return value of non-zero as failing to match the specified resource type. Signed-off-by: Rui Wang --- drivers/acpi/ioapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 2449377..8ab6d42 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -46,7 +46,7 @@ static acpi_status setup_res(struct acpi_resource *acpi_res, void *data) struct resource_win win; res->flags = 0; - if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM) == 0) + if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM)) return AE_OK; if (!acpi_dev_resource_memory(acpi_res, res)) { -- 1.8.3.1
Re: [PATCH 3/4] x86/ioapic: Fix lost ioapic resource after hot-removal and hotadd
On Wed, July 27, 2016 4:24 AM, Bjorn Helgaas wrote: > On Wed, Jul 27, 2016 at 12:13:16AM +0800, Rui Wang wrote: > > ioapic resource at 0xfecx gets lost from /proc/iomem after > > hot-removing and then hot-adding the ioapic devices. > > > > After system boot, in /proc/iomem: > > fec0-fecf : PNP0003:00 > > fec0-fec003ff : IOAPIC 0 > > fec01000-fec013ff : IOAPIC 1 > > fec4-fec403ff : IOAPIC 2 > > fec8-fec803ff : IOAPIC 3 > > fecc-fecc03ff : IOAPIC 4 > > > > Then hot-remove IOAPIC 2 and hot-add it again: > > fec0-fecf : PNP0003:00 > > fec0-fec003ff : IOAPIC 0 > > fec01000-fec013ff : IOAPIC 1 > > fec8-fec803ff : IOAPIC 3 > > fecc-fecc03ff : IOAPIC 4 > > > > The range at 0xfec4 is lost from /proc/iomem. It is because > > handle_ioapic_add() requests resource from either PCI config BAR or > > acpi _CRS, not both. But Intel platforms map the IOxAPIC registers > > s/acpi/ACPI/ > s/ioapic/IOAPIC/ throughout > > > at both the PCI config BAR (called MBAR) and the 0xfecX_YZ00 to > > 0xfecX_Y2FF range (called ABAR). Both of the ranges should be claimed > > I guess you mean the 0xfecX_YZ00-0xfecX_Y2FF range appears in _CRS? Yes. That range appears in _CRS for each IOAPIC. I'll make it cleaner in the commit message. Thanks Rui
Re: [PATCH 3/4] x86/ioapic: Fix lost ioapic resource after hot-removal and hotadd
On Wed, July 27, 2016 4:24 AM, Bjorn Helgaas wrote: > On Wed, Jul 27, 2016 at 12:13:16AM +0800, Rui Wang wrote: > > ioapic resource at 0xfecx gets lost from /proc/iomem after > > hot-removing and then hot-adding the ioapic devices. > > > > After system boot, in /proc/iomem: > > fec0-fecf : PNP0003:00 > > fec0-fec003ff : IOAPIC 0 > > fec01000-fec013ff : IOAPIC 1 > > fec4-fec403ff : IOAPIC 2 > > fec8-fec803ff : IOAPIC 3 > > fecc-fecc03ff : IOAPIC 4 > > > > Then hot-remove IOAPIC 2 and hot-add it again: > > fec0-fecf : PNP0003:00 > > fec0-fec003ff : IOAPIC 0 > > fec01000-fec013ff : IOAPIC 1 > > fec8-fec803ff : IOAPIC 3 > > fecc-fecc03ff : IOAPIC 4 > > > > The range at 0xfec4 is lost from /proc/iomem. It is because > > handle_ioapic_add() requests resource from either PCI config BAR or > > acpi _CRS, not both. But Intel platforms map the IOxAPIC registers > > s/acpi/ACPI/ > s/ioapic/IOAPIC/ throughout > > > at both the PCI config BAR (called MBAR) and the 0xfecX_YZ00 to > > 0xfecX_Y2FF range (called ABAR). Both of the ranges should be claimed > > I guess you mean the 0xfecX_YZ00-0xfecX_Y2FF range appears in _CRS? Yes. That range appears in _CRS for each IOAPIC. I'll make it cleaner in the commit message. Thanks Rui
Re: [PATCH 1/4] x86/ioapic: Support hot-removal of IOAPICs present during boot boot
On Wed, July 27, 2016 4:20 AM Bjorn Helgaas wrote: > On Wed, Jul 27, 2016 at 12:13:14AM +0800, Rui Wang wrote: > > IOAPICs present during system boot aren't added to ioapic_list, thus > > are unable to be hot-removed. Fix it by calling > > acpi_ioapic_add() during root bus enumeration. > > > > Signed-off-by: Rui Wang <rui.y.w...@intel.com> > > --- > > drivers/acpi/internal.h | 2 -- > > drivers/acpi/ioapic.c | 7 --- > > drivers/acpi/pci_root.c | 13 - drivers/pci/setup-bus.c | > > 5 - > > include/linux/acpi.h| 6 ++ > > 5 files changed, 26 insertions(+), 7 deletions(-) > > > > diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index > > 27cc7fe..6d8e67e 100644 > > --- a/drivers/acpi/internal.h > > +++ b/drivers/acpi/internal.h > > @@ -40,10 +40,8 @@ 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; } > > It would be nicer if the interface change and header file munging were in a > separate patch so they wouldn't obscure the meat of the change, i.e., the > addition of calls to acpi_ioapic_add(). Sure. I'll split it in a newer version. > > > static inline int acpi_ioapic_remove(struct acpi_pci_root *root) { > > return 0; } #endif #ifdef CONFIG_ACPI_DOCK diff --git > > a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ccdc8db..0f272e2 > > 100644 > > --- a/drivers/acpi/ioapic.c > > +++ b/drivers/acpi/ioapic.c > > @@ -189,16 +189,17 @@ exit: > > return AE_OK; > > } > > > > -int acpi_ioapic_add(struct acpi_pci_root *root) > > +int acpi_ioapic_add(acpi_handle root_handle) > > { > > acpi_status status, retval = AE_OK; > > > > - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device- > >handle, > > + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root_handle, > > UINT_MAX, handle_ioapic_add, NULL, > > -root->device->handle, (void **)); > > +root_handle, (void **)); > > > > return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : - > ENODEV; > > } > > +EXPORT_SYMBOL_GPL(acpi_ioapic_add); > > What loadable module needs to call this? It shouldn't be exported unless > there is such a module. It's called from the ioapic driver which is built-in. I'll remove the export. Thanks Rui
Re: [PATCH 1/4] x86/ioapic: Support hot-removal of IOAPICs present during boot boot
On Wed, July 27, 2016 4:20 AM Bjorn Helgaas wrote: > On Wed, Jul 27, 2016 at 12:13:14AM +0800, Rui Wang wrote: > > IOAPICs present during system boot aren't added to ioapic_list, thus > > are unable to be hot-removed. Fix it by calling > > acpi_ioapic_add() during root bus enumeration. > > > > Signed-off-by: Rui Wang > > --- > > drivers/acpi/internal.h | 2 -- > > drivers/acpi/ioapic.c | 7 --- > > drivers/acpi/pci_root.c | 13 - drivers/pci/setup-bus.c | > > 5 - > > include/linux/acpi.h| 6 ++ > > 5 files changed, 26 insertions(+), 7 deletions(-) > > > > diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index > > 27cc7fe..6d8e67e 100644 > > --- a/drivers/acpi/internal.h > > +++ b/drivers/acpi/internal.h > > @@ -40,10 +40,8 @@ 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; } > > It would be nicer if the interface change and header file munging were in a > separate patch so they wouldn't obscure the meat of the change, i.e., the > addition of calls to acpi_ioapic_add(). Sure. I'll split it in a newer version. > > > static inline int acpi_ioapic_remove(struct acpi_pci_root *root) { > > return 0; } #endif #ifdef CONFIG_ACPI_DOCK diff --git > > a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ccdc8db..0f272e2 > > 100644 > > --- a/drivers/acpi/ioapic.c > > +++ b/drivers/acpi/ioapic.c > > @@ -189,16 +189,17 @@ exit: > > return AE_OK; > > } > > > > -int acpi_ioapic_add(struct acpi_pci_root *root) > > +int acpi_ioapic_add(acpi_handle root_handle) > > { > > acpi_status status, retval = AE_OK; > > > > - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device- > >handle, > > + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root_handle, > > UINT_MAX, handle_ioapic_add, NULL, > > -root->device->handle, (void **)); > > +root_handle, (void **)); > > > > return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : - > ENODEV; > > } > > +EXPORT_SYMBOL_GPL(acpi_ioapic_add); > > What loadable module needs to call this? It shouldn't be exported unless > there is such a module. It's called from the ioapic driver which is built-in. I'll remove the export. Thanks Rui
[PATCH 2/4] x86/ioapic: Fix setup_res() failing to get resource
setup_res() doesn't actually get any resoure because it mistakenly checks the return value of acpi_dev_filter_resource_type(), which returns 0 on success, and 1 on failure. Fix it by taking the return value of non-zero as failing to match the specified resource type. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/ioapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 0f272e2..daf4a40 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -46,7 +46,7 @@ static acpi_status setup_res(struct acpi_resource *acpi_res, void *data) struct resource_win win; res->flags = 0; - if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM) == 0) + if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM)) return AE_OK; if (!acpi_dev_resource_memory(acpi_res, res)) { -- 1.8.3.1
[PATCH 3/4] x86/ioapic: Fix lost ioapic resource after hot-removal and hotadd
ioapic resource at 0xfecx gets lost from /proc/iomem after hot-removing and then hot-adding the ioapic devices. After system boot, in /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 Then hot-remove IOAPIC 2 and hot-add it again: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 The range at 0xfec4 is lost from /proc/iomem. It is because handle_ioapic_add() requests resource from either PCI config BAR or acpi _CRS, not both. But Intel platforms map the IOxAPIC registers at both the PCI config BAR (called MBAR) and the 0xfecX_YZ00 to 0xfecX_Y2FF range (called ABAR). Both of the ranges should be claimed from /proc/iomem for exclusive use. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/ioapic.c | 36 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index daf4a40..80b0b1a 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -97,7 +97,7 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, unsigned long long gsi_base; struct acpi_pci_ioapic *ioapic; struct pci_dev *dev = NULL; - struct resource *res = NULL; + struct resource *res = NULL, *pci_res, *crs_res; char *type = NULL; if (!acpi_is_ioapic(handle, )) @@ -137,23 +137,28 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, pci_set_master(dev); if (pci_request_region(dev, 0, type)) goto exit_disable; - res = >resource[0]; + pci_res = >resource[0]; ioapic->pdev = dev; } else { pci_dev_put(dev); dev = NULL; + } - res = >res; - acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, res); - if (res->flags == 0) { - acpi_handle_warn(handle, "failed to get resource\n"); - goto exit_free; - } else if (request_resource(_resource, res)) { - acpi_handle_warn(handle, "failed to insert resource\n"); - goto exit_free; - } + crs_res = >res; + acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + if (crs_res->flags == 0) { + acpi_handle_warn(handle, "failed to get resource\n"); + goto exit_release; + } else if (request_resource(_resource, crs_res)) { + acpi_handle_warn(handle, "failed to insert resource\n"); + goto exit_release; } + /* try pci resource first, then "_CRS" resource */ + res = pci_res; + if (!res || !res->flags) + res = crs_res; + if (acpi_register_ioapic(handle, res->start, (u32)gsi_base)) { acpi_handle_warn(handle, "failed to register IOAPIC\n"); goto exit_release; @@ -174,14 +179,13 @@ done: exit_release: if (dev) pci_release_region(dev, 0); - else - release_resource(res); + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); exit_disable: if (dev) pci_disable_device(dev); exit_put: pci_dev_put(dev); -exit_free: kfree(ioapic); exit: mutex_unlock(_list_lock); @@ -218,9 +222,9 @@ int acpi_ioapic_remove(struct acpi_pci_root *root) pci_release_region(ioapic->pdev, 0); pci_disable_device(ioapic->pdev); pci_dev_put(ioapic->pdev); - } else if (ioapic->res.flags && ioapic->res.parent) { - release_resource(>res); } + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); list_del(>list); kfree(ioapic); } -- 1.8.3.1
[PATCH 2/4] x86/ioapic: Fix setup_res() failing to get resource
setup_res() doesn't actually get any resoure because it mistakenly checks the return value of acpi_dev_filter_resource_type(), which returns 0 on success, and 1 on failure. Fix it by taking the return value of non-zero as failing to match the specified resource type. Signed-off-by: Rui Wang --- drivers/acpi/ioapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 0f272e2..daf4a40 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -46,7 +46,7 @@ static acpi_status setup_res(struct acpi_resource *acpi_res, void *data) struct resource_win win; res->flags = 0; - if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM) == 0) + if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM)) return AE_OK; if (!acpi_dev_resource_memory(acpi_res, res)) { -- 1.8.3.1
[PATCH 3/4] x86/ioapic: Fix lost ioapic resource after hot-removal and hotadd
ioapic resource at 0xfecx gets lost from /proc/iomem after hot-removing and then hot-adding the ioapic devices. After system boot, in /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 Then hot-remove IOAPIC 2 and hot-add it again: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec8-fec803ff : IOAPIC 3 fecc-fecc03ff : IOAPIC 4 The range at 0xfec4 is lost from /proc/iomem. It is because handle_ioapic_add() requests resource from either PCI config BAR or acpi _CRS, not both. But Intel platforms map the IOxAPIC registers at both the PCI config BAR (called MBAR) and the 0xfecX_YZ00 to 0xfecX_Y2FF range (called ABAR). Both of the ranges should be claimed from /proc/iomem for exclusive use. Signed-off-by: Rui Wang --- drivers/acpi/ioapic.c | 36 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index daf4a40..80b0b1a 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -97,7 +97,7 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, unsigned long long gsi_base; struct acpi_pci_ioapic *ioapic; struct pci_dev *dev = NULL; - struct resource *res = NULL; + struct resource *res = NULL, *pci_res, *crs_res; char *type = NULL; if (!acpi_is_ioapic(handle, )) @@ -137,23 +137,28 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, pci_set_master(dev); if (pci_request_region(dev, 0, type)) goto exit_disable; - res = >resource[0]; + pci_res = >resource[0]; ioapic->pdev = dev; } else { pci_dev_put(dev); dev = NULL; + } - res = >res; - acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, res); - if (res->flags == 0) { - acpi_handle_warn(handle, "failed to get resource\n"); - goto exit_free; - } else if (request_resource(_resource, res)) { - acpi_handle_warn(handle, "failed to insert resource\n"); - goto exit_free; - } + crs_res = >res; + acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + if (crs_res->flags == 0) { + acpi_handle_warn(handle, "failed to get resource\n"); + goto exit_release; + } else if (request_resource(_resource, crs_res)) { + acpi_handle_warn(handle, "failed to insert resource\n"); + goto exit_release; } + /* try pci resource first, then "_CRS" resource */ + res = pci_res; + if (!res || !res->flags) + res = crs_res; + if (acpi_register_ioapic(handle, res->start, (u32)gsi_base)) { acpi_handle_warn(handle, "failed to register IOAPIC\n"); goto exit_release; @@ -174,14 +179,13 @@ done: exit_release: if (dev) pci_release_region(dev, 0); - else - release_resource(res); + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); exit_disable: if (dev) pci_disable_device(dev); exit_put: pci_dev_put(dev); -exit_free: kfree(ioapic); exit: mutex_unlock(_list_lock); @@ -218,9 +222,9 @@ int acpi_ioapic_remove(struct acpi_pci_root *root) pci_release_region(ioapic->pdev, 0); pci_disable_device(ioapic->pdev); pci_dev_put(ioapic->pdev); - } else if (ioapic->res.flags && ioapic->res.parent) { - release_resource(>res); } + if (ioapic->res.flags && ioapic->res.parent) + release_resource(>res); list_del(>list); kfree(ioapic); } -- 1.8.3.1
[PATCH 1/4] x86/ioapic: Support hot-removal of IOAPICs present during boot
IOAPICs present during system boot aren't added to ioapic_list, thus are unable to be hot-removed. Fix it by calling acpi_ioapic_add() during root bus enumeration. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 7 --- drivers/acpi/pci_root.c | 13 - drivers/pci/setup-bus.c | 5 - include/linux/acpi.h| 6 ++ 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 27cc7fe..6d8e67e 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -40,10 +40,8 @@ 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 diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ccdc8db..0f272e2 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -189,16 +189,17 @@ exit: return AE_OK; } -int acpi_ioapic_add(struct acpi_pci_root *root) +int acpi_ioapic_add(acpi_handle root_handle) { acpi_status status, retval = AE_OK; - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device->handle, + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root_handle, UINT_MAX, handle_ioapic_add, NULL, -root->device->handle, (void **)); +root_handle, (void **)); return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } +EXPORT_SYMBOL_GPL(acpi_ioapic_add); int acpi_ioapic_remove(struct acpi_pci_root *root) { diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index ae3fe4e..d818c61 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,7 +614,18 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); - acpi_ioapic_add(root); + + /* +* This is only called for the hotadd case. For the boot-time +* case, we need to wait until after PCI initialization in +* order to deal with IOAPICs mapped in on a PCI BAR. +* +* This is currently x86-specific, because acpi_ioapic_add() +* is an empty function without CONFIG_ACPI_HOTPLUG_IOAPIC. +* And CONFIG_ACPI_HOTPLUG_IOAPIC depends on CONFIG_X86_IO_APIC +* (see drivers/acpi/Kconfig). +*/ + acpi_ioapic_add(root->device->handle); } pci_lock_rescan_remove(); diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 55641a3..e32c356 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "pci.h" unsigned int pci_flags; @@ -1779,8 +1780,10 @@ void __init pci_assign_unassigned_resources(void) { struct pci_bus *root_bus; - list_for_each_entry(root_bus, _root_buses, node) + list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + } } void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 288fac5..f5114dc 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -680,6 +680,12 @@ static inline enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev) #endif /* !CONFIG_ACPI */ +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +int acpi_ioapic_add(acpi_handle root); +#else +static inline int acpi_ioapic_add(acpi_handle root) { return 0; } +#endif + #ifdef CONFIG_ACPI void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, u32 pm1a_ctrl, u32 pm1b_ctrl)); -- 1.8.3.1
[PATCH 1/4] x86/ioapic: Support hot-removal of IOAPICs present during boot
IOAPICs present during system boot aren't added to ioapic_list, thus are unable to be hot-removed. Fix it by calling acpi_ioapic_add() during root bus enumeration. Signed-off-by: Rui Wang --- drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 7 --- drivers/acpi/pci_root.c | 13 - drivers/pci/setup-bus.c | 5 - include/linux/acpi.h| 6 ++ 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 27cc7fe..6d8e67e 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -40,10 +40,8 @@ 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 diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ccdc8db..0f272e2 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -189,16 +189,17 @@ exit: return AE_OK; } -int acpi_ioapic_add(struct acpi_pci_root *root) +int acpi_ioapic_add(acpi_handle root_handle) { acpi_status status, retval = AE_OK; - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device->handle, + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root_handle, UINT_MAX, handle_ioapic_add, NULL, -root->device->handle, (void **)); +root_handle, (void **)); return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } +EXPORT_SYMBOL_GPL(acpi_ioapic_add); int acpi_ioapic_remove(struct acpi_pci_root *root) { diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index ae3fe4e..d818c61 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,7 +614,18 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); - acpi_ioapic_add(root); + + /* +* This is only called for the hotadd case. For the boot-time +* case, we need to wait until after PCI initialization in +* order to deal with IOAPICs mapped in on a PCI BAR. +* +* This is currently x86-specific, because acpi_ioapic_add() +* is an empty function without CONFIG_ACPI_HOTPLUG_IOAPIC. +* And CONFIG_ACPI_HOTPLUG_IOAPIC depends on CONFIG_X86_IO_APIC +* (see drivers/acpi/Kconfig). +*/ + acpi_ioapic_add(root->device->handle); } pci_lock_rescan_remove(); diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 55641a3..e32c356 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "pci.h" unsigned int pci_flags; @@ -1779,8 +1780,10 @@ void __init pci_assign_unassigned_resources(void) { struct pci_bus *root_bus; - list_for_each_entry(root_bus, _root_buses, node) + list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + } } void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 288fac5..f5114dc 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -680,6 +680,12 @@ static inline enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev) #endif /* !CONFIG_ACPI */ +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +int acpi_ioapic_add(acpi_handle root); +#else +static inline int acpi_ioapic_add(acpi_handle root) { return 0; } +#endif + #ifdef CONFIG_ACPI void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, u32 pm1a_ctrl, u32 pm1b_ctrl)); -- 1.8.3.1
[PATCH 4/4] x86/ioapic: Fix ioapic failing to request resource
handle_ioapic_add() uses request_resource() to request ACPI "_CRS" resources. This can fail with the following error message: [ 247.325693] ACPI: \_SB_.IIO1.AID1: failed to insert resource This happens when there are multiple ioapics and DSDT groups their "_CRS" resources as the children of a parent resource, as seen from /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 In this case request_resource() fails because there's a conflicting resource which is the parent (fec-fecf). Fix it by using insert_resoure() which can request resources by taking the conflicting resource as the parent. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/ioapic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 80b0b1a..2c38ce0 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -146,10 +146,12 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, crs_res = >res; acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + crs_res->name = type; + crs_res->flags |= IORESOURCE_BUSY; if (crs_res->flags == 0) { acpi_handle_warn(handle, "failed to get resource\n"); goto exit_release; - } else if (request_resource(_resource, crs_res)) { + } else if (insert_resource(_resource, crs_res)) { acpi_handle_warn(handle, "failed to insert resource\n"); goto exit_release; } -- 1.8.3.1
[PATCH 4/4] x86/ioapic: Fix ioapic failing to request resource
handle_ioapic_add() uses request_resource() to request ACPI "_CRS" resources. This can fail with the following error message: [ 247.325693] ACPI: \_SB_.IIO1.AID1: failed to insert resource This happens when there are multiple ioapics and DSDT groups their "_CRS" resources as the children of a parent resource, as seen from /proc/iomem: fec0-fecf : PNP0003:00 fec0-fec003ff : IOAPIC 0 fec01000-fec013ff : IOAPIC 1 fec4-fec403ff : IOAPIC 2 In this case request_resource() fails because there's a conflicting resource which is the parent (fec-fecf). Fix it by using insert_resoure() which can request resources by taking the conflicting resource as the parent. Signed-off-by: Rui Wang --- drivers/acpi/ioapic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index 80b0b1a..2c38ce0 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -146,10 +146,12 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, crs_res = >res; acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); + crs_res->name = type; + crs_res->flags |= IORESOURCE_BUSY; if (crs_res->flags == 0) { acpi_handle_warn(handle, "failed to get resource\n"); goto exit_release; - } else if (request_resource(_resource, crs_res)) { + } else if (insert_resource(_resource, crs_res)) { acpi_handle_warn(handle, "failed to insert resource\n"); goto exit_release; } -- 1.8.3.1
[PATCH 0/4] Fixing a set of bugs for ioapic hotplug
Hi all, The 1st patch has been discussed before Bjorn went on vacation. I've fixed all the issues. Bjorn, please advise how we'll move forward. The remaining patches fix newly found bugs while testing ioapic hotplug. Regards, Rui Rui Wang (4): x86/ioapic: Support hot-removal of IOAPICs present during boot x86/ioapic: Fix setup_res() failing to get resource x86/ioapic: Fix lost ioapic resource after hot-removal and hotadd x86/ioapic: Fix ioapic failing to request resource drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 47 +++ drivers/acpi/pci_root.c | 13 - drivers/pci/setup-bus.c | 5 - include/linux/acpi.h| 6 ++ 5 files changed, 49 insertions(+), 24 deletions(-) -- 1.8.3.1
[PATCH 0/4] Fixing a set of bugs for ioapic hotplug
Hi all, The 1st patch has been discussed before Bjorn went on vacation. I've fixed all the issues. Bjorn, please advise how we'll move forward. The remaining patches fix newly found bugs while testing ioapic hotplug. Regards, Rui Rui Wang (4): x86/ioapic: Support hot-removal of IOAPICs present during boot x86/ioapic: Fix setup_res() failing to get resource x86/ioapic: Fix lost ioapic resource after hot-removal and hotadd x86/ioapic: Fix ioapic failing to request resource drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 47 +++ drivers/acpi/pci_root.c | 13 - drivers/pci/setup-bus.c | 5 - include/linux/acpi.h| 6 ++ 5 files changed, 49 insertions(+), 24 deletions(-) -- 1.8.3.1
[PATCH V5 1/3] x86/ioapic: Support hot-removal of IOAPICs present during boot
v5: Remove #ifdef CONFIG_X86 from setup-bus.c, making it neutral to archs. v4: Add comments explaining when to call acpi_ioapic_add(). v3: Previous versions break mips. This version fixes it. IOAPICs present during system boot aren't added to ioapic_list, thus are unable to be hot-removed. Fix it by calling acpi_ioapic_add() during root bus enumeration. Signed-off-by: Rui Wang <rui.y.w...@intel.com> --- drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 7 --- drivers/acpi/pci_root.c | 13 - drivers/pci/setup-bus.c | 5 - include/linux/acpi.h| 6 ++ 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 27cc7fe..6d8e67e 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -40,10 +40,8 @@ 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 diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ccdc8db..0f272e2 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -189,16 +189,17 @@ exit: return AE_OK; } -int acpi_ioapic_add(struct acpi_pci_root *root) +int acpi_ioapic_add(acpi_handle root_handle) { acpi_status status, retval = AE_OK; - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device->handle, + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root_handle, UINT_MAX, handle_ioapic_add, NULL, -root->device->handle, (void **)); +root_handle, (void **)); return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } +EXPORT_SYMBOL_GPL(acpi_ioapic_add); int acpi_ioapic_remove(struct acpi_pci_root *root) { diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index ae3fe4e..31e4440 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,7 +614,18 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); - acpi_ioapic_add(root); + + /* +* This is only called for the hotadd case. For the boot-time +* case, we need to wait until after PCI initialization in +* order to deal with IOAPICs mapped in on a PCI BAR. +* +* This is currently x86-specific, because acpi_ioapic_add() +* is an empty function without CONFIG_ACPI_HOTPLUG_IOAPIC. +* And CONFIG_ACPI_HOTPLUG_IOAPIC depends on CONFIG_X86_IO_APIC +* (see drivers/acpi/Kconfig). +*/ + acpi_ioapic_add(root->device->handle); } pci_lock_rescan_remove(); diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 55641a3..e32c356 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "pci.h" unsigned int pci_flags; @@ -1779,8 +1780,10 @@ void __init pci_assign_unassigned_resources(void) { struct pci_bus *root_bus; - list_for_each_entry(root_bus, _root_buses, node) + list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + } } void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 288fac5..f5114dc 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -680,6 +680,12 @@ static inline enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev) #endif /* !CONFIG_ACPI */ +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +int acpi_ioapic_add(acpi_handle root); +#else +static inline int acpi_ioapic_add(acpi_handle root) { return 0; } +#endif + #ifdef CONFIG_ACPI void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, u32 pm1a_ctrl, u32 pm1b_ctrl)); -- 1.8.3.1
[PATCH V5 1/3] x86/ioapic: Support hot-removal of IOAPICs present during boot
v5: Remove #ifdef CONFIG_X86 from setup-bus.c, making it neutral to archs. v4: Add comments explaining when to call acpi_ioapic_add(). v3: Previous versions break mips. This version fixes it. IOAPICs present during system boot aren't added to ioapic_list, thus are unable to be hot-removed. Fix it by calling acpi_ioapic_add() during root bus enumeration. Signed-off-by: Rui Wang --- drivers/acpi/internal.h | 2 -- drivers/acpi/ioapic.c | 7 --- drivers/acpi/pci_root.c | 13 - drivers/pci/setup-bus.c | 5 - include/linux/acpi.h| 6 ++ 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 27cc7fe..6d8e67e 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -40,10 +40,8 @@ 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 diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ccdc8db..0f272e2 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c @@ -189,16 +189,17 @@ exit: return AE_OK; } -int acpi_ioapic_add(struct acpi_pci_root *root) +int acpi_ioapic_add(acpi_handle root_handle) { acpi_status status, retval = AE_OK; - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device->handle, + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root_handle, UINT_MAX, handle_ioapic_add, NULL, -root->device->handle, (void **)); +root_handle, (void **)); return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; } +EXPORT_SYMBOL_GPL(acpi_ioapic_add); int acpi_ioapic_remove(struct acpi_pci_root *root) { diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index ae3fe4e..31e4440 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,7 +614,18 @@ static int acpi_pci_root_add(struct acpi_device *device, if (hotadd) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_root_bus_resources(root->bus); - acpi_ioapic_add(root); + + /* +* This is only called for the hotadd case. For the boot-time +* case, we need to wait until after PCI initialization in +* order to deal with IOAPICs mapped in on a PCI BAR. +* +* This is currently x86-specific, because acpi_ioapic_add() +* is an empty function without CONFIG_ACPI_HOTPLUG_IOAPIC. +* And CONFIG_ACPI_HOTPLUG_IOAPIC depends on CONFIG_X86_IO_APIC +* (see drivers/acpi/Kconfig). +*/ + acpi_ioapic_add(root->device->handle); } pci_lock_rescan_remove(); diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 55641a3..e32c356 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "pci.h" unsigned int pci_flags; @@ -1779,8 +1780,10 @@ void __init pci_assign_unassigned_resources(void) { struct pci_bus *root_bus; - list_for_each_entry(root_bus, _root_buses, node) + list_for_each_entry(root_bus, _root_buses, node) { pci_assign_unassigned_root_bus_resources(root_bus); + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); + } } void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 288fac5..f5114dc 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -680,6 +680,12 @@ static inline enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev) #endif /* !CONFIG_ACPI */ +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +int acpi_ioapic_add(acpi_handle root); +#else +static inline int acpi_ioapic_add(acpi_handle root) { return 0; } +#endif + #ifdef CONFIG_ACPI void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, u32 pm1a_ctrl, u32 pm1b_ctrl)); -- 1.8.3.1
Re: [PATCH V4 1/3] x86/ioapic: Support hot-removal of IOAPICs present during boot
On Fri, Jun 24, 2016 1:35 AM Bjorn Helgaas wrote: > On Thu, Jun 23, 2016 at 01:11:41PM +0800, Rui Wang wrote: > > On Wed, June 22, 2016 11:15 PM Bjorn Helgaas wrote: > > > [...] > > > > @@ -1779,8 +1780,12 @@ void __init > > > > pci_assign_unassigned_resources(void) > > > > { > > > > struct pci_bus *root_bus; > > > > > > > > - list_for_each_entry(root_bus, _root_buses, node) > > > > + list_for_each_entry(root_bus, _root_buses, node) { > > > > pci_assign_unassigned_root_bus_resources(root_bus); > > > > +#ifdef CONFIG_X86 > > > > + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); > > > > +#endif > > > > > > Doesn't this do the right thing even if you omit the #ifdefs, since > > > you define a stub function below? > > > > > > > No. Without the '#ifdef CONFIG_X86' it breaks MIPS arch. The stub > > function is within 'ifdef CONFIG_ACPI'. On archs without ACPI it > > doesn't compile due to 'undefined reference to acpi_ioapic_add'. > > But this *could* be made to work by defining a stub for the non- > CONFIG_ACPI case. That's what we generally do to avoid ifdefs in the code. That can be done. I'll make the change and do some cross-compiling tests first. Thanks Rui
Re: [PATCH V4 1/3] x86/ioapic: Support hot-removal of IOAPICs present during boot
On Fri, Jun 24, 2016 1:35 AM Bjorn Helgaas wrote: > On Thu, Jun 23, 2016 at 01:11:41PM +0800, Rui Wang wrote: > > On Wed, June 22, 2016 11:15 PM Bjorn Helgaas wrote: > > > [...] > > > > @@ -1779,8 +1780,12 @@ void __init > > > > pci_assign_unassigned_resources(void) > > > > { > > > > struct pci_bus *root_bus; > > > > > > > > - list_for_each_entry(root_bus, _root_buses, node) > > > > + list_for_each_entry(root_bus, _root_buses, node) { > > > > pci_assign_unassigned_root_bus_resources(root_bus); > > > > +#ifdef CONFIG_X86 > > > > + acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); > > > > +#endif > > > > > > Doesn't this do the right thing even if you omit the #ifdefs, since > > > you define a stub function below? > > > > > > > No. Without the '#ifdef CONFIG_X86' it breaks MIPS arch. The stub > > function is within 'ifdef CONFIG_ACPI'. On archs without ACPI it > > doesn't compile due to 'undefined reference to acpi_ioapic_add'. > > But this *could* be made to work by defining a stub for the non- > CONFIG_ACPI case. That's what we generally do to avoid ifdefs in the code. That can be done. I'll make the change and do some cross-compiling tests first. Thanks Rui