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 19 static struct xe_pxp *node_to_pxp(struct drm_info_node *node) 20 { 21 return node->info_ent->data; 22 } 23 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 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 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 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