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

Configure Feed

Select the types of activity you want to include in your feed.

drm/imagination: Validate fw trace group_mask

This value can come from two places: a module parameter or a debugfs file.
In both cases, validate it early to provide feedback to userspace at the
time the value is set instead of deferring until the value is used.

Reviewed-by: Alessio Belle <alessio.belle@imgtec.com>
Link: https://patch.msgid.link/20260113-device-support-info-v1-2-91e5db7f7294@imgtec.com
Signed-off-by: Matt Coster <matt.coster@imgtec.com>

+62 -14
+62 -14
drivers/gpu/drm/imagination/pvr_fw_trace.c
··· 12 12 #include <drm/drm_print.h> 13 13 14 14 #include <linux/build_bug.h> 15 + #include <linux/compiler_attributes.h> 15 16 #include <linux/dcache.h> 16 17 #include <linux/debugfs.h> 17 18 #include <linux/moduleparam.h> 18 19 #include <linux/sysfs.h> 19 20 #include <linux/types.h> 21 + 22 + static int 23 + validate_group_mask(struct pvr_device *pvr_dev, const u32 group_mask) 24 + { 25 + if (group_mask & ~ROGUE_FWIF_LOG_TYPE_GROUP_MASK) { 26 + drm_warn(from_pvr_device(pvr_dev), 27 + "Invalid fw_trace group mask 0x%08x (must be a subset of 0x%08x)", 28 + group_mask, ROGUE_FWIF_LOG_TYPE_GROUP_MASK); 29 + return -EINVAL; 30 + } 31 + 32 + return 0; 33 + } 34 + 35 + static inline u32 36 + build_log_type(const u32 group_mask) 37 + { 38 + if (!group_mask) 39 + return ROGUE_FWIF_LOG_TYPE_NONE; 40 + 41 + return group_mask | ROGUE_FWIF_LOG_TYPE_TRACE; 42 + } 20 43 21 44 /* 22 45 * Don't gate this behind CONFIG_DEBUG_FS so that it can be used as an initial ··· 52 29 * there's no reason to turn on fw_trace without it. 53 30 */ 54 31 #if IS_ENABLED(CONFIG_DEBUG_FS) 55 - module_param_named(init_fw_trace_mask, pvr_fw_trace_init_mask, hexint, 0600); 32 + static int 33 + pvr_fw_trace_init_mask_set(const char *val, const struct kernel_param *kp) 34 + { 35 + u32 mask = 0; 36 + int err; 37 + 38 + err = kstrtouint(val, 0, &mask); 39 + if (err) 40 + return err; 41 + 42 + err = validate_group_mask(NULL, mask); 43 + if (err) 44 + return err; 45 + 46 + *(unsigned int *)kp->arg = mask; 47 + 48 + return 0; 49 + } 50 + 51 + const struct kernel_param_ops pvr_fw_trace_init_mask_ops = { 52 + .set = pvr_fw_trace_init_mask_set, 53 + .get = param_get_hexint, 54 + }; 55 + 56 + param_check_hexint(init_fw_trace_mask, &pvr_fw_trace_init_mask); 57 + module_param_cb(init_fw_trace_mask, &pvr_fw_trace_init_mask_ops, &pvr_fw_trace_init_mask, 0600); 58 + __MODULE_PARM_TYPE(init_fw_trace_mask, "hexint"); 56 59 MODULE_PARM_DESC(init_fw_trace_mask, 57 60 "Enable FW trace for the specified groups at device init time"); 58 61 #endif ··· 91 42 92 43 tracebuf_ctrl->tracebuf_size_in_dwords = ROGUE_FW_TRACE_BUF_DEFAULT_SIZE_IN_DWORDS; 93 44 tracebuf_ctrl->tracebuf_flags = 0; 94 - 95 - if (fw_trace->group_mask) 96 - tracebuf_ctrl->log_type = fw_trace->group_mask | ROGUE_FWIF_LOG_TYPE_TRACE; 97 - else 98 - tracebuf_ctrl->log_type = ROGUE_FWIF_LOG_TYPE_NONE; 45 + tracebuf_ctrl->log_type = build_log_type(fw_trace->group_mask); 99 46 100 47 for (u32 thread_nr = 0; thread_nr < ARRAY_SIZE(fw_trace->buffers); thread_nr++) { 101 48 struct rogue_fwif_tracebuf_space *tracebuf_space = ··· 185 140 /** 186 141 * update_logtype() - Send KCCB command to trigger FW to update logtype 187 142 * @pvr_dev: Target PowerVR device 188 - * @group_mask: New log group mask. 143 + * @group_mask: New log group mask; must pass validate_group_mask(). 189 144 * 190 145 * Returns: 191 146 * * 0 if the provided @group_mask is the same as the current value (this is a ··· 198 153 update_logtype(struct pvr_device *pvr_dev, u32 group_mask) 199 154 { 200 155 struct pvr_fw_trace *fw_trace = &pvr_dev->fw_dev.fw_trace; 156 + struct drm_device *drm_dev = from_pvr_device(pvr_dev); 201 157 struct rogue_fwif_kccb_cmd cmd; 202 158 int idx; 203 159 int err; ··· 207 161 if (fw_trace->group_mask == group_mask) 208 162 return 0; 209 163 210 - if (group_mask) 211 - fw_trace->tracebuf_ctrl->log_type = ROGUE_FWIF_LOG_TYPE_TRACE | group_mask; 212 - else 213 - fw_trace->tracebuf_ctrl->log_type = ROGUE_FWIF_LOG_TYPE_NONE; 214 - 215 164 fw_trace->group_mask = group_mask; 165 + fw_trace->tracebuf_ctrl->log_type = build_log_type(group_mask); 216 166 217 167 down_read(&pvr_dev->reset_sem); 218 - if (!drm_dev_enter(from_pvr_device(pvr_dev), &idx)) { 168 + if (!drm_dev_enter(drm_dev, &idx)) { 219 169 err = -EIO; 220 170 goto err_up_read; 221 171 } ··· 514 472 static int pvr_fw_trace_mask_set(void *data, u64 value) 515 473 { 516 474 struct pvr_device *pvr_dev = data; 475 + const u32 group_mask = (u32)value; 476 + int err; 517 477 518 - return update_logtype(pvr_dev, (u32)value); 478 + err = validate_group_mask(pvr_dev, group_mask); 479 + if (err) 480 + return err; 481 + 482 + return update_logtype(pvr_dev, group_mask); 519 483 } 520 484 521 485 DEFINE_DEBUGFS_ATTRIBUTE(pvr_fw_trace_mask_fops, pvr_fw_trace_mask_get,