From: Oliver O'Halloran <oohall@gmail.com> Date: 2019-02-08 03:09:52
There's no need to the custom getter/setter functions so we should remove
them in favour of using the generic one. While we're here, change the type
of eeh_max_freeze to uint32_t and print the value in decimal rather than
hex because printing it in hex makes no sense.
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
arch/powerpc/include/asm/eeh.h | 2 +-
arch/powerpc/kernel/eeh.c | 21 +++------------------
2 files changed, 4 insertions(+), 19 deletions(-)
From: Oliver O'Halloran <oohall@gmail.com> Date: 2019-02-08 03:11:26
The EEH address cache is used to map a physical MMIO address back to a PCI
device. It's useful to know when it's being manipulated, but currently this
requires recompiling with #define DEBUG set. This is pointless since we
have dynamic_debug nowdays, so remove the #ifdef guard and add a pr_debug()
for the remove case too.
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
arch/powerpc/kernel/eeh_cache.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
From: Oliver O'Halloran <oohall@gmail.com> Date: 2019-02-08 03:13:20
Adds a debugfs file that can be read to view the contents of the EEH
address cache. This is pretty similar to the existing
eeh_addr_cache_print() function, but that function is intended to debug
issues inside of the kernel since it's #ifdef`ed out by default, and writes
into the kernel log.
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
arch/powerpc/include/asm/eeh.h | 3 +++
arch/powerpc/kernel/eeh.c | 2 +-
arch/powerpc/kernel/eeh_cache.c | 34 +++++++++++++++++++++++++++++----
3 files changed, 34 insertions(+), 5 deletions(-)
@@ -298,9 +299,34 @@ void eeh_addr_cache_build(void)eeh_addr_cache_insert_dev(dev);eeh_sysfs_add_device(dev);}+}-#ifdef DEBUG-/* Verify tree built up above, echo back the list of addrs. */-eeh_addr_cache_print(&pci_io_addr_cache_root);-#endif+staticinteeh_addr_cache_show(structseq_file*s,void*v)+{+structrb_node*n=rb_first(&pci_io_addr_cache_root.rb_root);+structpci_io_addr_range*piar;+intcnt=0;++spin_lock(&pci_io_addr_cache_root.piar_lock);+while(n){+piar=rb_entry(n,structpci_io_addr_range,rb_node);++seq_printf(s,"%s addr range %3d [%pap-%pap]: %s\n",+(piar->flags&IORESOURCE_IO)?"i/o":"mem",cnt,+&piar->addr_lo,&piar->addr_hi,pci_name(piar->pcidev));++n=rb_next(n);+cnt++;+}+spin_unlock(&pci_io_addr_cache_root.piar_lock);++return0;+}+DEFINE_SHOW_ATTRIBUTE(eeh_addr_cache);++voideeh_cache_debugfs_init(void)+{+debugfs_create_file_unsafe("eeh_address_cache",0400,+powerpc_debugfs_root,NULL,+&eeh_addr_cache_fops);}
From: Oliver O'Halloran <oohall@gmail.com> Date: 2019-02-08 03:15:01
To use this function at all #define DEBUG needs to be set in eeh_cache.c.
Considering that printing at pr_debug is probably not all that useful since
it adds the additional hurdle of requiring you to enable the debug print if
dynamic_debug is in use so this patch bumps it to pr_info.
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
arch/powerpc/kernel/eeh_cache.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: Oliver O'Halloran <oohall@gmail.com> Date: 2019-02-08 03:16:47
Add a helper to find the pci_controller structure based on the domain
number / phb id.
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
arch/powerpc/include/asm/pci-bridge.h | 2 ++
arch/powerpc/kernel/pci-common.c | 11 +++++++++++
2 files changed, 13 insertions(+)
@@ -274,6 +274,8 @@ extern int pcibios_map_io_space(struct pci_bus *bus);externstructpci_controller*pci_find_hose_for_OF_device(structdevice_node*node);+externstructpci_controller*pci_find_hose_for_domain(uint32_tdomain_nr);+/* Fill up host controller resources from the OF node */externvoidpci_process_bridge_OF_ranges(structpci_controller*hose,structdevice_node*dev,intprimary);
From: Oliver O'Halloran <oohall@gmail.com> Date: 2019-02-08 03:18:23
Currently when we detect an error we automatically invoke the EEH recovery
handler. This can be annoying when debugging EEH problems, or when working
on EEH itself so this patch adds a debugfs knob that will prevent a
recovery event from being queued up when an issue is detected.
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
arch/powerpc/include/asm/eeh.h | 1 +
arch/powerpc/kernel/eeh.c | 11 +++++++++++
arch/powerpc/kernel/eeh_event.c | 9 +++++++++
3 files changed, 21 insertions(+)
@@ -126,6 +126,15 @@ int eeh_send_failure_event(struct eeh_pe *pe)unsignedlongflags;structeeh_event*event;+/*+*Ifwe'vemanuallysupressedrecoveryeventsviadebugfs+*thenjustdropitonthefloor.+*/+if(eeh_debugfs_no_recover){+pr_err("EEH: Event dropped due to no_recover setting\n");+return0;+}+event=kzalloc(sizeof(*event),GFP_ATOMIC);if(!event){pr_err("EEH: out of memory, event not handled\n");
From: Oliver O'Halloran <oohall@gmail.com> Date: 2019-02-08 03:19:51
This patch adds a debugfs interface to force scheduling a recovery event.
This can be used to recover a specific PE or schedule a "special" recovery
even that checks for errors at the PHB level.
To force a recovery of a normal PE, use:
echo '<#pe>:<#phb>' > /sys/kernel/debug/powerpc/eeh_force_recover
To force a scan broken PHBs:
echo 'null' > /sys/kernel/debug/powerpc/eeh_force_recover
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
arch/powerpc/include/asm/eeh_event.h | 1 +
arch/powerpc/kernel/eeh.c | 60 ++++++++++++++++++++++++++++
arch/powerpc/kernel/eeh_event.c | 25 +++++++-----
3 files changed, 76 insertions(+), 10 deletions(-)
@@ -121,20 +121,11 @@ int eeh_event_init(void)*theactualeventwillbedeliveredinanormalcontext*(fromaworkqueue).*/-inteeh_send_failure_event(structeeh_pe*pe)+int__eeh_send_failure_event(structeeh_pe*pe){unsignedlongflags;structeeh_event*event;-/*-*Ifwe'vemanuallysupressedrecoveryeventsviadebugfs-*thenjustdropitonthefloor.-*/-if(eeh_debugfs_no_recover){-pr_err("EEH: Event dropped due to no_recover setting\n");-return0;-}-event=kzalloc(sizeof(*event),GFP_ATOMIC);if(!event){pr_err("EEH: out of memory, event not handled\n");
@@ -153,6 +144,20 @@ int eeh_send_failure_event(struct eeh_pe *pe)return0;}+inteeh_send_failure_event(structeeh_pe*pe)+{+/*+*Ifwe'vemanuallysupressedrecoveryeventsviadebugfs+*thenjustdropitonthefloor.+*/+if(eeh_debugfs_no_recover){+pr_err("EEH: Event dropped due to no_recover setting\n");+return0;+}++return__eeh_send_failure_event(pe);+}+/***eeh_remove_event-RemoveEEHeventfromthequeue*@pe:EventbindingtothePE
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2019-02-08 09:39:47
Oliver O'Halloran [off-list ref] writes:
There's no need to the custom getter/setter functions so we should remove
them in favour of using the generic one. While we're here, change the type
of eeh_max_freeze to uint32_t and print the value in decimal rather than
Please use kernel types, ie. u32.
Look fine otherwise.
cheers
@@ -298,9 +299,34 @@ void eeh_addr_cache_build(void)eeh_addr_cache_insert_dev(dev);eeh_sysfs_add_device(dev);}+}-#ifdef DEBUG-/* Verify tree built up above, echo back the list of addrs. */-eeh_addr_cache_print(&pci_io_addr_cache_root);-#endif+staticinteeh_addr_cache_show(structseq_file*s,void*v)+{+structrb_node*n=rb_first(&pci_io_addr_cache_root.rb_root);+structpci_io_addr_range*piar;+intcnt=0;++spin_lock(&pci_io_addr_cache_root.piar_lock);+while(n){+piar=rb_entry(n,structpci_io_addr_range,rb_node);++seq_printf(s,"%s addr range %3d [%pap-%pap]: %s\n",+(piar->flags&IORESOURCE_IO)?"i/o":"mem",cnt,+&piar->addr_lo,&piar->addr_hi,pci_name(piar->pcidev));++n=rb_next(n);+cnt++;+}
You can write that as a for loop can't you?
struct rb_node *n;
int i = 0;
for (n = rb_first(&pci_io_addr_cache_root.rb_root); n; n = rb_next(n), i++) {
piar = rb_entry(n, struct pci_io_addr_range, rb_node);
seq_printf(s, "%s addr range %3d [%pap-%pap]: %s\n",
(piar->flags & IORESOURCE_IO) ? "i/o" : "mem", i,
&piar->addr_lo, &piar->addr_hi, pci_name(piar->pcidev));
}
cheers
@@ -274,6 +274,8 @@ extern int pcibios_map_io_space(struct pci_bus *bus);externstructpci_controller*pci_find_hose_for_OF_device(structdevice_node*node);+externstructpci_controller*pci_find_hose_for_domain(uint32_tdomain_nr);
I know we use "hose" a lot in the PCI code, but it's a stupid name. Can
we not introduce new usages?
It returns a pci_controller so pci_find_controller_for_domain() ?
cheers
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2019-02-08 12:34:44
Oliver O'Halloran [off-list ref] writes:
This patch adds a debugfs interface to force scheduling a recovery event.
This can be used to recover a specific PE or schedule a "special" recovery
even that checks for errors at the PHB level.
To force a recovery of a normal PE, use:
echo '<#pe>:<#phb>' > /sys/kernel/debug/powerpc/eeh_force_recover
To force a scan broken PHBs:
echo 'null' > /sys/kernel/debug/powerpc/eeh_force_recover
From: Oliver <oohall@gmail.com> Date: 2019-02-08 12:55:27
On Fri, Feb 8, 2019 at 11:32 PM Michael Ellerman [off-list ref] wrote:
Oliver O'Halloran [off-list ref] writes:
quoted
This patch adds a debugfs interface to force scheduling a recovery event.
This can be used to recover a specific PE or schedule a "special" recovery
even that checks for errors at the PHB level.
To force a recovery of a normal PE, use:
echo '<#pe>:<#phb>' > /sys/kernel/debug/powerpc/eeh_force_recover
To force a scan broken PHBs:
echo 'null' > /sys/kernel/debug/powerpc/eeh_force_recover
Why 'null', that seems like an odd choice. Why not "all" or "scan" or
something?
When an EEH event occurs the bit that is sent to the event handler is
just a pointer the the struct eeh_pe. If the pointer is null it's then
treated as a special event which indicates a PHB failure. I agree it's
a bit dumb, but I don't really expect anyone except me or samb to use
this interface so I went with what would make sense to someone
familiar with the internals.
This is probably a side effect of special events being a PowerNV
specific concept. For a pseries guest there should never be any PHB
PEs since (hardware) PHBs are a concept that is hidden to to a guest.
It's like EEH is poorly thought out and full of layering violations or
something...
@@ -298,9 +299,34 @@ void eeh_addr_cache_build(void)eeh_addr_cache_insert_dev(dev);eeh_sysfs_add_device(dev);}+}-#ifdef DEBUG-/* Verify tree built up above, echo back the list of addrs. */-eeh_addr_cache_print(&pci_io_addr_cache_root);-#endif+staticinteeh_addr_cache_show(structseq_file*s,void*v)+{+structrb_node*n=rb_first(&pci_io_addr_cache_root.rb_root);+structpci_io_addr_range*piar;+intcnt=0;++spin_lock(&pci_io_addr_cache_root.piar_lock);+while(n){+piar=rb_entry(n,structpci_io_addr_range,rb_node);++seq_printf(s,"%s addr range %3d [%pap-%pap]: %s\n",+(piar->flags&IORESOURCE_IO)?"i/o":"mem",cnt,+&piar->addr_lo,&piar->addr_hi,pci_name(piar->pcidev));++n=rb_next(n);+cnt++;+}
You can write that as a for loop can't you?
struct rb_node *n;
int i = 0;
for (n = rb_first(&pci_io_addr_cache_root.rb_root); n; n = rb_next(n), i++) {
IIRC I did try that, but it's too long. 85 cols wide according to my editor.
@@ -298,9 +299,34 @@ void eeh_addr_cache_build(void)eeh_addr_cache_insert_dev(dev);eeh_sysfs_add_device(dev);}+}-#ifdef DEBUG-/* Verify tree built up above, echo back the list of addrs. */-eeh_addr_cache_print(&pci_io_addr_cache_root);-#endif+staticinteeh_addr_cache_show(structseq_file*s,void*v)+{+structrb_node*n=rb_first(&pci_io_addr_cache_root.rb_root);+structpci_io_addr_range*piar;+intcnt=0;++spin_lock(&pci_io_addr_cache_root.piar_lock);+while(n){+piar=rb_entry(n,structpci_io_addr_range,rb_node);++seq_printf(s,"%s addr range %3d [%pap-%pap]: %s\n",+(piar->flags&IORESOURCE_IO)?"i/o":"mem",cnt,+&piar->addr_lo,&piar->addr_hi,pci_name(piar->pcidev));++n=rb_next(n);+cnt++;+}
You can write that as a for loop can't you?
struct rb_node *n;
int i = 0;
for (n = rb_first(&pci_io_addr_cache_root.rb_root); n; n = rb_next(n), i++) {
IIRC I did try that, but it's too long. 85 cols wide according to my editor.
Don't care.
Long lines aren't inherently evil, they have some downsides but so do
the other options. In a case like this 85 columns would be preferable to
splitting the line or writing it a while loop.
cheers
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2019-02-11 02:26:29
Oliver [off-list ref] writes:
On Fri, Feb 8, 2019 at 11:32 PM Michael Ellerman [off-list ref] wrote:
quoted
Oliver O'Halloran [off-list ref] writes:
quoted
This patch adds a debugfs interface to force scheduling a recovery event.
This can be used to recover a specific PE or schedule a "special" recovery
even that checks for errors at the PHB level.
To force a recovery of a normal PE, use:
echo '<#pe>:<#phb>' > /sys/kernel/debug/powerpc/eeh_force_recover
To force a scan broken PHBs:
echo 'null' > /sys/kernel/debug/powerpc/eeh_force_recover
Why 'null', that seems like an odd choice. Why not "all" or "scan" or
something?
When an EEH event occurs the bit that is sent to the event handler is
just a pointer the the struct eeh_pe. If the pointer is null it's then
treated as a special event which indicates a PHB failure. I agree it's
a bit dumb, but I don't really expect anyone except me or samb to use
this interface so I went with what would make sense to someone
familiar with the internals.
Yeah, nah. Let's use something that's at least vaguely self documenting
so people like me can have some clue what it's doing.
cheers
From: Sam Bobroff <hidden> Date: 2019-02-13 04:39:40
On Fri, Feb 08, 2019 at 02:08:02PM +1100, Oliver O'Halloran wrote:
This patch adds a debugfs interface to force scheduling a recovery event.
This can be used to recover a specific PE or schedule a "special" recovery
even that checks for errors at the PHB level.
To force a recovery of a normal PE, use:
echo '<#pe>:<#phb>' > /sys/kernel/debug/powerpc/eeh_force_recover
How about placing these in the per-PHB debugfs directory?
echo '<#pe>' > /sys/kernel/debug/powerpc/PCI0000/eeh_force_recover
To force a scan broken PHBs:
echo 'null' > /sys/kernel/debug/powerpc/eeh_force_recover
And keep this one where it is, and just trigger with any write (or a '1'
or whatever)?
Sam.
@@ -121,20 +121,11 @@ int eeh_event_init(void)*theactualeventwillbedeliveredinanormalcontext*(fromaworkqueue).*/-inteeh_send_failure_event(structeeh_pe*pe)+int__eeh_send_failure_event(structeeh_pe*pe){unsignedlongflags;structeeh_event*event;-/*-*Ifwe'vemanuallysupressedrecoveryeventsviadebugfs-*thenjustdropitonthefloor.-*/-if(eeh_debugfs_no_recover){-pr_err("EEH: Event dropped due to no_recover setting\n");-return0;-}-event=kzalloc(sizeof(*event),GFP_ATOMIC);if(!event){pr_err("EEH: out of memory, event not handled\n");
@@ -153,6 +144,20 @@ int eeh_send_failure_event(struct eeh_pe *pe)return0;}+inteeh_send_failure_event(structeeh_pe*pe)+{+/*+*Ifwe'vemanuallysupressedrecoveryeventsviadebugfs+*thenjustdropitonthefloor.+*/+if(eeh_debugfs_no_recover){+pr_err("EEH: Event dropped due to no_recover setting\n");+return0;+}++return__eeh_send_failure_event(pe);+}+/***eeh_remove_event-RemoveEEHeventfromthequeue*@pe:EventbindingtothePE
From: Oliver <oohall@gmail.com> Date: 2019-02-13 05:20:32
On Wed, Feb 13, 2019 at 3:38 PM Sam Bobroff [off-list ref] wrote:
On Fri, Feb 08, 2019 at 02:08:02PM +1100, Oliver O'Halloran wrote:
quoted
This patch adds a debugfs interface to force scheduling a recovery event.
This can be used to recover a specific PE or schedule a "special" recovery
even that checks for errors at the PHB level.
To force a recovery of a normal PE, use:
echo '<#pe>:<#phb>' > /sys/kernel/debug/powerpc/eeh_force_recover
How about placing these in the per-PHB debugfs directory?
echo '<#pe>' > /sys/kernel/debug/powerpc/PCI0000/eeh_force_recover
quoted
To force a scan broken PHBs:
echo 'null' > /sys/kernel/debug/powerpc/eeh_force_recover
And keep this one where it is, and just trigger with any write (or a '1'
or whatever)?
The per-PHB directories only exist on PowerNV. I'd rather this was
merged as-is since it handles both platforms. If we want to add the
per-PHB debugfs stuff to pseries we can do it later.
@@ -121,20 +121,11 @@ int eeh_event_init(void)*theactualeventwillbedeliveredinanormalcontext*(fromaworkqueue).*/-inteeh_send_failure_event(structeeh_pe*pe)+int__eeh_send_failure_event(structeeh_pe*pe){unsignedlongflags;structeeh_event*event;-/*-*Ifwe'vemanuallysupressedrecoveryeventsviadebugfs-*thenjustdropitonthefloor.-*/-if(eeh_debugfs_no_recover){-pr_err("EEH: Event dropped due to no_recover setting\n");-return0;-}-event=kzalloc(sizeof(*event),GFP_ATOMIC);if(!event){pr_err("EEH: out of memory, event not handled\n");
@@ -153,6 +144,20 @@ int eeh_send_failure_event(struct eeh_pe *pe)return0;}+inteeh_send_failure_event(structeeh_pe*pe)+{+/*+*Ifwe'vemanuallysupressedrecoveryeventsviadebugfs+*thenjustdropitonthefloor.+*/+if(eeh_debugfs_no_recover){+pr_err("EEH: Event dropped due to no_recover setting\n");+return0;+}++return__eeh_send_failure_event(pe);+}+/***eeh_remove_event-RemoveEEHeventfromthequeue*@pe:EventbindingtothePE--