From patchwork Wed Dec 25 08:58:56 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gavin Shan X-Patchwork-Id: 305106 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 E3A852C012A for ; Wed, 25 Dec 2013 20:01:02 +1100 (EST) Received: from e9.ny.us.ibm.com (e9.ny.us.ibm.com [32.97.182.139]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4AE152C00B2 for ; Wed, 25 Dec 2013 19:59:08 +1100 (EST) Received: from /spool/local by e9.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 25 Dec 2013 03:59:04 -0500 Received: from d01dlp03.pok.ibm.com (9.56.250.168) by e9.ny.us.ibm.com (192.168.1.109) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 25 Dec 2013 03:59:03 -0500 Received: from b01cxnp22034.gho.pok.ibm.com (b01cxnp22034.gho.pok.ibm.com [9.57.198.24]) by d01dlp03.pok.ibm.com (Postfix) with ESMTP id 4D41FC90045 for ; Wed, 25 Dec 2013 03:59:01 -0500 (EST) Received: from d01av01.pok.ibm.com (d01av01.pok.ibm.com [9.56.224.215]) by b01cxnp22034.gho.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id rBP8x3Vn6029670 for ; Wed, 25 Dec 2013 08:59:03 GMT Received: from d01av01.pok.ibm.com (localhost [127.0.0.1]) by d01av01.pok.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id rBP8x2hL032150 for ; Wed, 25 Dec 2013 03:59:03 -0500 Received: from shangw (shangw.cn.ibm.com [9.125.213.121]) by d01av01.pok.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with SMTP id rBP8x0eL032079; Wed, 25 Dec 2013 03:59:01 -0500 Received: by shangw (Postfix, from userid 1000) id 5AC3530040F; Wed, 25 Dec 2013 16:58:59 +0800 (CST) From: Gavin Shan To: linuxppc-dev@lists.ozlabs.org Subject: [PATCH 4/4] powerpc/eeh: Eliminate AER gap Date: Wed, 25 Dec 2013 16:58:56 +0800 Message-Id: <1387961936-20451-4-git-send-email-shangw@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1387961936-20451-1-git-send-email-shangw@linux.vnet.ibm.com> References: <1387961936-20451-1-git-send-email-shangw@linux.vnet.ibm.com> MIME-Version: 1.0 X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 13122508-7182-0000-0000-0000096D7080 Cc: Gavin Shan X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" The patch intends to implement the backend of eeh_ops::restore_bars so that we can eliminate the gap of AER and PCI error reporting between pHyp and sapphire that is introduced by reset on one specific PE or the whole PHB. It's notable that the PHB3 and P7IOC is sharing the same code to eliminate the gap. The details on PHB3 is shown as follows: Offset - PHB3 - Root Complex (pcie_cap: 48 aer_cap: 100)  004 - 00100147 00100147 00100147 00100147  03C - 00020000 00020000 00020000 00020000  050 - 0000004F 0000000F 0000000F 0001000F (Different maximal payload size)  108 - 0008D000 0008D000 0008D000 0008D000  10C - 00072030 00072030 00072030 00072030  114 - 00002000 00000000 00002000 00002000  118 - 000001E0 000001E0 000001E0 000001E0  12C - 00000007 00000007 00000007 00000007 Switch upstream port (pcie_cap: 68 aer_cap: fb4)  004 - 00100547 00100007 00100547 00100547  03C - 00020100 00000100 00020100 00020100  070 - 00000857 00000810 00090817 00000817 (Different maximal payload size)  fbc - 00000000 00400000 00000000 00000000  fc0 - 00462030 00462030 00462030 00462030  fc8 - 00002000 0000f1c1 00002000 00002000  fcc - 000000E0 000000A0 000000ff 000000ff (same RWS bit#6/8) Switch downstream port (pcie_cap: 68 aer_cap: fb4)  004 - 00100547 00100007 00100547 00100547  03C - 00020100 00000100 00020100 00020100  070 - 00000857 00000810 00008017 00008017 (Different maximal payload size)  fbc - 00000000 00400000 00000000 00000000  fc0 - 00402000 00462030 00402000 00402000  fc8 - 00002000 0000f1c1 00002000 00002000  fcc - 000000e0 000000A0 000000ff 000000ff (same RWS bit#6/8) Endpoint (PCI_COMMAND, pcie_cap+0x8) 004 - 00100146 00100406 00100546 00100146 (Same error reporting) 068 - 0000585e 00002810 0010240e 0010240e (Same error reporting) Signed-off-by: Gavin Shan --- arch/powerpc/platforms/powernv/eeh-powernv.c | 145 +++++++++++++++++++++++++- 1 file changed, 144 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index df54b76..1d4e958 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -347,6 +347,148 @@ static int powernv_eeh_next_error(struct eeh_pe **pe) return -EEXIST; } +static void powernv_eeh_restore_root_port(struct device_node *dn, + int ecap, int aercap) +{ + u32 val; + + /* Enable SERR and parity checking */ + pnv_pci_cfg_read(dn, PCI_COMMAND, 2, &val); + val |= (PCI_COMMAND_SERR | PCI_COMMAND_PARITY); + pnv_pci_cfg_write(dn, PCI_COMMAND, 2, val); + + /* Enable reporting various errors */ + pnv_pci_cfg_read(dn, ecap + PCI_EXP_DEVCTL, 2, &val); + val |= (PCI_EXP_DEVCTL_URRE | PCI_EXP_DEVCTL_FERE | + PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_CERE); + pnv_pci_cfg_write(dn, ecap + PCI_EXP_DEVCTL, 2, val); + + /* Mask various unrecoverable errors */ + if (!aercap) return; + pnv_pci_cfg_read(dn, aercap + 0x8, 4, &val); + val |= 0x0008d000; + pnv_pci_cfg_write(dn, aercap + 0x8, 4, val); + + /* Report various unrecoverable errors as fatal errors */ + pnv_pci_cfg_write(dn, aercap + 0xc, 4, 0x00072030); + + /* Mask various recoverable errors */ + pnv_pci_cfg_read(dn, aercap + 0x14, 4, &val); + val |= 0x00002000; + pnv_pci_cfg_write(dn, aercap + 0x14, 4, val); + + /* Enable ECRC check */ + pnv_pci_cfg_read(dn, aercap + 0x18, 4, &val); + val |= 0x00000140; + pnv_pci_cfg_write(dn, aercap + 0x18, 4, val); + + /* Enable all error reporting */ + pnv_pci_cfg_read(dn, aercap + 0x2c, 4, &val); + val |= 0x00000007; + pnv_pci_cfg_write(dn, aercap + 0x2c, 4, val); +} + +static void powernv_eeh_restore_sw_port(struct device_node *dn, + int ecap, int aercap) +{ + struct eeh_dev *edev = of_node_to_eeh_dev(dn); + struct pnv_phb *phb = edev->phb->private_data; + u32 val; + + /* Enable SERR and parity checking and disable INTx */ + pnv_pci_cfg_read(dn, PCI_COMMAND, 2, &val); + val |= (PCI_COMMAND_INTX_DISABLE | + PCI_COMMAND_SERR | PCI_COMMAND_PARITY); + pnv_pci_cfg_write(dn, PCI_COMMAND, 2, val); + + /* Disable partity error and enable system error */ + pnv_pci_cfg_read(dn, PCI_BRIDGE_CONTROL, 2, &val); + val &= ~PCI_BRIDGE_CTL_PARITY; + val |= PCI_BRIDGE_CTL_SERR; + pnv_pci_cfg_write(dn, PCI_BRIDGE_CONTROL, 2, val); + + /* Enable reporting various errors */ + pnv_pci_cfg_read(dn, ecap + PCI_EXP_DEVCTL, 2, &val); + val |= (PCI_EXP_DEVCTL_FERE | + PCI_EXP_DEVCTL_NFERE | + PCI_EXP_DEVCTL_CERE); + pnv_pci_cfg_write(dn, ecap + PCI_EXP_DEVCTL, 2, val); + + /* Unmask all unrecoverable errors */ + if (!aercap) return; + pnv_pci_cfg_write(dn, aercap + 0x8, 4, 0x0); + + /* Severity of unrecoverable errors */ + if (edev->mode & EEH_DEV_US_PORT) + val = 0x00462030; + else + val = 0x00402000; + pnv_pci_cfg_write(dn, aercap + 0xc, 4, val); + + /* Mask various correctable errors */ + if (phb->model == PNV_PHB_MODEL_PHB3 && + phb->rev < 0xa30003) + val = 0xffffffff; + else + val = 0x2000; + pnv_pci_cfg_write(dn, aercap + 0x14, 4, val); + + /* Enable ECRC generation and disable ECRC check */ + pnv_pci_cfg_read(dn, aercap + 0x18, 4, &val); + val &= ~0x00000100; + val |= 0x00000040; + pnv_pci_cfg_write(dn, aercap + 0x18, 4, val); +} + +static void powernv_eeh_restore_endpoint(struct device_node *dn, + int ecap, int aercap) +{ + struct eeh_dev *edev = of_node_to_eeh_dev(dn); + struct pnv_phb *phb = edev->phb->private_data; + u32 val; + + /* Enable SERR and parity checking */ + pnv_pci_cfg_read(dn, PCI_COMMAND, 2, &val); + val |= (PCI_COMMAND_SERR | PCI_COMMAND_PARITY); + pnv_pci_cfg_write(dn, PCI_COMMAND, 2, val); + + /* Enable reporting various errors */ + if (!ecap) return; + pnv_pci_cfg_read(dn, ecap + PCI_EXP_DEVCTL, 2, &val); + val &= ~PCI_EXP_DEVCTL_CERE; + val |= (PCI_EXP_DEVCTL_URRE | + PCI_EXP_DEVCTL_FERE | + PCI_EXP_DEVCTL_NFERE); + pnv_pci_cfg_write(dn, ecap + PCI_EXP_DEVCTL, 2, val); + + if (!aercap) return; + if (phb->model == PNV_PHB_MODEL_PHB3 && + phb->rev < 0xa30003) + pnv_pci_cfg_write(dn, aercap + 0x14, 4, 0xffffffff); + + /* Enable ECRC generation and check */ + pnv_pci_cfg_read(dn, aercap + 0x18, 4, &val); + val |= 0x00000140; + pnv_pci_cfg_write(dn, aercap + 0x18, 4, val); +} + +static void powernv_eeh_restore_bars(struct device_node *dn) +{ + struct eeh_dev *edev = of_node_to_eeh_dev(dn); + + if (!edev) return; + if (edev->mode & EEH_DEV_ROOT_PORT) + powernv_eeh_restore_root_port(dn, + edev->pcie_cap, edev->aer_cap); + else if ((edev->mode & EEH_DEV_US_PORT) || + (edev->mode & EEH_DEV_DS_PORT)) + powernv_eeh_restore_sw_port(dn, + edev->pcie_cap, edev->aer_cap); + else + powernv_eeh_restore_endpoint(dn, + edev->pcie_cap, edev->aer_cap); +} + static struct eeh_ops powernv_eeh_ops = { .name = "powernv", .init = powernv_eeh_init, @@ -362,7 +504,8 @@ static struct eeh_ops powernv_eeh_ops = { .configure_bridge = powernv_eeh_configure_bridge, .read_config = pnv_pci_cfg_read, .write_config = pnv_pci_cfg_write, - .next_error = powernv_eeh_next_error + .next_error = powernv_eeh_next_error, + .restore_bars = powernv_eeh_restore_bars }; /**