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

iio: backend: add debugFs interface

This adds a basic debugfs interface for backends. Two new ops are being
added:

* debugfs_reg_access: Analogous to the core IIO one but for backend
devices.
* debugfs_print_chan_status: One useful usecase for this one is for
testing test tones in a digital interface and "ask" the backend to
dump more details on why a test tone might have errors.

Signed-off-by: Nuno Sa <nuno.sa@analog.com>
Link: https://patch.msgid.link/20240802-dev-iio-backend-add-debugfs-v2-2-4cb62852f0d0@analog.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Nuno Sa and committed by
Jonathan Cameron
cdf01e08 2256f37e

+180
+20
Documentation/ABI/testing/debugfs-iio-backend
··· 1 + What: /sys/kernel/debug/iio/iio:deviceX/backendY/name 2 + KernelVersion: 6.11 3 + Contact: linux-iio@vger.kernel.org 4 + Description: 5 + Name of Backend Y connected to device X. 6 + 7 + What: /sys/kernel/debug/iio/iio:deviceX/backendY/direct_reg_access 8 + KernelVersion: 6.11 9 + Contact: linux-iio@vger.kernel.org 10 + Description: 11 + Directly access the registers of backend Y. Typical usage is: 12 + 13 + Reading address 0x50 14 + echo 0x50 > direct_reg_access 15 + cat direct_reg_access 16 + 17 + Writing address 0x50 18 + echo 0x50 0x3 > direct_reg_access 19 + //readback address 0x50 20 + cat direct_reg_access
+1
MAINTAINERS
··· 10894 10894 R: Olivier Moysan <olivier.moysan@foss.st.com> 10895 10895 L: linux-iio@vger.kernel.org 10896 10896 S: Maintained 10897 + F: Documentation/ABI/testing/debugfs-iio-backend 10897 10898 F: drivers/iio/industrialio-backend.c 10898 10899 F: include/linux/iio/backend.h 10899 10900
+145
drivers/iio/industrialio-backend.c
··· 32 32 #define dev_fmt(fmt) "iio-backend: " fmt 33 33 34 34 #include <linux/cleanup.h> 35 + #include <linux/debugfs.h> 35 36 #include <linux/device.h> 36 37 #include <linux/err.h> 37 38 #include <linux/errno.h> ··· 54 53 struct device *dev; 55 54 struct module *owner; 56 55 void *priv; 56 + const char *name; 57 + unsigned int cached_reg_addr; 58 + /* 59 + * This index is relative to the frontend. Meaning that for 60 + * frontends with multiple backends, this will be the index of this 61 + * backend. Used for the debugfs directory name. 62 + */ 63 + u8 idx; 57 64 }; 58 65 59 66 /* ··· 125 116 dev_dbg(__back->dev, "Op(%s) not implemented\n",\ 126 117 __stringify(op)); \ 127 118 } 119 + 120 + static ssize_t iio_backend_debugfs_read_reg(struct file *file, 121 + char __user *userbuf, 122 + size_t count, loff_t *ppos) 123 + { 124 + struct iio_backend *back = file->private_data; 125 + char read_buf[20]; 126 + unsigned int val; 127 + int ret, len; 128 + 129 + ret = iio_backend_op_call(back, debugfs_reg_access, 130 + back->cached_reg_addr, 0, &val); 131 + if (ret) 132 + return ret; 133 + 134 + len = scnprintf(read_buf, sizeof(read_buf), "0x%X\n", val); 135 + 136 + return simple_read_from_buffer(userbuf, count, ppos, read_buf, len); 137 + } 138 + 139 + static ssize_t iio_backend_debugfs_write_reg(struct file *file, 140 + const char __user *userbuf, 141 + size_t count, loff_t *ppos) 142 + { 143 + struct iio_backend *back = file->private_data; 144 + unsigned int val; 145 + char buf[80]; 146 + ssize_t rc; 147 + int ret; 148 + 149 + rc = simple_write_to_buffer(buf, sizeof(buf), ppos, userbuf, count); 150 + if (rc < 0) 151 + return rc; 152 + 153 + ret = sscanf(buf, "%i %i", &back->cached_reg_addr, &val); 154 + 155 + switch (ret) { 156 + case 1: 157 + return count; 158 + case 2: 159 + ret = iio_backend_op_call(back, debugfs_reg_access, 160 + back->cached_reg_addr, val, NULL); 161 + if (ret) 162 + return ret; 163 + return count; 164 + default: 165 + return -EINVAL; 166 + } 167 + } 168 + 169 + static const struct file_operations iio_backend_debugfs_reg_fops = { 170 + .open = simple_open, 171 + .read = iio_backend_debugfs_read_reg, 172 + .write = iio_backend_debugfs_write_reg, 173 + }; 174 + 175 + static ssize_t iio_backend_debugfs_read_name(struct file *file, 176 + char __user *userbuf, 177 + size_t count, loff_t *ppos) 178 + { 179 + struct iio_backend *back = file->private_data; 180 + char name[128]; 181 + int len; 182 + 183 + len = scnprintf(name, sizeof(name), "%s\n", back->name); 184 + 185 + return simple_read_from_buffer(userbuf, count, ppos, name, len); 186 + } 187 + 188 + static const struct file_operations iio_backend_debugfs_name_fops = { 189 + .open = simple_open, 190 + .read = iio_backend_debugfs_read_name, 191 + }; 192 + 193 + /** 194 + * iio_backend_debugfs_add - Add debugfs interfaces for Backends 195 + * @back: Backend device 196 + * @indio_dev: IIO device 197 + */ 198 + void iio_backend_debugfs_add(struct iio_backend *back, 199 + struct iio_dev *indio_dev) 200 + { 201 + struct dentry *d = iio_get_debugfs_dentry(indio_dev); 202 + struct dentry *back_d; 203 + char name[128]; 204 + 205 + if (!IS_ENABLED(CONFIG_DEBUG_FS) || !d) 206 + return; 207 + if (!back->ops->debugfs_reg_access && !back->name) 208 + return; 209 + 210 + snprintf(name, sizeof(name), "backend%d", back->idx); 211 + 212 + back_d = debugfs_create_dir(name, d); 213 + if (!back_d) 214 + return; 215 + 216 + if (back->ops->debugfs_reg_access) 217 + debugfs_create_file("direct_reg_access", 0600, back_d, back, 218 + &iio_backend_debugfs_reg_fops); 219 + 220 + if (back->name) 221 + debugfs_create_file("name", 0400, back_d, back, 222 + &iio_backend_debugfs_name_fops); 223 + } 224 + EXPORT_SYMBOL_NS_GPL(iio_backend_debugfs_add, IIO_BACKEND); 225 + 226 + /** 227 + * iio_backend_debugfs_print_chan_status - Print channel status 228 + * @back: Backend device 229 + * @chan: Channel number 230 + * @buf: Buffer where to print the status 231 + * @len: Available space 232 + * 233 + * One usecase where this is useful is for testing test tones in a digital 234 + * interface and "ask" the backend to dump more details on why a test tone might 235 + * have errors. 236 + * 237 + * RETURNS: 238 + * Number of copied bytes on success, negative error code on failure. 239 + */ 240 + ssize_t iio_backend_debugfs_print_chan_status(struct iio_backend *back, 241 + unsigned int chan, char *buf, 242 + size_t len) 243 + { 244 + if (!IS_ENABLED(CONFIG_DEBUG_FS)) 245 + return -ENODEV; 246 + 247 + return iio_backend_op_call(back, debugfs_print_chan_status, chan, buf, 248 + len); 249 + } 250 + EXPORT_SYMBOL_NS_GPL(iio_backend_debugfs_print_chan_status, IIO_BACKEND); 128 251 129 252 /** 130 253 * iio_backend_chan_enable - Enable a backend channel ··· 718 577 if (ret) 719 578 return ERR_PTR(ret); 720 579 580 + if (name) 581 + back->idx = index; 582 + 721 583 return back; 722 584 } 723 585 ··· 812 668 return -ENOMEM; 813 669 814 670 back->ops = info->ops; 671 + back->name = info->name; 815 672 back->owner = dev->driver->owner; 816 673 back->dev = dev; 817 674 back->priv = priv;
+14
include/linux/iio/backend.h
··· 22 22 IIO_BACKEND_DATA_SOURCE_MAX 23 23 }; 24 24 25 + #define iio_backend_debugfs_ptr(ptr) PTR_IF(IS_ENABLED(CONFIG_DEBUG_FS), ptr) 26 + 25 27 /** 26 28 * IIO_BACKEND_EX_INFO - Helper for an IIO extended channel attribute 27 29 * @_name: Attribute name ··· 83 81 * @extend_chan_spec: Extend an IIO channel. 84 82 * @ext_info_set: Extended info setter. 85 83 * @ext_info_get: Extended info getter. 84 + * @debugfs_print_chan_status: Print channel status into a buffer. 85 + * @debugfs_reg_access: Read or write register value of backend. 86 86 **/ 87 87 struct iio_backend_ops { 88 88 int (*enable)(struct iio_backend *back); ··· 117 113 const char *buf, size_t len); 118 114 int (*ext_info_get)(struct iio_backend *back, uintptr_t private, 119 115 const struct iio_chan_spec *chan, char *buf); 116 + int (*debugfs_print_chan_status)(struct iio_backend *back, 117 + unsigned int chan, char *buf, 118 + size_t len); 119 + int (*debugfs_reg_access)(struct iio_backend *back, unsigned int reg, 120 + unsigned int writeval, unsigned int *readval); 120 121 }; 121 122 122 123 /** ··· 172 163 int devm_iio_backend_register(struct device *dev, 173 164 const struct iio_backend_info *info, void *priv); 174 165 166 + ssize_t iio_backend_debugfs_print_chan_status(struct iio_backend *back, 167 + unsigned int chan, char *buf, 168 + size_t len); 169 + void iio_backend_debugfs_add(struct iio_backend *back, 170 + struct iio_dev *indio_dev); 175 171 #endif