lkml.org 
[lkml]   [2023]   [Feb]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    SubjectRe: [PATCH v2 5/5] apple-gmux: add debugfs interface
    From
    Hi,

    On 2/16/23 13:23, Orlando Chamberlain wrote:
    > Allow reading and writing gmux ports from userspace.
    >
    > For example:
    >
    > echo 4 > /sys/kernel/debug/apple_gmux/selected_port
    > cat /sys/kernel/debug/apple_gmux/selected_port_data | xxd -p
    >
    > Will show the gmux version information (00000005 in this case)
    >
    > Signed-off-by: Orlando Chamberlain <orlandoch.dev@gmail.com>
    > ---
    > v1->v2: Use debugfs instead of sysfs.
    > drivers/platform/x86/apple-gmux.c | 88 +++++++++++++++++++++++++++++++
    > 1 file changed, 88 insertions(+)
    >
    > diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
    > index 5bac6dcfada0..e8a35d98b113 100644
    > --- a/drivers/platform/x86/apple-gmux.c
    > +++ b/drivers/platform/x86/apple-gmux.c
    > @@ -22,6 +22,7 @@
    > #include <linux/delay.h>
    > #include <linux/pci.h>
    > #include <linux/vga_switcheroo.h>
    > +#include <linux/debugfs.h>
    > #include <asm/io.h>
    >
    > /**
    > @@ -66,6 +67,10 @@ struct apple_gmux_data {
    > enum vga_switcheroo_client_id switch_state_external;
    > enum vga_switcheroo_state power_state;
    > struct completion powerchange_done;
    > +
    > + /* debugfs data */
    > + u8 selected_port;
    > + struct dentry *debug_dentry;
    > };
    >
    > static struct apple_gmux_data *apple_gmux_data;
    > @@ -674,6 +679,87 @@ static void gmux_notify_handler(acpi_handle device, u32 value, void *context)
    > complete(&gmux_data->powerchange_done);
    > }
    >
    > +/**
    > + * DOC: Debugfs Interface
    > + *
    > + * gmux ports can be accessed from userspace as a debugfs interface. For example:
    > + *
    > + * # echo 4 > /sys/kernel/debug/apple_gmux/selected_port
    > + * # cat /sys/kernel/debug/apple_gmux/selected_port_data | xxd -p
    > + * 00000005
    > + *
    > + * Reads 4 bytes from port 4 (GMUX_PORT_VERSION_MAJOR).
    > + *
    > + * 1 and 4 byte writes are also allowed.
    > + */
    > +
    > +static ssize_t gmux_selected_port_data_write(struct file *file,
    > + const char __user *userbuf, size_t count, loff_t *ppos)
    > +{
    > + struct apple_gmux_data *gmux_data = file->private_data;
    > + int ret;
    > +
    > + if (*ppos)
    > + return -EINVAL;
    > +
    > + if (count == 1) {
    > + u8 data;
    > +
    > + ret = copy_from_user(&data, userbuf, 1);
    > + if (ret)
    > + return ret;
    > + gmux_write8(gmux_data, gmux_data->selected_port, data);
    > + } else if (count == 4) {
    > + u32 data;
    > +
    > + ret = copy_from_user(&data, userbuf, 4);
    > + if (ret)
    > + return ret;
    > + gmux_write32(gmux_data, gmux_data->selected_port, data);
    > + } else
    > + return -EINVAL;
    > +
    > + return count;
    > +}
    > +
    > +static ssize_t gmux_selected_port_data_read(struct file *file,
    > + char __user *userbuf, size_t count, loff_t *ppos)
    > +{
    > + struct apple_gmux_data *gmux_data = file->private_data;
    > + u32 data;
    > +
    > + data = gmux_read32(gmux_data, gmux_data->selected_port);
    > +
    > + return simple_read_from_buffer(userbuf, count, ppos, &data, sizeof(data));
    > +}
    > +
    > +static const struct file_operations gmux_port_data_ops = {
    > + .open = simple_open,
    > + .write = gmux_selected_port_data_write,
    > + .read = gmux_selected_port_data_read
    > +};
    > +
    > +static void gmux_init_debugfs(struct apple_gmux_data *gmux_data)
    > +{
    > + struct dentry *debug_dentry;
    > +
    > + debug_dentry = debugfs_create_dir(KBUILD_MODNAME, NULL);
    > +
    > + if (IS_ERR(debug_dentry))
    > + return;

    This error check is not necessary here. The debugfs_create_*
    and debugfs_remove_recursive() functions will happily take
    the ERR_PTR value and ignore it.

    This is what I tried to say when I said that no error handling
    is necessary with debugfs (by design).

    Regards,

    Hans


    > +
    > + gmux_data->debug_dentry = debug_dentry;
    > +
    > + debugfs_create_u8("selected_port", 0644, debug_dentry, &gmux_data->selected_port);
    > + debugfs_create_file("selected_port_data", 0644, debug_dentry,
    > + gmux_data, &gmux_port_data_ops);
    > +}
    > +
    > +static void gmux_fini_debugfs(struct apple_gmux_data *gmux_data)
    > +{
    > + debugfs_remove_recursive(gmux_data->debug_dentry);
    > +}
    > +
    > static int gmux_suspend(struct device *dev)
    > {
    > struct pnp_dev *pnp = to_pnp_dev(dev);
    > @@ -874,6 +960,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
    > goto err_register_handler;
    > }
    >
    > + gmux_init_debugfs(gmux_data);
    > return 0;
    >
    > err_register_handler:
    > @@ -905,6 +992,7 @@ static void gmux_remove(struct pnp_dev *pnp)
    > {
    > struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp);
    >
    > + gmux_fini_debugfs(gmux_data);
    > vga_switcheroo_unregister_handler();
    > gmux_disable_interrupts(gmux_data);
    > if (gmux_data->gpe >= 0) {

    \
     
     \ /
      Last update: 2023-03-27 00:25    [W:4.242 / U:0.116 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site