Received: by 10.223.185.116 with SMTP id b49csp4189987wrg; Tue, 6 Mar 2018 11:17:59 -0800 (PST) X-Google-Smtp-Source: AG47ELvkMGAFuEz6HX3JZXoWdxV5ryQwwRBOr/BcoIT6xlpE1cBCBNeSoA8YtBF53ZLQ0yBpdSVf X-Received: by 10.99.37.7 with SMTP id l7mr11247590pgl.212.1520363878994; Tue, 06 Mar 2018 11:17:58 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520363878; cv=none; d=google.com; s=arc-20160816; b=ZZtTiz/+lldtfpPES6jUif/GLwu+ij/rWOzFXFp6kWINm8O57DwysEyn5+kh8J0caD qVZkY6CbRI3nSZvqPZ3MM3k3wiYQ81IbButphx6bkbmosIxAEVK2+x9eToYXEALW2GUD 2RpSIFgZjFrLKi0ePaXwiNnVyIVv0wLLcQcE03EZPj6yS2hYhgFeyUU94UypQUykIOOI 7vxFYaWCf5BD4+MVrfbIKJrRV9+kPmQY9W3qqvN0u1yb83kp0h9932DrRQn5YiXiNsHe mxtBVVBQ/H2Wbo+x6hLmrqMTfMa4QpjqzWd8ngYkMv80gpyJagg9ipMmEXeC3yzxrzvQ St2A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject:dkim-signature :arc-authentication-results; bh=Ct9as1RdRCn9ls2B9BLbcykrVng3GvRtzMG+XnLjUGk=; b=pJ4XkmCs/COfflTrJn9sBOPFA1Vim/mZH7SrVdMTSCdy5CrfNwL+eEqFfJM8mfkIsY g8+zkzUB8/3QPDIG8nCkw+LsbYPhJJW/JYIZMmVyoolkNKawX8DCOJaoKYAIVCvCoPAy Q/9RS6HHFlUXHP0ZXGZtFmQJXYhqN8adC8IlRT88InpNHOQdPf/RwACxPbwiUVE/GSct xl1SnmO4U4FTDRNmsh/eeNtIH9IgZ0u2lZk059iL/rtsjzDTpePHeqtRPp8MuXH0pc9N 14xOISlOy3z7QgXRxrPok2W3P4a+Z8AB8f+sLel7wSt2e4uauTym2mFU3FLrvAf9brOw d7WA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@oracle.com header.s=corp-2017-10-26 header.b=IBxdnucO; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=oracle.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z8si10247279pgs.605.2018.03.06.11.17.43; Tue, 06 Mar 2018 11:17:58 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@oracle.com header.s=corp-2017-10-26 header.b=IBxdnucO; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=oracle.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754013AbeCFTQW (ORCPT + 99 others); Tue, 6 Mar 2018 14:16:22 -0500 Received: from userp2120.oracle.com ([156.151.31.85]:55050 "EHLO userp2120.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753454AbeCFTQU (ORCPT ); Tue, 6 Mar 2018 14:16:20 -0500 Received: from pps.filterd (userp2120.oracle.com [127.0.0.1]) by userp2120.oracle.com (8.16.0.22/8.16.0.22) with SMTP id w26JCFGY120220; Tue, 6 Mar 2018 19:16:17 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=subject : to : cc : references : from : message-id : date : mime-version : in-reply-to : content-type : content-transfer-encoding; s=corp-2017-10-26; bh=Ct9as1RdRCn9ls2B9BLbcykrVng3GvRtzMG+XnLjUGk=; b=IBxdnucOEholI2XlLSDj2Rtq8ZamOK0/TXDzLpJgPzSAeFpeLByR4A94YdMYT0e0Fpd3 51u6EVyQO85dhIgOlqNMx3R22EEc7wUtKMcDCzfwcydRU8dMOeR+ZuuzQTIo1JzW8JoX nFmawaFYJ1S0HAnEO3Q7Q2azYi4YrpIms32EjkBUV7zWHaIJslqB/lbppcIvzJBK1ESx zEcTd9Mm+oyMyNBbmEqXbINANJRE+mZtaFXMGdWaGiZvXqeHOqQ1MedhnWWvuKF+E9sL AE+kf9jxwchMBtCCs5+9kjdZLVoKJCBU180hhenclBVDp1GHeawESYlicsHZFlCYoypq mA== Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp2120.oracle.com with ESMTP id 2ghyns8dx5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 06 Mar 2018 19:16:16 +0000 Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.14.4) with ESMTP id w26JGGGF007755 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 6 Mar 2018 19:16:16 GMT Received: from abhmp0005.oracle.com (abhmp0005.oracle.com [141.146.116.11]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id w26JGF4L008105; Tue, 6 Mar 2018 19:16:16 GMT Received: from dhcp-10-152-37-204.usdhcp.oraclecorp.com (/10.152.37.204) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Tue, 06 Mar 2018 11:16:15 -0800 Subject: [PATCH v8] PCI: Workaround wrong flags completions for IDT switch To: Bjorn Helgaas , Sinan Kaya Cc: Bjorn Helgaas , "linux-pci@vger.kernel.org" , Linux Kernel Mailing List References: <59C02719.5050103@oracle.com> <9741d204-1dd6-2cc2-c133-2ef49c8a404b@codeaurora.org> <59CAB001.10207@oracle.com> <7084085b-89e7-80fa-d10b-06f121eb57be@codeaurora.org> <20171011192704.GN25517@bhelgaas-glaptop.roam.corp.google.com> From: James Puthukattukaran Message-ID: Date: Tue, 6 Mar 2018 14:15:38 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.6.0 MIME-Version: 1.0 In-Reply-To: <20171011192704.GN25517@bhelgaas-glaptop.roam.corp.google.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-Proofpoint-Virus-Version: vendor=nai engine=5900 definitions=8824 signatures=668685 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=3 malwarescore=0 phishscore=0 bulkscore=0 spamscore=0 mlxscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1711220000 definitions=main-1803060209 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The IDT switch incorrectly flags an ACS source violation on a read config request to an end point device on the completion (IDT 89H32H8G3-YC, errata #36) even though the PCI Express spec states that completions are never affected by ACS source violation (PCI Spec 3.1, Section 6.12.1.1). Here's the specific copy of the errata text "Item #36 - Downstream port applies ACS Source Validation to Completions Section 6.12.1.1 of the PCI Express Base Specification 3.1 states that completions are never affected by ACS Source Validation. However, completions received by a downstream port of the PCIe switch from a device that has not yet captured a PCIe bus number are incorrectly dropped by ACS source validation by the switch downstream port. Workaround: Issue a CfgWr1 to the downstream device before issuing the first CfgRd1 to the device. This allows the downstream device to capture its bus number; ACS source validation no longer stops completions from being forwarded by the downstream port. It has been observed that Microsoft Windows implements this workaround already; however, some versions of Linux and other operating systems may not. " The suggested workaround by IDT is to issue a configuration write to the downstream device before issuing the first config read. This allows the downstream device to capture its bus number, thus avoiding the ACS violation on the completion. In order to make sure that the device is ready for config accesses, we do what is currently done in making config reads till it succeeds and then do the config write as specified by the errata. However, to avoid hitting the errata issue when doing config reads, we disable ACS SV around this process. The patch does the following - 1. Disable ACS source violation if enabled. 2. Wait for config space access to become available by reading vendor id 3. Do a config write to the end point (errata workaround) 4. Enable ACS source validation (if it was enabled to begin with) Signed-off-by: James Puthukattukaran Signed-off-by: Yinghai Lu -- -v2: move workaround to pci_bus_read_dev_vendor_id() from pci_bus_check_dev() and move enable_acs_sv to drivers/pci/pci.c -- by Yinghai -v3: add bus->self check for root bus and virtual bus for sriov vfs. -v4: only do workaround for IDT switches -v5: tweak pci_std_enable_acs_sv to deal with unimplemented SV -v6: Added errata verbiage verbatim and resolved patch format issues -v7: changed int to bool for found and idt_workaround declarations. Also added bugzilla https://bugzilla.kernel.org/show_bug.cgi?id=196979 -v8: Rewrote the patch by adding a new acs quirk to keep the workaround out of the main code path --- drivers/pci/pci.h | 7 ++++ drivers/pci/probe.c | 16 ++++++--- drivers/pci/quirks.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 4 deletions(-) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index fcd8191..f12cb58 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -376,11 +376,18 @@ struct pci_dev_reset_methods { #ifdef CONFIG_PCI_QUIRKS int pci_dev_specific_reset(struct pci_dev *dev, int probe); +int pci_dev_specific_fixup_acs_quirk(struct pci_bus *bus , int devfn, + int enable, bool found); #else static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe) { return -ENOTTY; } +static inline int pci_dev_specific_fixup_acs_quirk(struct pc_bus *bus, + int devfn, int enable, bool found) +{ + return -ENOTTY; +} #endif #if defined(CONFIG_PCI_QUIRKS) && defined(CONFIG_ARM64) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index ef53774..9497d33 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2041,18 +2041,26 @@ static bool pci_bus_wait_crs(struct pci_bus *bus, int de vfn, u32 *l, bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l, int timeout) { + bool found = false; + int enable = -1; + + enable = pci_dev_specific_fixup_acs_quirk(bus, devfn, false, found); if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l)) - return false; + goto out; /* Some broken boards return 0 or ~0 if a slot is empty: */ if (*l == 0xffffffff || *l == 0x00000000 || *l == 0x0000ffff || *l == 0xffff0000) - return false; + goto out; + found = true; if (pci_bus_crs_vendor_id(*l)) - return pci_bus_wait_crs(bus, devfn, l, timeout); + found = pci_bus_wait_crs(bus, devfn, l, timeout); - return true; +out: + if (enable > 0) + pci_dev_specific_fixup_acs_quirk(bus, devfn, enable, found); + return found; } EXPORT_SYMBOL(pci_bus_read_dev_vendor_id); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 8b14bd3..7222853 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4839,3 +4839,98 @@ static void quirk_fsl_no_msi(struct pci_dev *pdev) pdev->no_msi = 1; } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_no_msi); + + + +/* + * Some IDT switches flag an ACS violation for config reads even though the + * PCI spec allows for it (PCIe 3.1, 6.1.12.1). It flags it because the bus + * number is not properly set in the completion. The workaround is to do a + * dummy write to properly latch number once the device is ready for config + * operations. + * + * So, the caller would disable ACS source validation, wait for the device + * hanging off this switch to be ready for config operations, and then + * call this routine again to enable it (if it was eabled to begin with) + */ +static int pci_idt_acs_quirk(struct pci_bus *bus, int devfn, int enable, + bool found) +{ + int pos; + u16 cap; + u16 ctrl; + int retval; + struct pci_dev *dev = bus->self; + + + /* Write 0 to the devfn device under the PCIE switch (bus->self) + * as part of forcing the devfn number to latch with the device below + */ + if (found) + pci_bus_write_config_word(bus, devfn, PCI_VENDOR_ID, 0); + + + /* Enable/disable ACS SV feature (based on enable flag) */ + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); + if (!pos) + return -ENODEV; + + pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap); + + if (!(cap & PCI_ACS_SV)) + return -ENODEV; + + pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl); + + retval = !!(ctrl & cap & PCI_ACS_SV); + if (enable) + ctrl |= (cap & PCI_ACS_SV); + else + ctrl &= ~(cap & PCI_ACS_SV); + + pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl); + return retval; +} + +static const struct pci_dev_acs_quirk{ + u16 vendor; + u16 device; + int (*fixup_acs)(struct pci_bus *bus, int devfn, int enable, bool found ); +} pci_dev_acs_quirks[] = { + { PCI_VENDOR_ID_IDT, 0x80b5, pci_idt_acs_quirk}, + {0} +}; + +int pci_dev_specific_fixup_acs_quirk(struct pci_bus *bus, int devfn, int enable , + bool found) +{ + const struct pci_dev_acs_quirk *i; + struct pci_dev *dev; + int ret; + + if (!bus || !bus->self) + return -ENOTTY; + + dev = bus->self; + + /* + * Allow devices that do not expose standard PCIe ACS capabilities + * or control to indicate their support here. Multi-function express + * devices which do not allow internal peer-to-peer between functions, + * but do not implement PCIe ACS may wish to return true here. + */ + for (i = pci_dev_acs_quirks; i->fixup_acs; i++) { + if ((i->vendor == dev->vendor || + i->vendor == (u16)PCI_ANY_ID) && + (i->device == dev->device || + i->device == (u16)PCI_ANY_ID)) { + ret = i->fixup_acs(bus, devfn, enable, found); + if (ret >= 0) + return ret; + } + } + + return -ENOTTY; +} + + On 10/11/2017 03:27 PM, Bjorn Helgaas wrote: > On Tue, Sep 26, 2017 at 04:03:13PM -0400, Sinan Kaya wrote: >> On 9/26/2017 3:52 PM, James Puthukattukaran wrote: >>>> I think you want to do the part above as part of a quirk that runs before >>>> the probe. >>> >>> I don't think there's a way to run this early enough? >> >> Bjorn? >> >> I have seen multiple quirk types in quirks.c some prefixed with EARLY and >> other LATE. > > I'm hoping an early quirk on the switch would be early enough, since > the workaround needs to be done for devices downstream from the > switch. > > Bjorn >