From: Sam Bobroff <hidden> Date: 2019-05-07 04:34:14
Hi all,
Here is v2, addressing feedback from v1.
Original cover letter follows, slightly updated for v2:
This patch set adds support for EEH recovery of hot plugged devices on pSeries
machines. Specifically, devices discovered by PCI rescanning using
/sys/bus/pci/rescan, which includes devices hotplugged by QEMU's device_add
command. (Upstream Linux pSeries guests running under QEMU/KVM don't currently
use slot power control for hotplugging.)
As a side effect this also provides EEH support for devices removed by
/sys/bus/pci/devices/*/remove and re-discovered by writing to /sys/bus/pci/rescan,
on all platforms.
The approach I've taken is to use the fact that the existing
pcibios_bus_add_device() platform hooks (which are used to set up EEH on
Virtual Function devices (VFs)) are actually called for all devices, so I've
widened their scope and made other adjustments necessary to allow them to work
for hotplugged and boot-time devices as well.
Because some of the changes are in generic PowerPC code, it's
possible that I've disturbed something for another PowerPC platform. I've tried
to minimize this by leaving that code alone as much as possible and so there
are a few cases where eeh_add_device_{early,late}() or eeh_add_sysfs_files() is
called more than once. I think these can be looked at later, as duplicate calls
are not harmful.
The first patch is a rework of the pcibios_init reordering patch I posted
earlier, which I've included here because it's necessary for this set.
I have done some testing for PowerNV on Power9 using a modified pnv_php module
and some testing on pSeries with slot power control using a modified rpaphp
module, and the EEH-related parts seem to work.
Cheers,
Sam.
Patch set changelog follows:
Patch set v2:
Patch 1/6: powerpc/64: Adjust order in pcibios_init()
Patch 2/6: powerpc/eeh: Clear stale EEH_DEV_NO_HANDLER flag
* Also clear EEH_DEV_NO_HANDLER in eeh_handle_special_event().
Patch 3/6 (was 4/8): powerpc/eeh: Improve debug messages around device addition
Patch 4/6 (was 6/8): powerpc/eeh: Initialize EEH address cache earlier
Patch 5/6 (was 3/8 and 7/8): powerpc/eeh: EEH for pSeries hot plug
- Dropped changes to the PowerNV PHB EEH flag, instead refactor just enough to
use the existing flag from multiple places.
- Merge the little remaining work from the above change into the patch where
it's used.
Patch 6/6 (was 5/8 and 8/8): powerpc/eeh: Refactor around eeh_probe_devices()
- As it's so small, merged the enablement message patch into this one (where it's used).
- Reworked enablement messages.
Patch set v1:
Patch 1/8: powerpc/64: Adjust order in pcibios_init()
Patch 2/8: powerpc/eeh: Clear stale EEH_DEV_NO_HANDLER flag
Patch 3/8: powerpc/eeh: Convert PNV_PHB_FLAG_EEH to global flag
Patch 4/8: powerpc/eeh: Improve debug messages around device addition
Patch 5/8: powerpc/eeh: Add eeh_show_enabled()
Patch 6/8: powerpc/eeh: Initialize EEH address cache earlier
Patch 7/8: powerpc/eeh: EEH for pSeries hot plug
Patch 8/8: powerpc/eeh: Remove eeh_probe_devices() and eeh_addr_cache_build()
Sam Bobroff (6):
powerpc/64: Adjust order in pcibios_init()
powerpc/eeh: Clear stale EEH_DEV_NO_HANDLER flag
powerpc/eeh: Improve debug messages around device addition
powerpc/eeh: Initialize EEH address cache earlier
powerpc/eeh: EEH for pSeries hot plug
powerpc/eeh: Refactor around eeh_probe_devices()
arch/powerpc/include/asm/eeh.h | 8 +--
arch/powerpc/kernel/eeh.c | 33 ++++-----
arch/powerpc/kernel/eeh_cache.c | 29 +-------
arch/powerpc/kernel/eeh_driver.c | 11 ++-
arch/powerpc/kernel/of_platform.c | 3 +-
arch/powerpc/kernel/pci-common.c | 4 --
arch/powerpc/kernel/pci_32.c | 4 ++
arch/powerpc/kernel/pci_64.c | 12 +++-
arch/powerpc/platforms/powernv/eeh-powernv.c | 57 ++++++++++-----
arch/powerpc/platforms/pseries/eeh_pseries.c | 75 +++++++++++---------
arch/powerpc/platforms/pseries/pci.c | 3 +-
11 files changed, 127 insertions(+), 112 deletions(-)
--
2.19.0.2.gcad72f5712
From: Sam Bobroff <hidden> Date: 2019-05-07 04:31:46
The pcibios_init() function for 64 bit PowerPC currently calls
pci_bus_add_devices() before pcibios_resource_survey(), which seems
incorrect because it adds devices and attempts to bind their drivers
before allocating their resources (although no problems seem to be
apparent).
So move the call to pci_bus_add_devices() to after
pcibios_resource_survey(), while extracting call to the
pcibios_fixup() hook so that it remains in the same location.
This will also allow the ppc_md.pcibios_bus_add_device() hooks to
perform actions that depend on PCI resources, both during rescanning
(where this is already the case) and at boot time, to support future
work.
Signed-off-by: Sam Bobroff <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
arch/powerpc/kernel/pci-common.c | 4 ----
arch/powerpc/kernel/pci_32.c | 4 ++++
arch/powerpc/kernel/pci_64.c | 12 +++++++++---
3 files changed, 13 insertions(+), 7 deletions(-)
@@ -1383,10 +1383,6 @@ void __init pcibios_resource_survey(void)pr_debug("PCI: Assigning unassigned resources...\n");pci_assign_unassigned_resources();}--/* Call machine dependent fixup */-if(ppc_md.pcibios_fixup)-ppc_md.pcibios_fixup();}/* This is used by the PCI hotplug driver to allocate resource
From: Sam Bobroff <hidden> Date: 2019-05-07 04:33:03
The EEH address cache is currently initialized and populated by a
single function: eeh_addr_cache_build(). While the initial population
of the cache can only be done once resources are allocated,
initialization (just setting up a spinlock) could be done much
earlier.
So move the initialization step into a separate function and call it
from a core_initcall (rather than a subsys initcall).
This will allow future work to make use of the cache during boot time
PCI scanning.
Signed-off-by: Sam Bobroff <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
arch/powerpc/include/asm/eeh.h | 3 +++
arch/powerpc/kernel/eeh.c | 2 ++
arch/powerpc/kernel/eeh_cache.c | 13 +++++++++++--
3 files changed, 16 insertions(+), 2 deletions(-)
From: Sam Bobroff <hidden> Date: 2019-05-07 04:35:23
The EEH_DEV_NO_HANDLER flag is used by the EEH system to prevent the
use of driver callbacks in drivers that have been bound part way
through the recovery process. This is necessary to prevent later stage
handlers from being called when the earlier stage handlers haven't,
which can be confusing for drivers.
However, the flag is set for all devices that are added after boot
time and only cleared at the end of the EEH recovery process. This
results in hot plugged devices erroneously having the flag set during
the first recovery after they are added (causing their driver's
handlers to be incorrectly ignored).
To remedy this, clear the flag at the beginning of recovery
processing. The flag is still cleared at the end of recovery
processing, although it is no longer really necessary.
Also clear the flag during eeh_handle_special_event(), for the same
reasons.
Signed-off-by: Sam Bobroff <redacted>
---
v2 * Also clear EEH_DEV_NO_HANDLER in eeh_handle_special_event().
arch/powerpc/kernel/eeh_driver.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
@@ -819,6 +819,10 @@ void eeh_handle_normal_event(struct eeh_pe *pe)result=PCI_ERS_RESULT_DISCONNECT;}+eeh_for_each_pe(pe,tmp_pe)+eeh_pe_for_each_dev(tmp_pe,edev,tmp)+edev->mode&=~EEH_DEV_NO_HANDLER;+/* Walk the various device drivers attached to this slot through*aresetsequence,givingeachanopportunitytodowhatitneeds*toaccomplishthereset.Eachchildgetsareportofthe
@@ -1078,6 +1083,10 @@ void eeh_handle_special_event(void)(phb_pe->state&EEH_PE_RECOVERING))continue;+eeh_for_each_pe(pe,tmp_pe)+eeh_pe_for_each_dev(tmp_pe,edev,tmp_edev)+edev->mode&=~EEH_DEV_NO_HANDLER;+/* Notify all devices to be down */eeh_pe_state_clear(pe,EEH_PE_PRI_BUS,true);eeh_set_channel_state(pe,pci_channel_io_perm_failure);
@@ -251,6 +253,10 @@ static void *pseries_eeh_probe(struct pci_dn *pdn, void *data)intenable=0;intret;+pr_debug("%s: probing %04x:%02x:%02x.%01x\n",+__func__,pdn->phb->global_number,pdn->busno,+PCI_SLOT(pdn->devfn),PCI_FUNC(pdn->devfn));+/* Retrieve OF node and eeh device */edev=pdn_to_eeh_dev(pdn);if(!edev||edev->pe)
@@ -294,7 +300,12 @@ static void *pseries_eeh_probe(struct pci_dn *pdn, void *data)/* Enable EEH on the device */ret=eeh_ops->set_option(&pe,EEH_OPT_ENABLE);-if(!ret){+if(ret){+pr_debug("%s: EEH failed to enable on %02x:%02x.%01x PHB#%x-PE#%x (code %d)\n",+__func__,pdn->busno,PCI_SLOT(pdn->devfn),+PCI_FUNC(pdn->devfn),pe.phb->global_number,+pe.addr,ret);+}else{/* Retrieve PE address */edev->pe_config_addr=eeh_ops->get_pe_addr(&pe);pe.addr=edev->pe_config_addr;
@@ -310,11 +321,6 @@ static void *pseries_eeh_probe(struct pci_dn *pdn, void *data)if(enable){eeh_add_flag(EEH_ENABLED);eeh_add_to_parent_pe(edev);--pr_debug("%s: EEH enabled on %02x:%02x.%01x PHB#%x-PE#%x\n",-__func__,pdn->busno,PCI_SLOT(pdn->devfn),-PCI_FUNC(pdn->devfn),pe.phb->global_number,-pe.addr);}elseif(pdn->parent&&pdn_to_eeh_dev(pdn->parent)&&(pdn_to_eeh_dev(pdn->parent))->pe){/* This device doesn't support EEH, but it may have an
From: Sam Bobroff <hidden> Date: 2019-05-07 04:37:48
Now that EEH support for all devices (on PowerNV and pSeries) is
provided by the pcibios bus add device hooks, eeh_probe_devices() and
eeh_addr_cache_build() are redundant and can be removed.
Move the EEH enabled message into it's own function so that it can be
called from multiple places.
Note that previously on pSeries, useless EEH sysfs files were created
for some devices that did not have EEH support and this change
prevents them from being created.
Signed-off-by: Sam Bobroff <redacted>
---
v2 - As it's so small, merged the enablement message patch into this one (where it's used).
- Reworked enablement messages.
arch/powerpc/include/asm/eeh.h | 7 ++---
arch/powerpc/kernel/eeh.c | 27 ++++++-----------
arch/powerpc/kernel/eeh_cache.c | 32 --------------------
arch/powerpc/platforms/powernv/eeh-powernv.c | 4 +--
arch/powerpc/platforms/pseries/pci.c | 3 +-
5 files changed, 14 insertions(+), 59 deletions(-)
From: Sam Bobroff <hidden> Date: 2019-05-07 04:39:01
On PowerNV and pSeries, devices currently acquire EEH support from
several different places: Boot-time devices from eeh_probe_devices()
and eeh_addr_cache_build(), Virtual Function devices from the pcibios
bus add device hooks and hot plugged devices from pci_hp_add_devices()
(with other platforms using other methods as well). Unfortunately,
pSeries machines currently discover hot plugged devices using
pci_rescan_bus(), not pci_hp_add_devices(), and so those devices do
not receive EEH support.
Rather than adding another case for pci_rescan_bus(), this change
widens the scope of the pcibios bus add device hooks so that they can
handle all devices. As a side effect this also supports devices
discovered after manually rescanning via /sys/bus/pci/rescan.
Note that on PowerNV, this change allows the EEH subsystem to become
enabled after boot as long as it has not been forced off, which was
not previously possible (it was already possible on pSeries).
Signed-off-by: Sam Bobroff <redacted>
---
v2 - Dropped changes to the PowerNV PHB EEH flag, instead refactor just enough to
use the existing flag from multiple places.
- Merge the little remaining work from the above change into the patch where
it's used.
arch/powerpc/kernel/eeh.c | 2 +-
arch/powerpc/kernel/of_platform.c | 3 +-
arch/powerpc/platforms/powernv/eeh-powernv.c | 39 +++++++++-----
arch/powerpc/platforms/pseries/eeh_pseries.c | 54 ++++++++++----------
4 files changed, 56 insertions(+), 42 deletions(-)
@@ -55,44 +55,44 @@ static int ibm_get_config_addr_info;staticintibm_get_config_addr_info2;staticintibm_configure_pe;-#ifdef CONFIG_PCI_IOVvoidpseries_pcibios_bus_add_device(structpci_dev*pdev){structpci_dn*pdn=pci_get_pdn(pdev);-structpci_dn*physfn_pdn;-structeeh_dev*edev;-if(!pdev->is_virtfn)+if(eeh_has_flag(EEH_FORCE_DISABLED))return;pr_debug("%s: EEH: Setting up device %s.\n",__func__,pci_name(pdev));+#ifdef CONFIG_PCI_IOV+if(pdev->is_virtfn){+structpci_dn*physfn_pdn;-pdn->device_id=pdev->device;-pdn->vendor_id=pdev->vendor;-pdn->class_code=pdev->class;-/*-*Lastallowunfreezereturncodeusedforretrieval-*byuserspaceineeh-sysfstoshowthelastcommand-*completionfromplatform.-*/-pdn->last_allow_rc=0;-physfn_pdn=pci_get_pdn(pdev->physfn);-pdn->pe_number=physfn_pdn->pe_num_map[pdn->vf_index];-edev=pdn_to_eeh_dev(pdn);--/*-*ThefollowingoperationswillfailifVF'ssysfsfiles-*aren'tcreatedoritsresourcesaren'tfinalized.-*/+pdn->device_id=pdev->device;+pdn->vendor_id=pdev->vendor;+pdn->class_code=pdev->class;+/*+*Lastallowunfreezereturncodeusedforretrieval+*byuserspaceineeh-sysfstoshowthelastcommand+*completionfromplatform.+*/+pdn->last_allow_rc=0;+physfn_pdn=pci_get_pdn(pdev->physfn);+pdn->pe_number=physfn_pdn->pe_num_map[pdn->vf_index];+}+#endifeeh_add_device_early(pdn);eeh_add_device_late(pdev);-edev->pe_config_addr=(pdn->busno<<16)|(pdn->devfn<<8);-eeh_rmv_from_parent_pe(edev);/* Remove as it is adding to bus pe */-eeh_add_to_parent_pe(edev);/* Add as VF PE type */-eeh_sysfs_add_device(pdev);+#ifdef CONFIG_PCI_IOV+if(pdev->is_virtfn){+structeeh_dev*edev=pdn_to_eeh_dev(pdn);-}+edev->pe_config_addr=(pdn->busno<<16)|(pdn->devfn<<8);+eeh_rmv_from_parent_pe(edev);/* Remove as it is adding to bus pe */+eeh_add_to_parent_pe(edev);/* Add as VF PE type */+}#endif+eeh_sysfs_add_device(pdev);+}/**Bufferforreportingslot-error-detailrtascalls.Itshere
@@ -159,10 +159,8 @@ static int pseries_eeh_init(void)/* Set EEH probe mode */eeh_add_flag(EEH_PROBE_MODE_DEVTREE|EEH_ENABLE_IO_FOR_LOG);-#ifdef CONFIG_PCI_IOV/* Set EEH machine dependent code */ppc_md.pcibios_bus_add_device=pseries_pcibios_bus_add_device;-#endifreturn0;}
From: Oliver <oohall@gmail.com> Date: 2019-06-05 05:50:46
On Tue, May 7, 2019 at 2:30 PM Sam Bobroff [off-list ref] wrote:
quoted hunk
Now that EEH support for all devices (on PowerNV and pSeries) is
provided by the pcibios bus add device hooks, eeh_probe_devices() and
eeh_addr_cache_build() are redundant and can be removed.
Move the EEH enabled message into it's own function so that it can be
called from multiple places.
Note that previously on pSeries, useless EEH sysfs files were created
for some devices that did not have EEH support and this change
prevents them from being created.
Signed-off-by: Sam Bobroff <redacted>
---
v2 - As it's so small, merged the enablement message patch into this one (where it's used).
- Reworked enablement messages.
arch/powerpc/include/asm/eeh.h | 7 ++---
arch/powerpc/kernel/eeh.c | 27 ++++++-----------
arch/powerpc/kernel/eeh_cache.c | 32 --------------------
arch/powerpc/platforms/powernv/eeh-powernv.c | 4 +--
arch/powerpc/platforms/pseries/pci.c | 3 +-
5 files changed, 14 insertions(+), 59 deletions(-)
The one concern I have about this is that PAPR requires us to enable
EEH for the device before we do any config accesses. From PAPR:
R1–7.3.11.1–5. For the EEH option: If a device driver is going to
enable EEH and the platform has not defaulted
to EEH enabled, then it must do so before it does any operations with
its IOA, including any configuration
cycles or Load or Store operations.
So if we want to be strictly compatible we'd need to ensure the
set-eeh-option RTAS call happens before we read the VDID in
pci_scan_device(). The pseries eeh_probe() function does this
currently, but if we defer it until the pcibios call happens we'll
have done a pile of config accesses before then. Maybe it doesn't
matter, but we'd need to do further testing under phyp or work out
some other way to ensure it's done pre-probe.
@@ -397,6 +394,10 @@ static void *pnv_eeh_probe(struct pci_dn *pdn, void *data) int ret; int config_addr = (pdn->busno << 8) | (pdn->devfn);+ pr_debug("%s: probing %04x:%02x:%02x.%01x\n",+ __func__, hose->global_number, pdn->busno,+ PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn));+ /* * When probing the root bridge, which doesn't have any * subordinate PCI devices. We don't have OF node for
@@ -251,6 +253,10 @@ static void *pseries_eeh_probe(struct pci_dn *pdn, void *data)intenable=0;intret;+pr_debug("%s: probing %04x:%02x:%02x.%01x\n",+__func__,pdn->phb->global_number,pdn->busno,+PCI_SLOT(pdn->devfn),PCI_FUNC(pdn->devfn));+/* Retrieve OF node and eeh device */edev=pdn_to_eeh_dev(pdn);if(!edev||edev->pe)
@@ -294,7 +300,12 @@ static void *pseries_eeh_probe(struct pci_dn *pdn, void *data)/* Enable EEH on the device */ret=eeh_ops->set_option(&pe,EEH_OPT_ENABLE);-if(!ret){+if(ret){+pr_debug("%s: EEH failed to enable on %02x:%02x.%01x PHB#%x-PE#%x (code %d)\n",+__func__,pdn->busno,PCI_SLOT(pdn->devfn),+PCI_FUNC(pdn->devfn),pe.phb->global_number,+pe.addr,ret);+}else{
edev!=NULL here so you could do dev_dbg(&edev->pdev->dev,...) and skip
PCI_SLOT/PCI_FUNC. Or is (edev!=NULL && edev->pdev==NULL) possible (it
could be, just asking)?
@@ -310,11 +321,6 @@ static void *pseries_eeh_probe(struct pci_dn *pdn, void *data) if (enable) { eeh_add_flag(EEH_ENABLED); eeh_add_to_parent_pe(edev);-- pr_debug("%s: EEH enabled on %02x:%02x.%01x PHB#%x-PE#%x\n",- __func__, pdn->busno, PCI_SLOT(pdn->devfn),- PCI_FUNC(pdn->devfn), pe.phb->global_number,- pe.addr); } else if (pdn->parent && pdn_to_eeh_dev(pdn->parent) && (pdn_to_eeh_dev(pdn->parent))->pe) { /* This device doesn't support EEH, but it may have an
@@ -397,6 +394,10 @@ static void *pnv_eeh_probe(struct pci_dn *pdn, void *data) int ret; int config_addr = (pdn->busno << 8) | (pdn->devfn);+ pr_debug("%s: probing %04x:%02x:%02x.%01x\n",+ __func__, hose->global_number, pdn->busno,+ PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn));+ /* * When probing the root bridge, which doesn't have any * subordinate PCI devices. We don't have OF node for
@@ -251,6 +253,10 @@ static void *pseries_eeh_probe(struct pci_dn *pdn, void *data)intenable=0;intret;+pr_debug("%s: probing %04x:%02x:%02x.%01x\n",+__func__,pdn->phb->global_number,pdn->busno,+PCI_SLOT(pdn->devfn),PCI_FUNC(pdn->devfn));+/* Retrieve OF node and eeh device */edev=pdn_to_eeh_dev(pdn);if(!edev||edev->pe)
@@ -294,7 +300,12 @@ static void *pseries_eeh_probe(struct pci_dn *pdn, void *data)/* Enable EEH on the device */ret=eeh_ops->set_option(&pe,EEH_OPT_ENABLE);-if(!ret){+if(ret){+pr_debug("%s: EEH failed to enable on %02x:%02x.%01x PHB#%x-PE#%x (code %d)\n",+__func__,pdn->busno,PCI_SLOT(pdn->devfn),+PCI_FUNC(pdn->devfn),pe.phb->global_number,+pe.addr,ret);+}else{
edev!=NULL here so you could do dev_dbg(&edev->pdev->dev,...) and skip
PCI_SLOT/PCI_FUNC. Or is (edev!=NULL && edev->pdev==NULL) possible (it
could be, just asking)?
I can see that edev will be non-NULL here, but that pr_debug() pattern
(using the PDN information to form the PCI address) is quite common
across the EEH code, so I think rather than changing a couple of
specific cases, I should do a separate cleanup patch and introduce
something like pdn_debug(pdn, "...."). What do you think?
(I don't know exactly when edev->pdev can be NULL.)
@@ -310,11 +321,6 @@ static void *pseries_eeh_probe(struct pci_dn *pdn, void *data) if (enable) { eeh_add_flag(EEH_ENABLED); eeh_add_to_parent_pe(edev);-- pr_debug("%s: EEH enabled on %02x:%02x.%01x PHB#%x-PE#%x\n",- __func__, pdn->busno, PCI_SLOT(pdn->devfn),- PCI_FUNC(pdn->devfn), pe.phb->global_number,- pe.addr); } else if (pdn->parent && pdn_to_eeh_dev(pdn->parent) && (pdn_to_eeh_dev(pdn->parent))->pe) { /* This device doesn't support EEH, but it may have an
From: Sam Bobroff <hidden> Date: 2019-06-19 05:55:18
On Wed, Jun 05, 2019 at 03:49:15PM +1000, Oliver wrote:
On Tue, May 7, 2019 at 2:30 PM Sam Bobroff [off-list ref] wrote:
quoted
Now that EEH support for all devices (on PowerNV and pSeries) is
provided by the pcibios bus add device hooks, eeh_probe_devices() and
eeh_addr_cache_build() are redundant and can be removed.
Move the EEH enabled message into it's own function so that it can be
called from multiple places.
Note that previously on pSeries, useless EEH sysfs files were created
for some devices that did not have EEH support and this change
prevents them from being created.
Signed-off-by: Sam Bobroff <redacted>
---
v2 - As it's so small, merged the enablement message patch into this one (where it's used).
- Reworked enablement messages.
arch/powerpc/include/asm/eeh.h | 7 ++---
arch/powerpc/kernel/eeh.c | 27 ++++++-----------
arch/powerpc/kernel/eeh_cache.c | 32 --------------------
arch/powerpc/platforms/powernv/eeh-powernv.c | 4 +--
arch/powerpc/platforms/pseries/pci.c | 3 +-
5 files changed, 14 insertions(+), 59 deletions(-)
The one concern I have about this is that PAPR requires us to enable
EEH for the device before we do any config accesses. From PAPR:
R1–7.3.11.1–5. For the EEH option: If a device driver is going to
enable EEH and the platform has not defaulted
to EEH enabled, then it must do so before it does any operations with
its IOA, including any configuration
cycles or Load or Store operations.
So if we want to be strictly compatible we'd need to ensure the
set-eeh-option RTAS call happens before we read the VDID in
pci_scan_device(). The pseries eeh_probe() function does this
currently, but if we defer it until the pcibios call happens we'll
have done a pile of config accesses before then. Maybe it doesn't
matter, but we'd need to do further testing under phyp or work out
some other way to ensure it's done pre-probe.
Hmm! I had not looked at this specifically, but I don't think I've made
it any worse. The reordering is all underneath pcibios_init(), and it
changes things from this...
for each PHB: pcibios_scan_phb() and then pci_bus_add_devices().
pcibios_resource_survey() [calls ppc_md.pcibios_fixup()->eeh_probe_devices()]
... to this:
for each PHB: pcibios_scan_phb()
pcibios_resource_survey()
for each PHB: pci_bus_add_devices()
ppc_md.pcibios_fixup()->eeh_probe_devices()
So either way, the EEH probe (and therefore setup) happens last. Moving
the probe into pseries_pcibios_bus_add_device() actually moves it a
little earlier than before.
Just for kicks, I instrumented rtas_pci_read_config() and it shows
that there are indeed several accesses before the probe function is
called. Here's the first:
pcibios_init() ->
pcibios_scan_phb() ->
__of_scan_bus() ->
of_scan_pci_dev() ->
of_create_pci_dev() ->
set_pcie_port_type() ->
pci_find_capability()
Most of that is PowerPC specific, and there's already an EEH hack in
of_scan_pci_dev(), so I tried a quick hack to probe there and it does
seem at least boot OK. And it's before any accesses! :-)
What do you think? (Although, I think I'd prefer to leave this as follow
up work.)
@@ -397,6 +394,10 @@ static void *pnv_eeh_probe(struct pci_dn *pdn, void *data) int ret; int config_addr = (pdn->busno << 8) | (pdn->devfn);+ pr_debug("%s: probing %04x:%02x:%02x.%01x\n",+ __func__, hose->global_number, pdn->busno,+ PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn));+ /* * When probing the root bridge, which doesn't have any * subordinate PCI devices. We don't have OF node for
@@ -251,6 +253,10 @@ static void *pseries_eeh_probe(struct pci_dn *pdn, void *data)intenable=0;intret;+pr_debug("%s: probing %04x:%02x:%02x.%01x\n",+__func__,pdn->phb->global_number,pdn->busno,+PCI_SLOT(pdn->devfn),PCI_FUNC(pdn->devfn));+/* Retrieve OF node and eeh device */edev=pdn_to_eeh_dev(pdn);if(!edev||edev->pe)
@@ -294,7 +300,12 @@ static void *pseries_eeh_probe(struct pci_dn *pdn, void *data)/* Enable EEH on the device */ret=eeh_ops->set_option(&pe,EEH_OPT_ENABLE);-if(!ret){+if(ret){+pr_debug("%s: EEH failed to enable on %02x:%02x.%01x PHB#%x-PE#%x (code %d)\n",+__func__,pdn->busno,PCI_SLOT(pdn->devfn),+PCI_FUNC(pdn->devfn),pe.phb->global_number,+pe.addr,ret);+}else{
edev!=NULL here so you could do dev_dbg(&edev->pdev->dev,...) and skip
PCI_SLOT/PCI_FUNC. Or is (edev!=NULL && edev->pdev==NULL) possible (it
could be, just asking)?
I can see that edev will be non-NULL here, but that pr_debug() pattern
(using the PDN information to form the PCI address) is quite common
across the EEH code, so I think rather than changing a couple of
specific cases, I should do a separate cleanup patch and introduce
something like pdn_debug(pdn, "...."). What do you think?
I'd switch them all to already existing dev_dbg/pci_debug rather than
adding pdn_debug as imho it should not have been used in the first place
really...
(I don't know exactly when edev->pdev can be NULL.)
... and if you switch to dev_dbg/pci_debug, I think quite soon you'll
know if it can or cannot be NULL :)
@@ -310,11 +321,6 @@ static void *pseries_eeh_probe(struct pci_dn *pdn, void *data) if (enable) { eeh_add_flag(EEH_ENABLED); eeh_add_to_parent_pe(edev);-- pr_debug("%s: EEH enabled on %02x:%02x.%01x PHB#%x-PE#%x\n",- __func__, pdn->busno, PCI_SLOT(pdn->devfn),- PCI_FUNC(pdn->devfn), pe.phb->global_number,- pe.addr); } else if (pdn->parent && pdn_to_eeh_dev(pdn->parent) && (pdn_to_eeh_dev(pdn->parent))->pe) { /* This device doesn't support EEH, but it may have an
On Thu, Jun 20, 2019 at 12:40 PM Alexey Kardashevskiy [off-list ref] wrote:
On 19/06/2019 14:27, Sam Bobroff wrote:
quoted
On Tue, Jun 11, 2019 at 03:47:58PM +1000, Alexey Kardashevskiy wrote:
quoted
On 07/05/2019 14:30, Sam Bobroff wrote:
quoted
Also remove useless comment.
Signed-off-by: Sam Bobroff <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
*snip*
quoted
I can see that edev will be non-NULL here, but that pr_debug() pattern
(using the PDN information to form the PCI address) is quite common
across the EEH code, so I think rather than changing a couple of
specific cases, I should do a separate cleanup patch and introduce
something like pdn_debug(pdn, "...."). What do you think?
I'd switch them all to already existing dev_dbg/pci_debug rather than
adding pdn_debug as imho it should not have been used in the first place
really...
quoted
(I don't know exactly when edev->pdev can be NULL.)
... and if you switch to dev_dbg/pci_debug, I think quite soon you'll
know if it can or cannot be NULL :)
As far as I can tell edev->pdev is NULL in two cases:
1. Before eeh_device_add_late() has been called on the pdev. The late
part of the add maps the pdev to an edev and sets the pdev's edev
pointer and vis a vis.
2. While recoverying EEH unaware devices. Unaware devices are
destroyed and rescanned and the edev->pdev pointer is cleared by
pcibios_device_release()
In most of these cases it should be safe to use the pci_*() functions
rather than making a new one up for printing pdns. In the cases where
we might not have a PCI dev i'd make a new set of prints that take an
EEH dev rather than a pci_dn since i'd like pci_dn to die sooner
rather than later.
Oliver
From: Sam Bobroff <hidden> Date: 2019-07-16 06:50:54
On Thu, Jun 20, 2019 at 01:45:24PM +1000, Oliver O'Halloran wrote:
On Thu, Jun 20, 2019 at 12:40 PM Alexey Kardashevskiy [off-list ref] wrote:
quoted
On 19/06/2019 14:27, Sam Bobroff wrote:
quoted
On Tue, Jun 11, 2019 at 03:47:58PM +1000, Alexey Kardashevskiy wrote:
quoted
On 07/05/2019 14:30, Sam Bobroff wrote:
quoted
Also remove useless comment.
Signed-off-by: Sam Bobroff <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
*snip*
quoted
I can see that edev will be non-NULL here, but that pr_debug() pattern
(using the PDN information to form the PCI address) is quite common
across the EEH code, so I think rather than changing a couple of
specific cases, I should do a separate cleanup patch and introduce
something like pdn_debug(pdn, "...."). What do you think?
I'd switch them all to already existing dev_dbg/pci_debug rather than
adding pdn_debug as imho it should not have been used in the first place
really...
quoted
(I don't know exactly when edev->pdev can be NULL.)
... and if you switch to dev_dbg/pci_debug, I think quite soon you'll
know if it can or cannot be NULL :)
As far as I can tell edev->pdev is NULL in two cases:
1. Before eeh_device_add_late() has been called on the pdev. The late
part of the add maps the pdev to an edev and sets the pdev's edev
pointer and vis a vis.
2. While recoverying EEH unaware devices. Unaware devices are
destroyed and rescanned and the edev->pdev pointer is cleared by
pcibios_device_release()
In most of these cases it should be safe to use the pci_*() functions
rather than making a new one up for printing pdns. In the cases where
we might not have a PCI dev i'd make a new set of prints that take an
EEH dev rather than a pci_dn since i'd like pci_dn to die sooner
rather than later.
Oliver
I'll change the calls in {pnv,pseries}_pcibios_bus_add_device() and
eeh_add_device_late() to use dev_dbg() and post a new version.
For {pnv,pseries}_eeh_probe() I'm not sure what we can do; there's no
pci_dev available yet and while it would be nice to use the eeh_dev
rather than the pdn, it doesn't seem to have the bus/device/fn
information we need. Am I missing something there? (The code in the
probe functions seems to get it from the pci_dn.)
If there isn't an easy way around this, would it therefore be reasonable
to just leave them open-coded as they are?
Cheers,
Sam.
From: Oliver O'Halloran <oohall@gmail.com> Date: 2019-07-16 07:02:46
On Tue, 2019-07-16 at 16:48 +1000, Sam Bobroff wrote:
On Thu, Jun 20, 2019 at 01:45:24PM +1000, Oliver O'Halloran wrote:
quoted
On Thu, Jun 20, 2019 at 12:40 PM Alexey Kardashevskiy [off-list ref] wrote:
quoted
On 19/06/2019 14:27, Sam Bobroff wrote:
quoted
On Tue, Jun 11, 2019 at 03:47:58PM +1000, Alexey Kardashevskiy wrote:
quoted
On 07/05/2019 14:30, Sam Bobroff wrote:
quoted
Also remove useless comment.
Signed-off-by: Sam Bobroff <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
*snip*
quoted
I can see that edev will be non-NULL here, but that pr_debug() pattern
(using the PDN information to form the PCI address) is quite common
across the EEH code, so I think rather than changing a couple of
specific cases, I should do a separate cleanup patch and introduce
something like pdn_debug(pdn, "...."). What do you think?
I'd switch them all to already existing dev_dbg/pci_debug rather than
adding pdn_debug as imho it should not have been used in the first place
really...
quoted
(I don't know exactly when edev->pdev can be NULL.)
... and if you switch to dev_dbg/pci_debug, I think quite soon you'll
know if it can or cannot be NULL :)
As far as I can tell edev->pdev is NULL in two cases:
1. Before eeh_device_add_late() has been called on the pdev. The late
part of the add maps the pdev to an edev and sets the pdev's edev
pointer and vis a vis.
2. While recoverying EEH unaware devices. Unaware devices are
destroyed and rescanned and the edev->pdev pointer is cleared by
pcibios_device_release()
In most of these cases it should be safe to use the pci_*() functions
rather than making a new one up for printing pdns. In the cases where
we might not have a PCI dev i'd make a new set of prints that take an
EEH dev rather than a pci_dn since i'd like pci_dn to die sooner
rather than later.
Oliver
I'll change the calls in {pnv,pseries}_pcibios_bus_add_device() and
eeh_add_device_late() to use dev_dbg() and post a new version.
For {pnv,pseries}_eeh_probe() I'm not sure what we can do; there's no
pci_dev available yet and while it would be nice to use the eeh_dev
rather than the pdn, it doesn't seem to have the bus/device/fn
information we need. Am I missing something there? (The code in the
probe functions seems to get it from the pci_dn.)
We do have a pci_dev in the powernv case since pnv_eeh_probe() isn't
called until the late probe happens (which is after the pci_dev has
been created). I've got some patches to rework the probe path to make
this a bit clearer, but they need a bit more work.
If there isn't an easy way around this, would it therefore be reasonable
to just leave them open-coded as they are?
I've had this patch floating around a while that should do the trick.
The PCI_BUSNO macro is probably unnecessary since I'm sure there is
something that does it in generic code, but I couldn't find it.
From 61ff8c23c4d13ff640fb2d069dcedacdf2ee22dd Mon Sep 17 00:00:00 2001
From: Oliver O'Halloran <oohall@gmail.com>
Date: Thu, 18 Apr 2019 18:25:13 +1000
Subject: [PATCH] powerpc/eeh: Add bdfn field to eeh_dev
Preperation for removing pci_dn from the powernv EEH code. The only thing we
really use pci_dn for is to get the bdfn of the device for config space
accesses, so adding that information to eeh_dev reduces the need to carry
around the pci_dn.
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
arch/powerpc/include/asm/eeh.h | 2 ++
arch/powerpc/include/asm/ppc-pci.h | 2 ++
arch/powerpc/kernel/eeh_dev.c | 2 ++
3 files changed, 6 insertions(+)
From: Sam Bobroff <hidden> Date: 2019-07-18 05:26:22
On Tue, Jul 16, 2019 at 05:00:44PM +1000, Oliver O'Halloran wrote:
On Tue, 2019-07-16 at 16:48 +1000, Sam Bobroff wrote:
quoted
On Thu, Jun 20, 2019 at 01:45:24PM +1000, Oliver O'Halloran wrote:
quoted
On Thu, Jun 20, 2019 at 12:40 PM Alexey Kardashevskiy [off-list ref] wrote:
quoted
On 19/06/2019 14:27, Sam Bobroff wrote:
quoted
On Tue, Jun 11, 2019 at 03:47:58PM +1000, Alexey Kardashevskiy wrote:
quoted
On 07/05/2019 14:30, Sam Bobroff wrote:
quoted
Also remove useless comment.
Signed-off-by: Sam Bobroff <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
*snip*
quoted
I can see that edev will be non-NULL here, but that pr_debug() pattern
(using the PDN information to form the PCI address) is quite common
across the EEH code, so I think rather than changing a couple of
specific cases, I should do a separate cleanup patch and introduce
something like pdn_debug(pdn, "...."). What do you think?
I'd switch them all to already existing dev_dbg/pci_debug rather than
adding pdn_debug as imho it should not have been used in the first place
really...
quoted
(I don't know exactly when edev->pdev can be NULL.)
... and if you switch to dev_dbg/pci_debug, I think quite soon you'll
know if it can or cannot be NULL :)
As far as I can tell edev->pdev is NULL in two cases:
1. Before eeh_device_add_late() has been called on the pdev. The late
part of the add maps the pdev to an edev and sets the pdev's edev
pointer and vis a vis.
2. While recoverying EEH unaware devices. Unaware devices are
destroyed and rescanned and the edev->pdev pointer is cleared by
pcibios_device_release()
In most of these cases it should be safe to use the pci_*() functions
rather than making a new one up for printing pdns. In the cases where
we might not have a PCI dev i'd make a new set of prints that take an
EEH dev rather than a pci_dn since i'd like pci_dn to die sooner
rather than later.
Oliver
I'll change the calls in {pnv,pseries}_pcibios_bus_add_device() and
eeh_add_device_late() to use dev_dbg() and post a new version.
For {pnv,pseries}_eeh_probe() I'm not sure what we can do; there's no
pci_dev available yet and while it would be nice to use the eeh_dev
rather than the pdn, it doesn't seem to have the bus/device/fn
information we need. Am I missing something there? (The code in the
probe functions seems to get it from the pci_dn.)
We do have a pci_dev in the powernv case since pnv_eeh_probe() isn't
called until the late probe happens (which is after the pci_dev has
been created). I've got some patches to rework the probe path to make
this a bit clearer, but they need a bit more work.
quoted
If there isn't an easy way around this, would it therefore be reasonable
to just leave them open-coded as they are?
I've had this patch floating around a while that should do the trick.
The PCI_BUSNO macro is probably unnecessary since I'm sure there is
something that does it in generic code, but I couldn't find it.
Looks good, I'll try including it and create a dev_dbg style function
or macro that takes an edev.
I don't think I can use it in the pcibios bus add device handlers (where
there is no edev, or where it may be attached to the wrong device) but
I'll use it for all the other cases.
If it works out well I can follow up and update more of the EEH logging
to use it :-)
quoted hunk
From 61ff8c23c4d13ff640fb2d069dcedacdf2ee22dd Mon Sep 17 00:00:00 2001
From: Oliver O'Halloran <oohall@gmail.com>
Date: Thu, 18 Apr 2019 18:25:13 +1000
Subject: [PATCH] powerpc/eeh: Add bdfn field to eeh_dev
Preperation for removing pci_dn from the powernv EEH code. The only thing we
really use pci_dn for is to get the bdfn of the device for config space
accesses, so adding that information to eeh_dev reduces the need to carry
around the pci_dn.
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
arch/powerpc/include/asm/eeh.h | 2 ++
arch/powerpc/include/asm/ppc-pci.h | 2 ++
arch/powerpc/kernel/eeh_dev.c | 2 ++
3 files changed, 6 insertions(+)