[PATCH RFC 09/26] accel/habanalabs: Use the SGT mapping type

Jason Gunthorpe
2026-02-18T00:12:08Z

habana has special code to check pci_p2pdma_distance() and rejects any
importer that cannot do P2P DMA to its MMIO.

Convert this directly to a SGT_P2P match which does the same check
inside the matching logic.

Someday this should be converted to use dma_buf_phys_vec_to_sgt() which
does the P2P checking correctly, for both direct and IOMMU based cases,
instead of this hack.

Remove the now empty attach function.

Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
drivers/accel/habanalabs/common/memory.c | 54 +++++++++++-------------
1 file changed, 24 insertions(+), 30 deletions(-)

diff --git a/drivers/accel/habanalabs/common/memory.c b/drivers/accel/habanalabs/common/memory.c
index 633db4bff46fc4..58dbc3c7f0877a 100644
--- a/drivers/accel/habanalabs/common/memory.c
+++ b/drivers/accel/habanalabs/common/memory.c
@@ -9,10 +9,10 @@
#include "habanalabs.h"
#include "../include/hw_ip/mmu/mmu_general.h"

+#include <linux/dma-buf-mapping.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
-#include <linux/pci-p2pdma.h>

MODULE_IMPORT_NS("DMA_BUF");

@@ -1704,23 +1704,6 @@ static struct sg_table *alloc_sgt_from_device_pages(struct hl_device *hdev, u64
return ERR_PTR(rc);
}

-static int hl_dmabuf_attach(struct dma_buf *dmabuf,
- struct dma_buf_attachment *attachment)
-{
- struct hl_dmabuf_priv *hl_dmabuf;
- struct hl_device *hdev;
- int rc;
-
- hl_dmabuf = dmabuf->priv;
- hdev = hl_dmabuf->ctx->hdev;
-
- rc = pci_p2pdma_distance(hdev->pdev, attachment->dev, true);
-
- if (rc < 0)
- attachment->peer2peer = false;
- return 0;
-}
-
static struct sg_table *hl_map_dmabuf(struct dma_buf_attachment *attachment,
enum dma_data_direction dir)
{
@@ -1734,11 +1717,6 @@ static struct sg_table *hl_map_dmabuf(struct dma_buf_attachment *attachment,
hl_dmabuf = dma_buf->priv;
hdev = hl_dmabuf->ctx->hdev;

- if (!attachment->peer2peer) {
- dev_dbg(hdev->dev, "Failed to map dmabuf because p2p is disabled\n");
- return ERR_PTR(-EPERM);
- }
-
exported_size = hl_dmabuf->dmabuf->size;
offset = hl_dmabuf->offset;
phys_pg_pack = hl_dmabuf->phys_pg_pack;
@@ -1753,8 +1731,10 @@ static struct sg_table *hl_map_dmabuf(struct dma_buf_attachment *attachment,
page_size = hl_dmabuf->dmabuf->size;
}

- sgt = alloc_sgt_from_device_pages(hdev, pages, npages, page_size, exported_size, offset,
- attachment->dev, dir);
+ sgt = alloc_sgt_from_device_pages(hdev, pages, npages, page_size,
+ exported_size, offset,
+ dma_buf_sgt_dma_device(attachment),
+ dir);
if (IS_ERR(sgt))
dev_err(hdev->dev, "failed (%ld) to initialize sgt for dmabuf\n", PTR_ERR(sgt));

@@ -1776,9 +1756,9 @@ static void hl_unmap_dmabuf(struct dma_buf_attachment *attachment,
* a sync of the memory to the CPU's cache, as it never resided inside that cache.
*/
for_each_sgtable_dma_sg(sgt, sg, i)
- dma_unmap_resource(attachment->dev, sg_dma_address(sg),
- sg_dma_len(sg), dir,
- DMA_ATTR_SKIP_CPU_SYNC);
+ dma_unmap_resource(dma_buf_sgt_dma_device(attachment),
+ sg_dma_address(sg), sg_dma_len(sg), dir,
+ DMA_ATTR_SKIP_CPU_SYNC);

/* Need to restore orig_nents because sg_free_table use that field */
sgt->orig_nents = sgt->nents;
@@ -1848,11 +1828,25 @@ static void hl_release_dmabuf(struct dma_buf *dmabuf)
kfree(hl_dmabuf);
}

-static const struct dma_buf_ops habanalabs_dmabuf_ops = {
- .attach = hl_dmabuf_attach,
+static const struct dma_buf_mapping_sgt_exp_ops hl_dma_buf_sgt_ops = {
.map_dma_buf = hl_map_dmabuf,
.unmap_dma_buf = hl_unmap_dmabuf,
+};
+
+static int hl_match_mapping(struct dma_buf_match_args *args)
+{
+ struct hl_dmabuf_priv *hl_dmabuf = args->dmabuf->priv;
+ struct dma_buf_mapping_match sgt_match[] = {
+ DMA_BUF_EMAPPING_SGT_P2P(&hl_dma_buf_sgt_ops,
+ hl_dmabuf->ctx->hdev->pdev),
+ };
+
+ return dma_buf_match_mapping(args, sgt_match, ARRAY_SIZE(sgt_match));
+}
+
+static const struct dma_buf_ops habanalabs_dmabuf_ops = {
.release = hl_release_dmabuf,
+ .match_mapping = hl_match_mapping,
};

static int export_dmabuf(struct hl_ctx *ctx,
--
2.43.0