Commit ff6cd29b authored by Lucas De Marchi's avatar Lucas De Marchi
Browse files

drm/xe: Cleanup unwind of gt initialization



The only thing in xe_gt_remove() that really needs to happen on the
device remove callback is the xe_uc_remove(). That's because of the
following call chain:

	xe_gt_remove()
	  xe_uc_remove()
	    xe_gsc_remove()
	      xe_gsc_proxy_remove()

Move xe_gsc_proxy_remove() to be handled as a xe_device_remove_action,
so it's recorded when it should run during device removal. The rest can
be handled normally by devm infra.

Besides removing the deep call chain above, xe_device_probe() doesn't
have to unwind the gt loop and it's also more in line with the
xe_device_probe() style.

Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: default avatarDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Reviewed-by: default avatarHimal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250213192909.996148-7-lucas.demarchi@intel.com


Signed-off-by: default avatarLucas De Marchi <lucas.demarchi@intel.com>
parent c0aeb90b
Loading
Loading
Loading
Loading
+2 −19
Original line number Diff line number Diff line
@@ -750,7 +750,6 @@ int xe_device_probe(struct xe_device *xe)
	struct xe_tile *tile;
	struct xe_gt *gt;
	int err;
	u8 last_gt;
	u8 id;

	xe->probing = true;
@@ -861,18 +860,16 @@ int xe_device_probe(struct xe_device *xe)
		return err;

	for_each_gt(gt, xe, id) {
		last_gt = id;

		err = xe_gt_init(gt);
		if (err)
			goto err_fini_gt;
			return err;
	}

	xe_heci_gsc_init(xe);

	err = xe_oa_init(xe);
	if (err)
		goto err_fini_gt;
		return err;

	err = xe_display_init(xe);
	if (err)
@@ -911,14 +908,6 @@ int xe_device_probe(struct xe_device *xe)
err_fini_oa:
	xe_oa_fini(xe);

err_fini_gt:
	for_each_gt(gt, xe, id) {
		if (id < last_gt)
			xe_gt_remove(gt);
		else
			break;
	}

	return err;
}

@@ -987,9 +976,6 @@ static void xe_device_remove_display(struct xe_device *xe)

void xe_device_remove(struct xe_device *xe)
{
	struct xe_gt *gt;
	u8 id;

	xe_oa_unregister(xe);

	xe_device_remove_display(xe);
@@ -998,9 +984,6 @@ void xe_device_remove(struct xe_device *xe)

	xe_heci_gsc_fini(xe);

	for_each_gt(gt, xe, id)
		xe_gt_remove(gt);

	xe_device_call_remove_actions(xe);
}

+0 −9
Original line number Diff line number Diff line
@@ -555,15 +555,6 @@ void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc)
		flush_work(&gsc->work);
}

/**
 * xe_gsc_remove() - Clean up the GSC structures before driver removal
 * @gsc: the GSC uC
 */
void xe_gsc_remove(struct xe_gsc *gsc)
{
	xe_gsc_proxy_remove(gsc);
}

/*
 * wa_14015076503: if the GSC FW is loaded, we need to alert it before doing a
 * GSC engine reset by writing a notification bit in the GS1 register and then
+0 −1
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@ int xe_gsc_init(struct xe_gsc *gsc);
int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc);
void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc);
void xe_gsc_load_start(struct xe_gsc *gsc);
void xe_gsc_remove(struct xe_gsc *gsc);
void xe_gsc_hwe_irq_handler(struct xe_hw_engine *hwe, u16 intr_vec);

void xe_gsc_wa_14015076503(struct xe_gt *gt, bool prep);
+29 −34
Original line number Diff line number Diff line
@@ -423,6 +423,34 @@ static int proxy_channel_alloc(struct xe_gsc *gsc)
	return 0;
}

static void xe_gsc_proxy_remove(void *arg)
{
	struct xe_gsc *gsc = arg;
	struct xe_gt *gt = gsc_to_gt(gsc);
	struct xe_device *xe = gt_to_xe(gt);
	unsigned int fw_ref = 0;

	if (!gsc->proxy.component_added)
		return;

	/* disable HECI2 IRQs */
	xe_pm_runtime_get(xe);
	fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC);
	if (!fw_ref)
		xe_gt_err(gt, "failed to get forcewake to disable GSC interrupts\n");

	/* try do disable irq even if forcewake failed */
	gsc_proxy_irq_toggle(gsc, false);

	xe_force_wake_put(gt_to_fw(gt), fw_ref);
	xe_pm_runtime_put(xe);

	xe_gsc_wait_for_worker_completion(gsc);

	component_del(xe->drm.dev, &xe_gsc_proxy_component_ops);
	gsc->proxy.component_added = false;
}

/**
 * xe_gsc_proxy_init() - init objects and MEI component required by GSC proxy
 * @gsc: the GSC uC
@@ -462,40 +490,7 @@ int xe_gsc_proxy_init(struct xe_gsc *gsc)

	gsc->proxy.component_added = true;

	/* the component must be removed before unload, so can't use drmm for cleanup */

	return 0;
}

/**
 * xe_gsc_proxy_remove() - remove the GSC proxy MEI component
 * @gsc: the GSC uC
 */
void xe_gsc_proxy_remove(struct xe_gsc *gsc)
{
	struct xe_gt *gt = gsc_to_gt(gsc);
	struct xe_device *xe = gt_to_xe(gt);
	unsigned int fw_ref = 0;

	if (!gsc->proxy.component_added)
		return;

	/* disable HECI2 IRQs */
	xe_pm_runtime_get(xe);
	fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC);
	if (!fw_ref)
		xe_gt_err(gt, "failed to get forcewake to disable GSC interrupts\n");

	/* try do disable irq even if forcewake failed */
	gsc_proxy_irq_toggle(gsc, false);

	xe_force_wake_put(gt_to_fw(gt), fw_ref);
	xe_pm_runtime_put(xe);

	xe_gsc_wait_for_worker_completion(gsc);

	component_del(xe->drm.dev, &xe_gsc_proxy_component_ops);
	gsc->proxy.component_added = false;
	return xe_device_add_action_or_reset(xe, xe_gsc_proxy_remove, gsc);
}

/**
+0 −1
Original line number Diff line number Diff line
@@ -12,7 +12,6 @@ struct xe_gsc;

int xe_gsc_proxy_init(struct xe_gsc *gsc);
bool xe_gsc_proxy_init_done(struct xe_gsc *gsc);
void xe_gsc_proxy_remove(struct xe_gsc *gsc);
int xe_gsc_proxy_start(struct xe_gsc *gsc);

int xe_gsc_proxy_request_handler(struct xe_gsc *gsc);
Loading