From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Oliver O'Halloran <oohall@gmail.com>,
Michael Ellerman <mpe@ellerman.id.au>,
Sasha Levin <sashal@kernel.org>,
linuxppc-dev@lists.ozlabs.org
Subject: [PATCH AUTOSEL 5.2 52/70] powerpc/eeh: Clean up EEH PEs after recovery finishes
Date: Tue, 24 Sep 2019 12:45:31 -0400 [thread overview]
Message-ID: <20190924164549.27058-52-sashal@kernel.org> (raw)
In-Reply-To: <20190924164549.27058-1-sashal@kernel.org>
From: Oliver O'Halloran <oohall@gmail.com>
[ Upstream commit 799abe283e5103d48e079149579b4f167c95ea0e ]
When the last device in an eeh_pe is removed the eeh_pe structure itself
(and any empty parents) are freed since they are no longer needed. This
results in a crash when a hotplug driver is involved since the following
may occur:
1. Device is suprise removed.
2. Driver performs an MMIO, which fails and queues and eeh_event.
3. Hotplug driver receives a hotplug interrupt and removes any
pci_devs that were under the slot.
4. pci_dev is torn down and the eeh_pe is freed.
5. The EEH event handler thread processes the eeh_event and crashes
since the eeh_pe pointer in the eeh_event structure is no
longer valid.
Crashing is generally considered poor form. Instead of doing that use
the fact PEs are marked as EEH_PE_INVALID to keep them around until the
end of the recovery cycle, at which point we can safely prune any empty
PEs.
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20190903101605.2890-2-oohall@gmail.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/powerpc/kernel/eeh_driver.c | 36 ++++++++++++++++++++++++++++++--
arch/powerpc/kernel/eeh_event.c | 8 +++++++
arch/powerpc/kernel/eeh_pe.c | 23 +++++++++++++++++++-
3 files changed, 64 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 1fbe541856f5e..fe0c32fb9f96f 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -744,6 +744,33 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus,
*/
#define MAX_WAIT_FOR_RECOVERY 300
+
+/* Walks the PE tree after processing an event to remove any stale PEs.
+ *
+ * NB: This needs to be recursive to ensure the leaf PEs get removed
+ * before their parents do. Although this is possible to do recursively
+ * we don't since this is easier to read and we need to garantee
+ * the leaf nodes will be handled first.
+ */
+static void eeh_pe_cleanup(struct eeh_pe *pe)
+{
+ struct eeh_pe *child_pe, *tmp;
+
+ list_for_each_entry_safe(child_pe, tmp, &pe->child_list, child)
+ eeh_pe_cleanup(child_pe);
+
+ if (pe->state & EEH_PE_KEEP)
+ return;
+
+ if (!(pe->state & EEH_PE_INVALID))
+ return;
+
+ if (list_empty(&pe->edevs) && list_empty(&pe->child_list)) {
+ list_del(&pe->child);
+ kfree(pe);
+ }
+}
+
/**
* eeh_handle_normal_event - Handle EEH events on a specific PE
* @pe: EEH PE - which should not be used after we return, as it may
@@ -782,8 +809,6 @@ void eeh_handle_normal_event(struct eeh_pe *pe)
return;
}
- eeh_pe_state_mark(pe, EEH_PE_RECOVERING);
-
eeh_pe_update_time_stamp(pe);
pe->freeze_count++;
if (pe->freeze_count > eeh_max_freezes) {
@@ -973,6 +998,12 @@ void eeh_handle_normal_event(struct eeh_pe *pe)
return;
}
}
+
+ /*
+ * Clean up any PEs without devices. While marked as EEH_PE_RECOVERYING
+ * we don't want to modify the PE tree structure so we do it here.
+ */
+ eeh_pe_cleanup(pe);
eeh_pe_state_clear(pe, EEH_PE_RECOVERING, true);
}
@@ -1045,6 +1076,7 @@ void eeh_handle_special_event(void)
*/
if (rc == EEH_NEXT_ERR_FROZEN_PE ||
rc == EEH_NEXT_ERR_FENCED_PHB) {
+ eeh_pe_state_mark(pe, EEH_PE_RECOVERING);
eeh_handle_normal_event(pe);
} else {
pci_lock_rescan_remove();
diff --git a/arch/powerpc/kernel/eeh_event.c b/arch/powerpc/kernel/eeh_event.c
index 64cfbe41174b2..e36653e5f76b3 100644
--- a/arch/powerpc/kernel/eeh_event.c
+++ b/arch/powerpc/kernel/eeh_event.c
@@ -121,6 +121,14 @@ int __eeh_send_failure_event(struct eeh_pe *pe)
}
event->pe = pe;
+ /*
+ * Mark the PE as recovering before inserting it in the queue.
+ * This prevents the PE from being free()ed by a hotplug driver
+ * while the PE is sitting in the event queue.
+ */
+ if (pe)
+ eeh_pe_state_mark(pe, EEH_PE_RECOVERING);
+
/* We may or may not be called in an interrupt context */
spin_lock_irqsave(&eeh_eventlist_lock, flags);
list_add(&event->list, &eeh_eventlist);
diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c
index 854cef7b18f4d..f0813d50e0b1c 100644
--- a/arch/powerpc/kernel/eeh_pe.c
+++ b/arch/powerpc/kernel/eeh_pe.c
@@ -491,6 +491,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
int eeh_rmv_from_parent_pe(struct eeh_dev *edev)
{
struct eeh_pe *pe, *parent, *child;
+ bool keep, recover;
int cnt;
struct pci_dn *pdn = eeh_dev_to_pdn(edev);
@@ -516,10 +517,21 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev)
*/
while (1) {
parent = pe->parent;
+
+ /* PHB PEs should never be removed */
if (pe->type & EEH_PE_PHB)
break;
- if (!(pe->state & EEH_PE_KEEP)) {
+ /*
+ * XXX: KEEP is set while resetting a PE. I don't think it's
+ * ever set without RECOVERING also being set. I could
+ * be wrong though so catch that with a WARN.
+ */
+ keep = !!(pe->state & EEH_PE_KEEP);
+ recover = !!(pe->state & EEH_PE_RECOVERING);
+ WARN_ON(keep && !recover);
+
+ if (!keep && !recover) {
if (list_empty(&pe->edevs) &&
list_empty(&pe->child_list)) {
list_del(&pe->child);
@@ -528,6 +540,15 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev)
break;
}
} else {
+ /*
+ * Mark the PE as invalid. At the end of the recovery
+ * process any invalid PEs will be garbage collected.
+ *
+ * We need to delay the free()ing of them since we can
+ * remove edev's while traversing the PE tree which
+ * might trigger the removal of a PE and we can't
+ * deal with that (yet).
+ */
if (list_empty(&pe->edevs)) {
cnt = 0;
list_for_each_entry(child, &pe->child_list, child) {
--
2.20.1
next prev parent reply other threads:[~2019-09-24 16:48 UTC|newest]
Thread overview: 70+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-09-24 16:44 [PATCH AUTOSEL 5.2 01/70] drm/vkms: Fix crc worker races Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 02/70] drm/bridge: tc358767: Increase AUX transfer length limit Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 03/70] drm/bridge: adv7511: Attach to DSI host at probe time Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 04/70] drm/kms: Catch mode_object lifetime errors Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 05/70] drm/vkms: Avoid assigning 0 for possible_crtc Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 06/70] drm/panel: simple: fix AUO g185han01 horizontal blanking Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 07/70] drm/amd/display: add monitor patch to add T7 delay Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 08/70] video: ssd1307fb: Start page range at page_offset Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 09/70] drm/tinydrm/Kconfig: drivers: Select BACKLIGHT_CLASS_DEVICE Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 10/70] drm/stm: attach gem fence to atomic state Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 11/70] drm/panel: check failure cases in the probe func Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 12/70] drm/rockchip: Check for fast link training before enabling psr Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 13/70] drm/amdgpu: Fix hard hang for S/G display BOs Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 14/70] drm/radeon: Fix EEH during kexec Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 15/70] gpu: drm: radeon: Fix a possible null-pointer dereference in radeon_connector_set_property() Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 16/70] clk: imx8mq: Mark AHB clock as critical Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 17/70] PCI: rpaphp: Avoid a sometimes-uninitialized warning Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 18/70] pinctrl: stmfx: update pinconf settings Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 19/70] ipmi_si: Only schedule continuously in the thread in maintenance mode Sasha Levin
2019-09-24 16:44 ` [PATCH AUTOSEL 5.2 20/70] clk: qoriq: Fix -Wunused-const-variable Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 21/70] clk: sunxi-ng: v3s: add missing clock slices for MMC2 module clocks Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 22/70] drm/amd/display: fix issue where 252-255 values are clipped Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 23/70] drm/amd/display: Fix frames_to_insert math Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 24/70] drm/amd/display: reprogram VM config when system resume Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 25/70] powerpc/powernv/ioda2: Allocate TCE table levels on demand for default DMA window Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 26/70] drm/amd/powerplay/smu7: enforce minimal VBITimeout (v2) Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 27/70] clk: actions: Don't reference clk_init_data after registration Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 28/70] clk: sirf: " Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 29/70] clk: meson: axg-audio: " Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 30/70] clk: sprd: " Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 31/70] clk: zx296718: " Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 32/70] powerpc/xmon: Check for HV mode when dumping XIVE info from OPAL Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 33/70] powerpc/rtas: use device model APIs and serialization during LPM Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 34/70] powerpc/futex: Fix warning: 'oldval' may be used uninitialized in this function Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 35/70] powerpc/64s/radix: Remove redundant pfn_pte bitop, add VM_BUG_ON Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 36/70] powerpc/64s/radix: Fix memory hotplug section page table creation Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 37/70] powerpc/pseries/mobility: use cond_resched when updating device tree Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 38/70] powerpc/perf: fix imc allocation failure handling Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 39/70] pinctrl: tegra: Fix write barrier placement in pmx_writel Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 40/70] powerpc/eeh: Clear stale EEH_DEV_NO_HANDLER flag Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 41/70] vfio_pci: Restore original state on release Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 42/70] drm/nouveau/kms/tu102-: disable input lut when input is already FP16 Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 43/70] drm/nouveau/volt: Fix for some cards having 0 maximum voltage Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 44/70] pinctrl: amd: disable spurious-firing GPIO IRQs Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 45/70] clk: renesas: mstp: Set GENPD_FLAG_ALWAYS_ON for clock domain Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 46/70] clk: renesas: cpg-mssr: " Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 47/70] drm/amd/display: support spdif Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 48/70] selftests/powerpc: Retry on host facility unavailable Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 49/70] drm/amdgpu/si: fix ASIC tests Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 50/70] powerpc/64s/exception: machine check use correct cfar for late handler Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 51/70] pstore: fs superblock limits Sasha Levin
2019-09-24 16:45 ` Sasha Levin [this message]
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 53/70] powerpc/imc: Dont create debugfs files for cpu-less nodes Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 54/70] clk: qcom: gcc-sdm845: Use floor ops for sdcc clks Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 55/70] powerpc/pseries: correctly track irq state in default idle Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 56/70] pinctrl: meson-gxbb: Fix wrong pinning definition for uart_c Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 57/70] mailbox: mediatek: cmdq: clear the event in cmdq initial flow Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 58/70] arm64: fix unreachable code issue with cmpxchg Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 59/70] clk: at91: select parent if main oscillator or bypass is enabled Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 60/70] clk: imx: pll14xx: avoid glitch when set rate Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 61/70] clk: imx: clk-pll14xx: unbypass PLL by default Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 62/70] clk: Make clk_bulk_get_all() return a valid "id" Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 63/70] powerpc: dump kernel log before carrying out fadump or kdump Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 64/70] mbox: qcom: add APCS child device for QCS404 Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 65/70] clk: sprd: add missing kfree Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 66/70] scsi: core: Reduce memory required for SCSI logging Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 67/70] dma-buf/sw_sync: Synchronize signal vs syncpt free Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 68/70] drm: fix module name in edid_firmware log message Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 69/70] f2fs: fix to drop meta/node pages during umount Sasha Levin
2019-09-24 16:45 ` [PATCH AUTOSEL 5.2 70/70] ext4: fix potential use after free after remounting with noblock_validity Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190924164549.27058-52-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=mpe@ellerman.id.au \
--cc=oohall@gmail.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).