Skip to content

Commit b6eebb0

Browse files
oohalmpe
authored andcommitted
powerpc/eeh: Make early EEH init pseries specific
The eeh_ops->probe() function is called from two different contexts: 1. On pseries, where we set EEH_PROBE_MODE_DEVTREE, it's called in eeh_add_device_early() which is supposed to run before we create a pci_dev. 2. On PowerNV, where we set EEH_PROBE_MODE_DEV, it's called in eeh_device_add_late() which is supposed to run *after* the pci_dev is created. The "early" probe is required because PAPR requires that we perform an RTAS call to enable EEH support on a device before we start interacting with it via config space or MMIO. This requirement doesn't exist on PowerNV and shoehorning two completely separate initialisation paths into a common interface just results in a convoluted code everywhere. Additionally the early probe requires the probe function to take an pci_dn rather than a pci_dev argument. We'd like to make pci_dn a pseries specific data structure since there's no real requirement for them on PowerNV. To help both goals move the early probe into the pseries containment zone so the platform depedence is more explicit. Reviewed-by: Sam Bobroff <[email protected]> Signed-off-by: Oliver O'Halloran <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 3ff32ef commit b6eebb0

File tree

9 files changed

+64
-81
lines changed

9 files changed

+64
-81
lines changed

arch/powerpc/include/asm/eeh.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,6 @@ int __exit eeh_ops_unregister(const char *name);
301301
int eeh_check_failure(const volatile void __iomem *token);
302302
int eeh_dev_check_failure(struct eeh_dev *edev);
303303
void eeh_addr_cache_init(void);
304-
void eeh_add_device_early(struct pci_dn *);
305-
void eeh_add_device_tree_early(struct pci_dn *);
306304
void eeh_add_device_late(struct pci_dev *);
307305
void eeh_remove_device(struct pci_dev *);
308306
int eeh_unfreeze_pe(struct eeh_pe *pe);
@@ -358,10 +356,6 @@ static inline int eeh_check_failure(const volatile void __iomem *token)
358356

359357
static inline void eeh_addr_cache_init(void) { }
360358

361-
static inline void eeh_add_device_early(struct pci_dn *pdn) { }
362-
363-
static inline void eeh_add_device_tree_early(struct pci_dn *pdn) { }
364-
365359
static inline void eeh_add_device_late(struct pci_dev *dev) { }
366360

367361
static inline void eeh_remove_device(struct pci_dev *dev) { }
@@ -370,6 +364,14 @@ static inline void eeh_remove_device(struct pci_dev *dev) { }
370364
#define EEH_IO_ERROR_VALUE(size) (-1UL)
371365
#endif /* CONFIG_EEH */
372366

367+
#if defined(CONFIG_PPC_PSERIES) && defined(CONFIG_EEH)
368+
void pseries_eeh_init_edev(struct pci_dn *pdn);
369+
void pseries_eeh_init_edev_recursive(struct pci_dn *pdn);
370+
#else
371+
static inline void pseries_eeh_add_device_early(struct pci_dn *pdn) { }
372+
static inline void pseries_eeh_add_device_tree_early(struct pci_dn *pdn) { }
373+
#endif
374+
373375
#ifdef CONFIG_PPC64
374376
/*
375377
* MMIO read/write operations with EEH support.

arch/powerpc/kernel/eeh.c

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,52 +1106,6 @@ static int eeh_init(void)
11061106

11071107
core_initcall_sync(eeh_init);
11081108

1109-
/**
1110-
* eeh_add_device_early - Enable EEH for the indicated device node
1111-
* @pdn: PCI device node for which to set up EEH
1112-
*
1113-
* This routine must be used to perform EEH initialization for PCI
1114-
* devices that were added after system boot (e.g. hotplug, dlpar).
1115-
* This routine must be called before any i/o is performed to the
1116-
* adapter (inluding any config-space i/o).
1117-
* Whether this actually enables EEH or not for this device depends
1118-
* on the CEC architecture, type of the device, on earlier boot
1119-
* command-line arguments & etc.
1120-
*/
1121-
void eeh_add_device_early(struct pci_dn *pdn)
1122-
{
1123-
struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
1124-
1125-
if (!edev)
1126-
return;
1127-
1128-
if (!eeh_has_flag(EEH_PROBE_MODE_DEVTREE))
1129-
return;
1130-
1131-
eeh_ops->probe(pdn, NULL);
1132-
}
1133-
1134-
/**
1135-
* eeh_add_device_tree_early - Enable EEH for the indicated device
1136-
* @pdn: PCI device node
1137-
*
1138-
* This routine must be used to perform EEH initialization for the
1139-
* indicated PCI device that was added after system boot (e.g.
1140-
* hotplug, dlpar).
1141-
*/
1142-
void eeh_add_device_tree_early(struct pci_dn *pdn)
1143-
{
1144-
struct pci_dn *n;
1145-
1146-
if (!pdn)
1147-
return;
1148-
1149-
list_for_each_entry(n, &pdn->child_list, list)
1150-
eeh_add_device_tree_early(n);
1151-
eeh_add_device_early(pdn);
1152-
}
1153-
EXPORT_SYMBOL_GPL(eeh_add_device_tree_early);
1154-
11551109
/**
11561110
* eeh_add_device_late - Perform EEH initialization for the indicated pci device
11571111
* @dev: pci device for which to set up EEH

arch/powerpc/kernel/of_platform.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,9 @@ static int of_pci_phb_probe(struct platform_device *dev)
6262
/* Init pci_dn data structures */
6363
pci_devs_phb_init_dynamic(phb);
6464

65-
/* Create EEH devices for the PHB */
65+
/* Create EEH PEs for the PHB */
6666
eeh_dev_phb_init_dynamic(phb);
6767

68-
/* Register devices with EEH */
69-
if (dev->dev.of_node->child)
70-
eeh_add_device_tree_early(PCI_DN(dev->dev.of_node));
71-
7268
/* Scan the bus */
7369
pcibios_scan_phb(phb);
7470
if (phb->bus == NULL)

arch/powerpc/platforms/powernv/eeh-powernv.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,7 @@ static int eeh_event_irq = -EINVAL;
4040

4141
void pnv_pcibios_bus_add_device(struct pci_dev *pdev)
4242
{
43-
struct pci_dn *pdn = pci_get_pdn(pdev);
44-
45-
if (!pdn || eeh_has_flag(EEH_FORCE_DISABLED))
46-
return;
47-
4843
dev_dbg(&pdev->dev, "EEH: Setting up device\n");
49-
eeh_add_device_early(pdn);
5044
eeh_add_device_late(pdev);
5145
}
5246

arch/powerpc/platforms/pseries/eeh_pseries.c

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ void pseries_pcibios_bus_add_device(struct pci_dev *pdev)
6767
pdn->pe_number = physfn_pdn->pe_num_map[pdn->vf_index];
6868
}
6969
#endif
70-
eeh_add_device_early(pdn);
70+
pseries_eeh_init_edev(pdn);
7171
#ifdef CONFIG_PCI_IOV
7272
if (pdev->is_virtfn) {
7373
struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
@@ -221,34 +221,52 @@ static int pseries_eeh_find_ecap(struct pci_dn *pdn, int cap)
221221
}
222222

223223
/**
224-
* pseries_eeh_probe - EEH probe on the given device
224+
* pseries_eeh_init_edev - initialise the eeh_dev and eeh_pe for a pci_dn
225+
*
225226
* @pdn: PCI device node
226-
* @data: Unused
227227
*
228-
* When EEH module is installed during system boot, all PCI devices
229-
* are checked one by one to see if it supports EEH. The function
230-
* is introduced for the purpose.
228+
* When we discover a new PCI device via the device-tree we create a
229+
* corresponding pci_dn and we allocate, but don't initialise, an eeh_dev.
230+
* This function takes care of the initialisation and inserts the eeh_dev
231+
* into the correct eeh_pe. If no eeh_pe exists we'll allocate one.
231232
*/
232-
static void *pseries_eeh_probe(struct pci_dn *pdn, void *data)
233+
void pseries_eeh_init_edev(struct pci_dn *pdn)
233234
{
234235
struct eeh_dev *edev;
235236
struct eeh_pe pe;
236237
u32 pcie_flags;
237238
int enable = 0;
238239
int ret;
239240

240-
/* Retrieve OF node and eeh device */
241+
if (WARN_ON_ONCE(!eeh_has_flag(EEH_PROBE_MODE_DEVTREE)))
242+
return;
243+
244+
/*
245+
* Find the eeh_dev for this pdn. The storage for the eeh_dev was
246+
* allocated at the same time as the pci_dn.
247+
*
248+
* XXX: We should probably re-visit that.
249+
*/
241250
edev = pdn_to_eeh_dev(pdn);
242-
if (!edev || edev->pe)
243-
return NULL;
251+
if (!edev)
252+
return;
253+
254+
/*
255+
* If ->pe is set then we've already probed this device. We hit
256+
* this path when a pci_dev is removed and rescanned while recovering
257+
* a PE (i.e. for devices where the driver doesn't support error
258+
* recovery).
259+
*/
260+
if (edev->pe)
261+
return;
244262

245263
/* Check class/vendor/device IDs */
246264
if (!pdn->vendor_id || !pdn->device_id || !pdn->class_code)
247-
return NULL;
265+
return;
248266

249267
/* Skip for PCI-ISA bridge */
250268
if ((pdn->class_code >> 8) == PCI_CLASS_BRIDGE_ISA)
251-
return NULL;
269+
return;
252270

253271
eeh_edev_dbg(edev, "Probing device\n");
254272

@@ -315,9 +333,29 @@ static void *pseries_eeh_probe(struct pci_dn *pdn, void *data)
315333

316334
/* Save memory bars */
317335
eeh_save_bars(edev);
336+
}
337+
338+
/**
339+
* pseries_eeh_init_edev_recursive - Enable EEH for the indicated device
340+
* @pdn: PCI device node
341+
*
342+
* This routine must be used to perform EEH initialization for the
343+
* indicated PCI device that was added after system boot (e.g.
344+
* hotplug, dlpar).
345+
*/
346+
void pseries_eeh_init_edev_recursive(struct pci_dn *pdn)
347+
{
348+
struct pci_dn *n;
349+
350+
if (!pdn)
351+
return;
352+
353+
list_for_each_entry(n, &pdn->child_list, list)
354+
pseries_eeh_init_edev_recursive(n);
318355

319-
return NULL;
356+
pseries_eeh_init_edev(pdn);
320357
}
358+
EXPORT_SYMBOL_GPL(pseries_eeh_init_edev_recursive);
321359

322360
/**
323361
* pseries_eeh_set_option - Initialize EEH or MMIO/DMA reenable
@@ -775,7 +813,6 @@ static int pseries_notify_resume(struct pci_dn *pdn)
775813
static struct eeh_ops pseries_eeh_ops = {
776814
.name = "pseries",
777815
.init = pseries_eeh_init,
778-
.probe = pseries_eeh_probe,
779816
.set_option = pseries_eeh_set_option,
780817
.get_pe_addr = pseries_eeh_get_pe_addr,
781818
.get_state = pseries_eeh_get_state,

arch/powerpc/platforms/pseries/pci_dlpar.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ struct pci_controller *init_phb_dynamic(struct device_node *dn)
3737
eeh_dev_phb_init_dynamic(phb);
3838

3939
if (dn->child)
40-
eeh_add_device_tree_early(PCI_DN(dn));
40+
pseries_eeh_init_edev_recursive(PCI_DN(dn));
4141

4242
pcibios_scan_phb(phb);
4343
pcibios_finish_adding_to_bus(phb->bus);

drivers/pci/hotplug/rpadlpar_core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ static void dlpar_pci_add_bus(struct device_node *dn)
140140
struct pci_controller *phb = pdn->phb;
141141
struct pci_dev *dev = NULL;
142142

143-
eeh_add_device_tree_early(pdn);
143+
pseries_eeh_init_edev_recursive(pdn);
144144

145145
/* Add EADS device to PHB bus, adding new entry to bus->devices */
146146
dev = of_create_pci_dev(dn, phb->bus, pdn->devfn);

drivers/pci/hotplug/rpaphp_core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
493493
return retval;
494494

495495
if (state == PRESENT) {
496-
eeh_add_device_tree_early(PCI_DN(slot->dn));
496+
pseries_eeh_init_edev_recursive(PCI_DN(slot->dn));
497497

498498
pci_lock_rescan_remove();
499499
pci_hp_add_devices(slot->bus);

drivers/pci/hotplug/rpaphp_pci.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ int rpaphp_enable_slot(struct slot *slot)
9696
}
9797

9898
if (list_empty(&bus->devices)) {
99-
eeh_add_device_tree_early(PCI_DN(slot->dn));
99+
pseries_eeh_init_edev_recursive(PCI_DN(slot->dn));
100100
pci_hp_add_devices(bus);
101101
}
102102

0 commit comments

Comments
 (0)