Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: 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>

+47 -99
+2 -19
drivers/gpu/drm/xe/xe_device.c
··· 750 750 struct xe_tile *tile; 751 751 struct xe_gt *gt; 752 752 int err; 753 - u8 last_gt; 754 753 u8 id; 755 754 756 755 xe->probing = true; ··· 860 861 return err; 861 862 862 863 for_each_gt(gt, xe, id) { 863 - last_gt = id; 864 - 865 864 err = xe_gt_init(gt); 866 865 if (err) 867 - goto err_fini_gt; 866 + return err; 868 867 } 869 868 870 869 xe_heci_gsc_init(xe); 871 870 872 871 err = xe_oa_init(xe); 873 872 if (err) 874 - goto err_fini_gt; 873 + return err; 875 874 876 875 err = xe_display_init(xe); 877 876 if (err) ··· 907 910 908 911 err_fini_oa: 909 912 xe_oa_fini(xe); 910 - 911 - err_fini_gt: 912 - for_each_gt(gt, xe, id) { 913 - if (id < last_gt) 914 - xe_gt_remove(gt); 915 - else 916 - break; 917 - } 918 913 919 914 return err; 920 915 } ··· 976 987 977 988 void xe_device_remove(struct xe_device *xe) 978 989 { 979 - struct xe_gt *gt; 980 - u8 id; 981 - 982 990 xe_oa_unregister(xe); 983 991 984 992 xe_device_remove_display(xe); ··· 983 997 xe_oa_fini(xe); 984 998 985 999 xe_heci_gsc_fini(xe); 986 - 987 - for_each_gt(gt, xe, id) 988 - xe_gt_remove(gt); 989 1000 990 1001 xe_device_call_remove_actions(xe); 991 1002 }
-9
drivers/gpu/drm/xe/xe_gsc.c
··· 555 555 flush_work(&gsc->work); 556 556 } 557 557 558 - /** 559 - * xe_gsc_remove() - Clean up the GSC structures before driver removal 560 - * @gsc: the GSC uC 561 - */ 562 - void xe_gsc_remove(struct xe_gsc *gsc) 563 - { 564 - xe_gsc_proxy_remove(gsc); 565 - } 566 - 567 558 /* 568 559 * wa_14015076503: if the GSC FW is loaded, we need to alert it before doing a 569 560 * GSC engine reset by writing a notification bit in the GS1 register and then
-1
drivers/gpu/drm/xe/xe_gsc.h
··· 17 17 int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc); 18 18 void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc); 19 19 void xe_gsc_load_start(struct xe_gsc *gsc); 20 - void xe_gsc_remove(struct xe_gsc *gsc); 21 20 void xe_gsc_hwe_irq_handler(struct xe_hw_engine *hwe, u16 intr_vec); 22 21 23 22 void xe_gsc_wa_14015076503(struct xe_gt *gt, bool prep);
+29 -34
drivers/gpu/drm/xe/xe_gsc_proxy.c
··· 423 423 return 0; 424 424 } 425 425 426 + static void xe_gsc_proxy_remove(void *arg) 427 + { 428 + struct xe_gsc *gsc = arg; 429 + struct xe_gt *gt = gsc_to_gt(gsc); 430 + struct xe_device *xe = gt_to_xe(gt); 431 + unsigned int fw_ref = 0; 432 + 433 + if (!gsc->proxy.component_added) 434 + return; 435 + 436 + /* disable HECI2 IRQs */ 437 + xe_pm_runtime_get(xe); 438 + fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC); 439 + if (!fw_ref) 440 + xe_gt_err(gt, "failed to get forcewake to disable GSC interrupts\n"); 441 + 442 + /* try do disable irq even if forcewake failed */ 443 + gsc_proxy_irq_toggle(gsc, false); 444 + 445 + xe_force_wake_put(gt_to_fw(gt), fw_ref); 446 + xe_pm_runtime_put(xe); 447 + 448 + xe_gsc_wait_for_worker_completion(gsc); 449 + 450 + component_del(xe->drm.dev, &xe_gsc_proxy_component_ops); 451 + gsc->proxy.component_added = false; 452 + } 453 + 426 454 /** 427 455 * xe_gsc_proxy_init() - init objects and MEI component required by GSC proxy 428 456 * @gsc: the GSC uC ··· 490 462 491 463 gsc->proxy.component_added = true; 492 464 493 - /* the component must be removed before unload, so can't use drmm for cleanup */ 494 - 495 - return 0; 496 - } 497 - 498 - /** 499 - * xe_gsc_proxy_remove() - remove the GSC proxy MEI component 500 - * @gsc: the GSC uC 501 - */ 502 - void xe_gsc_proxy_remove(struct xe_gsc *gsc) 503 - { 504 - struct xe_gt *gt = gsc_to_gt(gsc); 505 - struct xe_device *xe = gt_to_xe(gt); 506 - unsigned int fw_ref = 0; 507 - 508 - if (!gsc->proxy.component_added) 509 - return; 510 - 511 - /* disable HECI2 IRQs */ 512 - xe_pm_runtime_get(xe); 513 - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC); 514 - if (!fw_ref) 515 - xe_gt_err(gt, "failed to get forcewake to disable GSC interrupts\n"); 516 - 517 - /* try do disable irq even if forcewake failed */ 518 - gsc_proxy_irq_toggle(gsc, false); 519 - 520 - xe_force_wake_put(gt_to_fw(gt), fw_ref); 521 - xe_pm_runtime_put(xe); 522 - 523 - xe_gsc_wait_for_worker_completion(gsc); 524 - 525 - component_del(xe->drm.dev, &xe_gsc_proxy_component_ops); 526 - gsc->proxy.component_added = false; 465 + return xe_device_add_action_or_reset(xe, xe_gsc_proxy_remove, gsc); 527 466 } 528 467 529 468 /**
-1
drivers/gpu/drm/xe/xe_gsc_proxy.h
··· 12 12 13 13 int xe_gsc_proxy_init(struct xe_gsc *gsc); 14 14 bool xe_gsc_proxy_init_done(struct xe_gsc *gsc); 15 - void xe_gsc_proxy_remove(struct xe_gsc *gsc); 16 15 int xe_gsc_proxy_start(struct xe_gsc *gsc); 17 16 18 17 int xe_gsc_proxy_request_handler(struct xe_gsc *gsc);
+1
drivers/gpu/drm/xe/xe_gsc_types.h
··· 13 13 #include <linux/workqueue.h> 14 14 15 15 #include "xe_uc_fw_types.h" 16 + #include "xe_device_types.h" 16 17 17 18 struct xe_bo; 18 19 struct xe_exec_queue;
+15 -20
drivers/gpu/drm/xe/xe_gt.c
··· 141 141 xe_force_wake_put(gt_to_fw(gt), fw_ref); 142 142 } 143 143 144 - /** 145 - * xe_gt_remove() - Clean up the GT structures before driver removal 146 - * @gt: the GT object 147 - * 148 - * This function should only act on objects/structures that must be cleaned 149 - * before the driver removal callback is complete and therefore can't be 150 - * deferred to a drmm action. 151 - */ 152 - void xe_gt_remove(struct xe_gt *gt) 153 - { 154 - int i; 155 - 156 - xe_uc_remove(&gt->uc); 157 - 158 - for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) 159 - xe_hw_fence_irq_finish(&gt->fence_irq[i]); 160 - 161 - xe_gt_disable_host_l2_vram(gt); 162 - } 163 - 164 144 static void gt_reset_worker(struct work_struct *w); 165 145 166 146 static int emit_nop_job(struct xe_gt *gt, struct xe_exec_queue *q) ··· 563 583 return err; 564 584 } 565 585 586 + static void xe_gt_fini(void *arg) 587 + { 588 + struct xe_gt *gt = arg; 589 + int i; 590 + 591 + for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) 592 + xe_hw_fence_irq_finish(&gt->fence_irq[i]); 593 + 594 + xe_gt_disable_host_l2_vram(gt); 595 + } 596 + 566 597 int xe_gt_init(struct xe_gt *gt) 567 598 { 568 599 int err; ··· 585 594 gt->ring_ops[i] = xe_ring_ops_get(gt, i); 586 595 xe_hw_fence_irq_init(&gt->fence_irq[i]); 587 596 } 597 + 598 + err = devm_add_action_or_reset(gt_to_xe(gt)->drm.dev, xe_gt_fini, gt); 599 + if (err) 600 + return err; 588 601 589 602 err = xe_gt_pagefault_init(gt); 590 603 if (err)
-1
drivers/gpu/drm/xe/xe_gt.h
··· 54 54 void xe_gt_reset_async(struct xe_gt *gt); 55 55 void xe_gt_sanitize(struct xe_gt *gt); 56 56 int xe_gt_sanitize_freq(struct xe_gt *gt); 57 - void xe_gt_remove(struct xe_gt *gt); 58 57 59 58 /** 60 59 * xe_gt_wait_for_reset - wait for gt's async reset to finalize.
-13
drivers/gpu/drm/xe/xe_uc.c
··· 289 289 } 290 290 291 291 /** 292 - * xe_uc_remove() - Clean up the UC structures before driver removal 293 - * @uc: the UC object 294 - * 295 - * This function should only act on objects/structures that must be cleaned 296 - * before the driver removal callback is complete and therefore can't be 297 - * deferred to a drmm action. 298 - */ 299 - void xe_uc_remove(struct xe_uc *uc) 300 - { 301 - xe_gsc_remove(&uc->gsc); 302 - } 303 - 304 - /** 305 292 * xe_uc_declare_wedged() - Declare UC wedged 306 293 * @uc: the UC object 307 294 *
-1
drivers/gpu/drm/xe/xe_uc.h
··· 20 20 int xe_uc_start(struct xe_uc *uc); 21 21 int xe_uc_suspend(struct xe_uc *uc); 22 22 int xe_uc_sanitize_reset(struct xe_uc *uc); 23 - void xe_uc_remove(struct xe_uc *uc); 24 23 void xe_uc_declare_wedged(struct xe_uc *uc); 25 24 26 25 #endif