On Fri, 2023-06-16 at 10:46 +0300, Ilpo Järvinen wrote: > On Thu, 15 Jun 2023, Srinivas Pandruvada wrote: > > > [...] > > + seq_puts(s, help); > > The appropriate place to this kinda information would seem to be: > > Documentation/ABI/testing/debugfs-... file. I prefer to add to Documentation. But this is for validation folks, who struggle to get documentation, will ask you 10 question before using. Hence added here. But I don't have strong preference here. I can move to doc area. > > > + > > + return 0; > > +} > > +DEFINE_SHOW_ATTRIBUTE(tpmi_help); > > + > > +static int tpmi_pfs_dbg_show(struct seq_file *s, void *unused) > > +{ > > + struct intel_tpmi_info *tpmi_info = s->private; > > + int i, ret; > > + > > + seq_printf(s, "tpmi PFS start offset 0x:%llx\n", tpmi_info- > > >pfs_start); > > + seq_puts(s, > > "tpmi_id\t\tnum_entries\tentry_size\t\tcap_offset\tattribute\tfull_ > > base_pointer_for_memmap\tlocked\tdisabled\n"); > > + for (i = 0; i < tpmi_info->feature_count; ++i) { > > + struct intel_tpmi_pm_feature *pfs; > > + int locked, disabled; > > + > > + pfs = &tpmi_info->tpmi_features[i]; > > + ret = tpmi_read_feature_status(tpmi_info, pfs- > > >pfs_header.tpmi_id, &locked, &disabled); > > + if (ret) { > > + locked = 'U'; > > + disabled = 'U'; > > + } else { > > + disabled = disabled ? 'Y' : 'N'; > > + locked = locked ? 'Y' : 'N'; > > + } > > + seq_printf(s, > > "0x%02x\t\t0x%02x\t\t0x%06x\t\t0x%04x\t\t0x%02x\t\t0x%x\t\t\t%c\t%c > > \n", > > The last hex is just %x (not %08x), is it intentional? Not intentional. > > > + pfs->pfs_header.tpmi_id, pfs- > > >pfs_header.num_entries, pfs->pfs_header.entry_size, > > + pfs->pfs_header.cap_offset, pfs- > > >pfs_header.attribute, pfs->vsec_offset, locked, disabled); > > Please split parameters to 100 columns (I'm okay with the string > exceeding it). > > It would help here if you add pointer also to pfs_header struct. ;-) > Will think about it if useful. > > + } > > + > > + return 0; > > +} > > +DEFINE_SHOW_ATTRIBUTE(tpmi_pfs_dbg); > > + > > +#define MEM_DUMP_COLUMN_COUNT 8 > > + > > +static int tpmi_mem_dump_show(struct seq_file *s, void *unused) > > +{ > > + size_t row_size = MEM_DUMP_COLUMN_COUNT * sizeof(u32); > > + struct intel_tpmi_pm_feature *pfs = s->private; > > + int count, ret = 0; > > + void __iomem *mem; > > + u16 size; > > + u32 off; > > + > > + off = pfs->vsec_offset; > > + > > + mutex_lock(&tpmi_dev_lock); > > + > > + for (count = 0; count < pfs->pfs_header.num_entries; > > ++count) { > > + u8 *buffer; > > Why only this is declared here? I see no consistency based on > variable usage/scope. I will fix this. > > > + size = pfs->pfs_header.entry_size * sizeof(u32); > > Can this overflow? No. Coming from a trusted architectural source. The system will not pass BIOS if they are wrong. > > > + buffer = kmalloc(size, GFP_KERNEL); > > + if (!buffer) { > > + ret = -ENOMEM; > > + goto done_mem_show; > > + } > > + > > + seq_printf(s, "TPMI Instance:%d offset:0x%x\n", > > count, off); > > + > > + mem = ioremap(off, size); > > + if (!mem) { > > + ret = -ENOMEM; > > + kfree(buffer); > > + goto done_mem_show; > > + } > > + > > + memcpy_fromio(buffer, mem, size); > > + > > + seq_hex_dump(s, " ", DUMP_PREFIX_OFFSET, row_size, > > sizeof(u32), buffer, size, false); > > + > > + iounmap(mem); > > + kfree(buffer); > > + > > + off += size; > > + } > > + > > +done_mem_show: > > + mutex_unlock(&tpmi_dev_lock); > > + > > + return ret; > > +} > > +DEFINE_SHOW_ATTRIBUTE(tpmi_mem_dump); > > + > > +static ssize_t mem_write(struct file *file, const char __user > > *userbuf, size_t len, loff_t *ppos) > > +{ > > + struct seq_file *m = file->private_data; > > + struct intel_tpmi_pm_feature *pfs = m->private; > > + u32 addr, value, punit; > > + u32 num_elems, *array; > > + void __iomem *mem; > > + u16 size; > > + int ret; > > + > > + ret = parse_int_array_user(userbuf, len, (int **)&array); > > + if (ret < 0) > > + return ret; > > + > > + num_elems = *array; > > + if (num_elems != 3) { > > + ret = -EINVAL; > > + goto exit_write; > > + } > > + > > + punit = array[1]; > > + addr = array[2]; > > + value = array[3]; > > + > > + if (punit >= pfs->pfs_header.num_entries) { > > + ret = -EINVAL; > > + goto exit_write; > > + } > > + > > + size = pfs->pfs_header.entry_size * sizeof(u32); > > There's no consistency in the code, some places do: entry_size * 4 > and > here it's entry_size * sizeof(u32). Please convert all of them to the > latter one. You need to do one additional patch to convert the > existing > users but that's perfectly fine as an additional cleanup patch (don't > try to put it either of these patches "while at it"). Good idea. > > > + if (addr >= size) { > > + ret = -EINVAL; > > + goto exit_write; > > + } > > + > > + mutex_lock(&tpmi_dev_lock); > > + > > + mem = ioremap(pfs->vsec_offset + (punit * size), size); > > Unnecessary parenthesis. ok > > > + if (!mem) { > > + ret = -ENOMEM; > > + goto unlock_mem_write; > > + } > > + > > + writel(value, mem + addr); > > + > > + iounmap(mem); > > + > > + ret = len; > > + > > +unlock_mem_write: > > + mutex_unlock(&tpmi_dev_lock); > > + > > +exit_write: > > + kfree(array); > > + > > + return ret; > > +} > > + > > +static int mem_write_show(struct seq_file *s, void *unused) > > +{ > > + return 0; > > +} > > + > > +static int mem_write_open(struct inode *inode, struct file *file) > > +{ > > + return single_open(file, mem_write_show, inode->i_private); > > +} > > + > > +static const struct file_operations mem_write_ops = { > > + .open = mem_write_open, > > + .read = seq_read, > > + .write = mem_write, > > + .llseek = seq_lseek, > > + .release = single_release, > > +}; > > + > > +#define tpmi_to_dev(info) (&info->vsec_dev->pcidev->dev) > > + > > +static void tpmi_dbgfs_register(struct intel_tpmi_info *tpmi_info) > > +{ > > + struct dentry *top_dir; > > + char name[64]; > > + int i; > > + > > + snprintf(name, sizeof(name), "tpmi-%s", > > dev_name(tpmi_to_dev(tpmi_info))); > > + top_dir = debugfs_create_dir(name, NULL); > > + if (IS_ERR_OR_NULL(top_dir)) > > + return; > > + > > + tpmi_info->dbgfs_dir = top_dir; > > + > > + debugfs_create_file("pfs_dump", 0444, top_dir, tpmi_info, > > + &tpmi_pfs_dbg_fops); > > One line. OK > > > + debugfs_create_file("help", 0444, top_dir, NULL, > > &tpmi_help_fops); > > + for (i = 0; i < tpmi_info->feature_count; ++i) { > > + struct intel_tpmi_pm_feature *pfs; > > + struct dentry *dir; > > + > > + pfs = &tpmi_info->tpmi_features[i]; > > + snprintf(name, sizeof(name), "tpmi-id-%02x", pfs- > > >pfs_header.tpmi_id); > > + dir = debugfs_create_dir(name, top_dir); > > + > > + debugfs_create_file("mem_dump", 0444, dir, pfs, > > + &tpmi_mem_dump_fops); > > + debugfs_create_file("mem_write", 0644, dir, pfs, > > + &mem_write_ops); > > These too can be put to one line. > OK Thanks, Srinivas >