drm/xe: Cleanup unwind of gt initialization
authorLucas De Marchi <lucas.demarchi@intel.com>
Thu, 13 Feb 2025 19:29:03 +0000 (11:29 -0800)
committerLucas De Marchi <lucas.demarchi@intel.com>
Fri, 14 Feb 2025 19:42:55 +0000 (11:42 -0800)
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: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Reviewed-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250213192909.996148-7-lucas.demarchi@intel.com
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
drivers/gpu/drm/xe/xe_device.c
drivers/gpu/drm/xe/xe_gsc.c
drivers/gpu/drm/xe/xe_gsc.h
drivers/gpu/drm/xe/xe_gsc_proxy.c
drivers/gpu/drm/xe/xe_gsc_proxy.h
drivers/gpu/drm/xe/xe_gsc_types.h
drivers/gpu/drm/xe/xe_gt.c
drivers/gpu/drm/xe/xe_gt.h
drivers/gpu/drm/xe/xe_uc.c
drivers/gpu/drm/xe/xe_uc.h

index 8203c80faca5d8451e25cecabf7cc8c4cb41ffeb..398fad6c53658a5b35d111092459b091c120cb9c 100644 (file)
@@ -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 @@ err_fini_display:
 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);
 }
 
index 1eb791ddc375c7b5af482932dadf84692f9bdbe6..fd41113f857251b63161d332a8dbae449fc8aa43 100644 (file)
@@ -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
index e282b9ef6ec4d5b4956bb5ffdb0ccb1d328b0d19..d99f66c38075c46435fb890e23df81996596dd69 100644 (file)
@@ -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);
index 24cc6a4f9a96a2941f7cc7d6e9d2600a85b0914e..31c90577faf0b0dbc790f849641ab7d6de5b05f9 100644 (file)
@@ -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);
 }
 
 /**
index c511ade6b8637839756aeb2e61bfaf85b95c0217..fdef56995cd43ebbb919572429e3428619f508b5 100644 (file)
@@ -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);
index 5926de20214c8a9053e4bc430cb3d52ccb785cbe..97c056656df05b573e8ab94180e70cbb474c079f 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/workqueue.h>
 
 #include "xe_uc_fw_types.h"
+#include "xe_device_types.h"
 
 struct xe_bo;
 struct xe_exec_queue;
index 9fb8f1e678dc81d949405d0f97c696bcf1d2e604..c33040278e1aa6327e04dbeb09dc2287d542cf5a 100644 (file)
@@ -141,26 +141,6 @@ static void xe_gt_disable_host_l2_vram(struct xe_gt *gt)
        xe_force_wake_put(gt_to_fw(gt), fw_ref);
 }
 
-/**
- * xe_gt_remove() - Clean up the GT structures before driver removal
- * @gt: the GT object
- *
- * This function should only act on objects/structures that must be cleaned
- * before the driver removal callback is complete and therefore can't be
- * deferred to a drmm action.
- */
-void xe_gt_remove(struct xe_gt *gt)
-{
-       int i;
-
-       xe_uc_remove(&gt->uc);
-
-       for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i)
-               xe_hw_fence_irq_finish(&gt->fence_irq[i]);
-
-       xe_gt_disable_host_l2_vram(gt);
-}
-
 static void gt_reset_worker(struct work_struct *w);
 
 static int emit_nop_job(struct xe_gt *gt, struct xe_exec_queue *q)
@@ -583,6 +563,17 @@ out_fw:
        return err;
 }
 
+static void xe_gt_fini(void *arg)
+{
+       struct xe_gt *gt = arg;
+       int i;
+
+       for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i)
+               xe_hw_fence_irq_finish(&gt->fence_irq[i]);
+
+       xe_gt_disable_host_l2_vram(gt);
+}
+
 int xe_gt_init(struct xe_gt *gt)
 {
        int err;
@@ -595,6 +586,10 @@ int xe_gt_init(struct xe_gt *gt)
                xe_hw_fence_irq_init(&gt->fence_irq[i]);
        }
 
+       err = devm_add_action_or_reset(gt_to_xe(gt)->drm.dev, xe_gt_fini, gt);
+       if (err)
+               return err;
+
        err = xe_gt_pagefault_init(gt);
        if (err)
                return err;
index e504cc33ade4fbd2c530bde4484cfb5e00297915..187fa6490eafcd824eecf4b3160d6e02f89c5be0 100644 (file)
@@ -54,7 +54,6 @@ int xe_gt_resume(struct xe_gt *gt);
 void xe_gt_reset_async(struct xe_gt *gt);
 void xe_gt_sanitize(struct xe_gt *gt);
 int xe_gt_sanitize_freq(struct xe_gt *gt);
-void xe_gt_remove(struct xe_gt *gt);
 
 /**
  * xe_gt_wait_for_reset - wait for gt's async reset to finalize.
index 0d073a9987c2e8732e120049832ddba3b80caf9a..d8167e818280b3eff52ecdb872faa625a6fe895f 100644 (file)
@@ -288,19 +288,6 @@ int xe_uc_suspend(struct xe_uc *uc)
        return xe_guc_suspend(&uc->guc);
 }
 
-/**
- * xe_uc_remove() - Clean up the UC structures before driver removal
- * @uc: the UC object
- *
- * This function should only act on objects/structures that must be cleaned
- * before the driver removal callback is complete and therefore can't be
- * deferred to a drmm action.
- */
-void xe_uc_remove(struct xe_uc *uc)
-{
-       xe_gsc_remove(&uc->gsc);
-}
-
 /**
  * xe_uc_declare_wedged() - Declare UC wedged
  * @uc: the UC object
index 506517c1133397f746d53284e3f45a72fd4935a8..3813c1ede450ee321e76c26f8d7677094a75ada9 100644 (file)
@@ -20,7 +20,6 @@ void xe_uc_stop(struct xe_uc *uc);
 int xe_uc_start(struct xe_uc *uc);
 int xe_uc_suspend(struct xe_uc *uc);
 int xe_uc_sanitize_reset(struct xe_uc *uc);
-void xe_uc_remove(struct xe_uc *uc);
 void xe_uc_declare_wedged(struct xe_uc *uc);
 
 #endif