On Fri, 2025-09-26 at 14:56 +0200, Christian König wrote:
On 26.09.25 10:46, Thomas Hellström wrote:
Add a function to the dma_buf_attach_ops to indicate whether the connection is a private interconnect. If so the function returns the address to an interconnect-defined structure that can be used for further negotiating.
Also add a field to the dma_buf_attachment that indicates whether a private interconnect is used by the attachment.
Signed-off-by: Thomas Hellström thomas.hellstrom@linux.intel.com
include/linux/dma-buf.h | 51 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index d58e329ac0e7..25dbf1fea09a 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -442,6 +442,39 @@ struct dma_buf { #endif }; +/* RFC: Separate header for the interconnect defines? */
+/**
- struct dma_buf_interconnect - Private interconnect
- @name: The name of the interconnect
- */
+struct dma_buf_interconnect {
- const char *name;
+};
+/**
- struct dma_buf_interconnect_attach_ops - Interconnect attach
ops base-class
- Declared for type-safety. Interconnect implementations should
subclass to
- implement negotiation-specific ops.
- */
+struct dma_buf_interconnect_attach_ops { +};
+/**
- struct dma_buf_interconnect_attach - Interconnect state
- @interconnect: The struct dma_buf_interconnect identifying the
interconnect
- Interconnect implementations subclass as needed for attachment
state
- that can't be stored elsewhere. It could, for example, hold a
pointer
- to a replacement of the sg-list after the attachment has been
mapped.
- If no additional state is needed, an exporter could define a
single
- static instance of this struct.
- */
+struct dma_buf_interconnect_attach {
- const struct dma_buf_interconnect *interconnect;
+};
/** * struct dma_buf_attach_ops - importer operations for an attachment * @@ -475,6 +508,21 @@ struct dma_buf_attach_ops { * point to the new location of the DMA-buf. */ void (*move_notify)(struct dma_buf_attachment *attach);
- /**
* @supports_interconnect: [optional] - Does the driver
support a local interconnect?
*
* Does the importer support a private interconnect? The
interconnect is
* identified using a unique address defined instantiated
either by the driver
* if the interconnect is driver-private or globally
* (RFC added to the dma-buf-interconnect.c file) if
cross-driver.
*
* Return: A pointer to the interconnect-private
attach_ops structure if supported,
* %NULL otherwise.
*/
- const struct dma_buf_interconnect_attach_ops *
- (*supports_interconnect)(struct dma_buf_attachment
*attach,
const struct dma_buf_interconnect
*interconnect);
This looks like it sits in the wrong structure. The dma_buf_attach_ops are the operations provided by the importer, e.g. move notification.
When we want to check if using an interconnect is possible we need to do that on the exporter, e.g. dma_buf_ops().
Well both exporter and exporter has specific information WRT this. The ultimate decision is done in the exporter attach() callback, just like pcie_p2p. And the exporter acknowledges that by setting the dma_buf_attachment::interconnect_attach field. In analogy with the dma_buf_attachment::peer2peer member.
So the above function mimics the dma_buf_attach_ops::allow_peer2peer bool, except it's not a single interconnect so we'd either use a set of bools, one for each potential interconnect, or a function like this. A function has the benefit that it can also provide any additional attach ops the interconnect might need.
So the flow becomes: 1) Importer calls exporter attach() with a non-NULL supports_interconnect() to signal that it supports some additional interconnects. 2) exporter calls supports_interconnect(my_interconnect) to figure out whether the importer supports a specific interconnect it wants to try. This is similar to the exporter checking "allow_peer2peer" (or rather the core checking "allow_peer2peer" on the behalf of the exporter). 3) Importer finds it supports the interconnect and provides additional dma_buf_interconnect_attach_ops. 4) Now the exporter checks that the interconnect is indeed possible. This is similar to calling pci_p2p_distance(), but interconnect- specific. This might involve querying the importer, for example if the importer feels like the exporting device:bar pair does indeed have an implicit VF_PF connection. This can be done if needed using the dma_buf_interconnect_attach_ops. 5) Exporter is happy, and sets the dma_buf_attachment::interconnect_attach field. This is similar to setting the dma_buf_attachment::peer2peer field.
So basically this is the pcie peer2peer negotiation flow generalized. It would be trivial to implement the pcie peer2peer negotiation as a private protocol using the above.
I think we should have an map_interconnect(connector type descriptor) that the importer can use to establish a mapping for itself.
Additional to that we need an unmap_interconnect() to let the exporter know that an importer doesn't need a specific mapping any more.
Is this to not overload the map_attachment() and unmap_attachment() functions that otherwise could be used? Is it because they return an sg_table? Yeah, that could make sense but not for the interconnect negotiation itself, right? That happens during attach time like pcie_p2p?
}; /** @@ -484,6 +532,8 @@ struct dma_buf_attach_ops { * @node: list of dma_buf_attachment, protected by dma_resv lock of the dmabuf. * @peer2peer: true if the importer can handle peer resources without pages. * @priv: exporter specific attachment data.
- @interconnect_attach: Private interconnect state for the
connection if used,
- NULL otherwise.
* @importer_ops: importer operations for this attachment, if provided * dma_buf_map/unmap_attachment() must be called with the dma_resv lock held. * @importer_priv: importer specific attachment data. @@ -503,6 +553,7 @@ struct dma_buf_attachment { struct list_head node; bool peer2peer; const struct dma_buf_attach_ops *importer_ops;
- struct dma_buf_interconnect_attach *interconnect_attach;
We already have an importer and an exporter private void *. Do we really need that?
See above. It looks like the exporter private is largely unused in xekmd at least but the importer would want to inspect that as well, to find out whether the attachment indeed is an interconnect attachment. And I'm not sure whether a driver that already uses the exporter priv would ever want to use a private interconnect like this.
Thanks, Thomas
Regards, Christian.
void *importer_priv; void *priv; };