From: Bjorn Helgaas <helgaas@kernel.org>
To: Will Davis <wdavis@nvidia.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>,
Alex Williamson <alex.williamson@redhat.com>,
Joerg Roedel <joro@8bytes.org>,
iommu@lists.linux-foundation.org, linux-pci@vger.kernel.org,
Konrad Wilk <konrad.wilk@oracle.com>,
Mark Hounschell <markh@compro.net>,
"David S. Miller" <davem@davemloft.net>,
Jonathan Corbet <corbet@lwn.net>,
Terence Ripperda <tripperda@nvidia.com>,
John Hubbard <jhubbard@nvidia.com>,
Jerome Glisse <jglisse@redhat.com>
Subject: Re: [PATCH 09/22] PCI: Add pci_peer_traffic_supported()
Date: Thu, 24 Sep 2015 16:49:21 -0500 [thread overview]
Message-ID: <20150924214921.GH10481@localhost> (raw)
In-Reply-To: <1442337067-22964-10-git-send-email-wdavis@nvidia.com>
On Tue, Sep 15, 2015 at 12:10:54PM -0500, Will Davis wrote:
> 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 <wdavis@nvidia.com>
> ---
> drivers/pci/pci.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/pci.h | 3 ++
> 2 files changed, 102 insertions(+)
>
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 0008c95..b8ba0f0 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -25,6 +25,7 @@
> #include <linux/device.h>
> #include <linux/pm_runtime.h>
> #include <linux/pci_hotplug.h>
> +#include <linux/iommu.h>
> #include <asm-generic/pci-bridge.h>
> #include <asm/setup.h>
> #include "pci.h"
> @@ -4302,6 +4303,104 @@ void pci_ignore_hotplug(struct pci_dev *dev)
> }
> EXPORT_SYMBOL_GPL(pci_ignore_hotplug);
>
> +bool pci_peer_traffic_supported(struct pci_dev *dev, struct pci_dev *peer)
> +{
> + struct pci_host_bridge *dev_host_bridge;
> + struct pci_host_bridge *peer_host_bridge;
> +
> + /*
> + * 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 false;
> +
> + if (pci_is_pcie(dev) && pci_is_pcie(peer)) {
Can you use the same "return errors early" trick here to unindent
everything below, e.g.,
if (!pci_is_pcie(dev) || !pci_is_pcie(peer))
return false;
> + /*
> + * 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"
> + */
> + struct pci_dev *rpdev = dev->bus->self;
> + struct pci_dev *rppeer = peer->bus->self;
This will oops if rpdev or rppeer is a VF on a "virtual" bus (bus->self
is NULL in that case); see the comment near pci_is_root_bus().
> + struct pci_dev *common_upstream;
> + int pos;
> + u16 cap;
> +
> + while ((rpdev) && (pci_is_pcie(rpdev)) &&
> + (pci_pcie_type(rpdev) != PCI_EXP_TYPE_ROOT_PORT))
> + rpdev = rpdev->bus->self;
I think we might need some sort of pcie_root_port() function. We already
have a static pcie_find_root_port() that is basically the same. And
dmar_find_matched_atsr_unit() does something very similar. And
ixgbe_io_error_detected(). And myri10ge_enable_ecrc().
> +
> + while ((rppeer) && (pci_is_pcie(rppeer)) &&
> + (pci_pcie_type(rppeer) != PCI_EXP_TYPE_ROOT_PORT))
> + rppeer = rppeer->bus->self;
> +
> + common_upstream = pci_find_common_upstream_dev(dev, peer);
This (and the ACS check) logically belongs above the rpdev/rppeer stuff.
> + /*
> + * 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(rpdev, 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(rpdev, pos + PCI_ACS_CAP, &cap);
> + if ((rpdev == rppeer && common_upstream) &&
> + (((common_upstream != rpdev) &&
> + !pci_acs_enabled(common_upstream, PCI_ACS_UF)) ||
> + ((common_upstream == rpdev) && ((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(rpdev, PCI_ACS_RR))
> + return rpdev == rppeer;
> +
> + /*
> + * 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);
> + }
> +
> + return false;
> +}
> +
> #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE
> static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0};
> static DEFINE_SPINLOCK(resource_alignment_lock);
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 8262b9e..db0cb51 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -824,6 +824,8 @@ void pci_stop_root_bus(struct pci_bus *bus);
> void pci_remove_root_bus(struct pci_bus *bus);
> void pci_setup_cardbus(struct pci_bus *bus);
> 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))
> #define dev_num_vf(d) ((dev_is_pci(d) ? pci_num_vf(to_pci_dev(d)) : 0))
> @@ -1914,4 +1916,5 @@ static inline bool pci_ari_enabled(struct pci_bus *bus)
> {
> return bus->self && bus->self->ari_enabled;
> }
> +
> #endif /* LINUX_PCI_H */
> --
> 2.5.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
next prev parent reply other threads:[~2015-09-24 21:49 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-15 17:10 [PATCH 00/22] DMA-API/PCI map_peer_resource support for peer-to-peer Will Davis
2015-09-15 17:10 ` Will Davis
2015-09-15 17:10 ` [PATCH 01/22] lib/Kconfig: add HAS_DMA_P2P for peer-to-peer support Will Davis
2015-09-15 17:10 ` Will Davis
2015-09-15 17:10 ` [PATCH 02/22] linux/types.h: Add dma_peer_addr_t type Will Davis
2015-09-15 17:10 ` Will Davis
2015-09-15 17:10 ` [PATCH 03/22] dma-debug: add checking for map/unmap_peer_resource Will Davis
2015-09-15 17:10 ` Will Davis
2015-09-15 17:10 ` [PATCH 07/22] PCI: Export pci_find_host_bridge() Will Davis
2015-09-15 17:10 ` Will Davis
2015-09-15 17:10 ` [PATCH 08/22] PCI: Add pci_find_common_upstream_dev() Will Davis
2015-09-15 17:10 ` Will Davis
2015-09-15 17:10 ` [PATCH 09/22] PCI: Add pci_peer_traffic_supported() Will Davis
2015-09-15 17:10 ` Will Davis
2015-09-24 21:49 ` Bjorn Helgaas [this message]
2015-10-21 10:10 ` Benjamin Herrenschmidt
2015-09-15 17:10 ` [PATCH 10/22] PCI: Add pci_resource_to_peer() Will Davis
2015-09-15 17:10 ` Will Davis
[not found] ` <1442337067-22964-11-git-send-email-wdavis-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2015-09-24 21:36 ` Bjorn Helgaas
2015-09-24 21:36 ` Bjorn Helgaas
2015-09-15 17:10 ` [PATCH 11/22] swiotlb: Add map_peer_resource stub Will Davis
2015-09-15 17:10 ` Will Davis
2015-09-15 19:40 ` Konrad Rzeszutek Wilk
2015-09-15 19:49 ` William Davis
2015-09-15 17:10 ` [PATCH 12/22] x86, swiotlb: Add swiotlb_map_peer_resource() to swiotlb_dma_ops Will Davis
2015-09-15 17:10 ` Will Davis
2015-09-15 17:11 ` [PATCH 16/22] iommu/amd: Implement (un)map_peer_resource Will Davis
2015-09-15 17:11 ` Will Davis
2015-09-15 17:11 ` [PATCH 17/22] iommu/vt-d: implement (un)map_peer_resource Will Davis
2015-09-15 17:11 ` Will Davis
2015-09-15 17:11 ` [PATCH 18/22] x86: add pci-nommu implementation of map_peer_resource Will Davis
2015-09-15 17:11 ` Will Davis
2015-09-15 17:11 ` [PATCH 19/22] x86: Calgary: Add map_peer_resource stub Will Davis
2015-09-15 17:11 ` Will Davis
[not found] ` <1442337067-22964-1-git-send-email-wdavis-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2015-09-15 17:10 ` [PATCH 04/22] DMA-API: Introduce dma_(un)map_peer_resource Will Davis
2015-09-15 17:10 ` Will Davis
2015-09-15 17:10 ` [PATCH 05/22] dma-mapping: pci: add pci_(un)map_peer_resource Will Davis
2015-09-15 17:10 ` Will Davis
2015-09-15 17:10 ` [PATCH 06/22] DMA-API: Add peer resource mapping documentation Will Davis
2015-09-15 17:10 ` Will Davis
2015-09-15 17:10 ` [PATCH 13/22] x86, platform: Add swiotlb_map_peer_resource() to sta2x11_dma_ops Will Davis
2015-09-15 17:10 ` Will Davis
2015-09-15 17:10 ` [PATCH 14/22] swiotlb-xen: add map_peer_resource stub Will Davis
2015-09-15 17:10 ` Will Davis
2015-09-15 17:11 ` [PATCH 15/22] pci-swiotlb-xen: add xen_swiotlb_map_peer_resource to xen_swiotlb_dma_ops Will Davis
2015-09-15 17:11 ` Will Davis
2015-09-15 17:11 ` [PATCH 20/22] x86: gart: Add map_peer_resource stub Will Davis
2015-09-15 17:11 ` Will Davis
2015-09-15 17:11 ` [PATCH 21/22] x86: add dma_peer_mapping_error() Will Davis
2015-09-15 17:11 ` Will Davis
2015-09-15 17:11 ` [PATCH 22/22] x86: declare support for DMA P2P Will Davis
2015-09-15 17:11 ` Will Davis
2015-09-24 21:28 ` [PATCH 00/22] DMA-API/PCI map_peer_resource support for peer-to-peer Bjorn Helgaas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150924214921.GH10481@localhost \
--to=helgaas@kernel.org \
--cc=alex.williamson@redhat.com \
--cc=bhelgaas@google.com \
--cc=corbet@lwn.net \
--cc=davem@davemloft.net \
--cc=iommu@lists.linux-foundation.org \
--cc=jglisse@redhat.com \
--cc=jhubbard@nvidia.com \
--cc=joro@8bytes.org \
--cc=konrad.wilk@oracle.com \
--cc=linux-pci@vger.kernel.org \
--cc=markh@compro.net \
--cc=tripperda@nvidia.com \
--cc=wdavis@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.