From patchwork Wed Jun 22 08:24:51 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "dongbo (E)" X-Patchwork-Id: 639020 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3rZHqB105pz9s3T for ; Wed, 22 Jun 2016 18:30:46 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751133AbcFVI3q (ORCPT ); Wed, 22 Jun 2016 04:29:46 -0400 Received: from szxga02-in.huawei.com ([119.145.14.65]:22849 "EHLO szxga02-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750978AbcFVI33 convert rfc822-to-8bit (ORCPT ); Wed, 22 Jun 2016 04:29:29 -0400 Received: from 172.24.1.137 (EHLO SZXEMI414-HUB.china.huawei.com) ([172.24.1.137]) by szxrg02-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id DJE22121; Wed, 22 Jun 2016 16:25:51 +0800 (CST) Received: from SZXEMI502-MBS.china.huawei.com ([169.254.6.136]) by SZXEMI414-HUB.china.huawei.com ([10.86.210.49]) with mapi id 14.03.0235.001; Wed, 22 Jun 2016 16:24:52 +0800 From: "dongbo (E)" To: "jingoohan1@gmail.com" , "pratyush.anand@gmail.com" , "bhelgaas@google.com" CC: "linux-pci@vger.kernel.org" , "linux-kernel@vger.kernel.org" , Linuxarm , Zhanweitao Subject: [PATCH] Decouple CFG and IO in Designware PCIe Driver Thread-Topic: [PATCH] Decouple CFG and IO in Designware PCIe Driver Thread-Index: AQHRzF5zqdLbWQFi4kuXkKcfA0h9kZ/1JOEA Date: Wed, 22 Jun 2016 08:24:51 +0000 Message-ID: Accept-Language: zh-CN, en-US Content-Language: zh-CN X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.63.194.120] MIME-Version: 1.0 X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A090202.576A4B90.0126, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=169.254.6.136, so=2013-06-18 04:22:30, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: d60f0bf99a187ab1f444959b46cf6ec1 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From: Dong Bo In designware PCIe driver, the iatu0 is used for both CFG and IO accesses. When PCIe sends CFGs to peripherals (e.g. lspci), iatu0 frequently switches between CFG and IO alternatively. If the LIMIT of MEMORY is a value between CFGs BASE_ADDR and IOs LIMIT, this probably results in a MEMORY beging matched to be an IO by mistake. Considering the following configurations: MEMORY -> BASE_ADDR: 0xb4100000, LIMIT: 0xb4100FFF, TYPE=mem CFG -> BASE_ADDR: 0xb4000000, LIMIT: 0xb4000FFF, TYPE=cfg IO -> BASE_ADDR: 0xFFFFFFFF, LIMIT: 0xFFFFFFFE, TYPE=io Suppose PCIe has just completed a CFG access, to switch back to IO, it set the BASE_ADDR to 0xFFFFFFFF, LIMIT 0xFFFFFFFE and TYPE to io. When another CFG access come, PCIe first set BASE_ADDR to 0xb4000000 to switch to CFG. At this moment, a MEMORY access shows up, due to `0xb4000000 <= MEMORY BASE_ADDR <= MEMORY LIMIE <= 0xFFFFFFF, it matches with iatu0. And it is treated as an IO access by mistake, then sent to perpheral. This patch fixes the problem by decoupling CFG and IO, reassigning iatu2 to IO. Signed-off-by: Dong Bo --- drivers/pci/host/pcie-designware.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index aafd766..1a40305 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -51,6 +51,7 @@ #define PCIE_ATU_VIEWPORT 0x900 #define PCIE_ATU_REGION_INBOUND (0x1 << 31) #define PCIE_ATU_REGION_OUTBOUND (0x0 << 31) +#define PCIE_ATU_REGION_INDEX2 (0x2 << 0) #define PCIE_ATU_REGION_INDEX1 (0x1 << 0) #define PCIE_ATU_REGION_INDEX0 (0x0 << 0) #define PCIE_ATU_CR1 0x904 @@ -603,9 +604,6 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, type, cpu_addr, busdev, cfg_size); ret = dw_pcie_cfg_read(va_cfg_base + where, size, val); - dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, - PCIE_ATU_TYPE_IO, pp->io_base, - pp->io_bus_addr, pp->io_size); return ret; } @@ -640,9 +638,6 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, type, cpu_addr, busdev, cfg_size); ret = dw_pcie_cfg_write(va_cfg_base + where, size, val); - dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, - PCIE_ATU_TYPE_IO, pp->io_base, - pp->io_bus_addr, pp->io_size); return ret; } @@ -778,10 +773,15 @@ void dw_pcie_setup_rc(struct pcie_port *pp) * uses its own address translation component rather than ATU, so * we should not program the ATU here. */ - if (!pp->ops->rd_other_conf) + if (!pp->ops->rd_other_conf) { dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1, PCIE_ATU_TYPE_MEM, pp->mem_base, pp->mem_bus_addr, pp->mem_size); + dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX2, + PCIE_ATU_TYPE_IO, pp->io_base, + pp->io_bus_addr, pp->io_size); + + } dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);