Received: by 10.213.65.68 with SMTP id h4csp450892imn; Sun, 25 Mar 2018 04:02:38 -0700 (PDT) X-Google-Smtp-Source: AG47ELtHXOK0bCKXBhB6LahA+VbQYL+H0XHjqMQbbFOJQJAyn6NM34IcUpxBeDafERvkSuuO31Ur X-Received: by 2002:a17:902:28a4:: with SMTP id f33-v6mr15121096plb.115.1521975758111; Sun, 25 Mar 2018 04:02:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521975758; cv=none; d=google.com; s=arc-20160816; b=bgzN3lUi8eE527zECYFMLP2wyVuUNumsFb4KANLfdYC9cUHHUqvsMHbOWWQgoNebIm TV7rU5ugOoAh2aCFE9u/Mr8Othxkd2TnKBsDB3DTchmmEYaUUHUkkdM860NPv7k8J76H hH4+fErNbKmvkQ5DQLkvWoYAmbzsysS7jyqOHmpBECrm9Tl8BDBXp6ECaB8zFnh4YAtx Mv6Z2p3jRkA5p82E3+7uYTIT7hQJZQIua3Hk3mJWSmyRV9MI1/bZC2RpKoO1m9FqFTjv VxAhaDwQxfJ+HGCA3UrMzT6UsJl0MorNFmhDmyfXD1hh8+ft5uVXon5eYL2lbqS4Epde +TgQ== 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:mime-version :references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-authentication-results; bh=y3YXG7RnmvrF+I7znPo7q9CvKyWJNMGhdeWwkSJ7fxU=; b=U4cV+C7DP22bnSr1wfoySF2ecx4YECV4Mp4rowb5c0OrzfX8HjRdHZV1gQLiR/lQ6Y v+Hod5gnNjB2AbTGnTrVH90+yn+nb44aYsfvxZlmHJ114KV4GMi5ZJJow6qgQrR/j3Yw YVN1M2lYkdlVArrj8NLPDS22JLJujk1H4xZmQfZNpH4UTBZuxlbMF9vMAYvvqGc6UmYn XqRoKe5jYzEKguGyPjhSct/pnkc7GDhEPQXafUXudmaPLZOyob3RmZtmnftCNnL4i0/Q JCRWjQCii+dC8tO/HUoIQKZWqGSp0xHVtf8J7uVZqYvQ1/dm1qaWk3iBcnSHmH8sipkS Uy9g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=HPeWiuzz; 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 t9si8784610pgq.271.2018.03.25.04.02.23; Sun, 25 Mar 2018 04:02:38 -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=HPeWiuzz; 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 S1752749AbeCYLAK (ORCPT + 99 others); Sun, 25 Mar 2018 07:00:10 -0400 Received: from mail-wm0-f65.google.com ([74.125.82.65]:52971 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752115AbeCYLAF (ORCPT ); Sun, 25 Mar 2018 07:00:05 -0400 Received: by mail-wm0-f65.google.com with SMTP id l9so10537945wmh.2; Sun, 25 Mar 2018 04:00:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=y3YXG7RnmvrF+I7znPo7q9CvKyWJNMGhdeWwkSJ7fxU=; b=HPeWiuzzNSAOxbCcSHc5cnARnDzZqLe2IdJFpE60IZ3Q1e4bVY8aVOVrVQne/Ev1eT ZPTsoYE756mMyCysEMfWtG/DxcyYiu6l/plxC64huCI1ESsU3dICsfFEcox7fKT8F0M9 XAwBp/PHBMzaGhErgFL5rju8HyWI6oww0K8yElfkLmy1hgoCanD99cQ6NLf3CrH7VMj/ MpPgdGchglx4V33SjWpSW5Fo+TVyvdZTKQFzF/KMkfsb1eOOmS0SCcpdh0levaWjU/fR iK9aIvzt3P4BAMF0VVSGVkhmNI3JOLjfyoxQcWypysLI2M5U0KSL2LLntY2UcWfVPilQ AFbg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=y3YXG7RnmvrF+I7znPo7q9CvKyWJNMGhdeWwkSJ7fxU=; b=RxmvuoKYUm73UDjk4frD4/AJ50FRn8UkJ3mX0EKof0CYCrT8vGgF/f6fjJW2snYGqR O+5CnRGwIMGjfroRJlTiXERgG/sPYwrhF9mmsm2SO2ymU1g9cVoZHDnTxg9OMx4Uo6ei VAnrpfASoo0kItBbdNDoVcMW2U3/RL93o/+ii6c7QP88/5TmD8cbk9v8NVID2o1ywpFY O41FoUwbMusfkNpwD2hCfEKjbpMDOEZZi04qLOY9cwJnXpIPWNBlYADQguS5XbojFARO NLhcNiGCXMx0xTLCMZWnlGRiBahC7+Bopj6+Rp8qcsoTUxGad2fuBRu9qx9PrMklJR0s EYIw== X-Gm-Message-State: AElRT7HAXPzegNAVRI0QDcwiWLL8+Nvbgp/Ng0oPbE8uMJSgxx76iT9V TZI4ytpjvClW4IcPoGQBGXtQXA== X-Received: by 10.28.183.68 with SMTP id h65mr11067659wmf.35.1521975604007; Sun, 25 Mar 2018 04:00:04 -0700 (PDT) Received: from baker.fritz.box ([2a02:908:1257:4460:80f2:8bcd:4355:2edc]) by smtp.gmail.com with ESMTPSA id z3sm20492230wme.3.2018.03.25.04.00.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 25 Mar 2018 04:00:03 -0700 (PDT) From: "=?UTF-8?q?Christian=20K=C3=B6nig?=" X-Google-Original-From: =?UTF-8?q?Christian=20K=C3=B6nig?= To: linaro-mm-sig@lists.linaro.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, amd-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/8] PCI: Add pci_peer_traffic_supported() Date: Sun, 25 Mar 2018 12:59:55 +0200 Message-Id: <20180325110000.2238-3-christian.koenig@amd.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20180325110000.2238-1-christian.koenig@amd.com> References: <20180325110000.2238-1-christian.koenig@amd.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: "wdavis@nvidia.com" Add checks for topology and ACS configuration to determine whether or not peer traffic should be supported between two PCI devices. Signed-off-by: Will Davis Signed-off-by: Christian König --- drivers/pci/pci.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 1 + 2 files changed, 113 insertions(+) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index f6a4dd10d9b0..efdca3c9dad1 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -5285,6 +5286,117 @@ void pci_ignore_hotplug(struct pci_dev *dev) } EXPORT_SYMBOL_GPL(pci_ignore_hotplug); +static bool pci_peer_host_traffic_supported(struct pci_host_bridge *host) +{ + struct pci_dev *bridge = pci_get_slot(host->bus, PCI_DEVFN(0, 0)); + unsigned short vendor, device; + + if (!bridge) + return false; + + vendor = bridge->vendor; + device = bridge->device; + pci_dev_put(bridge); + + /* AMD ZEN host bridges can do peer to peer */ + if (vendor == PCI_VENDOR_ID_AMD && device == 0x1450) + return true; + + /* TODO: Extend that to a proper whitelist */ + return false; +} + +bool pci_peer_traffic_supported(struct pci_dev *dev, struct pci_dev *peer) +{ + struct pci_dev *rp_dev, *rp_peer, *common_upstream; + struct pci_host_bridge *peer_host_bridge; + struct pci_host_bridge *dev_host_bridge; + int pos; + u16 cap; + + /* This is tricky enough, focus on PCIe for now */ + if (!pci_is_pcie(dev) || !pci_is_pcie(peer)) + return false; + + /* + * Disallow the peer-to-peer traffic if the devices do not share a + * host bridge. The PCI specifications does not make any guarantees + * about P2P capabilities between devices under separate domains. + * + * PCI Local Bus Specification Revision 3.0, section 3.10: + * "Peer-to-peer transactions crossing multiple host bridges + * PCI host bridges may, but are not required to, support PCI + * peer-to-peer transactions that traverse multiple PCI host + * bridges." + */ + dev_host_bridge = pci_find_host_bridge(dev->bus); + peer_host_bridge = pci_find_host_bridge(peer->bus); + if (dev_host_bridge != peer_host_bridge) + return pci_peer_host_traffic_supported(dev_host_bridge); + + rp_dev = pcie_find_root_port(dev); + rp_peer = pcie_find_root_port(peer); + common_upstream = pci_find_common_upstream_dev(dev, peer); + + /* + * Access Control Services (ACS) Checks + * + * ACS has a capability bit for P2P Request Redirects (RR), + * but unfortunately it doesn't tell us much about the real + * capabilities of the hardware. + * + * PCI Express Base Specification Revision 3.0, section + * 6.12.1.1: + * "ACS P2P Request Redirect: must be implemented by Root + * Ports that support peer-to-peer traffic with other + * Root Ports; [80]" + * but + * "[80] Root Port indication of ACS P2P Request Redirect + * or ACS P2P Completion Redirect support does not imply + * any particular level of peer-to-peer support by the + * Root Complex, or that peer-to-peer traffic is + * supported at all" + */ + + /* + * If ACS is not implemented, we have no idea about P2P + * support. Optimistically allow this if there is a common + * upstream device. + */ + pos = pci_find_ext_capability(rp_dev, PCI_EXT_CAP_ID_ACS); + if (!pos) + return common_upstream != NULL; + + /* + * If the devices are under the same root port and have a common + * upstream device, allow if the root port is further upstream + * from the common upstream device and the common upstream + * device has Upstream Forwarding disabled, or if the root port + * is the common upstream device and ACS is not implemented. + */ + pci_read_config_word(rp_dev, pos + PCI_ACS_CAP, &cap); + if ((rp_dev == rp_peer && common_upstream) && + (((common_upstream != rp_dev) && + !pci_acs_enabled(common_upstream, PCI_ACS_UF)) || + ((common_upstream == rp_dev) && ((cap & PCI_ACS_RR) == 0)))) + return true; + + /* + * If ACS RR is implemented and disabled, allow only if the + * devices are under the same root port. + */ + if (cap & PCI_ACS_RR && !pci_acs_enabled(rp_dev, PCI_ACS_RR)) + return rp_dev == rp_peer; + + /* + * If ACS RR is not implemented, or is implemented and enabled, + * only allow if there's a translation agent enabled to do the + * redirect. + */ + return iommu_present(&pci_bus_type); +} +EXPORT_SYMBOL(pci_peer_traffic_supported); + resource_size_t __weak pcibios_default_alignment(void) { return 0; diff --git a/include/linux/pci.h b/include/linux/pci.h index 0d29f5cdcb04..3c8eaa505991 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -921,6 +921,7 @@ void pci_remove_root_bus(struct pci_bus *bus); void pci_setup_cardbus(struct pci_bus *bus); void pcibios_setup_bridge(struct pci_bus *bus, unsigned long type); void pci_sort_breadthfirst(void); +bool pci_peer_traffic_supported(struct pci_dev *dev, struct pci_dev *peer); #define dev_is_pci(d) ((d)->bus == &pci_bus_type) #define dev_is_pf(d) ((dev_is_pci(d) ? to_pci_dev(d)->is_physfn : false)) -- 2.14.1