Skip to content

Commit 776e3b5

Browse files
committed
drm/xe: Add callback support for driver remove
xe device probe uses devm cleanup in most places. However there are a few cases where this is not possible: when the driver interacts with component add/del. In that case, the resource group would be cleanup while the entire device resources are in the process of cleanup. One example is the xe_gsc_proxy and display using that to interact with mei and audio. Add a callback-based remove so the exception doesn't make the probe use multiple error handling styles. v2: Change internal API to mimic the devm API. This will make it easier to migrate in future when devm can be used. Cc: Daniele Ceraolo Spurio <[email protected]> Cc: Rodrigo Vivi <[email protected]> Cc: Thomas Hellström <[email protected]> Reviewed-by: Rodrigo Vivi <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] Signed-off-by: Lucas De Marchi <[email protected]>
1 parent 6884d20 commit 776e3b5

File tree

4 files changed

+88
-1
lines changed

4 files changed

+88
-1
lines changed

drivers/gpu/drm/xe/xe_device.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@
6565

6666
#include <generated/xe_wa_oob.h>
6767

68+
struct xe_device_remove_action {
69+
struct list_head node;
70+
void (*action)(void *);
71+
void *data;
72+
};
73+
6874
static int xe_file_open(struct drm_device *dev, struct drm_file *file)
6975
{
7076
struct xe_device *xe = to_xe_device(dev);
@@ -746,6 +752,9 @@ int xe_device_probe(struct xe_device *xe)
746752
u8 last_gt;
747753
u8 id;
748754

755+
xe->probing = true;
756+
INIT_LIST_HEAD(&xe->remove_action_list);
757+
749758
xe_pat_init_early(xe);
750759

751760
err = xe_sriov_init(xe);
@@ -886,6 +895,8 @@ int xe_device_probe(struct xe_device *xe)
886895

887896
xe_vsec_init(xe);
888897

898+
xe->probing = false;
899+
889900
return devm_add_action_or_reset(xe->drm.dev, xe_device_sanitize, xe);
890901

891902
err_fini_display:
@@ -907,6 +918,61 @@ int xe_device_probe(struct xe_device *xe)
907918
return err;
908919
}
909920

921+
/**
922+
* xe_device_call_remove_actions - Call the remove actions
923+
* @xe: xe device instance
924+
*
925+
* This is only to be used by xe_pci and xe_device to call the remove actions
926+
* while removing the driver or handling probe failures.
927+
*/
928+
void xe_device_call_remove_actions(struct xe_device *xe)
929+
{
930+
struct xe_device_remove_action *ra, *tmp;
931+
932+
list_for_each_entry_safe(ra, tmp, &xe->remove_action_list, node) {
933+
ra->action(ra->data);
934+
list_del(&ra->node);
935+
kfree(ra);
936+
}
937+
938+
xe->probing = false;
939+
}
940+
941+
/**
942+
* xe_device_add_action_or_reset - Add an action to run on driver removal
943+
* @xe: xe device instance
944+
* @action: Function that should be called on device remove
945+
* @data: Pointer to data passed to @action implementation
946+
*
947+
* This adds a custom action to the list of remove callbacks executed on device
948+
* remove, before any dev or drm managed resources are removed. This is only
949+
* needed if the action leads to component_del()/component_master_del() since
950+
* that is not compatible with devres cleanup.
951+
*
952+
* Returns: 0 on success or a negative error code on failure, in which case
953+
* @action is already called.
954+
*/
955+
int xe_device_add_action_or_reset(struct xe_device *xe,
956+
void (*action)(void *), void *data)
957+
{
958+
struct xe_device_remove_action *ra;
959+
960+
drm_WARN_ON(&xe->drm, !xe->probing);
961+
962+
ra = kmalloc(sizeof(*ra), GFP_KERNEL);
963+
if (!ra) {
964+
action(data);
965+
return -ENOMEM;
966+
}
967+
968+
INIT_LIST_HEAD(&ra->node);
969+
ra->action = action;
970+
ra->data = data;
971+
list_add(&ra->node, &xe->remove_action_list);
972+
973+
return 0;
974+
}
975+
910976
static void xe_device_remove_display(struct xe_device *xe)
911977
{
912978
xe_display_unregister(xe);
@@ -932,6 +998,8 @@ void xe_device_remove(struct xe_device *xe)
932998

933999
for_each_gt(gt, xe, id)
9341000
xe_gt_remove(gt);
1001+
1002+
xe_device_call_remove_actions(xe);
9351003
}
9361004

9371005
void xe_device_shutdown(struct xe_device *xe)

drivers/gpu/drm/xe/xe_device.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ struct xe_device *xe_device_create(struct pci_dev *pdev,
4545
const struct pci_device_id *ent);
4646
int xe_device_probe_early(struct xe_device *xe);
4747
int xe_device_probe(struct xe_device *xe);
48+
int xe_device_add_action_or_reset(struct xe_device *xe,
49+
void (*action)(void *), void *data);
50+
void xe_device_call_remove_actions(struct xe_device *xe);
4851
void xe_device_remove(struct xe_device *xe);
4952
void xe_device_shutdown(struct xe_device *xe);
5053

drivers/gpu/drm/xe/xe_device_types.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,20 @@ struct xe_device {
428428
/** @tiles: device tiles */
429429
struct xe_tile tiles[XE_MAX_TILES_PER_DEVICE];
430430

431+
/**
432+
* @remove_action_list: list of actions to execute on device remove.
433+
* Use xe_device_add_remove_action() for that. Actions can only be added
434+
* during probe and are executed during the call from PCI subsystem to
435+
* remove the driver from the device.
436+
*/
437+
struct list_head remove_action_list;
438+
439+
/**
440+
* @probing: cover the section in which @remove_action_list can be used
441+
* to post cleaning actions
442+
*/
443+
bool probing;
444+
431445
/**
432446
* @mem_access: keep track of memory access in the device, possibly
433447
* triggering additional actions when they occur.

drivers/gpu/drm/xe/xe_pci.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -900,8 +900,10 @@ static int xe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
900900
return err;
901901

902902
err = xe_device_probe(xe);
903-
if (err)
903+
if (err) {
904+
xe_device_call_remove_actions(xe);
904905
return err;
906+
}
905907

906908
err = xe_pm_init(xe);
907909
if (err)

0 commit comments

Comments
 (0)