From patchwork Wed Sep 5 06:14:43 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gavin Shan X-Patchwork-Id: 181733 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [IPv6:::1]) by ozlabs.org (Postfix) with ESMTP id 386F22C0A23 for ; Wed, 5 Sep 2012 16:20:35 +1000 (EST) Received: by ozlabs.org (Postfix) id 940112C010B; Wed, 5 Sep 2012 16:15:24 +1000 (EST) Delivered-To: linuxppc-dev@ozlabs.org Received: from e3.ny.us.ibm.com (e3.ny.us.ibm.com [32.97.182.143]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "e3.ny.us.ibm.com", Issuer "GeoTrust SSL CA" (not verified)) by ozlabs.org (Postfix) with ESMTPS id CDDB52C012C for ; Wed, 5 Sep 2012 16:15:23 +1000 (EST) Received: from /spool/local by e3.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 5 Sep 2012 02:15:21 -0400 Received: from d01dlp03.pok.ibm.com (9.56.250.168) by e3.ny.us.ibm.com (192.168.1.103) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 5 Sep 2012 02:15:18 -0400 Received: from d01relay04.pok.ibm.com (d01relay04.pok.ibm.com [9.56.227.236]) by d01dlp03.pok.ibm.com (Postfix) with ESMTP id F043FC90041 for ; Wed, 5 Sep 2012 02:15:17 -0400 (EDT) Received: from d01av04.pok.ibm.com (d01av04.pok.ibm.com [9.56.224.64]) by d01relay04.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q856FHhw189566 for ; Wed, 5 Sep 2012 02:15:17 -0400 Received: from d01av04.pok.ibm.com (loopback [127.0.0.1]) by d01av04.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q856FHjA026982 for ; Wed, 5 Sep 2012 02:15:17 -0400 Received: from shangw ([9.125.30.105]) by d01av04.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id q856FCCo026346; Wed, 5 Sep 2012 02:15:16 -0400 Received: by shangw (Postfix, from userid 1000) id 442A13028D1; Wed, 5 Sep 2012 14:15:13 +0800 (CST) From: Gavin Shan To: linuxppc-dev@ozlabs.org Subject: [PATCH 08/21] ppc/eeh: create PEs duing EEH initialization Date: Wed, 5 Sep 2012 14:14:43 +0800 Message-Id: <1346825696-13960-9-git-send-email-shangw@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1346825696-13960-1-git-send-email-shangw@linux.vnet.ibm.com> References: <1346825696-13960-1-git-send-email-shangw@linux.vnet.ibm.com> X-Content-Scanned: Fidelis XPS MAILER x-cbid: 12090506-8974-0000-0000-00000D1B5DD4 X-IBM-ISS-SpamDetectors: X-IBM-ISS-DetailInfo: BY=3.00000293; HX=3.00000196; KW=3.00000007; PH=3.00000001; SC=3.00000007; SDB=6.00171424; UDB=6.00038880; UTC=2012-09-05 06:15:19 Cc: Gavin Shan X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" The patch creates PEs and associated the newly created PEs with it parent/silbing as well as EEH devices. It would become more straight to trace EEH errors and recover them accordingly. Once the EEH functionality on one PCI IOA has been enabled, we tries to create PE against it. If there's existing PE, to which the current PCI IOA should be attached, the existing PE will be converted from "device" type to "bus" type accordingly. Signed-off-by: Gavin Shan --- arch/powerpc/include/asm/eeh.h | 1 + arch/powerpc/platforms/pseries/eeh.c | 6 ++ arch/powerpc/platforms/pseries/eeh_pe.c | 89 +++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 1cc1388..e41107d 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -166,6 +166,7 @@ static inline void eeh_unlock(void) typedef void *(*eeh_traverse_func)(void *data, void *flag); int __devinit eeh_phb_pe_create(struct pci_controller *phb); +int eeh_pe_create(struct eeh_dev *edev); void * __devinit eeh_dev_init(struct device_node *dn, void *data); void __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb); diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 0ba7e3b..99937da 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -895,6 +895,8 @@ static void *eeh_early_enable(struct device_node *dn, void *data) eeh_subsystem_enabled = 1; edev->mode |= EEH_MODE_SUPPORTED; + eeh_pe_create(edev); + pr_debug("EEH: %s: eeh enabled, config=%x pe_config=%x\n", dn->full_name, edev->config_addr, edev->pe_config_addr); @@ -908,6 +910,10 @@ static void *eeh_early_enable(struct device_node *dn, void *data) /* Parent supports EEH. */ edev->mode |= EEH_MODE_SUPPORTED; edev->config_addr = of_node_to_eeh_dev(dn->parent)->config_addr; + edev->pe_config_addr = of_node_to_eeh_dev(dn->parent)->pe_config_addr; + + eeh_pe_create(edev); + return NULL; } } diff --git a/arch/powerpc/platforms/pseries/eeh_pe.c b/arch/powerpc/platforms/pseries/eeh_pe.c index f019953..56aab91 100644 --- a/arch/powerpc/platforms/pseries/eeh_pe.c +++ b/arch/powerpc/platforms/pseries/eeh_pe.c @@ -247,3 +247,92 @@ static struct eeh_pe *eeh_pe_get_parent(struct eeh_dev *edev) return NULL; } +/** + * eeh_pe_create - Create EEH PE according to EEH device + * @edev: EEH device + * + * Create EEH PE according to the specified EEH device and + * put the EEH PE into appropriate place in the PE hierarchy + * tree. + */ +int eeh_pe_create(struct eeh_dev *edev) +{ + struct eeh_pe *pe, *parent; + + /* + * Search the PE has been existing or not according + * to the PE address. If that has been existing, the + * PE should be composed of PCI bus and its subordinate + * components. + */ + pe = eeh_pe_get(edev); + if (pe) { + if (!edev->pe_config_addr) { + pr_err("%s: PE with addr 0x%x already exists\n", + __func__, edev->config_addr); + return -EEXIST; + } + + /* Mark the PE as type of PCI bus */ + pe->type = EEH_PE_BUS; + edev->pe = pe; + + /* Put the edev to PE */ + list_add_tail(&edev->list, &pe->edevs); + + pr_info("EEH: Add %s to Bus PE#%x\n", + edev->dn->full_name, pe->addr); + + return 0; + } + + /* Create a new EEH PE */ + pe = kzalloc(sizeof(struct eeh_pe), GFP_KERNEL); + if (!pe) { + pr_err("%s: out of memory!\n", __func__); + return -ENOMEM; + } + pe->addr = edev->pe_config_addr; + pe->config_addr = edev->config_addr; + pe->type = EEH_PE_DEVICE; + pe->phb = edev->phb; + INIT_LIST_HEAD(&pe->child_list); + INIT_LIST_HEAD(&pe->child); + INIT_LIST_HEAD(&pe->edevs); + + /* + * Put the new EEH PE into hierarchy tree. If the parent + * can't be found, the newly created PE will be attached + * to PHB directly. Otherwise, we have to associate the + * PE with its parent. + */ + parent = eeh_pe_get_parent(edev); + if (!parent) { + parent = eeh_phb_pe_get(edev->phb); + if (!parent) { + pr_err("%s: No PHB PE is found (PHB Domain=%d)\n", + __func__, edev->phb->global_number); + edev->pe = NULL; + kfree(pe); + return -EEXIST; + } + + pe->parent = parent; + } else { + pe->parent = parent; + } + + /* + * Put the newly created PE into the child list and + * link the EEH device accordingly. + */ + list_add_tail(&pe->child, &parent->child_list); + list_add_tail(&edev->list, &pe->edevs); + edev->pe = pe; + + pr_info("EEH: Add %s to Device PE#%x, Parent PE#%x\n", + edev->dn->full_name, pe->addr, pe->parent->addr); + + return 0; +} +