Download raw body.
[PATCH 0/4] i915 dg2 patches
On Thu, Sep 10, 2026 at 10:13:48PM +0300, kisekinopureya wrote:
> This patch series adds necessary changes to i915 for Intel Arc (DG2).
> I've been using it for a week on -current and haven't observed any
> panic/crashes yet. I don't have an integrated gpu, i can't confirm
> whether the changes broke integrated gpus.
>
> This is my first patch to the mailing list, please let me know
> if I need to adjust anything.
>
> dmesg
> ...
> inteldrm0: msi, DG2, gen 12
> inteldrm0: 1920x1080, 32bpp
> wsdisplay0 at inteldrm0 mux 1: console (std, vt100 emulation), using wskbd0
> inteldrm0 at pci3 dev 0 function 0 "Intel Arc A770" rev 0x08
> drm0 at inteldrm0
> ...
>
> glxinfo -B
> ...
> direct rendering: Yes
> Extended renderer info (GLX_MESA_query_renderer):
> Vendor: Intel (0x8086)
> Device: Mesa Intel(R) Arc(tm) A770 Graphics (DG2) (0x56a0)
> Version: 25.0.7
> Accelerated: yes
> ...
>
>
> kisekinopureya (4):
> remove force_probe for dg2
> unstub intel_slicemask_from_xehp_dssmask
> disable huc for dg2
> port gem and ttm memory management to uvm
Disabling HuC to avoid MEI is interesting.
For comparison, here is a diff from one of my dg2 branches from a few
months ago. I don't remember the state, I suspect there were problems
initialising GuC or with MEI.
Needs dma_tag_lookup() change I committed earlier today.
diff --git sys/dev/pci/drm/drm_linux.c sys/dev/pci/drm/drm_linux.c
index 53a6efd90e2..3405463a620 100644
--- sys/dev/pci/drm/drm_linux.c
+++ sys/dev/pci/drm/drm_linux.c
@@ -3487,6 +3487,37 @@ dma_unmap_resource(struct device *dev, dma_addr_t addr, size_t size,
STUB();
}
+int
+dma_map_sgtable(struct device *dev, struct sg_table *sgt,
+ enum dma_data_direction dir, unsigned long attrs)
+{
+ bus_dma_tag_t dmat = dma_tag_lookup(dev);
+ bus_dma_segment_t seg;
+ int error, i;
+ struct scatterlist *sg;
+
+ error = bus_dmamap_create(dmat, sgt->sgl->length, sgt->nents,
+ sgt->sgl->length, 0, BUS_DMA_WAITOK, &sgt->dmamap);
+ if (error)
+ return -ENOMEM;
+
+ sgt->dmamap->dm_mapsize = 0;
+ sgt->dmamap->dm_nsegs = 0;
+ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+ sgt->dmamap->dm_segs[i].ds_addr = VM_PAGE_TO_PHYS(sg->__page);
+ sgt->dmamap->dm_segs[i].ds_len = sgt->sgl->length;
+ sgt->dmamap->dm_nsegs++;
+ sgt->dmamap->dm_mapsize += sgt->sgl->length;
+ }
+ sgt->dmamap->dm_nsegs = sgt->nents;
+ error = bus_dmamap_load_raw(dmat, sgt->dmamap, sgt->dmamap->dm_segs,
+ sgt->dmamap->dm_nsegs, sgt->dmamap->dm_mapsize, BUS_DMA_WAITOK);
+ if (error)
+ return -ENOMEM;
+
+ return 0;
+}
+
#ifdef BUS_DMA_FIXED
#include <linux/iommu.h>
diff --git sys/dev/pci/drm/i915/gem/i915_gem_object.h sys/dev/pci/drm/i915/gem/i915_gem_object.h
index b266814d3fb..0fb18d0aa43 100644
--- sys/dev/pci/drm/i915/gem/i915_gem_object.h
+++ sys/dev/pci/drm/i915/gem/i915_gem_object.h
@@ -855,10 +855,10 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st,
size_t size, struct intel_memory_region *mr,
struct address_space *mapping,
unsigned int max_segment,
- struct drm_i915_gem_object *obj);
+ struct uvm_object *);
void shmem_sg_free_table(struct sg_table *st, struct address_space *mapping,
bool dirty, bool backup,
- struct drm_i915_gem_object *obj);
+ struct uvm_object *, size_t);
#endif
void __shmem_writeback(size_t size, struct address_space *mapping);
diff --git sys/dev/pci/drm/i915/gem/i915_gem_shmem.c sys/dev/pci/drm/i915/gem/i915_gem_shmem.c
index ee8034c9c63..970b47f8fd6 100644
--- sys/dev/pci/drm/i915/gem/i915_gem_shmem.c
+++ sys/dev/pci/drm/i915/gem/i915_gem_shmem.c
@@ -34,7 +34,7 @@ static void check_release_folio_batch(struct folio_batch *fbatch)
void shmem_sg_free_table(struct sg_table *st, struct address_space *mapping,
bool dirty, bool backup,
- struct drm_i915_gem_object *obj)
+ struct uvm_object *uao, size_t uao_size)
{
struct sgt_iter sgt_iter;
struct folio_batch fbatch;
@@ -69,7 +69,7 @@ void shmem_sg_free_table(struct sg_table *st, struct address_space *mapping,
if (fbatch.nr)
check_release_folio_batch(&fbatch);
#else
- uvm_obj_unwire(obj->base.uao, 0, obj->base.size);
+ uvm_obj_unwire(uao, 0, uao_size);
#endif
sg_free_table(st);
@@ -79,7 +79,7 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st,
size_t size, struct intel_memory_region *mr,
struct address_space *mapping,
unsigned int max_segment,
- struct drm_i915_gem_object *obj)
+ struct uvm_object *uao)
{
unsigned int page_count; /* restricted by sg_alloc_table */
unsigned long i;
@@ -201,7 +201,7 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st,
st->nents = 0;
TAILQ_INIT(&plist);
- if (uvm_obj_wire(obj->base.uao, 0, obj->base.size, &plist)) {
+ if (uvm_obj_wire(uao, 0, size, &plist)) {
ret = -ENOMEM;
goto err_sg;
}
@@ -225,7 +225,7 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st,
err_sg:
sg_mark_end(sg);
if (sg != st->sgl) {
- shmem_sg_free_table(st, mapping, false, false, obj);
+ shmem_sg_free_table(st, mapping, false, false, uao, size);
} else {
mapping_clear_unevictable(mapping);
sg_free_table(st);
@@ -275,7 +275,7 @@ rebuild_st:
max_segment);
#else
ret = shmem_sg_alloc_table(i915, st, obj->base.size, mem, NULL,
- max_segment, obj);
+ max_segment, obj->base.uao);
#endif
if (ret)
goto err_st;
@@ -291,7 +291,7 @@ rebuild_st:
#ifdef __linux__
shmem_sg_free_table(st, mapping, false, false);
#else
- shmem_sg_free_table(st, NULL, false, false, obj);
+ shmem_sg_free_table(st, NULL, false, false, obj->base.uao, obj->base.size);
#endif
sg_free_table(st);
kfree(st);
@@ -320,7 +320,7 @@ err_pages:
#ifdef __linux__
shmem_sg_free_table(st, mapping, false, false);
#else
- shmem_sg_free_table(st, NULL, false, false, obj);
+ shmem_sg_free_table(st, NULL, false, false, obj->base.uao, obj->base.size);
#endif
/*
* shmemfs first checks if there is enough memory to allocate the page
@@ -459,7 +459,8 @@ void i915_gem_object_put_pages_shmem(struct drm_i915_gem_object *obj, struct sg_
obj->mm.dirty, obj->mm.madv == I915_MADV_WILLNEED);
#else
shmem_sg_free_table(pages, NULL,
- obj->mm.dirty, obj->mm.madv == I915_MADV_WILLNEED, obj);
+ obj->mm.dirty, obj->mm.madv == I915_MADV_WILLNEED,
+ obj->base.uao, obj->base.size);
#endif
kfree(pages);
obj->mm.dirty = false;
diff --git sys/dev/pci/drm/i915/gem/i915_gem_ttm.c sys/dev/pci/drm/i915/gem/i915_gem_ttm.c
index 570d0971fd4..00c4b9768b4 100644
--- sys/dev/pci/drm/i915/gem/i915_gem_ttm.c
+++ sys/dev/pci/drm/i915/gem/i915_gem_ttm.c
@@ -53,7 +53,11 @@ struct i915_ttm_tt {
struct i915_refct_sgt cached_rsgt;
bool is_shmem;
+#ifdef __linux__
struct file *filp;
+#else
+ struct uvm_object *filp;
+#endif
};
static const struct ttm_place sys_placement_flags = {
@@ -179,13 +183,11 @@ i915_ttm_placement_from_obj(const struct drm_i915_gem_object *obj,
placement->placement = places;
}
+#ifdef __linux__
static int i915_ttm_tt_shmem_populate(struct ttm_device *bdev,
struct ttm_tt *ttm,
struct ttm_operation_ctx *ctx)
{
- STUB();
- return -ENOSYS;
-#ifdef notyet
struct drm_i915_private *i915 = container_of(bdev, typeof(*i915), bdev);
struct intel_memory_region *mr = i915->mm.regions[INTEL_MEMORY_SYSTEM];
struct i915_ttm_tt *i915_tt = container_of(ttm, typeof(*i915_tt), ttm);
@@ -239,8 +241,58 @@ err_free_st:
shmem_sg_free_table(st, filp->f_mapping, false, false);
return err;
-#endif
}
+#else /* !__linux__ */
+static int i915_ttm_tt_shmem_populate(struct ttm_device *bdev,
+ struct ttm_tt *ttm,
+ struct ttm_operation_ctx *ctx)
+{
+ struct drm_i915_private *i915 = container_of(bdev, typeof(*i915), bdev);
+ struct intel_memory_region *mr = i915->mm.regions[INTEL_MEMORY_SYSTEM];
+ struct i915_ttm_tt *i915_tt = container_of(ttm, typeof(*i915_tt), ttm);
+ const unsigned int max_segment = i915_sg_segment_size(i915->drm.dev);
+ const size_t size = (size_t)ttm->num_pages << PAGE_SHIFT;
+ struct uvm_object *uao = i915_tt->filp;
+ struct sgt_iter sgt_iter;
+ struct sg_table *st;
+ struct vm_page *page;
+ unsigned long i;
+ int err;
+
+ if (!uao) {
+ uao = uao_create(size, 0);
+ if (uao == NULL)
+ return -ENOMEM;
+
+ i915_tt->filp = uao;
+ }
+
+ st = &i915_tt->cached_rsgt.table;
+ err = shmem_sg_alloc_table(i915, st, size, mr, /*filp->f_mapping*/NULL,
+ max_segment, uao);
+ if (err)
+ return err;
+
+ err = dma_map_sgtable(i915_tt->dev, st, DMA_BIDIRECTIONAL,
+ DMA_ATTR_SKIP_CPU_SYNC);
+ if (err)
+ goto err_free_st;
+
+ i = 0;
+ for_each_sgt_page(page, sgt_iter, st)
+ ttm->pages[i++] = page;
+
+ if (ttm->page_flags & TTM_TT_FLAG_SWAPPED)
+ ttm->page_flags &= ~TTM_TT_FLAG_SWAPPED;
+
+ return 0;
+
+err_free_st:
+ shmem_sg_free_table(st, NULL, false, false, uao, size);
+
+ return err;
+}
+#endif /* !__linux__ */
static void i915_ttm_tt_shmem_unpopulate(struct ttm_tt *ttm)
{
@@ -356,7 +408,11 @@ static void i915_ttm_tt_destroy(struct ttm_device *bdev, struct ttm_tt *ttm)
struct i915_ttm_tt *i915_tt = container_of(ttm, typeof(*i915_tt), ttm);
if (i915_tt->filp)
+#ifdef __linux__
fput(i915_tt->filp);
+#else
+ uao_detach(i915_tt->filp);
+#endif
ttm_tt_fini(ttm);
i915_refct_sgt_put(&i915_tt->cached_rsgt);
@@ -456,13 +512,14 @@ int i915_ttm_purge(struct drm_i915_gem_object *obj)
#ifdef __linux__
shmem_truncate_range(file_inode(i915_tt->filp),
0, (loff_t)-1);
+ fput(fetch_and_zero(&i915_tt->filp));
#else
rw_enter(obj->base.uao->vmobjlock, RW_WRITE);
obj->base.uao->pgops->pgo_flush(obj->base.uao, 0,
obj->base.size, PGO_ALLPAGES | PGO_FREE);
rw_exit(obj->base.uao->vmobjlock);
+ uao_detach(fetch_and_zero(&i915_tt->filp));
#endif
- fput(fetch_and_zero(&i915_tt->filp));
}
}
diff --git sys/dev/pci/drm/i915/gt/uc/intel_guc_fw.c sys/dev/pci/drm/i915/gt/uc/intel_guc_fw.c
index b1bda1b84f0..7847c374690 100644
--- sys/dev/pci/drm/i915/gt/uc/intel_guc_fw.c
+++ sys/dev/pci/drm/i915/gt/uc/intel_guc_fw.c
@@ -158,7 +158,7 @@ static inline bool guc_load_done(struct intel_uncore *uncore, u32 *status, bool
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
#define GUC_LOAD_RETRY_LIMIT 20
#else
-#define GUC_LOAD_RETRY_LIMIT 3
+#define GUC_LOAD_RETRY_LIMIT 20
#endif
static int guc_wait_ucode(struct intel_guc *guc)
diff --git sys/dev/pci/drm/i915/i915_pci.c sys/dev/pci/drm/i915/i915_pci.c
index 2f30756ac4a..ce56d2ea89f 100644
--- sys/dev/pci/drm/i915/i915_pci.c
+++ sys/dev/pci/drm/i915/i915_pci.c
@@ -738,7 +738,6 @@ static const struct intel_device_info adl_p_info = {
static const struct intel_device_info dg2_info = {
DG2_FEATURES,
- .require_force_probe = 1,
};
static const struct intel_device_info ats_m_info = {
[PATCH 0/4] i915 dg2 patches