Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp6186444imm; Mon, 23 Jul 2018 13:04:53 -0700 (PDT) X-Google-Smtp-Source: AAOMgpej2zyRcn6rvkkU5GNB+2C4yPeAo+TjPbuOtKHOtkJVq6E9XYS/2pQN7DZACgCEDHv92aFz X-Received: by 2002:a62:9f85:: with SMTP id v5-v6mr14635027pfk.27.1532376293693; Mon, 23 Jul 2018 13:04:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1532376293; cv=none; d=google.com; s=arc-20160816; b=sOwKPLVu25glUCqVW6lH8z1QEzDnqE4uLW47pd1VoicdJ7UHnYRToFz6CKYjR6aREJ NG6oIipNLCHMeuXMltlJWRhNcCBi3/piO65S8kQbi5mgz7y+eF0+RiCNAKid7yqUVgNV mr0YiZXodzdk2uQFJekMAwzGZMmDG9PQMl0H46V0Z9UxG3nUQM8ok2r23CiZWxvzBiK/ Jq7QM4eD9gYu8irAN3I4szH50vAP0LJMNZUDyJuSPMy2EsXU2+o46lJg161pg6PmgKtk F3JIogLiLlcN/6YOkG+VVElBSDHbcieBLZXtq0xZ1gyAmZZeRtzH0pof0aTq57wtCiTk P3/w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=mVN0/KosooXiwnBfEZP8VXUV6p1hNHyEazqP/6AlWtg=; b=fX1PhAw79zSTtPytGiKeGWcE6875a6VGuT/U0G2vdk85qwsc8565UBXPX/AILZXere rB6WCCTZOFhIx5vtKTU2tyT4i0sUATIdYQ55m8YUY5+Xw/TAK7Eqe8mi/XB+oWClcYDL zqsTqueS8fFn/h36ZCq8PbX6A1Kt2ZbApJNq4bgxPk1I+o48pj/MLUhnRuG4h845mEta RkZN2b8SpGFJ0PjApgOKZHqo9ov2SnfGCdR/snohDmAnGgRzVECPUo1TMDawFcB5gZfw UTp2M7bz3aWt221qAxKfMhgrHprHUmk965vlvOujh36HV4rg8NLeeEzDIu0NPjfj80ld tzJA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=rIzzHVyM; 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=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w15-v6si10423122plk.508.2018.07.23.13.04.38; Mon, 23 Jul 2018 13:04:53 -0700 (PDT) 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=@gmail.com header.s=20161025 header.b=rIzzHVyM; 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=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388070AbeGWVGg (ORCPT + 99 others); Mon, 23 Jul 2018 17:06:36 -0400 Received: from mail-oi0-f66.google.com ([209.85.218.66]:39050 "EHLO mail-oi0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387981AbeGWVGf (ORCPT ); Mon, 23 Jul 2018 17:06:35 -0400 Received: by mail-oi0-f66.google.com with SMTP id d189-v6so3397393oib.6; Mon, 23 Jul 2018 13:03:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=mVN0/KosooXiwnBfEZP8VXUV6p1hNHyEazqP/6AlWtg=; b=rIzzHVyM/0bH9r1us+snWneP7TVtJFRHxr/9UsxrY2r19diLFL/zUAVqpdnZwalFy9 3kd1walttxXIO9VGOl4aWS92Z/l3F1a5pmYVJ8YyOROV813aqEgYmwVfAkI5Drd+uId4 x90VBv2ue9n1zxyiSHTJ6moPLl8vt3/b1tpcBjSPdAP5ukOi2w0ltQhxiRMLEgn9rdGV RfZO9ypU3CxFK5zg0hRQ+PrC+fISgkm7Yq6Cbduvh05aYZMP3a6L6fs3J2MEGoZsHIaA 8s/niPhj44k6B2yuFJt9/9KEJo8t5Bi6n1+UUBSuYOVrtC06VQ0FZf3DqQkSt0F3RoHW Shtg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=mVN0/KosooXiwnBfEZP8VXUV6p1hNHyEazqP/6AlWtg=; b=H2lliqou3JMxwowZNK7gvbNGuOvGPYue39CVSOTsqxEr6K/7jo6q4fKT5OgEBCCyN0 o/Cvz6Tfito+O8CfwoH+eE1wFfOJag+E5lyql8BLZpB1hn9dh8PLED3Qs/a4dG1BpJrZ A/3GzU5v2qAAChO6JutwfQHAeuz9f9kUWLRkyQ+LHWeyVzPckT7VHTshmDslIo4zMckf 9xSPE5hsa6pUc7H1sEjcIGlz0L7HYO9A8GA0+M4rPrBH4aIoVhAil6Y8L5fjXEU60U6I bgxnqP3TvH5AZb/Ob1oqSGpfh1QJowmnX0sGztCTk3JPli3ePflYMTIL7maA6BWAb69V yFfg== X-Gm-Message-State: AOUpUlEo/uIBXTMnCIYw5dxJxv8+RJ4Puw9VheG2uwc3WipQQ9lOpHzY 1Xjoo8/qcLsTnM/ZBsOK19xBIbRdD2c= X-Received: by 2002:aca:190d:: with SMTP id l13-v6mr274168oii.216.1532376227492; Mon, 23 Jul 2018 13:03:47 -0700 (PDT) Received: from nuclearis2-1.lan (c-98-195-139-126.hsd1.tx.comcast.net. [98.195.139.126]) by smtp.gmail.com with ESMTPSA id n84-v6sm7530409oif.23.2018.07.23.13.03.46 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 23 Jul 2018 13:03:46 -0700 (PDT) From: Alexandru Gagniuc To: linux-pci@vger.kernel.org, bhelgaas@google.com Cc: keith.busch@intel.com, alex_gagniuc@dellteam.com, austin_bolen@dell.com, shyam_iyer@dell.com, jeffrey.t.kirsher@intel.com, ariel.elior@cavium.com, michael.chan@broadcom.com, ganeshgr@chelsio.com, tariqt@mellanox.com, jakub.kicinski@netronome.com, airlied@gmail.com, alexander.deucher@amd.com, mike.marciniszyn@intel.com, Alexandru Gagniuc , linux-kernel@vger.kernel.org Subject: [PATCH v5] PCI: Check for PCIe downtraining conditions Date: Mon, 23 Jul 2018 15:03:38 -0500 Message-Id: <20180723200339.23943-1-mr.nuke.me@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180718215359.GG128988@bhelgaas-glaptop.roam.corp.google.com> References: <20180718215359.GG128988@bhelgaas-glaptop.roam.corp.google.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org PCIe downtraining happens when both the device and PCIe port are capable of a larger bus width or higher speed than negotiated. Downtraining might be indicative of other problems in the system, and identifying this from userspace is neither intuitive, nor straightforward. The easiest way to detect this is with pcie_print_link_status(), since the bottleneck is usually the link that is downtrained. It's not a perfect solution, but it works extremely well in most cases. Signed-off-by: Alexandru Gagniuc --- For the sake of review, I've created a __pcie_print_link_status() which takes a 'verbose' argument. If we agree want to go this route, and update the users of pcie_print_link_status(), I can split this up in two patches. I prefer just printing this information in the core functions, and letting drivers not have to worry about this. Though there seems to be strong for not going that route, so here it goes: Changes since v4: - Use 'verbose' argumnet to print bandwidth under normal conditions - Without verbose, only downtraining conditions are reported Changes since v3: - Remove extra newline and parentheses. Changes since v2: - Check dev->is_virtfn flag Changes since v1: - Use pcie_print_link_status() instead of reimplementing logic drivers/pci/pci.c | 22 ++++++++++++++++++---- drivers/pci/probe.c | 21 +++++++++++++++++++++ include/linux/pci.h | 1 + 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 316496e99da9..414ad7b3abdb 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -5302,14 +5302,15 @@ u32 pcie_bandwidth_capable(struct pci_dev *dev, enum pci_bus_speed *speed, } /** - * pcie_print_link_status - Report the PCI device's link speed and width + * __pcie_print_link_status - Report the PCI device's link speed and width * @dev: PCI device to query + * @verbose: Be verbose -- print info even when enough bandwidth is available. * * Report the available bandwidth at the device. If this is less than the * device is capable of, report the device's maximum possible bandwidth and * the upstream link that limits its performance to less than that. */ -void pcie_print_link_status(struct pci_dev *dev) +void __pcie_print_link_status(struct pci_dev *dev, bool verbose) { enum pcie_link_width width, width_cap; enum pci_bus_speed speed, speed_cap; @@ -5319,11 +5320,11 @@ void pcie_print_link_status(struct pci_dev *dev) bw_cap = pcie_bandwidth_capable(dev, &speed_cap, &width_cap); bw_avail = pcie_bandwidth_available(dev, &limiting_dev, &speed, &width); - if (bw_avail >= bw_cap) + if (bw_avail >= bw_cap && verbose) pci_info(dev, "%u.%03u Gb/s available PCIe bandwidth (%s x%d link)\n", bw_cap / 1000, bw_cap % 1000, PCIE_SPEED2STR(speed_cap), width_cap); - else + else if (bw_avail < bw_cap) pci_info(dev, "%u.%03u Gb/s available PCIe bandwidth, limited by %s x%d link at %s (capable of %u.%03u Gb/s with %s x%d link)\n", bw_avail / 1000, bw_avail % 1000, PCIE_SPEED2STR(speed), width, @@ -5331,6 +5332,19 @@ void pcie_print_link_status(struct pci_dev *dev) bw_cap / 1000, bw_cap % 1000, PCIE_SPEED2STR(speed_cap), width_cap); } + +/** + * pcie_print_link_status - Report the PCI device's link speed and width + * @dev: PCI device to query + * + * Report the available bandwidth at the device. If this is less than the + * device is capable of, report the device's maximum possible bandwidth and + * the upstream link that limits its performance to less than that. + */ +void pcie_print_link_status(struct pci_dev *dev) +{ + __pcie_print_link_status(dev, true); +} EXPORT_SYMBOL(pcie_print_link_status); /** diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index ac876e32de4b..1f7336377c3b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2205,6 +2205,24 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) return dev; } +static void pcie_check_upstream_link(struct pci_dev *dev) +{ + if (!pci_is_pcie(dev)) + return; + + /* Look from the device up to avoid downstream ports with no devices. */ + if ((pci_pcie_type(dev) != PCI_EXP_TYPE_ENDPOINT) && + (pci_pcie_type(dev) != PCI_EXP_TYPE_LEG_END) && + (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM)) + return; + + /* Multi-function PCIe share the same link/status. */ + if (PCI_FUNC(dev->devfn) != 0 || dev->is_virtfn) + return; + + __pcie_print_link_status(dev, false); +} + static void pci_init_capabilities(struct pci_dev *dev) { /* Enhanced Allocation */ @@ -2240,6 +2258,9 @@ static void pci_init_capabilities(struct pci_dev *dev) /* Advanced Error Reporting */ pci_aer_init(dev); + /* Check link and detect downtrain errors */ + pcie_check_upstream_link(dev); + if (pci_probe_reset_function(dev) == 0) dev->reset_fn = 1; } diff --git a/include/linux/pci.h b/include/linux/pci.h index abd5d5e17aee..15bfab8f7a1b 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1088,6 +1088,7 @@ int pcie_set_mps(struct pci_dev *dev, int mps); u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev, enum pci_bus_speed *speed, enum pcie_link_width *width); +void __pcie_print_link_status(struct pci_dev *dev, bool verbose); void pcie_print_link_status(struct pci_dev *dev); int pcie_flr(struct pci_dev *dev); int __pci_reset_function_locked(struct pci_dev *dev); -- 2.17.1