* [PATCH] ppc/EEH: fix crash when adding a device in a slot with DDW
@ 2012-12-27 16:34 Thadeu Lima de Souza Cascardo
2012-12-28 5:18 ` Gavin Shan
0 siblings, 1 reply; 7+ messages in thread
From: Thadeu Lima de Souza Cascardo @ 2012-12-27 16:34 UTC (permalink / raw)
To: linuxppc-dev
Cc: shangw, linux-kernel, stable, paulus,
Thadeu Lima de Souza Cascardo, bhelgaas
The DDW code uses a eeh_dev struct from the pci_dev. However, this is
not set until eeh_add_device_late is called.
Since pci_bus_add_devices is called before eeh_add_device_late, the PCI
devices are added to the bus, making drivers' probe hooks to be called.
These will call set_dma_mask, which will call the DDW code, which will
require the eeh_dev struct from pci_dev. This would result in a crash,
due to a NULL dereference.
Calling eeh_add_device_late after pci_bus_add_devices would make the
system BUG, because device files shouldn't be added to devices there
were not added to the system. So, a new function is needed to add such
files only after pci_bus_add_devices have been called.
Cc: stable@vger.kernel.org
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/eeh.h | 3 +++
arch/powerpc/kernel/pci-common.c | 7 +++++--
arch/powerpc/platforms/pseries/eeh.c | 24 +++++++++++++++++++++++-
3 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index b0ef738..71aac19 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -201,6 +201,7 @@ int eeh_dev_check_failure(struct eeh_dev *edev);
void __init eeh_addr_cache_build(void);
void eeh_add_device_tree_early(struct device_node *);
void eeh_add_device_tree_late(struct pci_bus *);
+void eeh_add_device_tree_files(struct pci_bus *);
void eeh_remove_bus_device(struct pci_dev *, int);
/**
@@ -240,6 +241,8 @@ static inline void eeh_add_device_tree_early(struct device_node *dn) { }
static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
+static inline void eeh_add_device_tree_files(struct pci_bus *bus) { }
+
static inline void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe) { }
static inline void eeh_lock(void) { }
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 7f94f76..7b1f14c 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1480,11 +1480,14 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
pcibios_allocate_bus_resources(bus);
pcibios_claim_one_bus(bus);
+ /* Fixup EEH */
+ eeh_add_device_tree_late(bus);
+
/* Add new devices to global lists. Register in proc, sysfs. */
pci_bus_add_devices(bus);
- /* Fixup EEH */
- eeh_add_device_tree_late(bus);
+ /* Add EEH sysfs files */
+ eeh_add_device_tree_files(bus);
}
EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 9a04322..a667a34 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -788,7 +788,6 @@ static void eeh_add_device_late(struct pci_dev *dev)
dev->dev.archdata.edev = edev;
eeh_addr_cache_insert_dev(dev);
- eeh_sysfs_add_device(dev);
}
/**
@@ -815,6 +814,29 @@ void eeh_add_device_tree_late(struct pci_bus *bus)
EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
/**
+ * eeh_add_device_tree_files - Add EEH sysfs files for the indicated PCI bus
+ * @bus: PCI bus
+ *
+ * This routine must be used to add EEH sysfs files for PCI
+ * devices which are attached to the indicated PCI bus. The PCI bus
+ * is added after system boot through hotplug or dlpar.
+ */
+void eeh_add_device_tree_files(struct pci_bus *bus)
+{
+ struct pci_dev *dev;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ eeh_sysfs_add_device(dev);
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ struct pci_bus *subbus = dev->subordinate;
+ if (subbus)
+ eeh_add_device_tree_files(subbus);
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(eeh_add_device_tree_files);
+
+/**
* eeh_remove_device - Undo EEH setup for the indicated pci device
* @dev: pci device to be removed
* @purge_pe: remove the PE or not
--
1.7.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] ppc/EEH: fix crash when adding a device in a slot with DDW
2012-12-27 16:34 [PATCH] ppc/EEH: fix crash when adding a device in a slot with DDW Thadeu Lima de Souza Cascardo
@ 2012-12-28 5:18 ` Gavin Shan
2012-12-28 12:06 ` Thadeu Lima de Souza Cascardo
0 siblings, 1 reply; 7+ messages in thread
From: Gavin Shan @ 2012-12-28 5:18 UTC (permalink / raw)
To: Thadeu Lima de Souza Cascardo
Cc: shangw, linux-kernel, stable, paulus, bhelgaas, linuxppc-dev
On Thu, Dec 27, 2012 at 02:34:00PM -0200, Thadeu Lima de Souza Cascardo wrote:
>The DDW code uses a eeh_dev struct from the pci_dev. However, this is
>not set until eeh_add_device_late is called.
>
>Since pci_bus_add_devices is called before eeh_add_device_late, the PCI
>devices are added to the bus, making drivers' probe hooks to be called.
>These will call set_dma_mask, which will call the DDW code, which will
>require the eeh_dev struct from pci_dev. This would result in a crash,
>due to a NULL dereference.
>
>Calling eeh_add_device_late after pci_bus_add_devices would make the
>system BUG, because device files shouldn't be added to devices there
>were not added to the system. So, a new function is needed to add such
>files only after pci_bus_add_devices have been called.
>
Could you please explain for a bit how did you trigger the problem? I'm
not sure you got it while doing PCI hotplug or just saw the issue during
system bootup stage :-)
>Cc: stable@vger.kernel.org
>Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
>---
> arch/powerpc/include/asm/eeh.h | 3 +++
> arch/powerpc/kernel/pci-common.c | 7 +++++--
> arch/powerpc/platforms/pseries/eeh.c | 24 +++++++++++++++++++++++-
> 3 files changed, 31 insertions(+), 3 deletions(-)
>
>diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
>index b0ef738..71aac19 100644
>--- a/arch/powerpc/include/asm/eeh.h
>+++ b/arch/powerpc/include/asm/eeh.h
>@@ -201,6 +201,7 @@ int eeh_dev_check_failure(struct eeh_dev *edev);
> void __init eeh_addr_cache_build(void);
> void eeh_add_device_tree_early(struct device_node *);
> void eeh_add_device_tree_late(struct pci_bus *);
>+void eeh_add_device_tree_files(struct pci_bus *);
Since the function is going to add EEH specific sysfs files, its name would
be something like "eeh_add_sysfs_files" instead of "eeh_add_device_tree_files" :-)
> void eeh_remove_bus_device(struct pci_dev *, int);
>
> /**
>@@ -240,6 +241,8 @@ static inline void eeh_add_device_tree_early(struct device_node *dn) { }
>
> static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
>
>+static inline void eeh_add_device_tree_files(struct pci_bus *bus) { }
>+
It'd better to rename the function name to "eeh_add_sysfs_files" mentioned
as above.
> static inline void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe) { }
>
> static inline void eeh_lock(void) { }
>diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
>index 7f94f76..7b1f14c 100644
>--- a/arch/powerpc/kernel/pci-common.c
>+++ b/arch/powerpc/kernel/pci-common.c
>@@ -1480,11 +1480,14 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
> pcibios_allocate_bus_resources(bus);
> pcibios_claim_one_bus(bus);
>
>+ /* Fixup EEH */
>+ eeh_add_device_tree_late(bus);
>+
> /* Add new devices to global lists. Register in proc, sysfs. */
> pci_bus_add_devices(bus);
>
>- /* Fixup EEH */
>- eeh_add_device_tree_late(bus);
>+ /* Add EEH sysfs files */
>+ eeh_add_device_tree_files(bus);
The function name would be "eeh_add_sysfs_files" as above.
> }
> EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
>
By the way, arch/powerpc/kernel/of_platform.c::of_pci_phb_probe is also calling
to eeh_add_device_tree_late() as well. Since you have removed part of the logic
from original eeh_add_device_tree_late(), which is add EEH specific sysfs files,
and you put that part of logic to eeh_add_device_tree_files(). So I think you
also need make the similiar change for of_pci_phb_probe() as well :-)
>diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
>index 9a04322..a667a34 100644
>--- a/arch/powerpc/platforms/pseries/eeh.c
>+++ b/arch/powerpc/platforms/pseries/eeh.c
>@@ -788,7 +788,6 @@ static void eeh_add_device_late(struct pci_dev *dev)
> dev->dev.archdata.edev = edev;
>
> eeh_addr_cache_insert_dev(dev);
>- eeh_sysfs_add_device(dev);
> }
>
> /**
>@@ -815,6 +814,29 @@ void eeh_add_device_tree_late(struct pci_bus *bus)
> EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
>
> /**
>+ * eeh_add_device_tree_files - Add EEH sysfs files for the indicated PCI bus
>+ * @bus: PCI bus
>+ *
>+ * This routine must be used to add EEH sysfs files for PCI
>+ * devices which are attached to the indicated PCI bus. The PCI bus
>+ * is added after system boot through hotplug or dlpar.
>+ */
>+void eeh_add_device_tree_files(struct pci_bus *bus)
>+{
>+ struct pci_dev *dev;
>+
>+ list_for_each_entry(dev, &bus->devices, bus_list) {
>+ eeh_sysfs_add_device(dev);
>+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
>+ struct pci_bus *subbus = dev->subordinate;
>+ if (subbus)
>+ eeh_add_device_tree_files(subbus);
>+ }
>+ }
>+}
>+EXPORT_SYMBOL_GPL(eeh_add_device_tree_files);
>+
The function name mentioned as above.
>+/**
> * eeh_remove_device - Undo EEH setup for the indicated pci device
> * @dev: pci device to be removed
> * @purge_pe: remove the PE or not
>
Thanks,
Gavin
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] ppc/EEH: fix crash when adding a device in a slot with DDW
2012-12-28 5:18 ` Gavin Shan
@ 2012-12-28 12:06 ` Thadeu Lima de Souza Cascardo
2012-12-28 19:13 ` [PATCH 1/2] EEH/OF: checking for CONFIG_EEH is not needed Thadeu Lima de Souza Cascardo
2012-12-28 19:13 ` [PATCH 2/2] ppc/EEH: fix crash when adding a device in a slot with DDW Thadeu Lima de Souza Cascardo
0 siblings, 2 replies; 7+ messages in thread
From: Thadeu Lima de Souza Cascardo @ 2012-12-28 12:06 UTC (permalink / raw)
To: Gavin Shan; +Cc: linux-kernel, stable, paulus, bhelgaas, linuxppc-dev
On Fri, Dec 28, 2012 at 01:18:24PM +0800, Gavin Shan wrote:
> On Thu, Dec 27, 2012 at 02:34:00PM -0200, Thadeu Lima de Souza Cascardo wrote:
> >The DDW code uses a eeh_dev struct from the pci_dev. However, this is
> >not set until eeh_add_device_late is called.
> >
> >Since pci_bus_add_devices is called before eeh_add_device_late, the PCI
> >devices are added to the bus, making drivers' probe hooks to be called.
> >These will call set_dma_mask, which will call the DDW code, which will
> >require the eeh_dev struct from pci_dev. This would result in a crash,
> >due to a NULL dereference.
> >
> >Calling eeh_add_device_late after pci_bus_add_devices would make the
> >system BUG, because device files shouldn't be added to devices there
> >were not added to the system. So, a new function is needed to add such
> >files only after pci_bus_add_devices have been called.
> >
>
> Could you please explain for a bit how did you trigger the problem? I'm
> not sure you got it while doing PCI hotplug or just saw the issue during
> system bootup stage :-)
>
I did a DLPAR remove followed by a DLPAR add, using drmgr -r and drmgr
-a. The reason the issue is not trigerred during bootup is that there is
no driver registered yet. So no driver probe will call dma_set_mask.
> >Cc: stable@vger.kernel.org
> >Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
> >---
> > arch/powerpc/include/asm/eeh.h | 3 +++
> > arch/powerpc/kernel/pci-common.c | 7 +++++--
> > arch/powerpc/platforms/pseries/eeh.c | 24 +++++++++++++++++++++++-
> > 3 files changed, 31 insertions(+), 3 deletions(-)
> >
> >diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
> >index b0ef738..71aac19 100644
> >--- a/arch/powerpc/include/asm/eeh.h
> >+++ b/arch/powerpc/include/asm/eeh.h
> >@@ -201,6 +201,7 @@ int eeh_dev_check_failure(struct eeh_dev *edev);
> > void __init eeh_addr_cache_build(void);
> > void eeh_add_device_tree_early(struct device_node *);
> > void eeh_add_device_tree_late(struct pci_bus *);
> >+void eeh_add_device_tree_files(struct pci_bus *);
>
> Since the function is going to add EEH specific sysfs files, its name would
> be something like "eeh_add_sysfs_files" instead of "eeh_add_device_tree_files" :-)
It's indeed a better name.
>
> > void eeh_remove_bus_device(struct pci_dev *, int);
> >
> > /**
> >@@ -240,6 +241,8 @@ static inline void eeh_add_device_tree_early(struct device_node *dn) { }
> >
> > static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
> >
> >+static inline void eeh_add_device_tree_files(struct pci_bus *bus) { }
> >+
>
> It'd better to rename the function name to "eeh_add_sysfs_files" mentioned
> as above.
>
> > static inline void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe) { }
> >
> > static inline void eeh_lock(void) { }
> >diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
> >index 7f94f76..7b1f14c 100644
> >--- a/arch/powerpc/kernel/pci-common.c
> >+++ b/arch/powerpc/kernel/pci-common.c
> >@@ -1480,11 +1480,14 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
> > pcibios_allocate_bus_resources(bus);
> > pcibios_claim_one_bus(bus);
> >
> >+ /* Fixup EEH */
> >+ eeh_add_device_tree_late(bus);
> >+
> > /* Add new devices to global lists. Register in proc, sysfs. */
> > pci_bus_add_devices(bus);
> >
> >- /* Fixup EEH */
> >- eeh_add_device_tree_late(bus);
> >+ /* Add EEH sysfs files */
> >+ eeh_add_device_tree_files(bus);
>
> The function name would be "eeh_add_sysfs_files" as above.
>
> > }
> > EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
> >
>
> By the way, arch/powerpc/kernel/of_platform.c::of_pci_phb_probe is also calling
> to eeh_add_device_tree_late() as well. Since you have removed part of the logic
> from original eeh_add_device_tree_late(), which is add EEH specific sysfs files,
> and you put that part of logic to eeh_add_device_tree_files(). So I think you
> also need make the similiar change for of_pci_phb_probe() as well :-)
>
Good point. I will look into other call sites. However, I don't have
access to other platforms to test the patch.
> >diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
> >index 9a04322..a667a34 100644
> >--- a/arch/powerpc/platforms/pseries/eeh.c
> >+++ b/arch/powerpc/platforms/pseries/eeh.c
> >@@ -788,7 +788,6 @@ static void eeh_add_device_late(struct pci_dev *dev)
> > dev->dev.archdata.edev = edev;
> >
> > eeh_addr_cache_insert_dev(dev);
> >- eeh_sysfs_add_device(dev);
> > }
> >
> > /**
> >@@ -815,6 +814,29 @@ void eeh_add_device_tree_late(struct pci_bus *bus)
> > EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
> >
> > /**
> >+ * eeh_add_device_tree_files - Add EEH sysfs files for the indicated PCI bus
> >+ * @bus: PCI bus
> >+ *
> >+ * This routine must be used to add EEH sysfs files for PCI
> >+ * devices which are attached to the indicated PCI bus. The PCI bus
> >+ * is added after system boot through hotplug or dlpar.
> >+ */
> >+void eeh_add_device_tree_files(struct pci_bus *bus)
> >+{
> >+ struct pci_dev *dev;
> >+
> >+ list_for_each_entry(dev, &bus->devices, bus_list) {
> >+ eeh_sysfs_add_device(dev);
> >+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
> >+ struct pci_bus *subbus = dev->subordinate;
> >+ if (subbus)
> >+ eeh_add_device_tree_files(subbus);
> >+ }
> >+ }
> >+}
> >+EXPORT_SYMBOL_GPL(eeh_add_device_tree_files);
> >+
>
> The function name mentioned as above.
>
> >+/**
> > * eeh_remove_device - Undo EEH setup for the indicated pci device
> > * @dev: pci device to be removed
> > * @purge_pe: remove the PE or not
> >
>
> Thanks,
> Gavin
>
Regards,
Thadeu Cascardo.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/2] EEH/OF: checking for CONFIG_EEH is not needed
2012-12-28 12:06 ` Thadeu Lima de Souza Cascardo
@ 2012-12-28 19:13 ` Thadeu Lima de Souza Cascardo
2013-01-04 2:24 ` Gavin Shan
2012-12-28 19:13 ` [PATCH 2/2] ppc/EEH: fix crash when adding a device in a slot with DDW Thadeu Lima de Souza Cascardo
1 sibling, 1 reply; 7+ messages in thread
From: Thadeu Lima de Souza Cascardo @ 2012-12-28 19:13 UTC (permalink / raw)
To: linuxppc-dev
Cc: bhelgaas, paulus, linux-kernel, Thadeu Lima de Souza Cascardo,
shangw
The functions used are already defined as empty inline functions for the
case where EEH is disabled.
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
---
arch/powerpc/kernel/of_platform.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index 2049f2d..c5fc6b2 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -71,10 +71,8 @@ static int __devinit of_pci_phb_probe(struct platform_device *dev)
eeh_dev_phb_init_dynamic(phb);
/* Register devices with EEH */
-#ifdef CONFIG_EEH
if (dev->dev.of_node->child)
eeh_add_device_tree_early(dev->dev.of_node);
-#endif /* CONFIG_EEH */
/* Scan the bus */
pcibios_scan_phb(phb);
@@ -88,9 +86,7 @@ static int __devinit of_pci_phb_probe(struct platform_device *dev)
pcibios_claim_one_bus(phb->bus);
/* Finish EEH setup */
-#ifdef CONFIG_EEH
eeh_add_device_tree_late(phb->bus);
-#endif
/* Add probed PCI devices to the device model */
pci_bus_add_devices(phb->bus);
--
1.7.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/2] ppc/EEH: fix crash when adding a device in a slot with DDW
2012-12-28 12:06 ` Thadeu Lima de Souza Cascardo
2012-12-28 19:13 ` [PATCH 1/2] EEH/OF: checking for CONFIG_EEH is not needed Thadeu Lima de Souza Cascardo
@ 2012-12-28 19:13 ` Thadeu Lima de Souza Cascardo
2013-01-04 3:19 ` Gavin Shan
1 sibling, 1 reply; 7+ messages in thread
From: Thadeu Lima de Souza Cascardo @ 2012-12-28 19:13 UTC (permalink / raw)
To: linuxppc-dev
Cc: shangw, linux-kernel, stable, paulus,
Thadeu Lima de Souza Cascardo, bhelgaas
The DDW code uses a eeh_dev struct from the pci_dev. However, this is
not set until eeh_add_device_late is called.
Since pci_bus_add_devices is called before eeh_add_device_late, the PCI
devices are added to the bus, making drivers' probe hooks to be called.
These will call set_dma_mask, which will call the DDW code, which will
require the eeh_dev struct from pci_dev. This would result in a crash,
due to a NULL dereference.
Calling eeh_add_device_late after pci_bus_add_devices would make the
system BUG, because device files shouldn't be added to devices there
were not added to the system. So, a new function is needed to add such
files only after pci_bus_add_devices have been called.
Cc: stable@vger.kernel.org
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/eeh.h | 3 +++
arch/powerpc/kernel/of_platform.c | 3 +++
arch/powerpc/kernel/pci-common.c | 7 +++++--
arch/powerpc/platforms/pseries/eeh.c | 24 +++++++++++++++++++++++-
4 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index b0ef738..0f816da 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -201,6 +201,7 @@ int eeh_dev_check_failure(struct eeh_dev *edev);
void __init eeh_addr_cache_build(void);
void eeh_add_device_tree_early(struct device_node *);
void eeh_add_device_tree_late(struct pci_bus *);
+void eeh_add_sysfs_files(struct pci_bus *);
void eeh_remove_bus_device(struct pci_dev *, int);
/**
@@ -240,6 +241,8 @@ static inline void eeh_add_device_tree_early(struct device_node *dn) { }
static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
+static inline void eeh_add_sysfs_files(struct pci_bus *bus) { }
+
static inline void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe) { }
static inline void eeh_lock(void) { }
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index c5fc6b2..500dd32 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -91,6 +91,9 @@ static int __devinit of_pci_phb_probe(struct platform_device *dev)
/* Add probed PCI devices to the device model */
pci_bus_add_devices(phb->bus);
+ /* sysfs files should only be added after devices are added */
+ eeh_add_sysfs_files(phb->bus);
+
return 0;
}
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 7f94f76..4d3de7e 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1480,11 +1480,14 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
pcibios_allocate_bus_resources(bus);
pcibios_claim_one_bus(bus);
+ /* Fixup EEH */
+ eeh_add_device_tree_late(bus);
+
/* Add new devices to global lists. Register in proc, sysfs. */
pci_bus_add_devices(bus);
- /* Fixup EEH */
- eeh_add_device_tree_late(bus);
+ /* sysfs files should only be added after devices are added */
+ eeh_add_sysfs_files(bus);
}
EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 9a04322..6b73d6c 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -788,7 +788,6 @@ static void eeh_add_device_late(struct pci_dev *dev)
dev->dev.archdata.edev = edev;
eeh_addr_cache_insert_dev(dev);
- eeh_sysfs_add_device(dev);
}
/**
@@ -815,6 +814,29 @@ void eeh_add_device_tree_late(struct pci_bus *bus)
EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
/**
+ * eeh_add_sysfs_files - Add EEH sysfs files for the indicated PCI bus
+ * @bus: PCI bus
+ *
+ * This routine must be used to add EEH sysfs files for PCI
+ * devices which are attached to the indicated PCI bus. The PCI bus
+ * is added after system boot through hotplug or dlpar.
+ */
+void eeh_add_sysfs_files(struct pci_bus *bus)
+{
+ struct pci_dev *dev;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ eeh_sysfs_add_device(dev);
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ struct pci_bus *subbus = dev->subordinate;
+ if (subbus)
+ eeh_add_sysfs_files(subbus);
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(eeh_add_sysfs_files);
+
+/**
* eeh_remove_device - Undo EEH setup for the indicated pci device
* @dev: pci device to be removed
* @purge_pe: remove the PE or not
--
1.7.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] EEH/OF: checking for CONFIG_EEH is not needed
2012-12-28 19:13 ` [PATCH 1/2] EEH/OF: checking for CONFIG_EEH is not needed Thadeu Lima de Souza Cascardo
@ 2013-01-04 2:24 ` Gavin Shan
0 siblings, 0 replies; 7+ messages in thread
From: Gavin Shan @ 2013-01-04 2:24 UTC (permalink / raw)
To: Thadeu Lima de Souza Cascardo
Cc: bhelgaas, paulus, linuxppc-dev, linux-kernel, shangw
On Fri, Dec 28, 2012 at 05:13:18PM -0200, Thadeu Lima de Souza Cascardo wrote:
>The functions used are already defined as empty inline functions for the
>case where EEH is disabled.
>
>Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
Acked-by: Gavin Shan <shangw@linux.vnet.ibm.com>
>---
> arch/powerpc/kernel/of_platform.c | 4 ----
> 1 files changed, 0 insertions(+), 4 deletions(-)
>
>diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
>index 2049f2d..c5fc6b2 100644
>--- a/arch/powerpc/kernel/of_platform.c
>+++ b/arch/powerpc/kernel/of_platform.c
>@@ -71,10 +71,8 @@ static int __devinit of_pci_phb_probe(struct platform_device *dev)
> eeh_dev_phb_init_dynamic(phb);
>
> /* Register devices with EEH */
>-#ifdef CONFIG_EEH
> if (dev->dev.of_node->child)
> eeh_add_device_tree_early(dev->dev.of_node);
>-#endif /* CONFIG_EEH */
>
> /* Scan the bus */
> pcibios_scan_phb(phb);
>@@ -88,9 +86,7 @@ static int __devinit of_pci_phb_probe(struct platform_device *dev)
> pcibios_claim_one_bus(phb->bus);
>
> /* Finish EEH setup */
>-#ifdef CONFIG_EEH
> eeh_add_device_tree_late(phb->bus);
>-#endif
>
> /* Add probed PCI devices to the device model */
> pci_bus_add_devices(phb->bus);
Thanks,
Gavin
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] ppc/EEH: fix crash when adding a device in a slot with DDW
2012-12-28 19:13 ` [PATCH 2/2] ppc/EEH: fix crash when adding a device in a slot with DDW Thadeu Lima de Souza Cascardo
@ 2013-01-04 3:19 ` Gavin Shan
0 siblings, 0 replies; 7+ messages in thread
From: Gavin Shan @ 2013-01-04 3:19 UTC (permalink / raw)
To: Thadeu Lima de Souza Cascardo
Cc: shangw, linux-kernel, stable, paulus, bhelgaas, linuxppc-dev
On Fri, Dec 28, 2012 at 05:13:19PM -0200, Thadeu Lima de Souza Cascardo wrote:
>The DDW code uses a eeh_dev struct from the pci_dev. However, this is
>not set until eeh_add_device_late is called.
>
>Since pci_bus_add_devices is called before eeh_add_device_late, the PCI
>devices are added to the bus, making drivers' probe hooks to be called.
>These will call set_dma_mask, which will call the DDW code, which will
>require the eeh_dev struct from pci_dev. This would result in a crash,
>due to a NULL dereference.
>
>Calling eeh_add_device_late after pci_bus_add_devices would make the
>system BUG, because device files shouldn't be added to devices there
>were not added to the system. So, a new function is needed to add such
>files only after pci_bus_add_devices have been called.
>
Thanks, Cascardo. The change looks good to me :-)
Acked-by: Gavin Shan <shangw@linux.vnet.ibm.com>
>Cc: stable@vger.kernel.org
>Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
>---
> arch/powerpc/include/asm/eeh.h | 3 +++
> arch/powerpc/kernel/of_platform.c | 3 +++
> arch/powerpc/kernel/pci-common.c | 7 +++++--
> arch/powerpc/platforms/pseries/eeh.c | 24 +++++++++++++++++++++++-
> 4 files changed, 34 insertions(+), 3 deletions(-)
>
>diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
>index b0ef738..0f816da 100644
>--- a/arch/powerpc/include/asm/eeh.h
>+++ b/arch/powerpc/include/asm/eeh.h
>@@ -201,6 +201,7 @@ int eeh_dev_check_failure(struct eeh_dev *edev);
> void __init eeh_addr_cache_build(void);
> void eeh_add_device_tree_early(struct device_node *);
> void eeh_add_device_tree_late(struct pci_bus *);
>+void eeh_add_sysfs_files(struct pci_bus *);
> void eeh_remove_bus_device(struct pci_dev *, int);
>
> /**
>@@ -240,6 +241,8 @@ static inline void eeh_add_device_tree_early(struct device_node *dn) { }
>
> static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
>
>+static inline void eeh_add_sysfs_files(struct pci_bus *bus) { }
>+
> static inline void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe) { }
>
> static inline void eeh_lock(void) { }
>diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
>index c5fc6b2..500dd32 100644
>--- a/arch/powerpc/kernel/of_platform.c
>+++ b/arch/powerpc/kernel/of_platform.c
>@@ -91,6 +91,9 @@ static int __devinit of_pci_phb_probe(struct platform_device *dev)
> /* Add probed PCI devices to the device model */
> pci_bus_add_devices(phb->bus);
>
>+ /* sysfs files should only be added after devices are added */
>+ eeh_add_sysfs_files(phb->bus);
>+
> return 0;
> }
>
>diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
>index 7f94f76..4d3de7e 100644
>--- a/arch/powerpc/kernel/pci-common.c
>+++ b/arch/powerpc/kernel/pci-common.c
>@@ -1480,11 +1480,14 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
> pcibios_allocate_bus_resources(bus);
> pcibios_claim_one_bus(bus);
>
>+ /* Fixup EEH */
>+ eeh_add_device_tree_late(bus);
>+
> /* Add new devices to global lists. Register in proc, sysfs. */
> pci_bus_add_devices(bus);
>
>- /* Fixup EEH */
>- eeh_add_device_tree_late(bus);
>+ /* sysfs files should only be added after devices are added */
>+ eeh_add_sysfs_files(bus);
> }
> EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
>
>diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
>index 9a04322..6b73d6c 100644
>--- a/arch/powerpc/platforms/pseries/eeh.c
>+++ b/arch/powerpc/platforms/pseries/eeh.c
>@@ -788,7 +788,6 @@ static void eeh_add_device_late(struct pci_dev *dev)
> dev->dev.archdata.edev = edev;
>
> eeh_addr_cache_insert_dev(dev);
>- eeh_sysfs_add_device(dev);
> }
>
> /**
>@@ -815,6 +814,29 @@ void eeh_add_device_tree_late(struct pci_bus *bus)
> EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
>
> /**
>+ * eeh_add_sysfs_files - Add EEH sysfs files for the indicated PCI bus
>+ * @bus: PCI bus
>+ *
>+ * This routine must be used to add EEH sysfs files for PCI
>+ * devices which are attached to the indicated PCI bus. The PCI bus
>+ * is added after system boot through hotplug or dlpar.
>+ */
>+void eeh_add_sysfs_files(struct pci_bus *bus)
>+{
>+ struct pci_dev *dev;
>+
>+ list_for_each_entry(dev, &bus->devices, bus_list) {
>+ eeh_sysfs_add_device(dev);
>+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
>+ struct pci_bus *subbus = dev->subordinate;
>+ if (subbus)
>+ eeh_add_sysfs_files(subbus);
>+ }
>+ }
>+}
>+EXPORT_SYMBOL_GPL(eeh_add_sysfs_files);
>+
>+/**
> * eeh_remove_device - Undo EEH setup for the indicated pci device
> * @dev: pci device to be removed
> * @purge_pe: remove the PE or not
>
Thanks,
Gavin
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2013-01-04 3:19 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-12-27 16:34 [PATCH] ppc/EEH: fix crash when adding a device in a slot with DDW Thadeu Lima de Souza Cascardo
2012-12-28 5:18 ` Gavin Shan
2012-12-28 12:06 ` Thadeu Lima de Souza Cascardo
2012-12-28 19:13 ` [PATCH 1/2] EEH/OF: checking for CONFIG_EEH is not needed Thadeu Lima de Souza Cascardo
2013-01-04 2:24 ` Gavin Shan
2012-12-28 19:13 ` [PATCH 2/2] ppc/EEH: fix crash when adding a device in a slot with DDW Thadeu Lima de Souza Cascardo
2013-01-04 3:19 ` Gavin Shan
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).