aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms/pseries/eeh_pe.c
diff options
context:
space:
mode:
authorGavin Shan <shangw@linux.vnet.ibm.com>2012-09-11 19:16:17 +0000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-09-18 15:32:23 +1000
commit20ee6a970858a0f5711ea32cb7f855a81704cb53 (patch)
treeb09241fc593a30f494d2bad75ae0e704465b995b /arch/powerpc/platforms/pseries/eeh_pe.c
parent5efc3ad7325d81b5a8e09bc14d5e21ce7272d934 (diff)
powerpc/eeh: Remove EEH PE for normal PCI hotplug
Function eeh_rmv_from_parent_pe() could be called by the path of either normal PCI hotplug, or EEH recovery. For the former case, we need purge the corresponding PE on removal of the associated PE bus. The patch tries to cover that by passing more information to function pcibios_remove_pci_devices() so that we know if the corresponding PE needs to be purged or be marked as "invalid". Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms/pseries/eeh_pe.c')
-rw-r--r--arch/powerpc/platforms/pseries/eeh_pe.c35
1 files changed, 23 insertions, 12 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh_pe.c b/arch/powerpc/platforms/pseries/eeh_pe.c
index 51fc56abb7a..30b8d96ed54 100644
--- a/arch/powerpc/platforms/pseries/eeh_pe.c
+++ b/arch/powerpc/platforms/pseries/eeh_pe.c
@@ -395,13 +395,14 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
/**
* eeh_rmv_from_parent_pe - Remove one EEH device from the associated PE
* @edev: EEH device
+ * @purge_pe: remove PE or not
*
* The PE hierarchy tree might be changed when doing PCI hotplug.
* Also, the PCI devices or buses could be removed from the system
* during EEH recovery. So we have to call the function remove the
* corresponding PE accordingly if necessary.
*/
-int eeh_rmv_from_parent_pe(struct eeh_dev *edev)
+int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe)
{
struct eeh_pe *pe, *parent, *child;
int cnt;
@@ -428,19 +429,29 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev)
if (pe->type & EEH_PE_PHB)
break;
- if (list_empty(&pe->edevs)) {
- cnt = 0;
- list_for_each_entry(child, &pe->child_list, child) {
- if (!(pe->type & EEH_PE_INVALID)) {
- cnt++;
- break;
- }
+ if (purge_pe) {
+ if (list_empty(&pe->edevs) &&
+ list_empty(&pe->child_list)) {
+ list_del(&pe->child);
+ kfree(pe);
+ } else {
+ break;
}
+ } else {
+ if (list_empty(&pe->edevs)) {
+ cnt = 0;
+ list_for_each_entry(child, &pe->child_list, child) {
+ if (!(pe->type & EEH_PE_INVALID)) {
+ cnt++;
+ break;
+ }
+ }
- if (!cnt)
- pe->type |= EEH_PE_INVALID;
- else
- break;
+ if (!cnt)
+ pe->type |= EEH_PE_INVALID;
+ else
+ break;
+ }
}
pe = parent;