From: Vivek Kasireddy <vivek.kasireddy@intel.com>
To: dri-devel@lists.freedesktop.org, intel-xe@lists.freedesktop.org,
linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org
Cc: "Vivek Kasireddy" <vivek.kasireddy@intel.com>,
"Matthew Brost" <matthew.brost@intel.com>,
"Thomas Hellström" <thomas.hellstrom@linux.intel.com>
Subject: [RFC 7/8] drm/xe/bo: Create new dma_addr array for dmabuf BOs associated with VFs
Date: Tue, 14 Oct 2025 00:08:57 -0700 [thread overview]
Message-ID: <20251014071243.811884-8-vivek.kasireddy@intel.com> (raw)
In-Reply-To: <20251014071243.811884-1-vivek.kasireddy@intel.com>
For BOs of type ttm_bo_type_sg, that are backed by PCI BAR addresses
associated with a VF, we need to adjust and translate these addresses
to LMEM addresses to make the BOs usable by the PF. Otherwise, the
BOs (i.e, PCI BAR addresses) are only accessible by the CPU and not
by the GPU.
In order to do the above, we first need to identify if the addresses
associated with an imported BO (type ttm_bo_type_sg) belong to System
RAM or a VF or other PCI devices. After we confirm that they belong to
a VF, we convert the BAR addresses to DPAs and create a new dma_addr
array (of type drm_pagemap_dma_addr) and populate it with the new
addresses along with the segment sizes.
Note that, all the above is only done if we are able to map the
dmabuf via the IOV interconnect. If not, we fallback to the legacy
mapping route using the sg table.
v2:
- Use dma_addr array instead of sg table to store translated addresses
(Matt)
v3:
- Remove the usage of iommu_iova_to_phys() as the imported BO would no
longer contain IOVAs and would instead have BAR addresses.
v4:
- Take a reference on the VF's backing object in LMEM (Michal)
- Create a new type for storing dma data
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
---
drivers/gpu/drm/xe/xe_bo.c | 148 +++++++++++++++++++++++--
drivers/gpu/drm/xe/xe_bo_types.h | 12 ++
drivers/gpu/drm/xe/xe_sriov_pf_types.h | 19 ++++
3 files changed, 167 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index 4410e28dee54..e05b7eace784 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -21,11 +21,13 @@
#include <trace/events/gpu_mem.h>
+#include "regs/xe_bars.h"
#include "xe_device.h"
#include "xe_dma_buf.h"
#include "xe_drm_client.h"
#include "xe_ggtt.h"
#include "xe_gt.h"
+#include "xe_gt_sriov_pf_config.h"
#include "xe_map.h"
#include "xe_migrate.h"
#include "xe_pm.h"
@@ -34,6 +36,7 @@
#include "xe_res_cursor.h"
#include "xe_shrinker.h"
#include "xe_sriov_vf_ccs.h"
+#include "xe_sriov_pf_helpers.h"
#include "xe_trace_bo.h"
#include "xe_ttm_stolen_mgr.h"
#include "xe_vm.h"
@@ -679,6 +682,99 @@ static int xe_bo_trigger_rebind(struct xe_device *xe, struct xe_bo *bo,
return ret;
}
+static struct pci_dev *xe_find_vf_dev(struct xe_device *xe,
+ phys_addr_t phys)
+{
+ struct pci_dev *pdev, *pf_pdev = to_pci_dev(xe->drm.dev);
+ resource_size_t io_start, io_size;
+
+ list_for_each_entry(pdev, &pf_pdev->bus->devices, bus_list) {
+ if (pdev->is_physfn)
+ continue;
+
+ io_start = pci_resource_start(pdev, LMEM_BAR);
+ io_size = pci_resource_len(pdev, LMEM_BAR);
+
+ if (phys >= io_start &&
+ phys < (io_start + io_size - PAGE_SIZE))
+ return pdev;
+ }
+
+ return NULL;
+}
+
+static void xe_bo_translate_io_xarray_to_dpa(struct xe_bo *bo,
+ struct xarray *ranges,
+ resource_size_t io_start,
+ int vfid)
+{
+ struct xe_device *xe = xe_bo_device(bo);
+ struct xe_gt *gt = xe_root_mmio_gt(xe);
+ struct xe_bo *lmem_obj;
+ struct range *range;
+ phys_addr_t phys;
+ unsigned long i;
+ dma_addr_t addr;
+ u64 offset;
+ void *entry;
+
+ lmem_obj = xe_gt_sriov_pf_config_get_lmem_obj(gt, ++vfid);
+ bo->dma_data.lmem_obj = xe_bo_get(lmem_obj);
+
+ xa_for_each(ranges, i, entry) {
+ range = entry;
+ phys = range->start;
+ offset = phys - io_start;
+ addr = xe_bo_addr(lmem_obj, offset, range_len(range));
+
+ bo->dma_data.dma_addr[i] = drm_pagemap_addr_encode(addr,
+ DRM_INTERCONNECT_DRIVER,
+ get_order(range_len(range)),
+ DMA_BIDIRECTIONAL);
+ }
+}
+
+
+static int xe_bo_xarray_to_dma_addr(struct dma_buf_ranges *ranges,
+ struct xe_bo *bo)
+{
+ struct xe_device *xe = xe_bo_device(bo);
+ struct drm_pagemap_addr *dma_addr;
+ resource_size_t io_start;
+ struct pci_dev *pdev;
+ struct range *range;
+ void *entry;
+ int vfid;
+
+ if (!IS_SRIOV_PF(xe))
+ return 0;
+
+ entry = xa_load(&ranges->ranges, 0);
+ range = entry;
+ if (page_is_ram(PFN_DOWN(range->start)))
+ return 0;
+
+ pdev = xe_find_vf_dev(xe, range->start);
+ if (!pdev)
+ return 0;
+
+ vfid = pci_iov_vf_id(pdev);
+ if (vfid < 0)
+ return 0;
+
+ dma_addr = kmalloc_array(ranges->nranges, sizeof(*dma_addr),
+ GFP_KERNEL);
+ if (!dma_addr)
+ return -ENOMEM;
+
+ bo->is_devmem_external = true;
+ bo->dma_data.dma_addr = dma_addr;
+ io_start = pci_resource_start(pdev, LMEM_BAR);
+ xe_bo_translate_io_xarray_to_dpa(bo, &ranges->ranges, io_start, vfid);
+
+ return 0;
+}
+
/*
* The dma-buf map_attachment() / unmap_attachment() is hooked up here.
* Note that unmapping the attachment is deferred to the next
@@ -696,7 +792,10 @@ static int xe_bo_move_dmabuf(struct ttm_buffer_object *ttm_bo,
ttm);
struct xe_device *xe = ttm_to_xe_device(ttm_bo->bdev);
bool device_unplugged = drm_dev_is_unplugged(&xe->drm);
- struct sg_table *sg;
+ struct dma_buf_ranges *ranges;
+ struct sg_table *sg = NULL;
+ bool allow_ic = false;
+ int ret = 0;
xe_assert(xe, attach);
xe_assert(xe, ttm_bo->ttm);
@@ -717,9 +816,27 @@ static int xe_bo_move_dmabuf(struct ttm_buffer_object *ttm_bo,
ttm_bo->sg = NULL;
}
- sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
- if (IS_ERR(sg))
- return PTR_ERR(sg);
+ if (attach->allow_ic &&
+ attach->interconnect.type == DMA_BUF_INTERCONNECT_IOV) {
+ allow_ic = true;
+
+ ranges = dma_buf_map_interconnect(attach);
+ if (IS_ERR(ranges)) {
+ allow_ic = false;
+ } else {
+ if (xe_bo_xarray_to_dma_addr(ranges,
+ ttm_to_xe_bo(ttm_bo))) {
+ dma_buf_unmap_interconnect(attach, ranges);
+ allow_ic = false;
+ }
+ }
+ attach->allow_ic = allow_ic;
+ }
+ if (!allow_ic) {
+ sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+ if (IS_ERR(sg))
+ return PTR_ERR(sg);
+ }
ttm_bo->sg = sg;
xe_tt->sg = sg;
@@ -727,7 +844,7 @@ static int xe_bo_move_dmabuf(struct ttm_buffer_object *ttm_bo,
out:
ttm_bo_move_null(ttm_bo, new_res);
- return 0;
+ return ret;
}
/**
@@ -1548,14 +1665,21 @@ static void xe_ttm_bo_delete_mem_notify(struct ttm_buffer_object *ttm_bo)
* Object is idle and about to be destroyed. Release the
* dma-buf attachment.
*/
- if (ttm_bo->type == ttm_bo_type_sg && ttm_bo->sg) {
- struct xe_ttm_tt *xe_tt = container_of(ttm_bo->ttm,
- struct xe_ttm_tt, ttm);
+ if (ttm_bo->type == ttm_bo_type_sg) {
+ if (ttm_bo->sg) {
+ struct xe_ttm_tt *xe_tt = container_of(ttm_bo->ttm,
+ struct xe_ttm_tt,
+ ttm);
- dma_buf_unmap_attachment(ttm_bo->base.import_attach, ttm_bo->sg,
- DMA_BIDIRECTIONAL);
- ttm_bo->sg = NULL;
- xe_tt->sg = NULL;
+ dma_buf_unmap_attachment(ttm_bo->base.import_attach,
+ ttm_bo->sg, DMA_BIDIRECTIONAL);
+ ttm_bo->sg = NULL;
+ xe_tt->sg = NULL;
+ }
+ if (bo->is_devmem_external) {
+ xe_bo_put(bo->dma_data.lmem_obj);
+ kfree(bo->dma_data.dma_addr);
+ }
}
}
diff --git a/drivers/gpu/drm/xe/xe_bo_types.h b/drivers/gpu/drm/xe/xe_bo_types.h
index d4fe3c8dca5b..8e416c4ffbca 100644
--- a/drivers/gpu/drm/xe/xe_bo_types.h
+++ b/drivers/gpu/drm/xe/xe_bo_types.h
@@ -108,6 +108,18 @@ struct xe_bo {
* from default
*/
u64 min_align;
+
+ /**
+ * @is_devmem_external: Whether this BO is an imported dma-buf that
+ * is LMEM based.
+ */
+ bool is_devmem_external;
+
+ /**
+ * @dma_data: DMA related data for an imported dmabuf BO that is LMEM
+ * based.
+ */
+ struct xe_sriov_dma_data dma_data;
};
#endif
diff --git a/drivers/gpu/drm/xe/xe_sriov_pf_types.h b/drivers/gpu/drm/xe/xe_sriov_pf_types.h
index 956a88f9f213..6d5f923f7fc4 100644
--- a/drivers/gpu/drm/xe/xe_sriov_pf_types.h
+++ b/drivers/gpu/drm/xe/xe_sriov_pf_types.h
@@ -11,6 +11,8 @@
#include "xe_sriov_pf_service_types.h"
+struct xe_bo;
+
/**
* struct xe_sriov_metadata - per-VF device level metadata
*/
@@ -42,4 +44,21 @@ struct xe_device_pf {
struct xe_sriov_metadata *vfs;
};
+/**
+ * struct xe_sriov_dma_data - DMA related data for LMEM based imported dmabuf
+ * BOs that are associated with a sriov VF.
+ *
+ * The data in this structure is valid only if driver is running in the
+ * @XE_SRIOV_MODE_PF mode.
+ */
+struct xe_sriov_dma_data {
+ /**
+ * @dma_addr: An array to store DMA addresses (DPAs) for imported
+ * dmabuf BOs that are LMEM based.
+ */
+ struct drm_pagemap_addr *dma_addr;
+
+ /** @lmem_obj: Ref taken on the LMEM obj that backs a VF's quota */
+ struct xe_bo *lmem_obj;
+};
#endif
--
2.50.1
next prev parent reply other threads:[~2025-10-14 7:14 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-14 7:08 [RFC 0/8] dma-buf: Add support for mapping dmabufs via interconnects Vivek Kasireddy
2025-10-14 7:08 ` [RFC 1/8] dma-buf: Add support for map/unmap APIs for interconnects Vivek Kasireddy
2025-10-20 9:34 ` Thomas Hellström
2025-10-21 5:45 ` Kasireddy, Vivek
2025-10-28 13:58 ` Christian König
2025-10-28 14:05 ` Jason Gunthorpe
2025-10-28 14:14 ` Christian König
2025-10-28 14:44 ` Jason Gunthorpe
2025-10-14 7:08 ` [RFC 2/8] dma-buf: Add a helper to match interconnects between exporter/importer Vivek Kasireddy
2025-10-17 15:58 ` Kasireddy, Vivek
2025-10-14 7:08 ` [RFC 3/8] dma-buf: Add support for IOV interconnect Vivek Kasireddy
2025-10-14 7:08 ` [RFC 4/8] vfio/pci/dmabuf: " Vivek Kasireddy
2025-10-14 7:08 ` [RFC 5/8] drm/xe/dma_buf: " Vivek Kasireddy
2025-10-14 7:08 ` [RFC 6/8] drm/xe/pf: Add a helper function to get a VF's backing object in LMEM Vivek Kasireddy
2025-10-14 7:08 ` Vivek Kasireddy [this message]
2025-10-14 7:08 ` [RFC 8/8] drm/xe/pt: Add an additional check for dmabuf BOs while doing bind Vivek Kasireddy
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=20251014071243.811884-8-vivek.kasireddy@intel.com \
--to=vivek.kasireddy@intel.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=intel-xe@lists.freedesktop.org \
--cc=linaro-mm-sig@lists.linaro.org \
--cc=linux-media@vger.kernel.org \
--cc=matthew.brost@intel.com \
--cc=thomas.hellstrom@linux.intel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox