From: Dongdong Liu <hidden> Date: 2021-10-09 10:52:55
10-Bit Tag capability, introduced in PCIe-4.0 increases the total Tag
field size from 8 bits to 10 bits.
This patchset is to enable 10-Bit tag for PCIe EP devices (include VF).
V9->V10:
- Rebased on V5.15-rc4.
- Fix some commets suggested by Krzysztof.
V8->V9:
- Rebased on V5.15-rc2.
- Rename pcie_devcap to devcap, pcie_devcap2 to devcap2 to keep the same
style with commit 691392448065 ("PCI: Cache PCIe Device Capabilities
register").
V7->V8:
- Add a kernel parameter pcie_tag_peer2peer to disable 10-bit tags.
- Provide sysfs file to enable 10-bit tags.
- Remove [PATCH V7 6/9] PCI: Enable 10-Bit Tag support for PCIe RP devices.
- Rebased on v5.14-rc6.
- Fix some other comments. Thanks to Bjorn who gave a lot of review
comments.
V6->V7:
- Rebased on v5.14-rc3.
- Change the "pci=disable_10bit_tag=" parameter to sysfs file to disable
10-Bit Tag Requester when need for p2pdma suggested by Leon.
- Fix comment for p2pdma 10-bit tag check.
V5->V6:
- Rebased on v5.14-rc2.
- Add Reviewed-by: Christoph Hellwig [off-list ref] in [PATCH V6 2/8].
- PCI: Add "pci=disable_10bit_tag=" parameter for peer-to-peer support.
- Add a 10-bit tag check in P2PDMA.
- Simplified implementation in [PATCH V6 6/8].
- Fix some comments in [PATCH V6 4/8].
V4->V5:
- Fix warning variable 'capa' is uninitialized.
- Fix warning unused variable 'pchild'.
V3->V4:
- Get the value of pcie_devcap2 in set_pcie_port_type().
- Add Reviewed-by: Christoph Hellwig [off-list ref] in [PATCH V4 1/6],
[PATCH V4 3/6], [PATCH V4 4/6], [PATCH V4 5/6].
- Fix some code style.
- Rebased on v5.13-rc6.
V2->V3:
- Use cached Device Capabilities Register suggested by Christoph.
- Fix code style to avoid > 80 char lines.
- Rename devcap2 to pcie_devcap2.
V1->V2: Fix some comments by Christoph.
- Store the devcap2 value in the pci_dev instead of reading it multiple
times.
- Change pci_info to pci_dbg to avoid the noisy log.
- Rename ext_10bit_tag_comp_path to ext_10bit_tag.
- Fix the compile error.
- Rebased on v5.13-rc1.
Dongdong Liu (8):
PCI: Use cached devcap in more places
PCI: Cache Device Capabilities 2 Register
PCI: Add 10-Bit Tag register definitions
PCI/sysfs: Add a 10-Bit Tag sysfs file PCIe Endpoint devices
PCI/IOV: Add 10-Bit Tag sysfs files for VF devices
PCI/P2PDMA: Add a 10-Bit Tag check in P2PDMA
PCI: Enable 10-Bit Tag support for PCIe Endpoint device
PCI/IOV: Enable 10-Bit Tag support for PCIe VF devices
Documentation/ABI/testing/sysfs-bus-pci | 41 +++++++++-
.../admin-guide/kernel-parameters.txt | 5 ++
drivers/media/pci/cobalt/cobalt-driver.c | 4 +-
.../net/ethernet/chelsio/cxgb4/cxgb4_main.c | 4 +-
drivers/pci/iov.c | 69 ++++++++++++++++
drivers/pci/p2pdma.c | 48 +++++++++++
drivers/pci/pci-sysfs.c | 81 +++++++++++++++++++
drivers/pci/pci.c | 12 +--
drivers/pci/pci.h | 9 +++
drivers/pci/pcie/aspm.c | 11 +--
drivers/pci/probe.c | 75 ++++++++++++++---
drivers/pci/quirks.c | 3 +-
include/linux/pci.h | 1 +
include/uapi/linux/pci_regs.h | 5 ++
14 files changed, 336 insertions(+), 32 deletions(-)
--
2.22.0
From: Dongdong Liu <hidden> Date: 2021-10-09 10:52:54
Add 10-Bit Tag register definitions for use in subsequen patches.
See the PCIe 5.0 spec section 7.5.3.15 and 9.3.3.2.
Signed-off-by: Dongdong Liu <redacted>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
include/uapi/linux/pci_regs.h | 5 +++++
1 file changed, 5 insertions(+)
@@ -6304,7 +6304,6 @@ static int cxgb4_iov_configure(struct pci_dev *pdev, int num_vfs)structpci_dev*pbridge;structport_info*pi;charname[IFNAMSIZ];-u32devcap2;u16flags;/* If we want to instantiate Virtual Functions, then our
@@ -6314,10 +6313,9 @@ static int cxgb4_iov_configure(struct pci_dev *pdev, int num_vfs)*/pbridge=pdev->bus->self;pcie_capability_read_word(pbridge,PCI_EXP_FLAGS,&flags);-pcie_capability_read_dword(pbridge,PCI_EXP_DEVCAP2,&devcap2);if((flags&PCI_EXP_FLAGS_VERS)<2||-!(devcap2&PCI_EXP_DEVCAP2_ARI)){+!(pbridge->devcap2&PCI_EXP_DEVCAP2_ARI)){/* Our parent bridge does not support ARI so issue a*warningandskipinstantiatingtheVFs.They*won'tbereachable.
@@ -3717,7 +3717,7 @@ int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask){structpci_bus*bus=dev->bus;structpci_dev*bridge;-u32cap,ctl2;+u32ctl2;if(!pci_is_pcie(dev))return-EINVAL;
@@ -3741,19 +3741,17 @@ int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask)while(bus->parent){bridge=bus->self;-pcie_capability_read_dword(bridge,PCI_EXP_DEVCAP2,&cap);-switch(pci_pcie_type(bridge)){/* Ensure switch ports support AtomicOp routing */casePCI_EXP_TYPE_UPSTREAM:casePCI_EXP_TYPE_DOWNSTREAM:-if(!(cap&PCI_EXP_DEVCAP2_ATOMIC_ROUTE))+if(!(bridge->devcap2&PCI_EXP_DEVCAP2_ATOMIC_ROUTE))return-EINVAL;break;/* Ensure root port supports all the sizes we care about */casePCI_EXP_TYPE_ROOT_PORT:-if((cap&cap_mask)!=cap_mask)+if((bridge->devcap2&cap_mask)!=cap_mask)return-EINVAL;break;}
From: Dongdong Liu <hidden> Date: 2021-10-09 10:52:57
Since commit 691392448065 ("PCI: Cache PCIe Device Capabilities register")
has already added a new member called devcap in struct pci_dev for
caching the PCIe Device Capabilities register to avoid reading
PCI_EXP_DEVCAP multiple times. Use devcap in more needed places.
Acked-by: Hans Verkuil <redacted>
Signed-off-by: Dongdong Liu <redacted>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
drivers/media/pci/cobalt/cobalt-driver.c | 4 ++--
drivers/pci/pcie/aspm.c | 11 ++++-------
drivers/pci/probe.c | 7 +------
drivers/pci/quirks.c | 3 +--
4 files changed, 8 insertions(+), 17 deletions(-)
@@ -831,8 +829,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)*DisableASPMforpre-1.1PCIedevice,wefollowMStouse*RBERbittodetermineifafunctionis1.1versiondevice*/-pcie_capability_read_dword(child,PCI_EXP_DEVCAP,®32);-if(!(reg32&PCI_EXP_DEVCAP_RBER)&&!aspm_force){+if(!(child->devcap&PCI_EXP_DEVCAP_RBER)&&!aspm_force){pci_info(child,"disabling ASPM on pre-1.1 PCIe device. You can enable it with 'pcie_aspm=force'\n");return-EINVAL;}
From: Dongdong Liu <hidden> Date: 2021-10-09 10:52:59
PCIe spec 5.0 r1.0 section 2.2.6.2 says:
If an Endpoint supports sending Requests to other Endpoints (as
opposed to host memory), the Endpoint must not send 10-Bit Tag
Requests to another given Endpoint unless an implementation-specific
mechanism determines that the Endpoint supports 10-Bit Tag Completer
capability.
Add a 10bit_tag sysfs file, write 0 to disable 10-Bit Tag Requester
when the driver does not bind the device. The typical use case is for
p2pdma when the peer device does not support 10-Bit Tag Completer.
Write 1 to enable 10-Bit Tag Requester when RC supports 10-Bit Tag
Completer capability. The typical use case is for host memory targeted
by DMA Requests. The 10bit_tag file content indicate current status of
10-Bit Tag Requester Enable.
Signed-off-by: Dongdong Liu <redacted>
---
Documentation/ABI/testing/sysfs-bus-pci | 18 +++++-
drivers/pci/pci-sysfs.c | 78 +++++++++++++++++++++++++
drivers/pci/pci.h | 2 +
drivers/pci/probe.c | 14 +++++
4 files changed, 111 insertions(+), 1 deletion(-)
@@ -156,7 +156,7 @@ Description: binary file containing the Vital Product Data for the device. It should follow the VPD format defined in PCI Specification 2.1 or 2.2, but users should consider- that some devices may have incorrectly formatted data. + that some devices may have incorrectly formatted data. If the underlying VPD has a writable section then the corresponding section of this file will be writable.
@@ -424,3 +424,19 @@ Description: The file is writable if the PF is bound to a driver that implements ->sriov_set_msix_vec_count().++What: /sys/bus/pci/devices/.../10bit_tag+Date: September 2021+Contact: Dongdong Liu <liudongdong3@huawei.com>+Description:+ The file will be visible when the device supports 10-Bit Tag+ Requester. The file is readable, the value indicate current+ status of 10-Bit Tag Requester Enable.+ 1 - enabled, 0 - disabled.++ The file is also writable, write 0 to disable 10-Bit Tag+ Requester when the driver does not bind the device. The typical+ use case is for p2pdma when the peer device does not support+ 10-Bit Tag Completer. Write 1 to enable 10-Bit Tag Requester+ when RC supports 10-Bit Tag Completer capability. The typical+ use case is for host memory targeted by DMA Requests.
From: Dongdong Liu <hidden> Date: 2021-10-09 10:53:04
PCIe spec 5.0 r1.0 section 2.2.6.2 says:
If an Endpoint supports sending Requests to other Endpoints (as
opposed to host memory), the Endpoint must not send 10-Bit Tag
Requests to another given Endpoint unless an implementation-specific
mechanism determines that the Endpoint supports 10-Bit Tag Completer
capability.
Add sriov_vf_10bit_tag file to query the status of VF 10-Bit Tag
Requester Enable.
Add a sriov_vf_10bit_tag_ctl sysfs file, write 0 to disable the VF
10-Bit Tag Requester. The typical use case is for p2pdma when the peer
device does not support 10-Bit Tag Completer. Write 1 to enable 10-Bit
Tag Requester when RC supports 10-Bit Tag Completer capability. The
typical use case is for host memory targeted by DMA Requests.
Signed-off-by: Dongdong Liu <redacted>
---
Documentation/ABI/testing/sysfs-bus-pci | 23 +++++++++++
drivers/pci/iov.c | 55 +++++++++++++++++++++++++
2 files changed, 78 insertions(+)
@@ -440,3 +440,26 @@ Description: 10-Bit Tag Completer. Write 1 to enable 10-Bit Tag Requester when RC supports 10-Bit Tag Completer capability. The typical use case is for host memory targeted by DMA Requests.++What: /sys/bus/pci/devices/.../sriov_vf_10bit_tag+Date: September 2021+Contact: Dongdong Liu <liudongdong3@huawei.com>+Description:+ This file is associated with a SR-IOV physical function (PF).+ It is visible when the device supports VF 10-Bit Tag Requester.+ It contains the status of VF 10-Bit Tag Requester Enable.+ The file is read-only.++What: /sys/bus/pci/devices/.../sriov_vf_10bit_tag_ctl+Date: September 2021+Contact: Dongdong Liu <liudongdong3@huawei.com>+Description:+ This file is associated with a SR-IOV virtual function (VF).+ It is visible when the device supports VF 10-Bit Tag+ Requester. The file is only writeable when the VF driver+ does not bind to a device. Write 0 to any VF's file disables+ 10-Bit Tag Requester for all VFs. The typical use case is for+ p2pdma when the peer device does not support 10-Bit Tag+ Completer. Write 1 to enable 10-Bit Tag Requester for all VFs+ when RC supports 10-Bit Tag Completer capability. The typical+ use case is for host memory targeted by DMA Requests.
From: Dongdong Liu <hidden> Date: 2021-10-09 10:53:06
Enable 10-Bit Tag Requester for the VF devices below the
Root Port that support 10-Bit Tag Completer.
Signed-off-by: Dongdong Liu <redacted>
---
drivers/pci/iov.c | 11 +++++++++++
1 file changed, 11 insertions(+)
From: Dongdong Liu <hidden> Date: 2021-10-09 10:53:06
Add a 10-Bit Tag check in the P2PDMA code to ensure that a device with
10-Bit Tag Requester doesn't interact with a device that does not
support 10-Bit Tag Completer. Before that happens, the kernel should
emit a warning.
"echo 0 > /sys/bus/pci/devices/.../10bit_tag" to disable 10-Bit Tag
Requester for PF device.
"echo 0 > /sys/bus/pci/devices/.../sriov_vf_10bit_tag_ctl" to disable
10-Bit Tag Requester for VF device.
Signed-off-by: Dongdong Liu <redacted>
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
---
drivers/pci/p2pdma.c | 48 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
@@ -410,6 +411,50 @@ static unsigned long map_types_idx(struct pci_dev *client)(client->bus->number<<8)|client->devfn;}+staticboolpci_10bit_tags_unsupported(structpci_dev*a,+structpci_dev*b,+boolverbose)+{+boolreq;+boolcomp;+u16ctl;+constchar*str="10bit_tag";++if(a->is_virtfn){+#ifdef CONFIG_PCI_IOV+req=!!(a->physfn->sriov->ctrl&+PCI_SRIOV_CTRL_VF_10BIT_TAG_REQ_EN);+#endif+}else{+pcie_capability_read_word(a,PCI_EXP_DEVCTL2,&ctl);+req=!!(ctl&PCI_EXP_DEVCTL2_10BIT_TAG_REQ_EN);+}++comp=!!(b->devcap2&PCI_EXP_DEVCAP2_10BIT_TAG_COMP);++/* 10-bit tags not enabled on requester */+if(!req)+returnfalse;++/* Completer can handle anything */+if(comp)+returnfalse;++if(!verbose)+returntrue;++pci_warn(a,"cannot be used for peer-to-peer DMA as 10-Bit Tag Requester enable is set for this device, but peer device (%s) does not support the 10-Bit Tag Completer\n",+pci_name(b));++if(a->is_virtfn)+str="sriov_vf_10bit_tag_ctl";++pci_warn(a,"to disable 10-Bit Tag Requester for this device, echo 0 > /sys/bus/pci/devices/%s/%s\n",+pci_name(a),str);++returntrue;+}+/**CalculatetheP2PDMAmappingtypeanddistancebetweentwoPCIdevices.*
From: Dongdong Liu <hidden> Date: 2021-10-09 10:53:07
10-Bit Tag capability, introduced in PCIe-4.0 increases the total Tag
field size from 8 bits to 10 bits.
PCIe spec 5.0 r1.0 section 2.2.6.2 "Considerations for Implementing
10-Bit Tag Capabilities" Implementation Note:
For platforms where the RC supports 10-Bit Tag Completer capability,
it is highly recommended for platform firmware or operating software
that configures PCIe hierarchies to Set the 10-Bit Tag Requester Enable
bit automatically in Endpoints with 10-Bit Tag Requester capability.
This enables the important class of 10-Bit Tag capable adapters that
send Memory Read Requests only to host memory.
It's safe to enable 10-bit tags for all devices below a Root Port that
supports them. Switches that lack 10-Bit Tag Completer capability are
still able to forward NPRs and Completions carrying 10-Bit Tags correctly,
since the two new Tag bits are in TLP Header bits that were formerly
Reserved.
PCIe spec 5.0 r1.0 section 2.2.6.2 says:
If an Endpoint supports sending Requests to other Endpoints (as opposed
to host memory), the Endpoint must not send 10-Bit Tag Requests to
another given Endpoint unless an implementation-specific mechanism
determines that the Endpoint supports 10-Bit Tag Completer capability.
It is not safe for P2P traffic if an Endpoint send 10-Bit Tag Requesters
to another Endpoint that does not support 10-Bit Tag Completer capability,
so we provide sysfs file to disable 10-Bit Tag Requester. Unbind the
device driver, set the sysfs file and then rebind the driver.
Add a kernel parameter pcie_tag_peer2peer that disables 10-Bit Tag
Requester for all PCIe devices. This configuration allows peer-to-peer
DMA between any pair of devices, possibly at the cost of reduced
performance.
Signed-off-by: Dongdong Liu <redacted>
---
.../admin-guide/kernel-parameters.txt | 5 ++
drivers/pci/iov.c | 3 ++
drivers/pci/pci-sysfs.c | 3 ++
drivers/pci/pci.c | 4 ++
drivers/pci/pci.h | 7 +++
drivers/pci/probe.c | 46 ++++++++++++++++++-
6 files changed, 67 insertions(+), 1 deletion(-)
@@ -3979,6 +3979,11 @@ any pair of devices, possibly at the cost of reduced performance. This also guarantees that hot-added devices will work.+ pcie_tag_peer2peer Disable 10-Bit Tag Requester for all+ PCIe devices. This configuration allows+ peer-to-peer DMA between any pair of devices,+ possibly at the cost of reduced performance.+ cbiosize=nn[KMG] The fixed amount of bus space which is reserved for the CardBus bridge's IO window. The default value is 256 bytes.
On Sat, Oct 09, 2021 at 06:49:36PM +0800, Dongdong Liu wrote:
Add a 10-Bit Tag check in the P2PDMA code to ensure that a device with
10-Bit Tag Requester doesn't interact with a device that does not
support 10-Bit Tag Completer.
Shouldn't this also take into account Extended Tags (8 bits)? I think
the only tag size guaranteed to be supported is 5 bits.
Before that happens, the kernel should emit a warning.
The warning is nice, but the critical thing is that the P2PDMA mapping
should fail so we don't attempt DMA in this situation. I guess that's
sort of what you're saying with "ensure that a device ... doesn't
interact with a device ..."
quoted hunk
"echo 0 > /sys/bus/pci/devices/.../10bit_tag" to disable 10-Bit Tag
Requester for PF device.
"echo 0 > /sys/bus/pci/devices/.../sriov_vf_10bit_tag_ctl" to disable
10-Bit Tag Requester for VF device.
Signed-off-by: Dongdong Liu <redacted>
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
---
drivers/pci/p2pdma.c | 48 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
@@ -410,6 +411,50 @@ static unsigned long map_types_idx(struct pci_dev *client)(client->bus->number<<8)|client->devfn;}+staticboolpci_10bit_tags_unsupported(structpci_dev*a,+structpci_dev*b,+boolverbose)+{+boolreq;+boolcomp;+u16ctl;+constchar*str="10bit_tag";++if(a->is_virtfn){+#ifdef CONFIG_PCI_IOV+req=!!(a->physfn->sriov->ctrl&+PCI_SRIOV_CTRL_VF_10BIT_TAG_REQ_EN);+#endif+}else{+pcie_capability_read_word(a,PCI_EXP_DEVCTL2,&ctl);+req=!!(ctl&PCI_EXP_DEVCTL2_10BIT_TAG_REQ_EN);+}++comp=!!(b->devcap2&PCI_EXP_DEVCAP2_10BIT_TAG_COMP);+/* 10-bit tags not enabled on requester */+if(!req)+returnfalse;++/* Completer can handle anything */+if(comp)+returnfalse;++if(!verbose)+returntrue;++pci_warn(a,"cannot be used for peer-to-peer DMA as 10-Bit Tag Requester enable is set for this device, but peer device (%s) does not support the 10-Bit Tag Completer\n",+pci_name(b));++if(a->is_virtfn)+str="sriov_vf_10bit_tag_ctl";++pci_warn(a,"to disable 10-Bit Tag Requester for this device, echo 0 > /sys/bus/pci/devices/%s/%s\n",+pci_name(a),str);++returntrue;+}+/**CalculatetheP2PDMAmappingtypeanddistancebetweentwoPCIdevices.*
On Sat, Oct 09, 2021 at 06:49:34PM +0800, Dongdong Liu wrote:
PCIe spec 5.0 r1.0 section 2.2.6.2 says:
If an Endpoint supports sending Requests to other Endpoints (as
opposed to host memory), the Endpoint must not send 10-Bit Tag
Requests to another given Endpoint unless an implementation-specific
mechanism determines that the Endpoint supports 10-Bit Tag Completer
capability.
Add a 10bit_tag sysfs file, write 0 to disable 10-Bit Tag Requester
when the driver does not bind the device. The typical use case is for
p2pdma when the peer device does not support 10-Bit Tag Completer.
Write 1 to enable 10-Bit Tag Requester when RC supports 10-Bit Tag
Completer capability. The typical use case is for host memory targeted
by DMA Requests. The 10bit_tag file content indicate current status of
10-Bit Tag Requester Enable.
Don't we have a hole here? We're adding knobs to control 10-Bit Tag
usage, but don't we have basically the same issues with Extended
(8-bit) Tags?
I wonder if we should be adding a more general "tags" file that can
manage both 8-bit and 10-bit tag usage.
On Sat, Oct 09, 2021 at 06:49:36PM +0800, Dongdong Liu wrote:
Add a 10-Bit Tag check in the P2PDMA code to ensure that a device with
10-Bit Tag Requester doesn't interact with a device that does not
support 10-Bit Tag Completer. Before that happens, the kernel should
emit a warning.
Signed-off-by: Dongdong Liu <redacted>
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
I need to be convinced that this check is in the right spot to catch
all potential P2PDMA situations. The pci_p2pmem_find() and
pci_p2pdma_distance() interfaces eventually call
calc_map_type_and_dist(). But those interfaces don't actually produce
DMA bus addresses, and I'm not convinced that all P2PDMA users use
them.
nvme *does* use them, but infiniband (rdma_rw_map_sg()) does not, and
it calls pci_p2pdma_map_sg().
amdgpu_dma_buf_attach() calls pci_p2pdma_distance_many() but I don't
know where it sets up P2PDMA transactions.
cxgb4 and qed mention "peer2peer", but I don't know whether they are
related; they don't seem to use any pci_p2p.* interfaces.
rcu_read_lock();
p2pdma = rcu_dereference(provider->p2pdma);
if (p2pdma)
--
2.22.0
I need to be convinced that this check is in the right spot to catch
all potential P2PDMA situations. The pci_p2pmem_find() and
pci_p2pdma_distance() interfaces eventually call
calc_map_type_and_dist(). But those interfaces don't actually produce
DMA bus addresses, and I'm not convinced that all P2PDMA users use
them.
nvme *does* use them, but infiniband (rdma_rw_map_sg()) does not, and
it calls pci_p2pdma_map_sg().
The rules of the current code is that calc_map_type_and_dist() must be
called before pci_p2pdma_map_sg(). The calc function caches the mapping
type in an xarray. If it was not called ahead of time,
pci_p2pdma_map_type() will return PCI_P2PDMA_MAP_NOT_SUPPORTED, and the
WARN_ON_ONCE will be hit in
pci_p2pdma_map_sg_attrs().
Both NVMe and RDMA (only used in the nvme fabrics code) do the correct
thing here and we can be sure calc_map_type_and_dist() is called before
any pages are mapped.
The patch set I'm currently working on will ensure that
calc_map_type_and_dist() is called before anyone maps a PCI P2PDMA page
with dma_map_sg*().
amdgpu_dma_buf_attach() calls pci_p2pdma_distance_many() but I don't
know where it sets up P2PDMA transactions.
The amdgpu driver hacked this in before proper support was done, but at
least it's using pci_p2pdma_distance_many() presumably before trying any
transfer. Though it's likely broken as it doesn't take into account the
mapping type and thus I think it always assumes traffic goes through the
host bridge (seeing it doesn't use pci_p2pdma_map_sg()).
cxgb4 and qed mention "peer2peer", but I don't know whether they are
related; they don't seem to use any pci_p2p.* interfaces.
I'm really not sure what these drivers are doing at all. However, I
think this is unrelated based on this old patch description[1]:
Open MPI, Intel MPI and other applications don't support the iWARP
requirement that the client side send the first RDMA message. This
class of application connection setup is called peer-2-peer. Typically
once the connection is setup, _both_ sides want to send data.
This patch enables supporting peer-2-peer over the chelsio rnic by
enforcing this iWARP requirement in the driver itself as part of RDMA
connection setup.
Logan
[1] http://lkml.iu.edu/hypermail/linux/kernel/0804.3/1416.html
I need to be convinced that this check is in the right spot to catch
all potential P2PDMA situations. The pci_p2pmem_find() and
pci_p2pdma_distance() interfaces eventually call
calc_map_type_and_dist(). But those interfaces don't actually produce
DMA bus addresses, and I'm not convinced that all P2PDMA users use
them.
nvme *does* use them, but infiniband (rdma_rw_map_sg()) does not, and
it calls pci_p2pdma_map_sg().
The rules of the current code is that calc_map_type_and_dist() must be
called before pci_p2pdma_map_sg(). The calc function caches the mapping
type in an xarray. If it was not called ahead of time,
pci_p2pdma_map_type() will return PCI_P2PDMA_MAP_NOT_SUPPORTED, and the
WARN_ON_ONCE will be hit in
pci_p2pdma_map_sg_attrs().
Seems like it requires fairly deep analysis to prove all this. Is
this something we don't want to put directly in the map path because
it's a hot path, or it just doesn't fit there in the model, or ...?
Both NVMe and RDMA (only used in the nvme fabrics code) do the correct
thing here and we can be sure calc_map_type_and_dist() is called before
any pages are mapped.
The patch set I'm currently working on will ensure that
calc_map_type_and_dist() is called before anyone maps a PCI P2PDMA page
with dma_map_sg*().
quoted
amdgpu_dma_buf_attach() calls pci_p2pdma_distance_many() but I don't
know where it sets up P2PDMA transactions.
The amdgpu driver hacked this in before proper support was done, but at
least it's using pci_p2pdma_distance_many() presumably before trying any
transfer. Though it's likely broken as it doesn't take into account the
mapping type and thus I think it always assumes traffic goes through the
host bridge (seeing it doesn't use pci_p2pdma_map_sg()).
What does it mean to go through the host bridge? Obviously DMA to
system memory would go through the host bridge, but this seems
different. Is this a "between PCI hierarchies" case like to a device
below a different root port? I don't know what the tag rules are for
that.
quoted
cxgb4 and qed mention "peer2peer", but I don't know whether they are
related; they don't seem to use any pci_p2p.* interfaces.
I'm really not sure what these drivers are doing at all. However, I
think this is unrelated based on this old patch description[1]:
Open MPI, Intel MPI and other applications don't support the iWARP
requirement that the client side send the first RDMA message. This
class of application connection setup is called peer-2-peer. Typically
once the connection is setup, _both_ sides want to send data.
This patch enables supporting peer-2-peer over the chelsio rnic by
enforcing this iWARP requirement in the driver itself as part of RDMA
connection setup.
From: Dongdong Liu <hidden> Date: 2021-10-28 07:45:15
Hi Bjorn
Many thanks for your review.
On 2021/10/28 6:28, Bjorn Helgaas wrote:
On Sat, Oct 09, 2021 at 06:49:34PM +0800, Dongdong Liu wrote:
quoted
PCIe spec 5.0 r1.0 section 2.2.6.2 says:
If an Endpoint supports sending Requests to other Endpoints (as
opposed to host memory), the Endpoint must not send 10-Bit Tag
Requests to another given Endpoint unless an implementation-specific
mechanism determines that the Endpoint supports 10-Bit Tag Completer
capability.
Add a 10bit_tag sysfs file, write 0 to disable 10-Bit Tag Requester
when the driver does not bind the device. The typical use case is for
p2pdma when the peer device does not support 10-Bit Tag Completer.
Write 1 to enable 10-Bit Tag Requester when RC supports 10-Bit Tag
Completer capability. The typical use case is for host memory targeted
by DMA Requests. The 10bit_tag file content indicate current status of
10-Bit Tag Requester Enable.
Don't we have a hole here? We're adding knobs to control 10-Bit Tag
usage, but don't we have basically the same issues with Extended
(8-bit) Tags?
From: Dongdong Liu <hidden> Date: 2021-10-28 07:56:50
On 2021/10/28 5:20, Bjorn Helgaas wrote:
On Sat, Oct 09, 2021 at 06:49:36PM +0800, Dongdong Liu wrote:
quoted
Add a 10-Bit Tag check in the P2PDMA code to ensure that a device with
10-Bit Tag Requester doesn't interact with a device that does not
support 10-Bit Tag Completer.
Shouldn't this also take into account Extended Tags (8 bits)? I think
the only tag size guaranteed to be supported is 5 bits.
As all PCIe completers are required to support 8-bit tags, seems no need
to take into account Extended Tags.
quoted
Before that happens, the kernel should emit a warning.
The warning is nice, but the critical thing is that the P2PDMA mapping
should fail so we don't attempt DMA in this situation. I guess that's
sort of what you're saying with "ensure that a device ... doesn't
interact with a device ..."
Yes, that is.
quoted
"echo 0 > /sys/bus/pci/devices/.../10bit_tag" to disable 10-Bit Tag
Requester for PF device.
"echo 0 > /sys/bus/pci/devices/.../sriov_vf_10bit_tag_ctl" to disable
10-Bit Tag Requester for VF device.
Signed-off-by: Dongdong Liu <redacted>
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
---
drivers/pci/p2pdma.c | 48 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
@@ -410,6 +411,50 @@ static unsigned long map_types_idx(struct pci_dev *client)(client->bus->number<<8)|client->devfn;}+staticboolpci_10bit_tags_unsupported(structpci_dev*a,+structpci_dev*b,+boolverbose)+{+boolreq;+boolcomp;+u16ctl;+constchar*str="10bit_tag";++if(a->is_virtfn){+#ifdef CONFIG_PCI_IOV+req=!!(a->physfn->sriov->ctrl&+PCI_SRIOV_CTRL_VF_10BIT_TAG_REQ_EN);+#endif+}else{+pcie_capability_read_word(a,PCI_EXP_DEVCTL2,&ctl);+req=!!(ctl&PCI_EXP_DEVCTL2_10BIT_TAG_REQ_EN);+}++comp=!!(b->devcap2&PCI_EXP_DEVCAP2_10BIT_TAG_COMP);+/* 10-bit tags not enabled on requester */+if(!req)+returnfalse;++/* Completer can handle anything */+if(comp)+returnfalse;++if(!verbose)+returntrue;++pci_warn(a,"cannot be used for peer-to-peer DMA as 10-Bit Tag Requester enable is set for this device, but peer device (%s) does not support the 10-Bit Tag Completer\n",+pci_name(b));++if(a->is_virtfn)+str="sriov_vf_10bit_tag_ctl";++pci_warn(a,"to disable 10-Bit Tag Requester for this device, echo 0 > /sys/bus/pci/devices/%s/%s\n",+pci_name(a),str);++returntrue;+}+/**CalculatetheP2PDMAmappingtypeanddistancebetweentwoPCIdevices.*
I need to be convinced that this check is in the right spot to catch
all potential P2PDMA situations. The pci_p2pmem_find() and
pci_p2pdma_distance() interfaces eventually call
calc_map_type_and_dist(). But those interfaces don't actually produce
DMA bus addresses, and I'm not convinced that all P2PDMA users use
them.
nvme *does* use them, but infiniband (rdma_rw_map_sg()) does not, and
it calls pci_p2pdma_map_sg().
The rules of the current code is that calc_map_type_and_dist() must be
called before pci_p2pdma_map_sg(). The calc function caches the mapping
type in an xarray. If it was not called ahead of time,
pci_p2pdma_map_type() will return PCI_P2PDMA_MAP_NOT_SUPPORTED, and the
WARN_ON_ONCE will be hit in
pci_p2pdma_map_sg_attrs().
Seems like it requires fairly deep analysis to prove all this. Is
this something we don't want to put directly in the map path because
it's a hot path, or it just doesn't fit there in the model, or ...?
Yes, that's pretty much what my next patch set does. It just took a
while to get there (adding the xarray, etc).
quoted
Both NVMe and RDMA (only used in the nvme fabrics code) do the correct
thing here and we can be sure calc_map_type_and_dist() is called before
any pages are mapped.
The patch set I'm currently working on will ensure that
calc_map_type_and_dist() is called before anyone maps a PCI P2PDMA page
with dma_map_sg*().
quoted
amdgpu_dma_buf_attach() calls pci_p2pdma_distance_many() but I don't
know where it sets up P2PDMA transactions.
The amdgpu driver hacked this in before proper support was done, but at
least it's using pci_p2pdma_distance_many() presumably before trying any
transfer. Though it's likely broken as it doesn't take into account the
mapping type and thus I think it always assumes traffic goes through the
host bridge (seeing it doesn't use pci_p2pdma_map_sg()).
What does it mean to go through the host bridge? Obviously DMA to
system memory would go through the host bridge, but this seems
different. Is this a "between PCI hierarchies" case like to a device
below a different root port? I don't know what the tag rules are for
that.
It means both devices are connected to the host bridge without a switch.
So TLPs are routed through the route complex and thus would be affected
by the IOMMU. I also don't know how the tag rules apply here. But the
code in this patch will ensure that no two devices with different tag
sizes will ever use p2pdma in any case.
Logan
On Thu, Oct 28, 2021 at 03:44:49PM +0800, Dongdong Liu wrote:
On 2021/10/28 6:28, Bjorn Helgaas wrote:
quoted
On Sat, Oct 09, 2021 at 06:49:34PM +0800, Dongdong Liu wrote:
quoted
PCIe spec 5.0 r1.0 section 2.2.6.2 says:
If an Endpoint supports sending Requests to other Endpoints (as
opposed to host memory), the Endpoint must not send 10-Bit Tag
Requests to another given Endpoint unless an implementation-specific
mechanism determines that the Endpoint supports 10-Bit Tag Completer
capability.
Add a 10bit_tag sysfs file, write 0 to disable 10-Bit Tag Requester
when the driver does not bind the device. The typical use case is for
p2pdma when the peer device does not support 10-Bit Tag Completer.
Write 1 to enable 10-Bit Tag Requester when RC supports 10-Bit Tag
Completer capability. The typical use case is for host memory targeted
by DMA Requests. The 10bit_tag file content indicate current status of
10-Bit Tag Requester Enable.
Don't we have a hole here? We're adding knobs to control 10-Bit Tag
usage, but don't we have basically the same issues with Extended
(8-bit) Tags?
Oh, right, I forgot that, thanks for the reminder! Let's add a
comment in pci_configure_extended_tags() to that effect so I'll
remember next time.
I think the appropriate reference is PCIe r5.0, sec 2.2.6.2, which
says "Receivers/Completers must handle 8-bit Tag values correctly
regardless of the setting of their Extended Tag Field Enable bit (see
Section 7.5.3.4)."
The Tag field was 8 bits all the way from PCIe r1.0, but until r2.1 it
said that by default, only the lower 5 bits are used.
The text about all Completers explicitly being required to support
8-bit Tags wasn't added until PCIe r3.0, which might explain some
confusion and the presence of the Extended Tag Field Enable bit.
At the same time, can you fold pci_configure_10bit_tags() directly
into pci_configure_extended_tags()? It's pretty small and I think it
will be easier if it's all in one place.
quoted
I wonder if we should be adding a more general "tags" file that can
manage both 8-bit and 10-bit tag usage.
I'm still thinking that maybe a generic name (without "10") would be
better, even though we don't need it to manage 8-bit tags. It's
conceivable that there could be even more tag bits in the future, and
it would be nice if we didn't have to add yet another file.
Bjorn
From: Dongdong Liu <hidden> Date: 2021-10-29 07:17:02
On 2021/10/29 1:24, Bjorn Helgaas wrote:
On Thu, Oct 28, 2021 at 03:44:49PM +0800, Dongdong Liu wrote:
quoted
On 2021/10/28 6:28, Bjorn Helgaas wrote:
quoted
On Sat, Oct 09, 2021 at 06:49:34PM +0800, Dongdong Liu wrote:
quoted
PCIe spec 5.0 r1.0 section 2.2.6.2 says:
If an Endpoint supports sending Requests to other Endpoints (as
opposed to host memory), the Endpoint must not send 10-Bit Tag
Requests to another given Endpoint unless an implementation-specific
mechanism determines that the Endpoint supports 10-Bit Tag Completer
capability.
Add a 10bit_tag sysfs file, write 0 to disable 10-Bit Tag Requester
when the driver does not bind the device. The typical use case is for
p2pdma when the peer device does not support 10-Bit Tag Completer.
Write 1 to enable 10-Bit Tag Requester when RC supports 10-Bit Tag
Completer capability. The typical use case is for host memory targeted
by DMA Requests. The 10bit_tag file content indicate current status of
10-Bit Tag Requester Enable.
Don't we have a hole here? We're adding knobs to control 10-Bit Tag
usage, but don't we have basically the same issues with Extended
(8-bit) Tags?
Oh, right, I forgot that, thanks for the reminder! Let's add a
comment in pci_configure_extended_tags() to that effect so I'll
remember next time.
Ok, Will do.
I think the appropriate reference is PCIe r5.0, sec 2.2.6.2, which
says "Receivers/Completers must handle 8-bit Tag values correctly
regardless of the setting of their Extended Tag Field Enable bit (see
Section 7.5.3.4)."
The Tag field was 8 bits all the way from PCIe r1.0, but until r2.1 it
said that by default, only the lower 5 bits are used.
The text about all Completers explicitly being required to support
8-bit Tags wasn't added until PCIe r3.0, which might explain some
confusion and the presence of the Extended Tag Field Enable bit.
Thanks for the clarification.
At the same time, can you fold pci_configure_10bit_tags() directly
into pci_configure_extended_tags()? It's pretty small and I think it
will be easier if it's all in one place.
OK, will do.
quoted
quoted
I wonder if we should be adding a more general "tags" file that can
manage both 8-bit and 10-bit tag usage.
I'm still thinking that maybe a generic name (without "10") would be
better, even though we don't need it to manage 8-bit tags. It's
conceivable that there could be even more tag bits in the future, and
it would be nice if we didn't have to add yet another file.