xref: /linux/drivers/gpu/drm/xe/xe_pxp_debugfs.c (revision 51c7960b87f465d01ea8d8ff174e81dd69f3b2b4)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2024 Intel Corporation
4  */
5 
6 #include "xe_pxp_debugfs.h"
7 
8 #include <linux/debugfs.h>
9 
10 #include <drm/drm_debugfs.h>
11 #include <drm/drm_managed.h>
12 #include <drm/drm_print.h>
13 
14 #include "xe_device.h"
15 #include "xe_pxp.h"
16 #include "xe_pxp_types.h"
17 #include "regs/xe_irq_regs.h"
18 
node_to_pxp(struct drm_info_node * node)19 static struct xe_pxp *node_to_pxp(struct drm_info_node *node)
20 {
21 	return node->info_ent->data;
22 }
23 
pxp_status_to_str(struct xe_pxp * pxp)24 static const char *pxp_status_to_str(struct xe_pxp *pxp)
25 {
26 	lockdep_assert_held(&pxp->mutex);
27 
28 	switch (pxp->status) {
29 	case XE_PXP_ERROR:
30 		return "error";
31 	case XE_PXP_NEEDS_TERMINATION:
32 		return "needs termination";
33 	case XE_PXP_TERMINATION_IN_PROGRESS:
34 		return "termination in progress";
35 	case XE_PXP_READY_TO_START:
36 		return "ready to start";
37 	case XE_PXP_ACTIVE:
38 		return "active";
39 	case XE_PXP_SUSPENDED:
40 		return "suspended";
41 	default:
42 		return "unknown";
43 	}
44 };
45 
pxp_info(struct seq_file * m,void * data)46 static int pxp_info(struct seq_file *m, void *data)
47 {
48 	struct xe_pxp *pxp = node_to_pxp(m->private);
49 	struct drm_printer p = drm_seq_file_printer(m);
50 	const char *status;
51 
52 	if (!xe_pxp_is_enabled(pxp))
53 		return -ENODEV;
54 
55 	mutex_lock(&pxp->mutex);
56 	status = pxp_status_to_str(pxp);
57 
58 	drm_printf(&p, "status: %s\n", status);
59 	drm_printf(&p, "instance counter: %u\n", pxp->key_instance);
60 	mutex_unlock(&pxp->mutex);
61 
62 	return 0;
63 }
64 
pxp_terminate(struct seq_file * m,void * data)65 static int pxp_terminate(struct seq_file *m, void *data)
66 {
67 	struct xe_pxp *pxp = node_to_pxp(m->private);
68 	struct drm_printer p = drm_seq_file_printer(m);
69 	int ready = xe_pxp_get_readiness_status(pxp);
70 
71 	if (ready < 0)
72 		return ready; /* disabled or error occurred */
73 	else if (!ready)
74 		return -EBUSY; /* init still in progress */
75 
76 	/* no need for a termination if PXP is not active */
77 	if (pxp->status != XE_PXP_ACTIVE) {
78 		drm_printf(&p, "PXP not active\n");
79 		return 0;
80 	}
81 
82 	/* simulate a termination interrupt */
83 	spin_lock_irq(&pxp->xe->irq.lock);
84 	xe_pxp_irq_handler(pxp->xe, KCR_PXP_STATE_TERMINATED_INTERRUPT);
85 	spin_unlock_irq(&pxp->xe->irq.lock);
86 
87 	drm_printf(&p, "PXP termination queued\n");
88 
89 	return 0;
90 }
91 
92 static const struct drm_info_list debugfs_list[] = {
93 	{"info", pxp_info, 0},
94 	{"terminate", pxp_terminate, 0},
95 };
96 
xe_pxp_debugfs_register(struct xe_pxp * pxp)97 void xe_pxp_debugfs_register(struct xe_pxp *pxp)
98 {
99 	struct drm_minor *minor;
100 	struct drm_info_list *local;
101 	struct dentry *root;
102 	int i;
103 
104 	if (!xe_pxp_is_enabled(pxp))
105 		return;
106 
107 	minor = pxp->xe->drm.primary;
108 	if (!minor->debugfs_root)
109 		return;
110 
111 #define DEBUGFS_SIZE	(ARRAY_SIZE(debugfs_list) * sizeof(struct drm_info_list))
112 	local = drmm_kmalloc(&pxp->xe->drm, DEBUGFS_SIZE, GFP_KERNEL);
113 	if (!local)
114 		return;
115 
116 	memcpy(local, debugfs_list, DEBUGFS_SIZE);
117 #undef DEBUGFS_SIZE
118 
119 	for (i = 0; i < ARRAY_SIZE(debugfs_list); ++i)
120 		local[i].data = pxp;
121 
122 	root = debugfs_create_dir("pxp", minor->debugfs_root);
123 	if (IS_ERR(root))
124 		return;
125 
126 	drm_debugfs_create_files(local,
127 				 ARRAY_SIZE(debugfs_list),
128 				 root, minor);
129 }
130