Commit 3748bef7 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-xe-fixes-2025-04-18' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-fixes



Driver Changes:
- Fix LRC address being written too late for GuC
- Fix notifier vs folio deadlock
- Fix race betwen dma_buf unmap and vram eviction
- Fix debugfs handling PXP terminations unconditionally

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Lucas De Marchi <lucas.demarchi@intel.com>
Link: https://lore.kernel.org/r/ndinq644zenywaaycxyfqqivsb2xer4z7err3dlpalbz33jfkm@ttabzsg6wnet
parents 9bca5bcd 78600df8
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -145,10 +145,7 @@ static void xe_dma_buf_unmap(struct dma_buf_attachment *attach,
			     struct sg_table *sgt,
			     enum dma_data_direction dir)
{
	struct dma_buf *dma_buf = attach->dmabuf;
	struct xe_bo *bo = gem_to_xe_bo(dma_buf->priv);

	if (!xe_bo_is_vram(bo)) {
	if (sg_page(sgt->sgl)) {
		dma_unmap_sgtable(attach->dev, sgt, dir, 0);
		sg_free_table(sgt);
		kfree(sgt);
+45 −30
Original line number Diff line number Diff line
@@ -490,24 +490,52 @@ static void fill_engine_enable_masks(struct xe_gt *gt,
		       engine_enable_mask(gt, XE_ENGINE_CLASS_OTHER));
}

static void guc_prep_golden_lrc_null(struct xe_guc_ads *ads)
/*
 * Write the offsets corresponding to the golden LRCs. The actual data is
 * populated later by guc_golden_lrc_populate()
 */
static void guc_golden_lrc_init(struct xe_guc_ads *ads)
{
	struct xe_device *xe = ads_to_xe(ads);
	struct xe_gt *gt = ads_to_gt(ads);
	struct iosys_map info_map = IOSYS_MAP_INIT_OFFSET(ads_to_map(ads),
			offsetof(struct __guc_ads_blob, system_info));
	size_t alloc_size, real_size;
	u32 addr_ggtt, offset;
	int class;

	offset = guc_ads_golden_lrc_offset(ads);
	addr_ggtt = xe_bo_ggtt_addr(ads->bo) + offset;

	for (class = 0; class < XE_ENGINE_CLASS_MAX; ++class) {
		u8 guc_class;

	for (guc_class = 0; guc_class <= GUC_MAX_ENGINE_CLASSES; ++guc_class) {
		guc_class = xe_engine_class_to_guc_class(class);

		if (!info_map_read(xe, &info_map,
				   engine_enabled_masks[guc_class]))
			continue;

		real_size = xe_gt_lrc_size(gt, class);
		alloc_size = PAGE_ALIGN(real_size);

		/*
		 * This interface is slightly confusing. We need to pass the
		 * base address of the full golden context and the size of just
		 * the engine state, which is the section of the context image
		 * that starts after the execlists LRC registers. This is
		 * required to allow the GuC to restore just the engine state
		 * when a watchdog reset occurs.
		 * We calculate the engine state size by removing the size of
		 * what comes before it in the context image (which is identical
		 * on all engines).
		 */
		ads_blob_write(ads, ads.eng_state_size[guc_class],
			       guc_ads_golden_lrc_size(ads) -
			       xe_lrc_skip_size(xe));
			       real_size - xe_lrc_skip_size(xe));
		ads_blob_write(ads, ads.golden_context_lrca[guc_class],
			       xe_bo_ggtt_addr(ads->bo) +
			       guc_ads_golden_lrc_offset(ads));
			       addr_ggtt);

		addr_ggtt += alloc_size;
	}
}

@@ -857,7 +885,7 @@ void xe_guc_ads_populate_minimal(struct xe_guc_ads *ads)

	xe_map_memset(ads_to_xe(ads), ads_to_map(ads), 0, 0, ads->bo->size);
	guc_policies_init(ads);
	guc_prep_golden_lrc_null(ads);
	guc_golden_lrc_init(ads);
	guc_mapping_table_init_invalid(gt, &info_map);
	guc_doorbell_init(ads);

@@ -883,7 +911,7 @@ void xe_guc_ads_populate(struct xe_guc_ads *ads)
	guc_policies_init(ads);
	fill_engine_enable_masks(gt, &info_map);
	guc_mmio_reg_state_init(ads);
	guc_prep_golden_lrc_null(ads);
	guc_golden_lrc_init(ads);
	guc_mapping_table_init(gt, &info_map);
	guc_capture_prep_lists(ads);
	guc_doorbell_init(ads);
@@ -903,18 +931,22 @@ void xe_guc_ads_populate(struct xe_guc_ads *ads)
		       guc_ads_private_data_offset(ads));
}

static void guc_populate_golden_lrc(struct xe_guc_ads *ads)
/*
 * After the golden LRC's are recorded for each engine class by the first
 * submission, copy them to the ADS, as initialized earlier by
 * guc_golden_lrc_init().
 */
static void guc_golden_lrc_populate(struct xe_guc_ads *ads)
{
	struct xe_device *xe = ads_to_xe(ads);
	struct xe_gt *gt = ads_to_gt(ads);
	struct iosys_map info_map = IOSYS_MAP_INIT_OFFSET(ads_to_map(ads),
			offsetof(struct __guc_ads_blob, system_info));
	size_t total_size = 0, alloc_size, real_size;
	u32 addr_ggtt, offset;
	u32 offset;
	int class;

	offset = guc_ads_golden_lrc_offset(ads);
	addr_ggtt = xe_bo_ggtt_addr(ads->bo) + offset;

	for (class = 0; class < XE_ENGINE_CLASS_MAX; ++class) {
		u8 guc_class;
@@ -931,26 +963,9 @@ static void guc_populate_golden_lrc(struct xe_guc_ads *ads)
		alloc_size = PAGE_ALIGN(real_size);
		total_size += alloc_size;

		/*
		 * This interface is slightly confusing. We need to pass the
		 * base address of the full golden context and the size of just
		 * the engine state, which is the section of the context image
		 * that starts after the execlists LRC registers. This is
		 * required to allow the GuC to restore just the engine state
		 * when a watchdog reset occurs.
		 * We calculate the engine state size by removing the size of
		 * what comes before it in the context image (which is identical
		 * on all engines).
		 */
		ads_blob_write(ads, ads.eng_state_size[guc_class],
			       real_size - xe_lrc_skip_size(xe));
		ads_blob_write(ads, ads.golden_context_lrca[guc_class],
			       addr_ggtt);

		xe_map_memcpy_to(xe, ads_to_map(ads), offset,
				 gt->default_lrc[class], real_size);

		addr_ggtt += alloc_size;
		offset += alloc_size;
	}

@@ -959,7 +974,7 @@ static void guc_populate_golden_lrc(struct xe_guc_ads *ads)

void xe_guc_ads_populate_post_load(struct xe_guc_ads *ads)
{
	guc_populate_golden_lrc(ads);
	guc_golden_lrc_populate(ads);
}

static int guc_ads_action_update_policies(struct xe_guc_ads *ads, u32 policy_offset)
+0 −24
Original line number Diff line number Diff line
@@ -19,29 +19,6 @@ static u64 xe_npages_in_range(unsigned long start, unsigned long end)
	return (end - start) >> PAGE_SHIFT;
}

/**
 * xe_mark_range_accessed() - mark a range is accessed, so core mm
 * have such information for memory eviction or write back to
 * hard disk
 * @range: the range to mark
 * @write: if write to this range, we mark pages in this range
 * as dirty
 */
static void xe_mark_range_accessed(struct hmm_range *range, bool write)
{
	struct page *page;
	u64 i, npages;

	npages = xe_npages_in_range(range->start, range->end);
	for (i = 0; i < npages; i++) {
		page = hmm_pfn_to_page(range->hmm_pfns[i]);
		if (write)
			set_page_dirty_lock(page);

		mark_page_accessed(page);
	}
}

static int xe_alloc_sg(struct xe_device *xe, struct sg_table *st,
		       struct hmm_range *range, struct rw_semaphore *notifier_sem)
{
@@ -331,7 +308,6 @@ int xe_hmm_userptr_populate_range(struct xe_userptr_vma *uvma,
	if (ret)
		goto out_unlock;

	xe_mark_range_accessed(&hmm_range, write);
	userptr->sg = &userptr->sgt;
	xe_hmm_userptr_set_mapped(uvma);
	userptr->notifier_seq = hmm_range.notifier_seq;
+11 −2
Original line number Diff line number Diff line
@@ -66,9 +66,18 @@ static int pxp_terminate(struct seq_file *m, void *data)
{
	struct xe_pxp *pxp = node_to_pxp(m->private);
	struct drm_printer p = drm_seq_file_printer(m);
	int ready = xe_pxp_get_readiness_status(pxp);

	if (!xe_pxp_is_enabled(pxp))
		return -ENODEV;
	if (ready < 0)
		return ready; /* disabled or error occurred */
	else if (!ready)
		return -EBUSY; /* init still in progress */

	/* no need for a termination if PXP is not active */
	if (pxp->status != XE_PXP_ACTIVE) {
		drm_printf(&p, "PXP not active\n");
		return 0;
	}

	/* simulate a termination interrupt */
	spin_lock_irq(&pxp->xe->irq.lock);