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